@@ -165,57 +165,61 @@ def moments(data, fudge_max_pix_factor, beam, beamsize, threshold=0):
165165
166166 rounded_barycenter = int (round (xbar )), int (round (ybar ))
167167 # basevalue and basepos will be needed for "tweaked moments".
168+ in_source_island = False
168169 try :
169170 if not data .mask [rounded_barycenter ]:
170- basepos = rounded_barycenter
171- else :
172- basepos = maxpos
171+ in_source_island = True
173172 except IndexError :
174- basepos = maxpos
173+ # rounded_barycenter is not part of the island.
174+ pass
175175 except AttributeError :
176176 # If the island is not masked at all, we can safely set basepos to
177177 # the rounded barycenter position.
178+ in_source_island = True
179+
180+ if in_source_island :
178181 basepos = rounded_barycenter
179- basevalue = data [basepos ]
180-
181- if np .sign (threshold ) == np .sign (basevalue ):
182- # Implementation of "tweaked moments", equation 2.67 from
183- # Spreeuw's thesis. In that formula the "base position" was the
184- # maximum pixel position, though. Here that is the rounded
185- # barycenter position, unless it's masked. If it's masked, it
186- # will be the maximum pixel position.
187- deltax , deltay = xbar - basepos [0 ], ybar - basepos [1 ]
182+ basevalue = data [basepos ]
188183
189- epsilon = np .log (2.0 ) * (
190- (np .cos (theta ) * deltax + np .sin (theta ) * deltay ) ** 2
191- + (np .cos (theta ) * deltay - np .sin (theta ) * deltax ) ** 2
192- * semiminor_tmp
193- / semimajor_tmp
194- )
184+ if np .sign (threshold ) == np .sign (basevalue ):
185+ # Implementation of "tweaked moments", equation 2.67 from
186+ # Spreeuw's thesis. In that formula the "base position" was the
187+ # maximum pixel position, though. Here that is the rounded
188+ # barycenter position, unless it's masked or not part of the island.
189+ # In those cases no "tweaked moments" extrapolation will be
190+ # applied, and we revert to data.max() * fudge_max_pix.
191+ deltax , deltay = xbar - basepos [0 ], ybar - basepos [1 ]
192+
193+ epsilon = np .log (2.0 ) * (
194+ (np .cos (theta ) * deltax + np .sin (theta ) * deltay ) ** 2
195+ + (np .cos (theta ) * deltay - np .sin (theta ) * deltax ) ** 2
196+ * semiminor_tmp
197+ / semimajor_tmp
198+ )
195199
196- # Set limits for the root finder similar to the bounds for
197- # Gaussian fits.
198- if basevalue > 0 :
199- low_bound = 0.5 * basevalue
200- upp_bound = 1.5 * basevalue
201- else :
202- low_bound = 1.5 * basevalue
203- upp_bound = 0.5 * basevalue
204-
205- # The number of iterations used for the root finder is also
206- # returned, but not used here.
207- peak , _ = newton_raphson_root_finder (
208- find_true_peak ,
209- basevalue ,
210- low_bound ,
211- upp_bound ,
212- 1e-8 ,
213- 100 ,
214- threshold ,
215- epsilon ,
216- semiminor_tmp ,
217- basevalue ,
218- )
200+ # Set limits for the root finder similar to the bounds for
201+ # Gaussian fits.
202+ if basevalue > 0 :
203+ low_bound = 0.5 * basevalue
204+ upp_bound = 2.0 * basevalue
205+ else :
206+ low_bound = 2.0 * basevalue
207+ upp_bound = 0.5 * basevalue
208+
209+ # The number of iterations used for the root finder is also
210+ # returned, but not used here.
211+ peak , _ = newton_raphson_root_finder (
212+ find_true_peak ,
213+ basevalue ,
214+ low_bound ,
215+ upp_bound ,
216+ 1e-8 ,
217+ 100 ,
218+ threshold ,
219+ epsilon ,
220+ semiminor_tmp ,
221+ basevalue ,
222+ )
219223
220224 if np .sign (threshold ) == np .sign (peak ):
221225 # The corrections below for the semi-major and semi-minor axes are
@@ -500,6 +504,7 @@ def moments_enhanced(
500504 rounded_barycenter = int (round (xbar )), int (round (ybar ))
501505 mask = (posx == rounded_barycenter [0 ]) & (posy == rounded_barycenter [1 ])
502506 in_source_island = mask .any ()
507+
503508 if in_source_island :
504509 # In this case the rounded barycenter position is in source_island.
505510 # Note that mask, from the way that posx and posy have been constructed,
@@ -520,8 +525,9 @@ def moments_enhanced(
520525 # Implementation of "tweaked moments", equation 2.66 from
521526 # Spreeuw's thesis. In that formula the "base position" was the
522527 # maximum pixel position, though. Here that is the rounded
523- # barycenter position, unless it's masked. If it's masked, it
524- # will be the maximum pixel position.
528+ # barycenter position, unless it's not part of the island. In that
529+ # case no "tweaked moments" extrapolation will be applied, and we
530+ # revert to source_island.max() * fudge_max_pix.
525531 exponent = np .log (2.0 ) * (
526532 ((np .cos (theta ) * deltax + np .sin (theta ) * deltay ) / smin ) ** 2
527533 + ((np .cos (theta ) * deltay - np .sin (theta ) * deltax ) / smaj )
@@ -592,50 +598,51 @@ def moments_enhanced(
592598 else :
593599 theta -= math .pi / 2.0
594600
595- if np .sign (threshold ) == np .sign (basevalue ) and in_source_island :
596- # Implementation of "tweaked moments", equation 2.67 from
597- # Spreeuw's thesis. In that formula the "base position" was the
598- # maximum pixel position. Here that is the rounded
599- # barycenter position, unless it's masked. If it's masked, it
600- # will be the maximum pixel position.
601- # The rounded barycenter position will buy us slightly more
602- # stability (established by testing) than the maximum pixel
603- # position.
604- # The condition is a sanity check for maps other than Stokes I,
605- # where the threshold can be negative. For Stokes I maps, which
606- # will have positive thresholds, at least for all
607- # non-pathological cases, this condition will always be true.
608-
609- epsilon = np .log (2.0 ) * (
610- (np .cos (theta ) * deltax + np .sin (theta ) * deltay ) ** 2
611- + (np .cos (theta ) * deltay - np .sin (theta ) * deltax ) ** 2
612- * semiminor_tmp
613- / semimajor_tmp
614- )
601+ if in_source_island :
602+ if np .sign (threshold ) == np .sign (basevalue ):
603+ # Implementation of "tweaked moments", equation 2.67 from
604+ # Spreeuw's thesis. In that formula the "base position" was the
605+ # maximum pixel position. Here that is the rounded
606+ # barycenter position, unless it's not part of the island. In
607+ # that case no "tweaked moments" extrapolation will be
608+ # applied, and we revert to source_island.max() *
609+ # fudge_max_pix.
610+ # The condition is a sanity check for maps other than Stokes I,
611+ # where the threshold can be negative. For Stokes I maps, which
612+ # will have positive thresholds, at least for all
613+ # non-pathological cases, this condition will always be true.
614+
615+ epsilon = np .log (2.0 ) * (
616+ (np .cos (theta ) * deltax + np .sin (theta ) * deltay ) ** 2
617+ + (np .cos (theta ) * deltay - np .sin (theta ) * deltax )
618+ ** 2
619+ * semiminor_tmp
620+ / semimajor_tmp
621+ )
615622
616- # Set limits for the root finder similar to the bounds for
617- # Gaussian fits.
618- if basevalue > 0 :
619- low_bound = 0.5 * basevalue
620- upp_bound = 2.0 * basevalue
621- else :
622- low_bound = 2.0 * basevalue
623- upp_bound = 0.5 * basevalue
624-
625- # The number of iterations used for the root finder is also
626- # returned, but not used here.
627- peak , _ = newton_raphson_root_finder (
628- find_true_peak ,
629- basevalue ,
630- low_bound ,
631- upp_bound ,
632- 1e-8 ,
633- 100 ,
634- threshold ,
635- epsilon ,
636- semiminor_tmp ,
637- basevalue ,
638- )
623+ # Set limits for the root finder similar to the bounds for
624+ # Gaussian fits.
625+ if basevalue > 0 :
626+ low_bound = 0.5 * basevalue
627+ upp_bound = 2.0 * basevalue
628+ else :
629+ low_bound = 2.0 * basevalue
630+ upp_bound = 0.5 * basevalue
631+
632+ # The number of iterations used for the root finder is also
633+ # returned, but not used here.
634+ peak , _ = newton_raphson_root_finder (
635+ find_true_peak ,
636+ basevalue ,
637+ low_bound ,
638+ upp_bound ,
639+ 1e-8 ,
640+ 100 ,
641+ threshold ,
642+ epsilon ,
643+ semiminor_tmp ,
644+ basevalue ,
645+ )
639646
640647 if np .sign (threshold ) == np .sign (peak ) and abs (peak ) > abs (
641648 threshold
0 commit comments