IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 19, 2012, 5:24:19 PM (14 years ago)
Author:
mhuber
Message:

merging latest r34040 trunk changes to branch

Location:
branches/meh_branches/ppstack_test
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/meh_branches/ppstack_test

  • branches/meh_branches/ppstack_test/Ohana/src/relphot/src/StarOps.c

    r31668 r34041  
    22
    33static int Nmax;
    4 static double *list;
    5 static double *dlist;
    6 
    7 // When we rationalize the images/mosaics, we are driving the negative cloud images back
    8 // to 0.0.  At the same time, we make a guess to the effective impact on all other images,
    9 // driven by the coupling of common stars.  This array carries the impact of those offsets
    10 // on each star
    11 static double *Moffset;
    12 
     4
     5typedef struct {
     6  int Nfew;
     7  int Ncode;
     8  int Nsys;
     9  int Nbad;
     10  int Ncal;
     11  int Nmos;
     12  int Ngrid;
     13  double *list;
     14  double *dlist;
     15  double *wlist;
     16  double *aplist;
     17  double *daplist;
     18} SetMrelInfo;
     19
     20enum {THREAD_RUN, THREAD_DONE};
     21
     22typedef struct {
     23  int entry;
     24  int state;
     25  Catalog *catalog;
     26  int Ncatalog;
     27  FlatCorrectionTable *flatcorr;
     28  SetMrelInfo summary;
     29} ThreadInfo;
     30
     31// ** internal functions:
     32void *setMrel_worker (void *data);
     33int setMrel_threaded (Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr);
     34int setMrel_catalog (Catalog *catalog, int Nc, int pass, FlatCorrectionTable *flatcorr, SetMrelInfo *results, int Nsecfilt);
     35int print_measure_set (Average *average, SecFilt *secfilt, Measure *measure);
     36
     37// we want to allocate the stats list,dlist arrays only once (or once per thread).
     38// this function finds the largest array so we can allocate that max size when needed
    1339void initMrel (Catalog *catalog, int Ncatalog) {
    1440
     
    2147    }
    2248  }
    23 
    24   ALLOCATE (list,    double, MAX (1, Nmax));
    25   ALLOCATE (dlist,   double, MAX (1, Nmax));
    26   ALLOCATE (Moffset, double, MAX (1, Nmax));
    2749
    2850
     
    4769}
    4870
    49 int setMrel (Catalog *catalog, int Ncatalog) {
     71void SetMrelInfoInit (SetMrelInfo *results, int allocLists) {
     72  results->Nfew  = 0;
     73  results->Ncode  = 0;
     74  results->Nsys  = 0;
     75  results->Nbad  = 0;
     76  results->Ncal  = 0;
     77  results->Nmos  = 0;
     78  results->Ngrid = 0;
     79  if (allocLists) {
     80    ALLOCATE (results->list,  double, Nmax);
     81    ALLOCATE (results->dlist, double, Nmax);
     82    ALLOCATE (results->wlist, double, Nmax);
     83  }
     84}
     85
     86void SetMrelInfoFree (SetMrelInfo *results) {
     87  free (results->list);
     88  free (results->dlist);
     89  free (results->wlist);
     90}
     91
     92void SetMrelInfoAccum (SetMrelInfo *summary, SetMrelInfo *results) {
     93  summary->Nfew  += results->Nfew ;
     94  summary->Ncode  += results->Ncode ;
     95  summary->Nsys  += results->Nsys ;
     96  summary->Nbad  += results->Nbad ;
     97  summary->Ncal  += results->Ncal ;
     98  summary->Nmos  += results->Nmos ;
     99  summary->Ngrid += results->Ngrid;
     100}
     101
     102// mutex to lock setMrel_worker operations
     103static pthread_mutex_t setMrel_mutex = PTHREAD_MUTEX_INITIALIZER;
     104static int nextCatalog = 0;
     105
     106// we have an array of catalogs (catalog, Ncatalog).  we need to hand out catalogs one at a time to
     107// the worker threads as they need
     108off_t getNextCatalogForThread (int Ncatalog) {
     109
     110  pthread_mutex_lock (&setMrel_mutex);
     111  if (nextCatalog >= Ncatalog) {
     112    pthread_mutex_unlock (&setMrel_mutex);
     113    return (-1);
     114  }
     115  int thisCatalog = nextCatalog;
     116  nextCatalog ++;
     117
     118  pthread_mutex_unlock (&setMrel_mutex);
     119  return (thisCatalog);
     120}
     121
     122// setMrel and setMrelOutput are extremely similar, but have slightly different implications:
     123// * setMrel uses the internal Tiny structures only
     124// * setMrelOutput skips stars for which there are too few good measurements
     125// * setMrelOutput is meant to be called repeatedly, relaxing the criteria for 'good' on each pass
     126// * setMrelOutput updates 2MASS average flags
     127// * setMrelOutput updates average EXT flags (PS1 and 2MASS)
     128
     129int setMrel (Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr) {
     130
     131  int i;
     132
     133  if (NTHREADS) {
     134    int status = setMrel_threaded (catalog, Ncatalog, flatcorr);
     135    return status;
     136  }
     137
     138  int Nsecfilt = GetPhotcodeNsecfilt ();
     139
     140  SetMrelInfo summary, results;
     141  SetMrelInfoInit (&summary, FALSE);
     142  SetMrelInfoInit (&results, TRUE);
     143
     144  for (i = 0; i < Ncatalog; i++) {
     145    // pass == -1 for anything other than the final pass
     146    setMrel_catalog (catalog, i, -1, flatcorr, &results, Nsecfilt);
     147    SetMrelInfoAccum (&summary, &results);
     148  }
     149  if (VERBOSE2) fprintf (stderr, "%d stars with no data in photcode, %d stars marked having too few measurements (Nbad: %d, Ncal: %d, Nmos: %d, Ngrid: %d, Nsys: %d)\n", summary.Ncode, summary.Nfew, summary.Nbad, summary.Ncal, summary.Nmos, summary.Ngrid, summary.Nsys);
     150
     151  SetMrelInfoFree (&results);
     152
     153  return (TRUE);
     154}
     155
     156int setMrelOutput (Catalog *catalog, int Ncatalog, int pass, FlatCorrectionTable *flatcorr) {
     157
     158  int i;
     159
     160  int Nsecfilt = GetPhotcodeNsecfilt ();
     161
     162  SetMrelInfo summary, results;
     163  SetMrelInfoInit (&summary, FALSE);
     164  SetMrelInfoInit (&results, TRUE); // allocates results->list,dlist,wlist
     165  ALLOCATE (results.aplist, double, Nmax);
     166  ALLOCATE (results.daplist, double, Nmax);
     167
     168  for (i = 0; i < Ncatalog; i++) {
     169    setMrel_catalog  (catalog, i, pass, flatcorr, &results, Nsecfilt); // XXX add arguments as needed for options
     170    SetMrelInfoAccum (&summary, &results);
     171  }
     172  if (VERBOSE2) fprintf (stderr, "%d stars with no data in photcode, %d stars marked having too few measurements (Nbad: %d, Ncal: %d, Nmos: %d, Ngrid: %d, Nsys: %d)\n", summary.Ncode, summary.Nfew, summary.Nbad, summary.Ncal, summary.Nmos, summary.Ngrid, summary.Nsys);
     173
     174  SetMrelInfoFree (&results);
     175  free (results.aplist);
     176  free (results.daplist);
     177  return (TRUE);
     178}
     179
     180int setMrel_threaded (Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr) {
     181
     182  int i;
     183
     184  SetMrelInfo summary;
     185  SetMrelInfoInit (&summary, FALSE);
     186
     187  pthread_attr_t attr;
     188  pthread_attr_init (&attr);
     189  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
     190 
     191  pthread_t *threads;
     192  ALLOCATE (threads, pthread_t, NTHREADS);
     193
     194  ThreadInfo *threadinfo;
     195  ALLOCATE (threadinfo, ThreadInfo, NTHREADS);
     196
     197  // each time this function is called, we cycle through the available catalogs.
     198  // make sure we start at 0
     199  nextCatalog = 0;;
     200
     201  // launch N worker threads
     202  for (i = 0; i < NTHREADS; i++) {
     203    threadinfo[i].entry = i;
     204    threadinfo[i].state = THREAD_RUN;
     205    threadinfo[i].catalog  =  catalog;
     206    threadinfo[i].Ncatalog = Ncatalog;
     207    threadinfo[i].flatcorr = flatcorr;
     208    SetMrelInfoInit (&threadinfo[i].summary, FALSE);
     209    pthread_create (&threads[i], NULL, setMrel_worker, &threadinfo[i]);
     210  }
     211  pthread_attr_destroy (&attr);
     212
     213  // wait until all threads have finished
     214  while (1) {
     215    int allDone = TRUE;
     216    for (i = 0; i < NTHREADS; i++) {
     217      if (threadinfo[i].state == THREAD_RUN) allDone = FALSE;
     218    }
     219    if (allDone) {
     220      break;
     221    }
     222    usleep (500000);
     223  }
     224
     225  // all threads are done, free the threads array and grab the info
     226  free (threads);
     227 
     228  // report stats & summary from the threads
     229  for (i = 0; i < NTHREADS; i++) {
     230    if (VERBOSE2) fprintf (stderr, "setMrel thread %d : %d stars with no data in photcode, %d stars marked having too few measurements (Nbad: %d, Ncal: %d, Nmos: %d, Ngrid: %d, Nsys: %d)\n",
     231             i,
     232             threadinfo[i].summary.Ncode,
     233             threadinfo[i].summary.Nfew,
     234             threadinfo[i].summary.Nbad,
     235             threadinfo[i].summary.Ncal,
     236             threadinfo[i].summary.Nmos,
     237             threadinfo[i].summary.Ngrid,
     238             threadinfo[i].summary.Nsys);
     239    SetMrelInfoAccum (&summary, &threadinfo[i].summary);
     240  }
     241  if (VERBOSE2) fprintf (stderr, "total : %d stars with no data in photcode, %d stars marked having too few measurements (Nbad: %d, Ncal: %d, Nmos: %d, Ngrid: %d, Nsys: %d)\n", summary.Ncode, summary.Nfew, summary.Nbad, summary.Ncal, summary.Nmos, summary.Ngrid, summary.Nsys);
     242  free (threadinfo);
     243
     244  return TRUE;
     245}
     246
     247void *setMrel_worker (void *data) {
     248
     249  ThreadInfo *threadinfo = data;
     250
     251  int Nsecfilt = GetPhotcodeNsecfilt ();
     252
     253  SetMrelInfo results;
     254  SetMrelInfoInit (&results, TRUE); // allocate list, dlist arrays here
     255
     256  while (1) {
     257
     258    off_t i = getNextCatalogForThread(threadinfo->Ncatalog);
     259    if (i == -1) {
     260      threadinfo->state = THREAD_DONE;
     261      return NULL;
     262    }
     263
     264    Catalog *catalog = threadinfo->catalog;
     265    FlatCorrectionTable *flatcorr = threadinfo->flatcorr;
     266
     267    // pass == -1 for anything other than the final pass
     268    setMrel_catalog (catalog, i, -1, flatcorr, &results, Nsecfilt);
     269    SetMrelInfoAccum (&threadinfo->summary, &results);
     270  }
     271
     272  SetMrelInfoFree (&results);
     273  return NULL;
     274}
     275
     276# define SKIP_THIS_MEAS(REASON) {                               \
     277    catalog[Nc].measureT[m].dbFlags |= ID_MEAS_SKIP_PHOTOM;     \
     278    if (catalog[Nc].measure) {                                  \
     279      catalog[Nc].measure [m].dbFlags |= ID_MEAS_SKIP_PHOTOM;   \
     280    }                                                           \
     281    results->REASON ++;                                         \
     282    continue; }
     283
     284
     285// setMrel_catalog is used in 3 different contexts:
     286
     287// * during the main relphot iterations:
     288// ** operations only apply to measureT / averageT
     289// ** we are applying the analysis to the bright subset catalog
     290// ** we skip any stars found to be bad (STAR_BAD)
     291
     292// * during the final pass
     293// ** operations are applied to all objects
     294// ** we have special tests for PS1 extended data, 2MASS extended & good data, & synthetic photometry
     295
     296// * during the stand-alone '-averages' mode (relphot_objects)
     297// ** no image data is loaded
     298// ** we only use the provided calibration (measure.Mcal)
     299// ** we skip outlier rejection of measurements
     300
     301// set the Mrel values for the specified catalog
     302// NOTE: here 'catalog' is a pointer to a specific catalog, not the root of the array
     303int setMrel_catalog (Catalog *catalog, int Nc, int pass, FlatCorrectionTable *flatcorr, SetMrelInfo *results, int Nsecfilt) {
    50304
    51305  off_t j, k, m;
    52   int i, N, Nfew, Nsys, Nbad, Ncal, Nmos, Ngrid;
     306  int N;
    53307  float Msys, Mcal, Mmos, Mgrid;
    54   StatType stats;
    55 
    56   int Nsecfilt = GetPhotcodeNsecfilt ();
    57   Nfew = Nsys = Nbad = Ncal = Nmos = Ngrid = 0;
    58 
    59   for (i = 0; i < Ncatalog; i++) {
    60     for (j = 0; j < catalog[i].Naverage; j++) {
    61 
    62       int Ns;
    63       for (Ns = 0; Ns < Nphotcodes; Ns++) {
    64 
    65         int thisCode = photcodes[Ns][0].code;
    66         int Nsec = GetPhotcodeNsec(thisCode);
    67 
    68         /* calculate the average value for a single star */
    69 
    70         // skip bad stars
    71         if (catalog[i].secfilt[Nsecfilt*j+Nsec].flags & STAR_BAD) continue;
    72         m = catalog[i].averageT[j].measureOffset;
    73 
    74         N = 0;
    75         for (k = 0; k < catalog[i].averageT[j].Nmeasure; k++, m++) {
    76           // skip measurements that do not match the current photcode
    77           int ecode = GetPhotcodeEquivCodebyCode (catalog[i].measureT[m].photcode);
    78           if (ecode != thisCode) { continue; }
    79 
    80           if (catalog[i].measureT[m].dbFlags & MEAS_BAD) {
    81             Nbad ++;
    82             continue;
    83           }
    84           // XXX allow REF stars (no Image Entry) to be included in the calculation this
    85           // should be optionally set, and should allow for REF stars to be downweighted by
    86           // more than their reported errors.  how such info is carried is unclear...
    87           if (getImageEntry (m, i) < 0) {
    88             Mcal = Mmos = Mgrid = 0;
    89           } else {
    90             Mcal  = getMcal  (m, i);
    91             if (isnan(Mcal)) {
    92               Ncal ++;
    93               continue;
    94             }
    95             Mmos  = getMmos  (m, i);
    96             if (isnan(Mmos)) {
    97               Nmos ++;
    98               continue;
    99             }
    100             Mgrid = getMgrid (m, i);
    101             if (isnan(Mgrid)) {
    102               Ngrid++;
    103               continue;
    104             }
    105           }
    106 
    107           Msys = PhotSysTiny (&catalog[i].measureT[m], &catalog[i].averageT[j], &catalog[i].secfilt[j*Nsecfilt]);
    108           if (isnan(Msys)) {
    109             Nsys++;
    110             continue;
    111           }
    112           list[N] = Msys - Mcal - Mmos - Mgrid;
    113           dlist[N] = MAX (catalog[i].measureT[m].dM, MIN_ERROR);
    114 
    115           // tie down reference photometry if the -refcode (code) option is selected
    116           if (refPhotcode) {
    117             if (GetPhotcodeEquivCodebyCode(catalog[i].measureT[m].photcode) == refPhotcode[0].equiv) {
    118               // increase the weight by a factor of 100:
    119               dlist[N] = 0.01*catalog[i].measureT[m].dM;
    120             }
    121           }
    122           N++;
    123         }
    124 
    125         // when performing the grid analysis, STAR_TOOFEW will be set to 1;
    126         if (N <= STAR_TOOFEW) { /* too few measurements */
    127           catalog[i].secfilt[Nsecfilt*j+Nsec].flags |= ID_STAR_FEW;
    128           Nfew ++;
     308
     309  StatType stats, apstats;
     310  liststats_setmode (&stats, STATMODE);
     311  liststats_setmode (&apstats, STATMODE);
     312
     313  double *list    = results->list;
     314  double *dlist   = results->dlist;
     315  double *wlist   = results->wlist;
     316  double *aplist  = results->aplist;
     317  double *daplist = results->daplist;
     318
     319  SetMrelInfoInit (results, FALSE); // do not allocate list,dlist,wlist arrays
     320
     321  int isSetMrelFinal = (pass >= 0);
     322
     323  for (j = 0; j < catalog[Nc].Naverage; j++) {
     324    // XXX accumulate all secfilt values in a single pass?
     325
     326    // option for a test print
     327    if (FALSE && (catalog[Nc].average[j].objID == 0x46a4) && (catalog[Nc].average[j].catID == 0xf40e)) {
     328      fprintf (stderr, "test obj\n");
     329      print_measure_set (&catalog[Nc].average[j], &catalog[Nc].secfilt[j*Nsecfilt], catalog[Nc].measure);
     330    }
     331
     332    int GoodPS1 = FALSE;
     333    int Good2MASS = FALSE;
     334    int Galaxy2MASS = FALSE;
     335
     336    int NextPS1 = 0;
     337    int NpsfPS1 = 0;
     338
     339    int Ns;
     340    for (Ns = 0; Ns < Nphotcodes; Ns++) {
     341
     342      int thisCode = photcodes[Ns][0].code;
     343      int Nsec = GetPhotcodeNsec(thisCode);
     344
     345      /* calculate the average mag in this SEC photcode for a single star */
     346
     347      /* star/photcodes already calibrated */
     348      if ( isSetMrelFinal && catalog[Nc].found[Nsecfilt*j+Nsec]) continue; 
     349     
     350      // skip bad stars
     351      if (!isSetMrelFinal && (catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags & STAR_BAD)) continue;
     352
     353      int Ncode = 0;
     354      int Next = 0;
     355      int haveSynth = FALSE;
     356
     357      int forceSynth = FALSE;
     358      int forceSynthEntry = -1;
     359
     360      int haveUbercal = FALSE;
     361
     362      int minUbercalDist = 1000;
     363   
     364      N = 0;
     365      m = catalog[Nc].averageT[j].measureOffset;
     366      for (k = 0; k < catalog[Nc].averageT[j].Nmeasure; k++, m++) {
     367
     368        // skip measurements that do not match the current photcode
     369        PhotCode *code = GetPhotcodebyCode (catalog[Nc].measureT[m].photcode);
     370        if (!code) continue;
     371        if (code->equiv != thisCode) { continue; }
     372        Ncode ++;
     373
     374        if (catalog[Nc].measureT[m].dbFlags & MEAS_BAD) SKIP_THIS_MEAS(Nbad);
     375
     376        if (getImageEntry (m, Nc) < 0) {
     377          // measurements without an image are either external reference photometry or
     378          // data for which the associated image has not been loaded (probably because of
     379          // overlaps).  Msys + measure.Mcal is our best guess of the true magnitude
     380          Mmos = Mgrid = 0;
     381          Mcal = catalog[Nc].measureT[m].Mcal; // check that this is zero for loaded REF value
    129382        } else {
    130           catalog[i].secfilt[Nsecfilt*j+Nsec].flags &= ~ID_STAR_FEW;
    131         }       
    132 
    133         liststats (list, dlist, N, &stats);
    134 
    135         catalog[i].secfilt[Nsecfilt*j+Nsec].M  = stats.mean;
    136         catalog[i].secfilt[Nsecfilt*j+Nsec].dM = stats.sigma;
    137         catalog[i].secfilt[Nsecfilt*j+Nsec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NAN_S_SHORT;
    138       }
    139     }
    140   }
    141   fprintf (stderr, "%d stars marked having too few measurements (Nbad: %d, Ncal: %d, Nmos: %d, Ngrid: %d, Nsys: %d)\n", Nfew, Nbad, Ncal, Nmos, Ngrid, Nsys);
    142 
    143   return (TRUE);
    144 }
    145 
    146 int setMrelOutput (Catalog *catalog, int Ncatalog, int mark) {
    147 
    148   int i, N;
    149   off_t j, k, m, Nmax;
    150   float Msys, Mcal, Mmos, Mgrid;
    151   double *list, *dlist;
    152   StatType stats;
    153   int Nsec, Nsecfilt, ecode;
    154 
    155   Nsecfilt = GetPhotcodeNsecfilt ();
    156 
    157   /* Nmeasure is now different, need to reallocate */
    158   Nmax = 0;
    159   for (i = 0; i < Ncatalog; i++) {
    160     for (j = 0; j < catalog[i].Naverage; j++) {
    161       Nmax = MAX (Nmax, catalog[i].averageT[j].Nmeasure);
    162     }
    163   }
    164   ALLOCATE (list, double, MAX (1, Nmax));
    165   ALLOCATE (dlist, double, MAX (1, Nmax));
    166 
    167   for (i = 0; i < Ncatalog; i++) {
    168     for (j = 0; j < catalog[i].Naverage; j++) {
    169       /* skip stars already calibrated */
    170       if (catalog[i].found[j]) continue; 
    171 
    172       int Ns;
    173       for (Ns = 0; Ns < Nphotcodes; Ns++) {
    174         int thisCode = photcodes[Ns][0].code;
    175         Nsec = GetPhotcodeNsec(thisCode);
    176 
    177         N = 0;
    178         m = catalog[i].averageT[j].measureOffset;
    179         for (k = 0; k < catalog[i].averageT[j].Nmeasure; k++, m++) {
    180           // skip measurements that do not match the current photcode
    181           ecode = GetPhotcodeEquivCodebyCode (catalog[i].measureT[m].photcode);
    182           if (ecode != thisCode) { continue; }
    183 
    184           if (catalog[i].measureT[m].dbFlags & MEAS_BAD) continue;
    185 
    186           // XXX allow REF stars (no Image Entry) to be included in the calculation this
    187           // should be optionally set, and should allow for REF stars to be downweighted by
    188           // more than their reported errors.  how such info is carried is unclear...
    189           if (getImageEntry (m, i) < 0) {
    190             Mcal = Mmos = Mgrid = 0;
    191           } else {
    192             Mcal  = getMcal  (m, i);
    193             if (isnan(Mcal)) continue;
    194             Mmos  = getMmos  (m, i);
    195             if (isnan(Mmos)) continue;
    196             Mgrid = getMgrid (m, i);
    197             if (isnan(Mgrid)) continue;
    198           }
    199 
    200           Msys = PhotSysTiny (&catalog[i].measureT[m], &catalog[i].averageT[j], &catalog[i].secfilt[j*Nsecfilt]);
    201           list[N] = Msys - Mcal - Mmos - Mgrid;
    202           dlist[N] = MAX (catalog[i].measureT[m].dM, MIN_ERROR);
    203           N++;
    204         }
    205         if (N < 1) continue;
    206 
    207         liststats (list, dlist, N, &stats);
    208         if (mark) catalog[i].found[j] = TRUE;
    209 
    210         /* use sigma or error in dM for output? */
    211         catalog[i].secfilt[Nsecfilt*j+Nsec].M  = stats.mean;
    212         catalog[i].secfilt[Nsecfilt*j+Nsec].dM = MAX (stats.error, stats.sigma);
    213         catalog[i].secfilt[Nsecfilt*j+Nsec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NAN_S_SHORT;
    214       }
    215     }
    216   }
    217 
    218   free (list);
    219   free (dlist);
    220   return (TRUE);
    221 }
    222 
    223 // For each average object, set the average mags based on existing equiv photometry.
    224 // NOTE: this function operates on the real Measure & Average structures, not the
    225 // MeasureTiny & AverageTiny structures
    226 int setMave (Catalog *catalog, int Ncatalog) {
    227 
    228   off_t j, k, m, Nmax;
    229   int i, Ns, Nsecfilt, N, Nc;
    230   float Msys;
    231   double *list, *dlist;
    232   StatType stats;
    233   PhotCode *code;
    234   DVOAverageFlags flagBits;
    235 
    236   flagBits = ID_OBJ_EXT | ID_OBJ_EXT_ALT | ID_OBJ_GOOD | ID_OBJ_GOOD_ALT;
    237 
    238   // pre-allocate a list for stats purposes
    239   Nmax = 0;
    240   for (i = 0; i < Ncatalog; i++) {
    241     for (j = 0; j < catalog[i].Naverage; j++) {
    242       Nmax = MAX (Nmax, catalog[i].average[j].Nmeasure);
    243     }
    244   }
    245   ALLOCATE (list, double, MAX (1, Nmax));
    246   ALLOCATE (dlist, double, MAX (1, Nmax));
    247 
    248   Nsecfilt = GetPhotcodeNsecfilt ();
    249 
    250 # define PSFQUALSTATS 1
    251   for (i = 0; i < Ncatalog; i++) {
    252     for (j = 0; j < catalog[i].Naverage; j++) {
    253 
    254       // update average photometry for each of the average filters
    255       for (Ns = 0; Ns < Nsecfilt; Ns++) {
    256 
    257         code = GetPhotcodebyNsec (Ns);
    258         Nc = code[0].code;
    259        
    260         N = 0;
    261         m = catalog[i].average[j].measureOffset;
    262         for (k = 0; k < catalog[i].average[j].Nmeasure; k++, m++) {
    263           if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
    264           if (GetPhotcodeEquivCodebyCode (catalog[i].measure[m].photcode) != Nc) continue;
    265 
    266           Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*Nsecfilt]);
    267           if (isnan(Msys)) continue;
    268 
    269           // XXX only apply this filter for psphot data from GPC1 for now...
    270           if (PSFQUALSTATS && (catalog[i].measure[m].photcode > 10000) && (catalog[i].measure[m].photcode < 10500)) {
    271               if (catalog[i].measure[m].psfQual < 0.85) continue;
    272           }
    273 
    274           // XXX make it optional to apply Mcal (do I need an extra field for advisory Mcal?)
    275           list[N] = Msys - catalog[i].measure[m].Mcal;
    276           dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
    277           N++;
    278         }
    279         if (N < 1) continue;
    280 
    281         liststats (list, dlist, N, &stats);
    282 
    283         /* use sigma or error in dM for output? */
    284         catalog[i].secfilt[Nsecfilt*j+Ns].M  = stats.mean;
    285         catalog[i].secfilt[Nsecfilt*j+Ns].dM = MAX (stats.error, stats.sigma);
    286         catalog[i].secfilt[Nsecfilt*j+Ns].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NAN_S_SHORT;
    287         catalog[i].secfilt[Nsecfilt*j+Ns].Ncode = N;
    288         catalog[i].secfilt[Nsecfilt*j+Ns].Nused = stats.Nmeas;
    289       }
    290 
    291       // update average flags based on the detection stats. 
    292       // XXX we need to clean this up -- this is a serious set of hacks...
    293       if (PSFQUALSTATS) {
    294         int Galaxy2MASS, GalaxySDSS, goodPS1, nEXT, nPSF, good2MASS;
    295 
    296         Galaxy2MASS = FALSE; // best guess for galaxy based on 2MASS J measurements (gal_contam == measure.flags[0x00400000 | 0x00800000])
    297         GalaxySDSS = FALSE;  // best guess for galaxy based on SDSS measurements (XXX need to fix SDSS flags)
    298         goodPS1 = FALSE;     // true if any PS1 measurements have psfQual > 0.85
    299         good2MASS = FALSE;   // true if 2MASS J measurements have significant detections
    300         nEXT = nPSF = 0;     // number of PS1 PSF vs EXT measurements
    301 
    302         m = catalog[i].average[j].measureOffset;
    303         for (k = 0; k < catalog[i].average[j].Nmeasure; k++, m++) {
    304 
    305           // PS1 data :
    306           if ((catalog[i].measure[m].photcode >= 10000) && (catalog[i].measure[m].photcode <= 10500)) {
    307             if (catalog[i].measure[m].psfQual > 0.85) {
    308               goodPS1 = TRUE;
    309               if (!isnan(catalog[i].measure[m].Map)) {
    310                 if (catalog[i].measure[m].M - catalog[i].measure[m].Map > 0.5) {
    311                   nEXT ++;
    312                 } else {
    313                   nPSF ++;
    314                 }
     383          Mcal  = getMcal  (m, Nc, flatcorr, catalog);
     384          if (isnan(Mcal))  SKIP_THIS_MEAS(Ncal);
     385          Mmos  = getMmos  (m, Nc);
     386          if (isnan(Mmos))  SKIP_THIS_MEAS(Nmos);
     387          Mgrid = getMgrid (m, Nc);
     388          if (isnan(Mgrid)) SKIP_THIS_MEAS(Ngrid);
     389        }
     390
     391        Msys = PhotSysTiny (&catalog[Nc].measureT[m], &catalog[Nc].averageT[j], &catalog[Nc].secfilt[j*Nsecfilt]);
     392        if (isnan(Msys)) SKIP_THIS_MEAS(Nsys);
     393
     394        list[N] = Msys - Mcal - Mmos - Mgrid;
     395
     396        int myUbercalDist = getUbercalDist(m,Nc);
     397        minUbercalDist = MIN(minUbercalDist, myUbercalDist);
     398
     399        if (isSetMrelFinal) {
     400          float Map = PhotAper (&catalog[Nc].measure[m]);
     401          aplist[N] = Map - Mcal - Mmos - Mgrid;
     402
     403          // special options for PS1 data
     404          if ((catalog[Nc].measure[m].photcode >= 10000) && (catalog[Nc].measure[m].photcode <= 10500)) {
     405            // count the extended detections
     406            if (!isnan(catalog[Nc].measure[m].Map)) {
     407              if (catalog[Nc].measure[m].M - catalog[Nc].measure[m].Map > 0.5) {
     408                Next ++;
     409                NextPS1 ++;
     410              } else {
     411                NpsfPS1 ++;
    315412              }
    316413            }
    317414          }
    318          
    319           // 2MASS data:
    320           if (catalog[i].measure[m].photcode == 2011) {
    321             if (catalog[i].measure[m].photFlags & 0x00c00000) {
     415          // count extended detections for 2MASS (XXX NOTE hardwired photcodes 2011, 2012, 2013)
     416          if ((catalog[Nc].measure[m].photcode >= 2011) && (catalog[Nc].measure[m].photcode <= 2013)) {
     417            if (catalog[Nc].measure[m].photFlags & 0x00c00000) {
     418              Next ++;
    322419              Galaxy2MASS = TRUE;
    323420            }
    324             if (catalog[i].measure[m].photFlags & 0x00000007) {
    325               good2MASS = TRUE;
     421            if (pass == 0) {
     422              if (catalog[Nc].measure[m].photFlags & 0x00000007) {
     423                Good2MASS = TRUE;
     424              } else {
     425                // detections without one of these bits should only be used in PASS_1
     426                SKIP_THIS_MEAS(Nbad);
     427                continue;
     428              }
    326429            }
    327           } 
    328         }
    329 
    330         // we attempt to set a few flags here; reset those bits before trying:
    331         catalog[i].average[j].flags &= ~flagBits;
    332 
    333         if (nEXT && (nEXT > nPSF)) {
    334           catalog[i].average[j].flags |= ID_OBJ_EXT;
    335         }
    336         if (goodPS1) {
    337           catalog[i].average[j].flags |= ID_OBJ_GOOD;
    338         }
    339         if (Galaxy2MASS) {
    340           catalog[i].average[j].flags |= ID_OBJ_EXT_ALT;
    341         }
    342         if (good2MASS) {
    343           catalog[i].average[j].flags |= ID_OBJ_GOOD_ALT;
    344         }
    345       }
    346     }
    347   }
    348 
    349   free (list);
    350   free (dlist);
     430          }
     431
     432          // Blindly accepth the SYNTH mags if we are above saturation, otherwise,
     433          // ignore SYNTH photcodes until PASS == 4 (where we also accept saturated stars)
     434          if ((catalog[Nc].measure[m].photcode >= 3001) && (catalog[Nc].measure[m].photcode <= 3005)) {
     435            // something of a hack: force object to use synth values if synth mags >>
     436            // saturation (3pi instrumental mags < -15)
     437            float MaxMagForceSynth = NAN;
     438            switch (catalog[Nc].measure[m].photcode) {
     439              case 3001:
     440                MaxMagForceSynth = 13.64;
     441                break;
     442              case 3002:
     443                MaxMagForceSynth = 13.76;
     444                break;
     445              case 3003:
     446                MaxMagForceSynth = 13.74;
     447                break;
     448              case 3004:
     449                MaxMagForceSynth = 12.94;
     450                break;
     451              case 3005:
     452                MaxMagForceSynth = 12.01;
     453                break;
     454            }
     455            if (catalog[Nc].measureT[m].M < MaxMagForceSynth) {
     456              forceSynth = TRUE;
     457              forceSynthEntry = N;
     458            } else {
     459              if (pass < 4) {
     460                SKIP_THIS_MEAS(Nbad);
     461                continue;
     462              }
     463              haveSynth = TRUE;
     464            }
     465          }
     466        }
     467
     468        // dlist gives the error per measurement, wlist gives the weight
     469        // we can modify the error and weight in a few ways:
     470        // 1) MIN_ERROR guarantees a floor
     471        // 2) photomErrSys is added in quadrature as a sytematic error, set per photcode
     472        // 3) UBERCAL measurements can have their weight increased by a big factor to help tie down the averages
     473        // 4) some reference photcode of some kind can be specified as fixed and have a high weight
     474        dlist[N] = MAX (hypot(catalog[Nc].measureT[m].dM, code->photomErrSys), MIN_ERROR);
     475        wlist[N] = 1.0;
     476
     477        // up-weight the ubercal values (or convergence can take a long time...)
     478        if (catalog[Nc].measureT[m].dbFlags & ID_MEAS_PHOTOM_UBERCAL) {
     479          wlist[N] = 10.0;
     480        }
     481
     482        // tie down reference photometry if the -refcode (code) option is selected
     483        // eg, -refcode g_SDSS
     484        // this probably makes no sense in the context of multifilter analysis
     485        if (refPhotcode) {
     486          if (code->code == refPhotcode->code) {
     487            wlist[N] = 100.0;
     488          }
     489        }
     490        N++;
     491      }
     492
     493      int Nminmeas = isSetMrelFinal ? 1 : STAR_TOOFEW + 1;
     494
     495      // when performing the grid analysis, STAR_TOOFEW should be set to 1;
     496      if (N < Nminmeas) { /* too few measurements */
     497        // fprintf (f, "%10.6f %10.6f %d %d %d\n", catalog[Nc].averageT[j].R, catalog[Nc].averageT[j].D, catalog[Nc].measureT[catalog[Nc].averageT[j].measureOffset].imageID, N, STAR_TOOFEW);
     498        catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_STAR_FEW;
     499        if (Ncode == 0) {
     500          results->Ncode ++;
     501        } else {
     502          results->Nfew ++;
     503        }
     504        continue;
     505      } else {
     506        catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags &= ~ID_STAR_FEW;
     507      }
     508
     509      if (forceSynth) {
     510        // use the single SYNTH value instead of the other mags here
     511        myAssert ((forceSynthEntry < N) && (forceSynthEntry >= 0), "programming error");
     512        list[0]  = list[forceSynthEntry];
     513        dlist[0] = dlist[forceSynthEntry];
     514        wlist[0] = wlist[forceSynthEntry];
     515        N = 1;
     516      }
     517      liststats (list, dlist, wlist, N, &stats);
     518
     519      catalog[Nc].secfilt[Nsecfilt*j+Nsec].M  = stats.mean;
     520      catalog[Nc].secfilt[Nsecfilt*j+Nsec].dM = stats.error;
     521      catalog[Nc].secfilt[Nsecfilt*j+Nsec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq + 1e-4) : NAN_S_SHORT;
     522
     523      // when running -averages, we have no information about the images, so we cannot set this
     524      if (minUbercalDist > -1) {
     525        catalog[Nc].secfilt[Nsecfilt*j+Nsec].ubercalDist = minUbercalDist;
     526      }
     527
     528      if (isSetMrelFinal) {
     529        catalog[Nc].found[Nsecfilt*j+Nsec] = TRUE;
     530
     531        catalog[Nc].secfilt[Nsecfilt*j+Nsec].Mstdev = 1000.0*stats.sigma; // Mstdev is in millimags (not enough space for more precision)
     532        catalog[Nc].secfilt[Nsecfilt*j+Nsec].Ncode = Ncode;
     533        catalog[Nc].secfilt[Nsecfilt*j+Nsec].Nused = stats.Nmeas;
     534
     535        catalog[Nc].secfilt[Nsecfilt*j+Nsec].M_80 = 1000 * stats.Upper80;
     536        catalog[Nc].secfilt[Nsecfilt*j+Nsec].M_20 = 1000 * stats.Lower20;
     537
     538        // NOTE : use the modified weight for apmags as well as psf mags
     539        liststats (aplist, daplist, wlist, N, &apstats);
     540
     541        catalog[Nc].secfilt[Nsecfilt*j+Nsec].Map  = apstats.mean;
     542
     543        // NOTE: for 2MASS measurements, Next should be 1, as should N
     544        if ((Next > 0) && (Next > 0.5*N)) {
     545          catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_OBJ_EXT;
     546        }
     547
     548        switch (pass) {
     549          case 0:
     550            catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_0;
     551            GoodPS1 = TRUE;
     552            break;
     553          case 1:
     554            catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_1;
     555            GoodPS1 = TRUE;
     556            break;
     557          case 2:
     558            catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_2;
     559            GoodPS1 = TRUE;
     560            break;
     561          case 3:
     562            catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_3;
     563            break;
     564          case 4:
     565            catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_PHOTOM_PASS_4;
     566            break;
     567        }
     568        if (haveSynth) {
     569          catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_USE_SYNTH;
     570        }       
     571        if (haveUbercal) {
     572          catalog[Nc].secfilt[Nsecfilt*j+Nsec].flags |= ID_SECF_USE_UBERCAL;
     573        }       
     574      }
     575    }
     576
     577    if (isSetMrelFinal) {
     578      DVOAverageFlags flagBits = ID_OBJ_EXT | ID_OBJ_EXT_ALT | ID_OBJ_GOOD | ID_OBJ_GOOD_ALT;
     579
     580      // we attempt to set a few flags here; reset those bits before trying:
     581      catalog[Nc].average[j].flags &= ~flagBits;
     582
     583      if (NextPS1 && (NextPS1 > NpsfPS1)) {
     584        catalog[Nc].average[j].flags |= ID_OBJ_EXT;
     585      }
     586      if (GoodPS1) {
     587        catalog[Nc].average[j].flags |= ID_OBJ_GOOD;
     588      }
     589      if (Galaxy2MASS) {
     590        catalog[Nc].average[j].flags |= ID_OBJ_EXT_ALT;
     591      }
     592      if (Good2MASS) {
     593        catalog[Nc].average[j].flags |= ID_OBJ_GOOD_ALT;
     594      }
     595    }
     596  }
    351597  return (TRUE);
    352598}
    353599
     600int print_measure_set (Average *average, SecFilt *secfilt, Measure *measure) {
     601
     602  off_t k;
     603
     604  int Nsecfilt = GetPhotcodeNsecfilt ();
     605
     606  off_t m = average[0].measureOffset;
     607
     608  for (k = 0; k < average[0].Nmeasure; k++, m++) {
     609    fprintf (stderr, "meas: %08x\n", measure[m].dbFlags);
     610  }
     611
     612  int Ns;
     613  for (Ns = 0; Ns < Nsecfilt; Ns++) {
     614    fprintf (stderr, "secf: %08x\n", secfilt[Ns].flags);
     615  }
     616  return 1;
     617}
     618
    354619/* set measure.Mcal for all measures except ID_MEAS_NOCAL and ID_IMAGE_PHOTOM_NOCAL */
    355 int setMcalOutput (Catalog *catalog, int Ncatalog) {
     620int setMcalOutput (Catalog *catalog, int Ncatalog, FlatCorrectionTable *flatcorr) {
    356621
    357622  int i;
     
    368633      for (k = 0; k < catalog[i].averageT[j].Nmeasure; k++, m++) {
    369634        if (catalog[i].measureT[m].dbFlags & MEAS_BAD) continue;
    370         Mcal  = getMcal  (m, i);
     635        Mcal  = getMcal  (m, i, flatcorr, catalog);
    371636        if (isnan(Mcal)) continue;
    372637        Mmos  = getMmos  (m, i);
     
    375640        if (isnan(Mgrid)) continue;
    376641
     642        // note that measurements for which the image is not selected will not be modified
     643        // (that is a good thing! -- we keep a prior calibration)
     644
    377645        // set the output calibration
    378646        catalog[i].measure[m].Mcal = Mcal + Mmos + Mgrid;
     647
     648        if (catalog[i].measureT[m].dbFlags & ID_MEAS_PHOTOM_UBERCAL) {
     649          myAssert (isfinite(catalog[i].measure[m].Mcal), "oops, broke an ubercal mag");
     650        }
    379651      }
    380652    }
     
    385657void clean_stars (Catalog *catalog, int Ncatalog) {
    386658
    387   int i, j, Ndel, Nave, Ntot, mark, Ns;
     659  int i, j, Ndel, Nave, Ntot, mark, Ns, Nscat, Nchi, Nnan;
    388660  float dM, Xm;
    389661  double Chisq, MaxScatter, MaxChisq;
    390662  double *xlist, *slist, *dlist;
     663
    391664  StatType stats;
     665  liststats_setmode (&stats, "MEAN");
    392666
    393667  if (VERBOSE) fprintf (stderr, "marking poor stars\n");
     
    404678
    405679  // eliminate bad stars using the stats for a single secfilt at a time
    406   // XXX DEP replace average.flags with secfilt flags
    407680  for (Ns = 0; Ns < Nphotcodes; Ns ++) {
    408681   
     
    423696    }
    424697 
    425     initstats ("MEAN");
    426     liststats (xlist, dlist, Ntot, &stats);
     698    liststats (xlist, dlist, NULL, Ntot, &stats);
    427699    MaxChisq = MAX (STAR_CHISQ, 2*stats.median);
    428     liststats (slist, dlist, Ntot, &stats);
     700
     701    liststats (slist, dlist, NULL, Ntot, &stats);
    429702    MaxScatter = MAX (STAR_SCATTER, 2*stats.median);
    430703    fprintf (stderr, "Max Scatter: %f, Max Chisq: %f\n", MaxScatter, MaxChisq);
    431704
    432     Ndel = Nave = 0;
     705    Ndel = Nave = Nscat = Nnan = Nchi = 0;
    433706    for (i = 0; i < Ncatalog; i++) {
    434707      for (j = 0; j < catalog[i].Naverage; j++) {
     
    440713          catalog[i].secfilt[Nsecfilt*j+Nsec].flags |= ID_STAR_POOR;
    441714          Ndel ++;
     715          if (dM > MaxScatter) { Nscat ++; }
     716          if (Xm == NAN_S_SHORT) { Nnan ++; }
     717          if (Chisq > MaxChisq) { Nchi ++; }
    442718        } else {
    443719          catalog[i].secfilt[Nsecfilt*j+Nsec].flags &= ~ID_STAR_POOR;
     
    446722      }
    447723    }
    448     fprintf (stderr, "%d stars marked variable, %d total\n", Ndel, Nave);
    449     initstats (STATMODE);
     724    fprintf (stderr, "%d stars marked variable (%d scat, %d nan, %d chi), %d total\n", Ndel, Nscat, Nnan, Nchi, Nave);
    450725  }
    451726  free (xlist);
     
    454729}
    455730
     731// clean_measures examines the stats for a single star.  It measures the INNER 50% mean
     732// and sigma, it then re-measures the mean and sigma using all stars with NSIGMA_CLIP (3)
     733// sigma of the INNER 50% mean.  it then flags any measurements which are more than
     734// NSIGMA_REJECT (5) sigma of the mean
     735
    456736# define NSIGMA_CLIP 3.0
    457737# define NSIGMA_REJECT 5.0
    458 void clean_measures (Catalog *catalog, int Ncatalog, int final) {
     738void clean_measures (Catalog *catalog, int Ncatalog, int final, FlatCorrectionTable *flatcorr) {
    459739
    460740  off_t j, k, m, Nmax, Ndel, Nave;
     
    463743  double *tlist, *list, *dlist;
    464744  float Msys, Mcal, Mmos, Mgrid;
    465   StatType stats;
    466745  int Ncal, Nmos, Ngrid, Nfew;
    467746
     
    484763  TOOFEW = MAX (5, STAR_TOOFEW);
    485764
     765  // stats structures for inner and full stats
     766  StatType instats, stats;
     767  liststats_setmode (&instats, "INNER_MEAN");
     768  liststats_setmode (&stats, "MEAN");
     769
    486770  Ndel = Nave = 0;
    487771  Ncal = Nmos = Ngrid = Nfew = 0;
     
    492776      for (Ns = 0; Ns < Nphotcodes; Ns++) {
    493777       
    494         /* on final processing, skip stars already measured */
    495         if (final && catalog[i].found[j]) continue; 
    496 
    497778        int thisCode = photcodes[Ns][0].code;
    498779        int Nsec = GetPhotcodeNsec(thisCode);
    499780       
     781        /* on final processing, skip stars already measured */
     782        if (final && catalog[i].found[Nsecfilt*j + Nsec]) continue; 
     783
    500784        /* skip bad stars to prevent them from becoming good (on inner sample) */
    501785        if (catalog[i].secfilt[Nsecfilt*j+Nsec].flags & STAR_BAD) continue; 
     
    509793          if (ecode != thisCode) { continue; }
    510794
    511           /* if (catalog[i].measureT[m].dbFlags & MEAS_BAD) continue; */
    512           Mcal  = getMcal  (m, i);
     795          // NOTE: we do not skip MEAS_BAD because this measurement is just an internal assessment of the outliers
     796          Mcal  = getMcal  (m, i, flatcorr, catalog);
    513797          if (isnan(Mcal)) { Ncal ++; continue; }
    514798          Mmos  = getMmos  (m, i);
     
    522806          N++;
    523807        }
    524         if (N <= TOOFEW) { Nfew ++; continue; }
     808        if (N <= TOOFEW) {
     809          Nfew ++;
     810          continue;
     811        }
    525812
    526813        /* 3-sigma clip based on stats of inner 50% */
    527814
    528815        // calculated mean of inner 50%
    529         initstats ("INNER_MEAN");
    530         liststats (list, dlist, N, &stats);
    531         stats.sigma = MAX (MIN_ERROR, stats.sigma); /* if measurements agree too well, sigma -> 0.0 */
     816        liststats (list, dlist, NULL, N, &instats);
     817        instats.sigma = MAX (MIN_ERROR, instats.sigma); /* if measurements agree too well, sigma -> 0.0 */
    532818
    533819        // ignore entries > 3sigma from inner mean
    534820        for (k = m = 0; k < N; k++) {
    535           if (fabs (list[k] - stats.median) < NSIGMA_CLIP*stats.sigma) {
     821          if (fabs (list[k] - instats.median) < NSIGMA_CLIP*instats.sigma) {
    536822            list[m] = list[k];
    537823            m++;
     
    539825        }
    540826        // recalculate the mean & sigma of the accepted measurements
    541         initstats ("MEAN");
    542         liststats (list, dlist, m, &stats);
     827        liststats (list, dlist, NULL, m, &stats);
    543828        stats.sigma = MAX (MIN_ERROR, stats.sigma);
    544829
     
    553838          if (ecode != thisCode) { continue; }
    554839
    555           /* if (catalog[i].measureT[m].dbFlags & MEAS_BAD) continue; */
    556           Mcal  = getMcal  (m, i);
     840          // NOTE: we do not skip MEAS_BAD because this measurement is just an internal assessment of the outliers
     841          Mcal  = getMcal  (m, i, flatcorr, catalog);
    557842          if (isnan(Mcal)) continue;
    558843          Mmos  = getMmos  (m, i);
     
    572857        /* mark bad measures (> 3 sigma deviant) */
    573858        for (k = 0; k < N; k++) {
    574           if (fabs (list[k] - stats.median) > NSIGMA_REJECT*stats.sigma) {
     859          // treat the scatter of the star as a systematic term.  this is a bit of an
     860          // over-estimage (a perfect Gauss distribution with perfect errors would have
     861          // mySigma = sqrt(2) too large)
     862          float mySigma = hypot (stats.sigma, dlist[k]);
     863          if (fabs (list[k] - stats.median) > NSIGMA_REJECT*mySigma) {
    575864            catalog[i].measureT[ilist[k]].dbFlags |= ID_MEAS_POOR_PHOTOM;
    576865            if (final) {
     
    585874    }
    586875  }
    587   initstats (STATMODE);
    588876  if (VERBOSE) fprintf (stderr, OFF_T_FMT" measures marked poor, "OFF_T_FMT" total\n", Ndel, Nave);
     877
    589878  free (list);
    590879  free (dlist);
     
    593882}
    594883
    595 StatType statsStarN (Catalog *catalog, int Ncatalog, int Nsec, int seccode) {
     884StatType statsStarN (Catalog *catalog, int Ncatalog, int Nsec, int seccode, FlatCorrectionTable *flatcorr) {
    596885
    597886  off_t j, k, m, Ntot;
     
    625914        int ecode = GetPhotcodeEquivCodebyCode (catalog[i].measureT[m].photcode);
    626915        if (ecode != seccode) { continue;}
    627         Mcal = getMcal  (m, i);
     916        Mcal = getMcal  (m, i, flatcorr, catalog);
    628917        if (isnan(Mcal)) { continue;}
    629918        Mmos = getMmos  (m, i);
     
    640929  }
    641930
    642   // fprintf (stderr, "N1: %d, N2: %d, N3: %d, N4: %d, N0: %d\n", N1, N2, N3, N4, N0);
    643   liststats (list, dlist, n, &stats);
     931  liststats_setmode (&stats, "MEAN");
     932
     933  liststats (list, dlist, NULL, n, &stats);
    644934  free (list);
    645935  free (dlist);
     
    680970  }
    681971
    682   liststats (list, dlist, n, &stats);
     972  liststats_setmode (&stats, "MEAN");
     973
     974  liststats (list, dlist, NULL, n, &stats);
    683975  free (list);
    684976  free (dlist);
     
    7121004
    7131005      dM = catalog[i].secfilt[Nsecfilt*j+Nsec].dM;
     1006      if (isnan(dM)) continue;
    7141007      list[n] = dM;
    7151008      dlist[n] = 1;
     
    7181011  }
    7191012
    720   liststats (list, dlist, n, &stats);
     1013  liststats_setmode (&stats, "MEAN");
     1014
     1015  liststats (list, dlist, NULL, n, &stats);
    7211016  free (list);
    7221017  free (dlist);
Note: See TracChangeset for help on using the changeset viewer.