diff --git a/docs/src/index.rst b/docs/src/index.rst index 94500e3e..fc544c6e 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -31,6 +31,7 @@ AARE python/experimental/index python/histogram/index python/pedestal/index + python/strixelremap/index pyFit diff --git a/docs/src/python/strixelremap/index.rst b/docs/src/python/strixelremap/index.rst new file mode 100644 index 00000000..18ece5a4 --- /dev/null +++ b/docs/src/python/strixelremap/index.rst @@ -0,0 +1,42 @@ +Pixel to Strixel Remapping +============================ + + +.. toctree:: + :caption: Pixel to Strixel Remapping + :maxdepth: 1 + + pySensorConfiguration + pyStrixelPixelRemapAlgorithm + pyPredefinedMaps + pyPredefinedSensorConfigs + + +Example Usage +------------- + +.. code:: python + + from aare import strixelremap + import numpy as np + + from aare import RawFile + + file = RawFile("path/to/master_file.json") # Load a raw file with strixel data + + _, frame = file.read_frame() # Read the first frame of the file + + rx_roi = frame.master().rois[0] # Get ROI of the frame + + # Get the pixel to strixel map for the 25 µm pitch strixels placed on Chip1 + pixel_to_strixel_map_25um = strixelremap.jungfrau_ilgad_singlechip_25um_strixel_map(user_roi = rx_roi, placement = strixelremap.Chip1) + + + # map(row, col) gives flattened index of the pixel mapped to strixel at (row, col) + order_map = pixel_to_strixel_map_25um.map + + strixels = np.empty(order_map.shape, dtype=np.uint16) + + # Apply the remapping to a given strixel data array + strixelremap.apply_remap(frame.astype(np.uint16), order_map, strixels) + \ No newline at end of file diff --git a/docs/src/python/strixelremap/pyPredefinedMaps.rst b/docs/src/python/strixelremap/pyPredefinedMaps.rst new file mode 100644 index 00000000..d54bdf1f --- /dev/null +++ b/docs/src/python/strixelremap/pyPredefinedMaps.rst @@ -0,0 +1,40 @@ +Predefined Pixel to Strixel Maps +================================ + +Includes predefined pixel to strixel maps for the sensor configurations introduced in :ref:`python_predefined_sensor_configs`. + +Predefined Maps for 2x2 cm iLGAD Sensor +---------------------------------------- + +.. py:currentmodule:: aare.strixelremap + +.. autofunction:: jungfrau_ilgad_singlechip_25um_strixel_map + +.. autofunction:: jungfrau_ilgad_singlechip_15um_strixel_map + +.. autofunction:: jungfrau_ilgad_singlechip_18um_strixel_map + +.. autofunction:: jungfrau_ilgad_strixel_maps + + +Predefined Maps for 2x2 cm TEW Sensor +---------------------------------------- + +.. autofunction:: jungfrau_tew_singlechip_25um_strixel_map + +.. autofunction:: jungfrau_tew_singlechip_15um_strixel_map + +.. autofunction:: jungfrau_tew_singlechip_18um_strixel_map + +.. autofunction:: jungfrau_tew_strixel_maps + + +Predefined Maps for 4x4 cm iLGAD Sensor +---------------------------------------- + +.. autofunction:: jungfrau_ilgad_quadbottom_25um_strixel_map + +.. autofunction:: jungfrau_ilgad_quadtop_25um_strixel_map + +.. autofunction:: jungfrau_ilgad_quad_25um_strixel_map + diff --git a/docs/src/python/strixelremap/pyPredefinedSensorConfigs.rst b/docs/src/python/strixelremap/pyPredefinedSensorConfigs.rst new file mode 100644 index 00000000..43614321 --- /dev/null +++ b/docs/src/python/strixelremap/pyPredefinedSensorConfigs.rst @@ -0,0 +1,151 @@ + +.. _python_predefined_sensor_configs: + +Predefined Sensor Configurations +================================= + +Includes all predefined sensor configurations for Jungfrau iLGAD (inverse Low-Gain Avalache Diode) and Jungfrau TEW (Thin Entrance Window) sensors. + +The PSI Photon Science Detector Group produces Jungfrau modules with three different sensor types: 2x2 cm iLGAD, 2x2 cm TEW and 4x4 cm iLGAD. + +Below are the predefined sensor configurations for all three sensor types. Detailed information about the sensor geometry, placement and rotation on the module, strixel types and their placement can be found in the dedicated sensor sections further below. + + +Predefined Sensor Configurations +--------------------------------- + +.. py:currentmodule:: aare.strixelremap + +.. data:: SingleChipMP_iLGAD + + Sensor configuration of the 2x2 cm iLGAD sensor with all strixel groups. + +.. data:: SingleChipMP_TEW + + Sensor configuration of the 2x2 cm TEW sensor with all strixel groups. + +.. data:: Quad_iLGAD + + Sensor configuration of the 4x4 cm iLGAD sensor with all strixel groups. + +.. _python_predefined_strixel_groups: + +Predefined Strixel Groups +--------------------------------- + +.. data:: StrxP25 + + Strixel geometry for 25 µm pitch strixels on iLGAD sensors (multiplicity = 3) + +.. data:: StrxP15 + + Strixel geometry for 15 µm pitch strixels on iLGAD sensors (multiplicity = 5) + +.. data:: StrxP18 + + Strixel geometry for 18.75 µm pitch strixels on iLGAD sensors (multiplicity = 4) + +.. data:: StrxP37 + + Strixel geometry for 37.5 µm pitch strixels on iLGAD sensors (multiplicity = 2) + + +.. _python_predefined_sensor_placements: + +Predefined Sensor Placements on Junfrau Modules +------------------------------------------------ + +The PSI Photon Science Detector Group produces Jungfrau modules with a 2x2 cm iLGAD/TEW sensor placed on the position of the second chip (Chip1) and the seventh chip (Chip6) of the module. +The larger 4x4cm iLGAD sensors are typically placed on the module's quad (Chip1+Chip2+Chip5+Chip6). + +.. data:: Chip1 + + Placement of the 2x2cm iLGAD sensor on the second chip (Chip1) of the Jungfrau module, with no rotation applied. + +.. data:: Chip6 + + Placement of the 2x2cm iLGAD sensor on the seventh chip (Chip6) of the Jungfrau module, with a 180-degree rotation applied. + +.. data:: Quad + + Placement of the 4x4cm iLGAD sensor on the quad (Chip1+Chip2+Chip5+Chip6) of the Jungfrau module, with no rotation applied. + +2x2 cm iLGAD Sensor: +--------------------- + +The 2x2 cm iLGAD sensor has a guardring that extends into (and renders unusable for photon detection) part of the active pixel area with height and width of 9 pixels each and spawns over 256x256 pixels. + +.. data:: SingleChipMP_iLGAD_pix + + Pixel geometry for the 2x2 cm iLGAD sensor. + +The PSI Photon Science Detector Group produces Jungfrau modules with 2x2 cm iLGAD sensors placed on the position of the second chip (Chip1) ``Chip1`` and the seventh chip (Chip6) ``Chip6`` of the module. +See :ref:`python_predefined_sensor_placements` for more information. + +The sensor is partitioned into three strixel groups ``StrxP25``, ``StrxP15`` and ``StrxP18``. See :ref:`python_predefined_strixel_groups` for more information. + +Strixel group ``StrxP25`` covers the bottom 25 % of the sensor's pixel area (minus the guard ring pixels). Strixel Group ``StrxP15`` covers the next 25 % of the sensor's pixel area. Strixel group ``StrxP18`` covers the top 50 % of the sensor's pixel, whereby it is divided into two partitions (each 25 % of the pixel area) with different dimensioning of the metal layers on top of strixel implants. + +.. data:: SingleChipMP_iLGAD_P25 + + Strixel group of 25 µm pitch strixels on the 2x2 cm iLGAD sensor. + +.. data:: SingleChipMP_iLGAD_P15 + + Strixel group of 15 µm pitch strixels on the 2x2 cm iLGAD sensor. + +.. data:: SingleChipMP_iLGAD_P18 + + Strixel group of 18.75 µm pitch strixels on the 2x2 cm iLGAD sensor. + +2x2 cm TEW Sensor: +--------------------- + +The 2x2 cm TEW sensor has no guardring extending into the active pixel area and spawns over 256x256 pixels. + +.. data:: SingleChipMP_TEW_pix + + Pixel geometry for the 2x2 cm TEW sensor. + +The Photon Detector Group produces Jungfrau modules with 2x2 cm TEW sensors placed on the position of the second chip (Chip1) ``Chip1`` and the seventh chip (Chip6) ``Chip6`` of the module. +See :ref:`python_predefined_sensor_placements` for more information. + +The sensor is again partitioned into three pixel groups ``StrxP25``, ``StrxP15`` and ``StrxP18``. See :ref:`python_predefined_strixel_groups` for more information. + +The partition is the same as for the 2x2 cm iLGAD sensor. + +.. data:: SingleChipMP_TEW_P25 + + Strixel group of 25 µm pitch strixels on the 2x2 cm TEW sensor. + +.. data:: SingleChipMP_TEW_P15 + + Strixel group of 15 µm pitch strixels on the 2x2 cm TEW sensor. + +.. data:: SingleChipMP_TEW_P18 + + Strixel group of 18.75 µm pitch strixels on the 2x2 cm TEW sensor. + +4x4 cm iLGAD Sensor: +--------------------- + +The 4x4 cm iLGAD sensor has a guardring height and width of 9 pixels each and spawns over 512x512 pixels. + +.. data:: Quad_iLGAD_pix + + Pixel geometry for the 4x4 cm iLGAD sensor. + +The 4x4 cm iLGAD sensor is typically placed on the module's quad (Chip1+Chip2+Chip5+Chip6) ``Quad``. See :ref:`python_predefined_sensor_placements` for more information. + +The sensor is partitioned into two strixel groups ``StrxP25``. See :ref:`python_predefined_strixel_groups` for more information. The bottom sensor half uses forward pixel-to-strixel routing and the top sensor half uses backward pixel to strixel routing. + +.. data:: Quad_iLGAD_bottomhalf + + Strixel group of 25 µm pitch strixels located on the bottom half of 4x4 cm iLGAD sensor. + +.. data:: Quad_iLGAD_tophalf + + Strixel group of 25 µm pitch strixels located on the top half of 4x4 cm iLGAD sensor. + + + diff --git a/docs/src/python/strixelremap/pySensorConfiguration.rst b/docs/src/python/strixelremap/pySensorConfiguration.rst new file mode 100644 index 00000000..046d2158 --- /dev/null +++ b/docs/src/python/strixelremap/pySensorConfiguration.rst @@ -0,0 +1,57 @@ +Sensor configurations +===================== + +Helper structs to define the sensor configuration, such as sensor pixel geometry, placement and rotation of the sensor on the module, the different strixel types on the sensor and its placement. + +.. py:currentmodule:: aare.strixelremap + +.. autoclass:: Rotation + :members: + +.. autoclass:: ModuloOrdering + :members: + +.. autoclass:: BondShift + :members: + :special-members: __init__ + +.. autoclass:: Guardring + :members: + :special-members: __init__ + +.. autoclass:: GroupRouting + :members: + :special-members: __init__ + +.. autoclass:: SensorPixelGeometry + :members: + :special-members: __init__ + + +.. autoclass:: GroupStrixelGeometry + :members: + :special-members: __init__ + +.. autoclass:: GroupConfig + :members: + :special-members: __init__ + +.. autoclass:: SensorModulePlacement + :members: + :special-members: __init__ + +.. autoclass:: StrixelGroupToPixelMap + :members: + :special-members: __init__ + +**Helper functions to create SensorConfig with N pixel groups:** + +.. autofunction:: SensorConfig + :noindex: + + +.. code:: python + + from aare import strixelremap + + SensorConfig(strixelremap.SingleChipMP_iLGAD_pix, [strixelremap.StrxP15, strixelremap.StrxP25]) # returns a SensorConfig_2PixelGroups \ No newline at end of file diff --git a/docs/src/python/strixelremap/pyStrixelPixelRemapAlgorithm.rst b/docs/src/python/strixelremap/pyStrixelPixelRemapAlgorithm.rst new file mode 100644 index 00000000..24cd0ecf --- /dev/null +++ b/docs/src/python/strixelremap/pyStrixelPixelRemapAlgorithm.rst @@ -0,0 +1,12 @@ +Strixel to Pixel Remapping +============================== + +.. py:currentmodule:: aare.strixelremap + +.. autofunction:: strixel_to_pixel_map + +.. autofunction:: strixel_to_pixel_maps + :noindex: + +.. autofunction:: apply_remap + diff --git a/python/aare/strixelremap/SensorConfig.py b/python/aare/strixelremap/SensorConfig.py index 8cd0a07f..50e119c3 100644 --- a/python/aare/strixelremap/SensorConfig.py +++ b/python/aare/strixelremap/SensorConfig.py @@ -20,3 +20,31 @@ def SensorConfig(sensor_geometry, group_configs): sensor_config_cls = getattr(strixelremap, f"SensorConfig_{N}PixelGroups") return sensor_config_cls(sensor_geometry, group_configs) + + +# helper function for easier documentation of templated strixel_to_pixel_maps +def strixel_to_pixel_maps(sensor_config : SensorConfig, placement : strixelremap.SensorModulePlacement, user_roi : strixelremap.InclusiveROI, bond_shift : strixelremap.BondShift = strixelremap.BondShift(0, 0)) -> list[strixelremap.StrixelGroupToPixelMap]: + """ + Creates a StrixeltoPixelMap for all GroupConfigs in a SensorConfig + + Parameters + ---------- + + sensor_config : SensorConfig + Configuration of the sensor, including all configurations of the strixel groups. + placement : SensorModulePlacement + Placement and orientation of the sensor on the module. + user_roi : InclusiveROI + User-defined region of interest. (in global module coordinates) + bond_shift : BondShift, optional + Shift applied to the bond positions. Default is (0, 0). + + Returns + ------- + + list[StrixelGroupToPixelMap] + map(row, col) contains the flattened pixel index of the corresponding source pixel in the user-provided input ROI for strixel defined at (row, col). + An entry of -1 indicates that the corresponding strixel position has no valid source pixel. + """ + + return strixelremap.strixel_to_pixel_maps_pybindfunc(sensor_config, placement, user_roi, bond_shift) \ No newline at end of file diff --git a/python/aare/strixelremap/__init__.py b/python/aare/strixelremap/__init__.py index a7170a98..1c5a8ab6 100644 --- a/python/aare/strixelremap/__init__.py +++ b/python/aare/strixelremap/__init__.py @@ -1,4 +1,6 @@ from .SensorConfig import SensorConfig +from .SensorConfig import strixel_to_pixel_maps + from .._aare.strixelremap import * diff --git a/python/src/StrixelRemap/bind_PredefinedVariables.hpp b/python/src/StrixelRemap/bind_PredefinedVariables.hpp index a109b80f..964d1f63 100644 --- a/python/src/StrixelRemap/bind_PredefinedVariables.hpp +++ b/python/src/StrixelRemap/bind_PredefinedVariables.hpp @@ -97,42 +97,44 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("user_roi").noconvert(), py::arg("placement").noconvert(), py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( - Generates a strixel-to-pixel remapping map for the Strx25 strixel group on a Jungfrau ILGAD sensor - Parameters - ---------- - user_roi : InclusiveROI - ROI in global module coordinate system. - placement : SensorModulePlacement - Placement and orientation of the sensor on the module. - bond_shift : BondShift, optional - Bonding shift applied before the configured sensor placement rotation. Default is (0, 0). - Returns - ------- - StrixelGroupToPixelMap - map(row, col) contains the flattened pixel index of the corresponding source pixel in the user-provided input ROI for strixel defined at (row, col). - An entry of -1 indicates that the corresponding strixel position has no valid source pixel. - )"); + Generates a strixel-to-pixel remapping map for the Strx25 strixel group on a Jungfrau ILGAD sensor + + Parameters + ---------- + user_roi : InclusiveROI + ROI in global module coordinate system. + placement : SensorModulePlacement + Placement and orientation of the sensor on the module. + bond_shift : BondShift, optional + Bonding shift applied before the configured sensor placement rotation. Default is (0, 0). + Returns + ------- + StrixelGroupToPixelMap + map(row, col) contains the flattened pixel index of the corresponding source pixel in the user-provided input ROI for strixel defined at (row, col). + An entry of -1 indicates that the corresponding strixel position has no valid source pixel. + )"); m.attr("jungfrau_ilgad_singlechip_15um_strixel_map") = py::cpp_function( &aare::remap::generate::jungfrau_ilgad_singlechip_15um_strixel_map, py::arg("user_roi").noconvert(), py::arg("placement").noconvert(), py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( - Generates a strixel-to-pixel remapping map for the Strx15 strixel group on a Jungfrau ILGAD sensor - Parameters - ---------- - user_roi : InclusiveROI - ROI in global module coordinate system. - placement : SensorModulePlacement - Placement and orientation of the sensor on the module. - bond_shift : BondShift, optional - Bonding shift applied before the configured sensor placement rotation. Default is (0, 0). - Returns - ------- - StrixelGroupToPixelMap - map(row, col) contains the flattened pixel index of the corresponding source pixel in the user-provided input ROI for strixel defined at (row, col). - An entry of -1 indicates that the corresponding strixel position has no valid source pixel. - )"); + Generates a strixel-to-pixel remapping map for the Strx15 strixel group on a Jungfrau ILGAD sensor + + Parameters + ---------- + user_roi : InclusiveROI + ROI in global module coordinate system. + placement : SensorModulePlacement + Placement and orientation of the sensor on the module. + bond_shift : BondShift, optional + Bonding shift applied before the configured sensor placement rotation. Default is (0, 0). + Returns + ------- + StrixelGroupToPixelMap + map(row, col) contains the flattened pixel index of the corresponding source pixel in the user-provided input ROI for strixel defined at (row, col). + An entry of -1 indicates that the corresponding strixel position has no valid source pixel. + )"); m.attr("jungfrau_ilgad_singlechip_18um_strixel_map") = py::cpp_function( &aare::remap::generate::jungfrau_ilgad_singlechip_18um_strixel_map, @@ -140,6 +142,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the Strx18 strixel group on a Jungfrau ILGAD sensor + Parameters ---------- user_roi : InclusiveROI @@ -161,6 +164,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a list of strixel-to-pixel remapping map for each strixel group on a Jungfrau ILGAD quad sensor + Parameters ---------- user_roi : InclusiveROI @@ -184,6 +188,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the Strx25 strixel group on a Jungfrau TEW sensor + Parameters ---------- user_roi : InclusiveROI @@ -205,6 +210,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the Strx15 strixel group on a Jungfrau TEW sensor + Parameters ---------- user_roi : InclusiveROI @@ -226,6 +232,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the Strx18 strixel group on a Jungfrau TEW sensor + Parameters ---------- user_roi : InclusiveROI @@ -247,6 +254,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a list of strixel-to-pixel remapping map for each strixel group on a Jungfrau TEW sensor + Parameters ---------- user_roi : InclusiveROI @@ -270,6 +278,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the bottom half of the Strx25 strixel group on a Jungfrau ILGAD quad sensor + Parameters ---------- user_roi : InclusiveROI @@ -291,6 +300,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the top half of the Strx25 strixel group on a Jungfrau ILGAD quad sensor + Parameters ---------- user_roi : InclusiveROI @@ -312,6 +322,7 @@ void define_predefinedStrixelPixelMaps(py::module &m) { py::arg("bond_shift").noconvert() = aare::remap::defs::BondShift{0, 0}, R"( Generates a strixel-to-pixel remapping map for the entire Strx25 strixel group on a Jungfrau ILGAD quad sensor + Parameters ---------- user_roi : InclusiveROI diff --git a/python/src/StrixelRemap/bind_StrixelRemap.hpp b/python/src/StrixelRemap/bind_StrixelRemap.hpp index e2dbba68..b519e4c7 100644 --- a/python/src/StrixelRemap/bind_StrixelRemap.hpp +++ b/python/src/StrixelRemap/bind_StrixelRemap.hpp @@ -223,11 +223,11 @@ void define_RemapAlgorithm(py::module &m) { Parameters ---------- - input : np.array + input : np.array[uint16_t, 2] Original array order_map : np.array[ssize_t, 2] Rule for remapping - output : np.array + output : np.array[uint16_t, 2] Remapped array )"); @@ -236,7 +236,8 @@ void define_RemapAlgorithm(py::module &m) { template void define_RemapAlgorithmforSensorConfig(py::module &m) { - m.def("strixel_to_pixel_maps", &aare::remap::algo::strixel_to_pixel_maps, + m.def("strixel_to_pixel_maps_pybindfunc", + &aare::remap::algo::strixel_to_pixel_maps, py::arg("sensor_config").noconvert(), py::arg("placement").noconvert(), py::arg("user_roi").noconvert(), py::arg("bond_shift").noconvert() =