How the Frames Pipeline Sets its Flags

The frames pipeline uses a set of flags for each object to call attention to possible problems and to record decisions made during processing. These flags apply both to the object as a whole (including data from each band), and to each band separately.

An OBJC is the entire object in its polychromatic glory, while an OBJECT1 is the measured object in just one of the bands.

Reading the following description will be easier if you have a nodding acquaintance with the frames pipeline, but it should be useful to all.

The Flags that Frames Uses:
A description of each flag.
When and Where Flags are Set as Frames Runs:
Pseudo-code describing how the flags are set.

The Flags that Frames Uses

0 OBJECT1_CANONICAL_CENTER
The quantities (psf counts, model fits and likelihoods) that are usually determined at an object's center as determined band-by-band were in fact determined at the canonical center (suitably transformed).

This is due to the object being to close to the edge to extract a profile at the local center and OBJECT1_EDGE is also set.

1 OBJECT1_BRIGHT
2 OBJECT1_EDGE
Object is too close to edge of frame in this band. Specifically, at least one of the following is true:

OBJECT1_EDGE objects will have OBJECT1_NODEBLEND set, and the object will not be deblended.

If OBJECT1_EDGE is set in any band, it will be set for the OBJC. Children inherit this flag.

3 OBJECT1_BLENDED
Object was determined to be a blend. The flag is set if:

If OBJECT1_EDGE is set in any band, it will be set for all bands, and for the OBJC itself.

If, while running the deblender, it so happens that only one child remains, this flag is turned off.

4 OBJECT1_CHILD
Object is a child, created by the deblender. This flag is set in all bands, and also in the OBJC.
5 OBJECT1_PEAKCENTER
The given center is the position of peak pixel, as attempts to determine a better centroid failed.

This flag is inherited by children.

6 OBJECT1_NODEBLEND
Although this object was marked as a blend, no deblending was attempted. This can happen because:
7 OBJECT1_NOPROFILE
Frames couldn't extract a radial profile. This can be caused by:
8 OBJECT1_NOPETRO
No Petrosian radius or other Petrosian quantities could be measured. This can be caused by:

This flag is inherited by the OBJC.

9 OBJECT1_MANYPETRO
Object has more than one possible Petrosian radius.

This flag is inherited by the OBJC.

10 OBJECT1_NOPETRO_BIG
The Petrosian ratio has not fallen to the value at which the Petrosian radius is defined at the outermost point of the extracted radial profile. OBJECT1_NOPETRO is set, and the "Petrosian radius" is set to the outermost point in the profile.
11 OBJECT1_DEBLEND_TOO_MANY_PEAKS
The object had the OBJECT1_DEBLEND flag set, but it contained too many candidate children. The OBJECT1_NODEBLEND flag is set, and the object is not deblended. The maximum allowable number of peaks is an input parameter to the frames pipeline.
12 OBJECT1_CR
Object contains at least one pixel which was contaminated by a cosmic ray. The OBJECT1_INTERP flag is also set.
13 OBJECT1_MANYR50
More than one radius was found to contain 50% of the Petrosian flux. (For this to happen part of the radial profile must be negative.)
14 OBJECT1_MANYR90
More than one radius was found to contain 90% of the Petrosian flux. (For this to happen part of the radial profile must be negative.)
15 OBJECT1_BAD_RADIAL
Measured profile includes points with a S/N <= 0.
16 OBJECT1_INCOMPLETE_PROFILE
A circle, centered on the object, of radius the "canonical" Petrosian radius extends beyond the edge of the frame. The radial profile is still measured from those parts of the object that do lie on the frame.
17 OBJECT1_INTERP
The object contains interpolated pixels (e.g. cosmic rays or bad columns).
18 OBJECT1_SATUR
The object contains saturated pixels; OBJECT1_INTERP is also set.
19 OBJECT1_NOTCHECKED
Object includes pixels that were not checked for peaks, for example the unsmoothed edges of frames, and the cores of subtracted or saturated stars. If no peaks are found in the checked part of the object it is rejected. Note that bright stars are detected before the wings are subtracted.
20 OBJECT1_SUBTRACTED
Object (presumably a star) had wings subtracted.
21 OBJECT1_NOSTOKES
Object has no measured Stokes params. This can happen because:
22 OBJECT1_BADSKY
The estimated sky level is so bad that the central value of the radial profile is crazily negative; this is usually the result of the subtraction of the wings of bright stars failing.
23 OBJECT1_PETROFAINT
At least one candidate Petrosian radius occured at an unacceptably low surface brightness; this can lead to OBJECT1_NOPETRO being set.
24 OBJECT1_TOO_LARGE
The object is (as it says) too large. The two ways that this can be set are:
25 OBJECT1_DEBLENDED_AS_PSF
When deblending an object, in this band this child was treated as a PSF. The two ways that this can happen are:
26 OBJECT1_DEBLEND_PRUNED
When solving for the weights to be assigned to each child the deblender encountered a nearly singular matrix, and therefore deleted at least one of the children.

This flag is propagated to the OBJC.

27 OBJECT1_ELLIPFAINT
No isophotal fits were performed. Possible reasons are:
28 OBJECT1_BINNED1
The object was detected in an unbinned image.
29 OBJECT1_BINNED2
The object was detected in a 2x2 binned image after all unbinned detections have been replaced by the background level.
30 OBJECT1_BINNED4
The object was detected in a 4x4 binned image. The objects detected in the 2x2 binned image are not removed before doing this.
31 OBJECT1_SPARE1
Not currently used.
32 OBJECT1_DETECTED
A meta-flag, defined as:
(OBJECT1_BINNED1 | OBJECT1_BINNED2 | OBJECT1_BINNED4)                [28,29,30]

When and Where Flags are Set as Frames Runs

The variable objc refers to an OBJC, while object1 refers to an OBJECT1. You are expected to imagine a loop over all filters, setting flags as appropriate.

The following pseudo-code roughly corresponds to the organisation of the frames pipeline, and bears some resemblence to C. The following idioms are used:

var |= FLAG;
Set the FLAG bit in the variable var
if(var & FLAG)
Is var's FLAG bit set?
var &= ~FLAG;
Clear the FLAG bit in the variable var

The numbers in the right hand margin refer to the previous section, where the individual flags are described.

find_objects
{
   if(pixels over threshold touch edge of frame) {
      object1->flags |= OBJECT1_EDGE;                                      [2]
   }
   if(object includes unsearched pixels (e.g. unsmoothed edges of frames)) {
      object1->flags |= OBJECT1_NOTCHECKED;                                [19]
      reject all peaks in NOTCHECKED parts of frame;
   }
/*
 * information about which mode object was detected in
 */
   if(bright objects) {
      object1->flags |= OBJECT1_BRIGHT;                                    [1]
   }

   if(not binned) {
      object1->flags |= OBJECT1_BINNED1;                                   [28]
   } else if(binned 2x2) {
      object1->flags |= OBJECT1_BINNED2;                                   [29]
   } else if(binned 4x4) {
      object1->flags |= OBJECT1_BINNED4;                                   [30]
   }
/*
 * information about pixels contained in object
 */
   if(object contains interpolated pixels) {
      object1->flags |= OBJECT1_INTERP;                                    [17]

      if(object contains cosmic ray contaminated pixels) {
         object1->flags |= OBJECT1_CR;                                     [12]
      }

      if(object contains saturated pixels after centering on peak) {
         object1->flags |= OBJECT1_SATUR;                                  [18]
      }
   }
}
find_centre
{
   if(saturated and saturated star centroider fails) {
      object1->flags |= OBJECT1_PEAKCENTER;                                [5]
   }
   
   if(too close to edge while searching for peak) {
      object1->flags |= OBJECT1_EDGE | OBJECT1_PEAKCENTER;               [2,5]
   }
   
   if(object has vanishing second derviative) {
      object1->flags |= OBJECT1_PEAKCENTER;                                [5]
   }

   if(object1->flags & OBJECT1_PEAKCENTER) {                               [5]
      take centre of brightest pixel as peak position;
   }

}
merge_colors
{
   if(more than one peaks is detected within an object in one band) {
      objc->flags |= OBJECT1_BLENDED;                                      [3]
   }

   if(distinct peaks found in different bands of same object) {
      objc->flags |= OBJECT1_BLENDED;                                      [3]
   }

   if(multiple distinct peaks in merged objects) {
      objc->flags |= OBJECT1_BLENDED;                                      [3]
   }
}
subtract_bright_stars
{
   if(object contains pixels from which star wings were subtracted) {
      object1->flags |= OBJECT1_SUBTRACTED;                                [20]
   }
   if(object is in part of frame where bright star wings exceeded 10 sky sigma,
                           or star wings increased variance by more than 50%) {
      object1->flags |= OBJECT1_NOTCHECKED;                                [19]
      
   }
}
measure_objects
{
/*
 * book keeping
 */
   if(detected as a bright object) {
      if(being remeasured after faint object detection) {
         make new object which is sibling of bright object;
         unset OBJECT1_BRIGHT in objc and object1;                         [1]
      }
   }

   create_object1s {
      objc->flags |= object1->flags & OBJECT1_BLENDED;                     [3]
   }
/*
 * extract profile
 */
   if(failed to extract radial profile) {
      object1->flags |= OBJECT1_EDGE | OBJECT1_NOPETRO | OBJECT1_NOPROFILE;
      give up measuring object in this band;                            [2,7,8]
   }

   if(pixel overflow while extracting radial profile) {
      object1->flags |= OBJECT1_SATUR;                                     [18]
   }
   
   if(object is still detected at edge of extracted profile (about 260arcsec)){
      object1->flags |= OBJECT1_TOO_LARGE;                                 [24]
   }

   if(measured profile includes points with a S/N <= 0) {
      object1->flags |= OBJECT1_BAD_RADIAL;                                [15]
   }
   
   if(central value of object more than 100 sigma below sky level) {
      object1->flags |= OBJECT1_BADSKY | OBJECT1_NOPETRO;                [8,22]
      give up measuring object in this band; something is horribly wrong.
   }

   if(radial profile has fewer than two points) {
      object1->flags |= OBJECT1_NOPROFILE;                                 [7]
      object1->flags |=
                       OBJECT1_NOPETRO | OBJECT1_ELLIPFAINT | OBJECT1_NOSTOKES;
      give up measuring Petrosian quantities, Stokes parameters, and
        isophotal quantities;                                         [8,21,27]
   }
/*
 * measure a few misc quantities
 */
   if(central surface brightness is below threshold for isophotal shape ||
      failed to fit ellipse at threshold +- delta) {
      object1->flags |= OBJECT1_ELLIPFAINT;                                [27]
      give up fitting ellipse;
   }

   if(failed to measure U or Q due to numerical difficulties) {
      object1->flags |= OBJECT1_NOSTOKES;                                  [21]
   }
/*
 * measure Petrosian quantities
 */
   while(surface brightness at innermost candidate for Petrosian radius
         is too low) {
      reject candidate;
      object1->flags |= OBJECT1_PETROFAINT;                                [23]
   }
   
   if(there are no Petrosian radii) {
      object1->flags |= OBJECT1_NOPETRO;                                   [8]
      if(we didn't reject any candidates for the Petrosian radius) {
         object1->flags |= OBJECT1_NOPETRO_BIG;                            [10]
         use outermost point in radial profile as "Petrosian" radius;
      } else {
         use fallback value for "Petrosian" radius;
      }
   } else {
      if(there is more than one Petrosian radius) {
         object1->flags |= OBJECT1_MANYPETRO;                              [9]
      }
   }
   
   if(more than one value of Petrosian 50% light radius) {
      object1->flags |= OBJECT1_MANYR50; /* how can this happen? */        [13]
   }
   if(more than one value of Petrosian 90% light radius) {
      object1->flags |= OBJECT1_MANYR90; /* how can this happen? */        [14]
   }

   if(object is less than one (r') Petrosian radius from edge of frame) {
      object1->flags |= OBJECT1_INCOMPLETE_PROFILE;                        [16]
   }
/*
 * Measure quantities about the centre determined in this band
 */
   if(local band is too close to the edge of the frame) {
      object1->flags |= OBJECT1_CANONICAL_CENTER | OBJECT1_EDGE;           [0][2]
      use (transformed) canonical center;
   }
/*
 * mark measured as a bright object
 */
   if(measuring bright objects) {
      objc->flags |= OBJECT1_BRIGHT;                                       [1]
   }
/*
 * propagate flags to and from OBJC
 */
   if(objc->flags & OBJECT1_BLENDED) {                                     [3]
      object1->flags |= OBJECT1_BLENDED;                                   [3]
   }

   objc->flags |= object1->flags & (OBJECT1_EDGE |                         [2]
                                    OBJECT1_BLENDED |                      [3]
                                    OBJECT1_CHILD |                        [4]
                                    OBJECT1_NOPETRO |                      [8]
                                    OBJECT1_MANYPETRO |                    [9]
                                    OBJECT1_INTERP |                       [17]
                                    OBJECT1_CR |                           [12]
                                    OBJECT1_SATUR |                        [18]
                                    OBJECT1_NOTCHECKED |                   [19]
                                    OBJECT1_BINNED1 |                      [28]
                                    OBJECT1_BINNED2 |                      [29]
                                    OBJECT1_BINNED4);                      [30]
}
deblender
{
   if(there are too many peaks in object) {
      objc->flags |= OBJECT1_NODEBLEND | OBJECT1_DEBLEND_TOO_MANY_PEAKS; [6,11]
      give up deblending;
   }
   
   make_new_child_from_objc {
      child->flags = objc->flags & (OBJECT1_EDGE |                         [2]
                                    OBJECT1_PEAKCENTER |                   [5]
                                    OBJECT1_INTERP |                       [17]
                                    OBJECT1_NOTCHECKED |                   [19]
                                    OBJECT1_SUBTRACTED);                   [20]
      child->flags |= OBJECT1_CHILD;                                       [4]
      
      child_object1->flags = object1->flags & (OBJECT1_EDGE |              [2]
                                               OBJECT1_PEAKCENTER |        [5]
                                               OBJECT1_NOTCHECKED |        [19]
                                               OBJECT1_SUBTRACTED);        [20]
      child_object1->flags |= (OBJECT1_CHILD & ~OBJECT1_DETECTED);       [4,32]
      child_object1->flags |= OBJECT1_BINNED1;                             [28]
   }

   phObjcDeblend {
      if(objc->flags & (OBJECT1_EDGE)) {                                   [2,18]
         objc->flags |= OBJECT1_NODEBLEND;                                 [6]
         give up, as saturation invalidates assumptions made by deblender;
      }
      
      if(child is consistent with PSF) {
         child_object1->flags |= OBJECT1_DEBLENDED_AS_PSF;                 [25]
      }
      
      deblend_template_find {
         if(template for this child is too large (more than half a frame)) {
            objc->parent->flags |= OBJECT1_TOO_LARGE | OBJECT1_NODEBLEND;[6,24]
            give up on deblending parent;
         }
         
         if(template hangs over edge of frame in any band) {
            objc->parent->flags |= OBJECT1_EDGE | OBJECT1_NODEBLEND;      [2,6]
            give up on deblending parent;
         }
         
         if(failed to find template in this band) {
            object1->flags &= ~OBJECT1_DETECTED;                           [32]
            object1->flags |= OBJECT1_DEBLENDED_AS_PSF;                    [25]
         }
         
         objc->flags |= object1->flags & OBJECT1_DETECTED;                 [32]
      }
      
      if(only one child remains) {
         objc->flags &= ~OBJECT1_BLENDED;                                  [3]
         no need to deblend;
      }
      
      if(at least one possible child is rejected due to singular matrix) {
         objc->flags |= OBJECT1_DEBLEND_PRUNED;                            [26]
         object1->flags |= OBJECT1_DEBLEND_PRUNED;                         [26]
      }
      
      if(child includes saturated pixels) {
         object1->flags |= OBJECT1_SATUR | OBJECT1_INTERP;              [17,18]
      }
   }
}