Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mcstas instrument geometry in the loader. #18

Merged
merged 10 commits into from
Jan 10, 2024
38 changes: 34 additions & 4 deletions docs/examples/workflow.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"## Collect Parameters and Providers\n",
"### Simulation(McStas) Data\n",
"There is a dedicated loader, ``load_mcstas_nexus`` for ``McStas`` simulation data workflow. <br>\n",
"``MaximumProbability`` can be manually provided to the loader to derive more realistic number of events. <br>\n",
"``MaximumProbability`` can be manually provided to the loader <br>\n",
"to derive more realistic number of events. <br>\n",
"It is because ``weights`` are given as probability, not number of events in a McStas file. <br>"
]
},
Expand Down Expand Up @@ -47,7 +48,9 @@
"source": [
"from typing import get_type_hints\n",
"param_reprs = {key.__name__: value for key, value in params.items()}\n",
"prov_reprs = {get_type_hints(prov)['return'].__name__: prov.__name__ for prov in providers}\n",
"prov_reprs = {\n",
" get_type_hints(prov)['return'].__name__: prov.__name__ for prov in providers\n",
"}\n",
"\n",
"# Providers and parameters to be used for pipeline\n",
"sc.DataGroup(**prov_reprs, **param_reprs)"
Expand Down Expand Up @@ -91,11 +94,38 @@
"da = nmx_workflow.compute(NMXData)\n",
"da"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Instrument View\n",
"\n",
"Pixel positions are not used for later steps,\n",
"but it is included in the coordinates for instrument view.\n",
"\n",
"All pixel positions are relative to the sample position,\n",
"therefore the sample is at (0, 0, 0).\n",
"\n",
"You can plot the instrument view like below.\n",
"\n",
"```python\n",
"import scippneutron as scn\n",
"\n",
"unnecessary_coords = list(coord for coord in da.coords if coord != 'position')\n",
"instrument_view_da = da.drop_coords(unnecessary_coords).flatten(['panel', 'id'], 'id').hist()\n",
"view = scn.instrument_view(instrument_view_da)\n",
"view.children[0].toolbar.cameraz()\n",
"view\n",
"```\n",
"\n",
"**It might be very slow or not work in the ``VS Code`` jupyter notebook editor.**"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "nmx-dev-39",
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
Expand All @@ -113,5 +143,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
19 changes: 9 additions & 10 deletions src/ess/nmx/mcstas_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

PixelIDs = NewType("PixelIDs", sc.Variable)
InputFilepath = NewType("InputFilepath", str)
NMXData = NewType("NMXData", sc.DataArray)
NMXData = NewType("NMXData", sc.DataGroup)

# McStas Configurations
MaximumProbability = NewType("MaximumProbability", int)
Expand Down Expand Up @@ -37,13 +37,6 @@ def _copy_partial_var(
return var


def _get_mcstas_pixel_ids() -> PixelIDs:
"""pixel IDs for each detector"""
intervals = [(1, 1638401), (2000001, 3638401), (4000001, 5638401)]
ids = [sc.arange('id', start, stop, unit=None) for start, stop in intervals]
return PixelIDs(sc.concat(ids, 'id'))


def load_mcstas_nexus(
file_path: InputFilepath,
max_probability: Optional[MaximumProbability] = None,
Expand All @@ -60,6 +53,9 @@ def load_mcstas_nexus(

"""

from .mcstas_xml import read_mcstas_geometry_xml

geometry = read_mcstas_geometry_xml(file_path)
probability = max_probability or DefaultMaximumProbability

with snx.File(file_path) as file:
Expand All @@ -76,6 +72,9 @@ def load_mcstas_nexus(
weights = (probability / weights.max()) * weights

loaded = sc.DataArray(data=weights, coords={'t': t_list, 'id': id_list})
grouped = loaded.group(_get_mcstas_pixel_ids())
coords = geometry.to_coords()
grouped = loaded.group(coords.pop('pixel_id'))
da = grouped.fold(dim='id', sizes={'panel': len(geometry.detectors), 'id': -1})
da.coords.update(coords)

return NMXData(grouped.fold(dim='id', sizes={'panel': 3, 'id': -1}))
return NMXData(da)
Loading