1818
1919def compute_wavelength_in_each_cluster (
2020 da : StreakClusteredData [RunType ],
21+ chopper_delay : WavelengthDefinitionChopperDelay ,
2122 mod_period : ModulationPeriod ,
2223 graph : GeometryCoordTransformGraph ,
2324) -> WavelengthDetector [RunType ]:
@@ -47,7 +48,7 @@ def compute_wavelength_in_each_cluster(
4748 sin_theta_L = sc .sin (da .bins .coords ['two_theta' ] / 2 ) * da .bins .coords ['Ltotal' ]
4849 t = time_of_arrival (
4950 da .bins .coords ['event_time_offset' ],
50- da .coords [ 'tc' ]. to ( unit = da . bins .coords ['event_time_offset' ]. unit ) ,
51+ da .bins .coords ['frame_cutoff_time' ] ,
5152 )
5253 for _ in range (15 ):
5354 s , t0 = _linear_regression_by_bin (sin_theta_L , t , da .data )
@@ -59,12 +60,33 @@ def compute_wavelength_in_each_cluster(
5960 too_far_from_center = (distance_to_self > max_distance_from_streak_line ),
6061 )
6162
62- da = da .assign_coords (t0 = sc .values (t0 ))
63- da = da .bins .assign_coords (tof = (t - sc .values (t0 )))
64- da = da .transform_coords (('wavelength' ,), graph = graph )
63+ # The t0 estimate from fitting is influenced by peak overlap, background,
64+ # and other factors that can make the estimate offset from the true
65+ # chopper opening time that it should match.
66+ # We know the true chopper opening times, so instead of using the t0 estimte
67+ # directly we can round the estimate to the closest chopper opening time.
68+ # That way the t0 estimate becomes more robust and is guaranteed to correspond to
69+ # a true chopper opening time.
70+ t0 = _round_t0_to_nearest_chopper_opening (sc .values (t0 ), mod_period , chopper_delay )
71+ da = da .assign_coords (t0 = t0 )
72+ da = da .bins .assign_coords (tof = (t - t0 ))
6573 return da
6674
6775
76+ def _round_t0_to_nearest_chopper_opening (
77+ t0 : sc .Variable ,
78+ mod_period : sc .Variable ,
79+ chopper_delay : sc .Variable ,
80+ ) -> sc .Variable :
81+ out = t0 - chopper_delay
82+ out /= mod_period
83+ out += 0.5
84+ sc .floor (out , out = out )
85+ out *= mod_period
86+ out += chopper_delay
87+ return out
88+
89+
6890def _linear_regression_by_bin (
6991 x : sc .Variable , y : sc .Variable , w : sc .Variable
7092) -> tuple [sc .Variable , sc .Variable ]:
@@ -124,14 +146,14 @@ def _compute_d_given_list_of_peaks(
124146
125147def time_of_arrival (
126148 event_time_offset : sc .Variable ,
127- tc : sc .Variable ,
149+ frame_cutoff_time : sc .Variable ,
128150):
129151 """Does frame unwrapping for pulse shaping chopper modes.
130152
131- Events before the "cutoff time" `tc` are assumed to come from the previous pulse."""
153+ Events before the "cutoff time" are assumed to come from the previous pulse."""
132154 _eto = event_time_offset
133155 T = sc .scalar (1 / 14 , unit = 's' ).to (unit = _eto .unit )
134- tc = tc .to (unit = _eto .unit )
156+ tc = frame_cutoff_time .to (unit = _eto .unit )
135157 return sc .where (_eto >= tc , _eto , _eto + T )
136158
137159
@@ -141,13 +163,13 @@ def _tof_from_dhkl(
141163 coarse_dhkl : sc .Variable ,
142164 Ltotal : sc .Variable ,
143165 mod_period : sc .Variable ,
144- time0 : sc .Variable ,
166+ chopper_delay : sc .Variable ,
145167) -> sc .Variable :
146168 """Computes tof for BEER given the dhkl peak that the event belongs to"""
147169 # Source: https://www.mcstas.org/download/components/current/contrib/NPI_tof_dhkl_detector.comp
148170 # tref = 2 * d_hkl * sin(theta) / hm * Ltotal
149- # tc = time_of_arrival - time0 - tref
150- # dt = floor(tc / mod_period + 0.5) * mod_period + time0
171+ # tc = time_of_arrival - chopper_delay - tref
172+ # dt = floor(tc / mod_period + 0.5) * mod_period + chopper_delay
151173 # tof = time_of_arrival - dt
152174 c = (- 2 * 1.0 / (scipp .constants .h / scipp .constants .m_n )).to (
153175 unit = f'{ time_of_arrival .unit } /m/angstrom'
@@ -156,12 +178,12 @@ def _tof_from_dhkl(
156178 out *= sc .sin (theta )
157179 out *= Ltotal
158180 out += time_of_arrival
159- out -= time0
181+ out -= chopper_delay
160182 out /= mod_period
161183 out += 0.5
162184 sc .floor (out , out = out )
163185 out *= mod_period
164- out += time0
186+ out += chopper_delay
165187 out *= - 1
166188 out += time_of_arrival
167189 return out
@@ -205,7 +227,7 @@ def tof_from_known_dhkl_graph(
205227 da : RawDetector [RunType ],
206228 mod_period : ModulationPeriod ,
207229 pulse_length : PulseLength ,
208- time0 : WavelengthDefinitionChopperDelay ,
230+ chopper_delay : WavelengthDefinitionChopperDelay ,
209231 dhkl_list : DHKLList ,
210232 gg : GeometryCoordTransformGraph ,
211233) -> ElasticCoordTransformGraph [RunType ]:
@@ -236,7 +258,7 @@ def _compute_coarse_dspacing(
236258 ** gg ,
237259 'pulse_length' : lambda : pulse_length ,
238260 'mod_period' : lambda : mod_period ,
239- 'time0 ' : lambda : time0 ,
261+ 'chopper_delay ' : lambda : chopper_delay ,
240262 'tof' : _tof_from_dhkl ,
241263 'time_of_arrival' : time_of_arrival ,
242264 'coarse_dhkl' : _compute_coarse_dspacing ,
0 commit comments