Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 16eed05

Browse files
committed
Restrict "tweaked moments" for "free shape"
1) Consider this the equivalent of commit f3b10b1. That commit tightened the condition for applying "tweaked moments" for forced beams: apply "tweaked moments" only when the rounded barycenter position is part of the island. The current commit tightens the conditions for "tweaked moments" for a "free shape" in the same way in the sense that a maximum pixel value and corresponding position can no longer be used as "basevalue" and "basepos", i.e. can no longer be used as the base point for a "tweaked moments" extrapolation. 2) Fixed a serious bug that occurs for "ill-formed" or large islands: "posx.size==posy.size!=no_pixels" is the source of error. Since we have indices "[0][0]" in the line "i = np.nonzero(mask)[0][0]" this will often still end up right, but we have encountered cases from a collection of 60 GRB images described here: #180 (comment) where a run "pyse GRB201006A/*.fits --vectorized --back-size-x 50 --back-size-y 50" will reveal serious problems, i.e. unrealistic peak brightnesses. This can occur on one machine, while not causing any problems on another machine with exactly the same code. This comes from the way the "np.empty" fills values in these lines in the "extract" module: https://github.com/transientskp/pyse/blob/591717fd72decbb7fc991bf2232be595c3f2b6f3/sourcefinder/extract.py#L2229 "xpositions = np.empty((num_islands, max_pixels), dtype=np.int32)" and https://github.com/transientskp/pyse/blob/591717fd72decbb7fc991bf2232be595c3f2b6f3/sourcefinder/extract.py#L2230 "ypositions = np.empty((num_islands, max_pixels), dtype=np.int32)" What is called "xpositions" and "ypositions" in the "extract" module is propagated to "posx" and "posy" in "fitting.moments_enhanced", respectively. The problem can occur for any island smaller than the largest island, i.e. for "no_pixels < max_pixels" from this line https://github.com/transientskp/pyse/blob/591717fd72decbb7fc991bf2232be595c3f2b6f3/sourcefinder/measure.py#L498 " mask = (posx == rounded_barycenter[0]) & (posy == rounded_barycenter[1]) " which generally causes "mask.size>no_pixels", i.e. "mask" generally becomes (much) larger than the island. This should nnever occur. 3) After the fix from 1) we end up with a maximum ratio "peak/maxi" of 1.62 from the 60 images described above, see this comment: #182 (comment). That is why "upp_bound = 2.0 * basevalue" seems appropriate, in the sense that this bound will never be reached. This implies that we could replace that line by "upp_bound = np.inf", but that seems a bit risky at this stage; we have not explored enough pathological cases yet. 4) The comment about the meaning of the "maxi" input to "measure.moments_enhanced" should be clearer now.
1 parent 591717f commit 16eed05

1 file changed

Lines changed: 9 additions & 12 deletions

File tree

sourcefinder/measure.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,9 @@ def moments_enhanced(
369369
island. Units: pixels.
370370
371371
maxi : float
372-
Peak pixel value within the island. Units: spectral brightness,
373-
typically Jy/beam. To clarify: source_island[maxpos] == maxi.
372+
Peak pixel value within the island. Pixel values represent spectral
373+
brightness (typically in Jy/beam).
374+
For clarity: source_island[maxpos] == maxi.
374375
375376
fudge_max_pix_factor : float
376377
Correction factor for underestimation of the peak by considering the
@@ -464,6 +465,8 @@ def moments_enhanced(
464465
# dump the redundant elements that have undetermined values.
465466
source_island = source_island[:no_pixels]
466467
noise_island = noise_island[:no_pixels]
468+
posx = posx[:no_pixels]
469+
posy = posy[:no_pixels]
467470
# The significance of a source detection is determined in this way.
468471
significance[0] = (source_island / noise_island).max()
469472

@@ -504,13 +507,7 @@ def moments_enhanced(
504507
i = np.nonzero(mask)[0][0]
505508
basepos = rounded_barycenter
506509
basevalue = source_island[i]
507-
else:
508-
# The rounded barycenter position is not in source_island, so we
509-
# revert to the maximum pixel position, which is always included.
510-
basepos = maxpos[0] - chunkpos[0], maxpos[1] - chunkpos[1]
511-
basevalue = maxi
512-
513-
deltax, deltay = xbar - basepos[0], ybar - basepos[1]
510+
deltax, deltay = xbar - basepos[0], ybar - basepos[1]
514511

515512
if force_beam:
516513
# If the restoring beam is forced, we use the beam parameters
@@ -595,7 +592,7 @@ def moments_enhanced(
595592
else:
596593
theta -= math.pi / 2.0
597594

598-
if np.sign(threshold) == np.sign(basevalue):
595+
if np.sign(threshold) == np.sign(basevalue) and in_source_island:
599596
# Implementation of "tweaked moments", equation 2.67 from
600597
# Spreeuw's thesis. In that formula the "base position" was the
601598
# maximum pixel position. Here that is the rounded
@@ -620,9 +617,9 @@ def moments_enhanced(
620617
# Gaussian fits.
621618
if basevalue > 0:
622619
low_bound = 0.5 * basevalue
623-
upp_bound = 1.5 * basevalue
620+
upp_bound = 2.0 * basevalue
624621
else:
625-
low_bound = 1.5 * basevalue
622+
low_bound = 2.0 * basevalue
626623
upp_bound = 0.5 * basevalue
627624

628625
# The number of iterations used for the root finder is also

0 commit comments

Comments
 (0)