diff --git a/Framework/DataHandling/src/LoadILLDiffraction.cpp b/Framework/DataHandling/src/LoadILLDiffraction.cpp index 345cbc8976e1c337df60663dc3e78ad8eef58e06..67aea61f645fc334cbb313d8e354eeed8d148226 100644 --- a/Framework/DataHandling/src/LoadILLDiffraction.cpp +++ b/Framework/DataHandling/src/LoadILLDiffraction.cpp @@ -48,6 +48,8 @@ constexpr double D20_PIXEL_SIZE = 0.1; constexpr double RAD_TO_DEG = 180. / M_PI; // A factor to compute E from lambda: E (mev) = waveToE/lambda(A) constexpr double WAVE_TO_E = 81.8; +// Number of pixels in the tubes for D2B +constexpr size_t D2B_NUMBER_PIXELS_IN_TUBES = 128; } // Register the algorithm into the AlgorithmFactory @@ -474,7 +476,10 @@ void LoadILLDiffraction::fillMovingInstrumentScan(const NXUInt &data, i < m_numberDetectorsActual + NUMBER_MONITORS; ++i) { for (size_t j = 0; j < m_numberScanPoints; ++j) { const auto tubeNumber = (i - NUMBER_MONITORS) / m_sizeDim2; - const auto pixelInTubeNumber = (i - NUMBER_MONITORS) % m_sizeDim2; + auto pixelInTubeNumber = (i - NUMBER_MONITORS) % m_sizeDim2; + if (m_instName == "D2B" && tubeNumber % 2 == 1) { + pixelInTubeNumber = D2B_NUMBER_PIXELS_IN_TUBES - 1 - pixelInTubeNumber; + } unsigned int y = data(static_cast<int>(j), static_cast<int>(tubeNumber), static_cast<int>(pixelInTubeNumber)); const auto wsIndex = j + i * m_numberScanPoints; @@ -513,7 +518,10 @@ void LoadILLDiffraction::fillStaticInstrumentScan(const NXUInt &data, auto &spectrum = m_outWorkspace->mutableY(i); auto &errors = m_outWorkspace->mutableE(i); const auto tubeNumber = (i - NUMBER_MONITORS) / m_sizeDim2; - const auto pixelInTubeNumber = (i - NUMBER_MONITORS) % m_sizeDim2; + auto pixelInTubeNumber = (i - NUMBER_MONITORS) % m_sizeDim2; + if (m_instName == "D2B" && tubeNumber % 2 == 1) { + pixelInTubeNumber = D2B_NUMBER_PIXELS_IN_TUBES - 1 - pixelInTubeNumber; + } for (size_t j = 0; j < m_numberScanPoints; ++j) { unsigned int y = data(static_cast<int>(j), static_cast<int>(tubeNumber), static_cast<int>(pixelInTubeNumber)); diff --git a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/PowderDiffILLDetEffCorr.py b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/PowderDiffILLDetEffCorr.py index ce39802e94b326fdf7047dcb77bbaea691746eb9..7b94e010fb01c17c3100035ead915d80df8ce85c 100644 --- a/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/PowderDiffILLDetEffCorr.py +++ b/Framework/PythonInterface/plugins/algorithms/WorkflowAlgorithms/PowderDiffILLDetEffCorr.py @@ -365,8 +365,10 @@ class PowderDiffILLDetEffCorr(PythonAlgorithm): inst = mtd[raw_ws].getInstrument() self._n_tubes = inst.getComponentByName('detectors').nelements() self._n_pixels_per_tube = inst.getComponentByName('detectors/tube_1').nelements() - self._n_scans_per_file = mtd[raw_ws].getRun().getLogData('ScanSteps').value + #self._n_scans_per_file = mtd[raw_ws].getRun().getLogData('ScanSteps').value + self._n_scans_per_file = 25 # TODO: In v2 this should be freely variable self._scan_points = self._n_scans_per_file * self._n_scan_files + self.log().information('Number of scan steps is: ' + str(self._scan_points)) if self._excluded_ranges.any(): n_excluded_ranges = int(len(self._excluded_ranges) / 2) self._excluded_ranges = np.split(self._excluded_ranges, n_excluded_ranges) @@ -603,6 +605,16 @@ class PowderDiffILLDetEffCorr(PythonAlgorithm): mtd[constants_ws].getAxis(1).setUnit('Label').setLabel('Cell #', '') mtd[constants_ws].setYUnitLabel('Calibration constant') + def _crop_last_time_index(self, ws, n_scan_points): + ws_index_list = "" + for pixel in range(self._n_tubes * self._n_pixels_per_tube): + start = n_scan_points * pixel + end = n_scan_points * (pixel + 1) - 2 + index_range = str(start)+"-"+str(end)+"," + ws_index_list += index_range + ws_index_list = ws_index_list[:-1] + ExtractSpectra(InputWorkspace=ws, OutputWorkspace=ws, WorkspaceIndexList=ws_index_list) + def _process_global(self): """ Performs the global derivation for D2B following the logic: @@ -618,7 +630,7 @@ class PowderDiffILLDetEffCorr(PythonAlgorithm): self._progress = Progress(self, start=0.0, end=1.0, nreports=self._n_scan_files) for index, numor in enumerate(self._input_files.split(',')): - self._progress.report('Pre-processing detector scan '+numor[-9:-3]) + self._progress.report('Pre-processing detector scan '+numor[-10:-4]) ws_name = '__raw_'+str(index) numors.append(ws_name) LoadILLDiffraction(Filename=numor, OutputWorkspace=ws_name, DataType="Raw") @@ -634,6 +646,12 @@ class PowderDiffILLDetEffCorr(PythonAlgorithm): if self._calib_file: ApplyDetectorScanEffCorr(InputWorkspace=ws_name, DetectorEfficiencyWorkspace=calib_ws, OutputWorkspace=ws_name) + n_scan_steps = mtd[ws_name].getRun().getLogData("ScanSteps").value + if n_scan_steps != self._n_scans_per_file: + self.log().warning("Run {0} has {1} scan points instead of {2}.". + format(numor[-10:-4], n_scan_steps, self._n_scans_per_file)) + self._crop_last_time_index(ws_name, n_scan_steps) + if self._calib_file: DeleteWorkspace(calib_ws) diff --git a/Testing/SystemTests/tests/analysis/reference/D2B_DetEffCorr_Ref.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/D2B_DetEffCorr_Ref.nxs.md5 index 504297da5d23c05a51b89eb2de86f05ef5cae222..84bb60db5731cf89818f71897aae330e01bdbbed 100644 --- a/Testing/SystemTests/tests/analysis/reference/D2B_DetEffCorr_Ref.nxs.md5 +++ b/Testing/SystemTests/tests/analysis/reference/D2B_DetEffCorr_Ref.nxs.md5 @@ -1 +1 @@ -6e114402c861e2129b6c095a083cbd67 +873cf3cebcd7dd988a225b7b83dac9d4 diff --git a/Testing/SystemTests/tests/analysis/reference/D2B_scan_test.nxs.md5 b/Testing/SystemTests/tests/analysis/reference/D2B_scan_test.nxs.md5 index 104bae5a321e7f0b4ca83362b94241090673402c..220691b026b4d0987927951056bd02332b9b0ba4 100644 --- a/Testing/SystemTests/tests/analysis/reference/D2B_scan_test.nxs.md5 +++ b/Testing/SystemTests/tests/analysis/reference/D2B_scan_test.nxs.md5 @@ -1 +1 @@ -9f58460c4b7784a46859d3445e32ed7a +fcca576f5a8318e520367dda4df9a148 diff --git a/docs/source/algorithms/LoadILLDiffraction-v1.rst b/docs/source/algorithms/LoadILLDiffraction-v1.rst index 7c41e24d031570f2876e39649e17a3ab6b64ed4b..ab2ed2b455259727fb212358eb53bc22689f70a5 100644 --- a/docs/source/algorithms/LoadILLDiffraction-v1.rst +++ b/docs/source/algorithms/LoadILLDiffraction-v1.rst @@ -50,6 +50,13 @@ D2B alignment For D2B, the loader applies tube alignment; first rotating them horizontally around the sample, then translating them vertically. This is done based on *tube_centers* and *tube_angles* parameters defined in the Instrument Parameter File. +D2B pixel numbering in tubes +---------------------------- + +For D2B it assumes that the counts written in the nexus file follow "U-shape" convention; that is, the first tube counts are written from bottom to top, the second one: from top to bottom, and so on. +Note that in the IDF of D2B detector IDs grow ascending from bottom to top for all the tubes. +The loader takes care that the correct counts are attributed to correct pixels. + Usage ----- .. include:: ../usagedata-note.txt diff --git a/docs/source/algorithms/PowderDiffILLDetEffCorr-v1.rst b/docs/source/algorithms/PowderDiffILLDetEffCorr-v1.rst index cd49ff356e53ec490366b7ff5b0a775d996cb865..bd446e7a0f1f7ccd51ee29d1a34ab4a903cb5046 100644 --- a/docs/source/algorithms/PowderDiffILLDetEffCorr-v1.rst +++ b/docs/source/algorithms/PowderDiffILLDetEffCorr-v1.rst @@ -149,6 +149,7 @@ Limitations For **D2B** it is assumed that the tubes and pixels pass through the exact same positions during the scan. That is, the tubes have to be aligned vertically and horizontally and the gap between each pair of neighboring tubes must be integer multiple of the scan step. +If some of the input files will have 26 scan points instead of 25, the last scan point data will be ignored. D20 Workflow ------------ diff --git a/docs/source/release/v3.13.0/diffraction.rst b/docs/source/release/v3.13.0/diffraction.rst index 38f7ce8b546f738865f702835ca80b04bf89c3e8..7b0da24142d9ac11df5afb5dcb00a9621c8529da 100644 --- a/docs/source/release/v3.13.0/diffraction.rst +++ b/docs/source/release/v3.13.0/diffraction.rst @@ -31,8 +31,10 @@ New Features ------------ - :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is extended to apply vertical and horizontal tube alignment for D2B, based on the IPF. +- :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is modified to comply with the U-shape convention for tube numbering for D2B. - :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to compute the detector efficiencies also for the 2-dimensional scanning diffractometer D2B at the ILL. - :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to provide automatic masking of the pixels with spurious calibration constants. +- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` will now ignore the last scan point data, if some of the input files have 26 points, instead of 25. - :ref:`PowderDiffILLDetScanReduction <algm-PowderDiffILLDetScanReduction>` is extended to provide initial masking of the top and bottom parts of the tubes, and final masking of the 2D outputs. - :ref:`WANDPowderReduction <algm-WANDPowderReduction>` performs powder diffraction data reduction for WAND² with calibration, monitor normalisation and background subtraction.