IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 41453 for trunk


Ignore:
Timestamp:
Dec 7, 2020, 12:27:41 PM (6 years ago)
Author:
eugene
Message:

working on adapting IRLS fitting with Priors for zero points

Location:
trunk/Ohana/src/relphot
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/relphot/Makefile

    r41390 r41453  
    2121
    2222test_liststats: $(BIN)/test_liststats.$(ARCH)
     23
     24test_fitirls: $(BIN)/test_fitirls.$(ARCH)
    2325
    2426install: $(DESTBIN)/relphot $(DESTBIN)/relphot_client
     
    4850$(SRC)/global_stats.$(ARCH).o    \
    4951$(SRC)/initialize.$(ARCH).o      \
     52$(SRC)/fit1d_irls.$(ARCH).o      \
    5053$(SRC)/liststats.$(ARCH).o       \
    5154$(SRC)/load_catalogs.$(ARCH).o   \
     
    107110$(SRC)/synthetic_mags.$(ARCH).o  \
    108111$(SRC)/plotstuff.$(ARCH).o       \
     112$(SRC)/fit1d_irls.$(ARCH).o      \
    109113$(SRC)/liststats.$(ARCH).o       \
    110114$(SRC)/initialize.$(ARCH).o      \
     
    137141$(BIN)/test_liststats.$(ARCH): $(TEST_LISTSTATS)
    138142
     143TEST_FITIRLS = \
     144$(SRC)/fit1d_irls.$(ARCH).o      \
     145$(SRC)/test_fitirls.$(ARCH).o
     146
     147$(TEST_FITIRLS): $(INC)/relphot.h
     148$(BIN)/test_fitirls.$(ARCH): $(TEST_FITIRLS)
     149
  • trunk/Ohana/src/relphot/include/relphot.h

    r41428 r41453  
    9191
    9292typedef struct {
    93   unsigned int start;
    94   unsigned int stop;
    9593  short photcode;
    9694  float McalPSF;
     
    110108  off_t NMEASURE;
    111109  off_t *measure;
    112 
    113   off_t Ncatalog; // XX not needed
    114   off_t NCATALOG; // XX not needed
    115110  off_t *catalog;
     111
     112  void *parent;
    116113} TGroup;
     114
     115// we have an array of TGroup times, each pointing to N sets of data values
     116typedef struct {
     117  unsigned int start;
     118  unsigned int stop;
     119  TGroup *byCode; // each of these contains the collection of images for the time and photcode
     120  int      nCode;
     121} TGTimes;
    117122
    118123typedef enum {
     
    163168
    164169} StatDataSet;
     170
     171typedef struct {
     172  double *xVector;            // complete list of values in independent variable (optional)
     173  double *yVector;            // complete list of values available
     174  double *dyVector;           // complete list of errors available
     175} FitDataType;
     176 
     177// this structure carries the data and pre-allocated arrays for
     178// 1D fitting with arbitrary order for data with external weights,
     179// optional priors, irls iterations, and bootstrap resampling
     180typedef struct {
     181  int     order;              // order of fit (e.g., y = C0 + C1*x has order = 1)
     182  int     nterm;              // number of fitted parameters (order + 1)
     183  int     mterm;              // number of summations needed for OLS (2*order + 1)
     184
     185  int     Nlist;              // total number of measurements in list (may be more than the number to use)
     186  int     Nbootstrap;         // number of bootstrap iterations
     187
     188  // input data & parameters:
     189  FitDataType *alldata;       // full data set
     190
     191  double *bPriorValue;        // prior value
     192  double *bPriorSigma;        // prior sigma
     193
     194  // internal / temporary arrays:
     195  FitDataType *keepdata;      // unclipped data for bootstrap analysis
     196  FitDataType *sample;        // sample for a bootstrap iteration
     197
     198  double *yOffVector;         // difference between yFit and yObs
     199
     200  double *tmpVector;          // internal copy of values to use in, e.g., calculation of median
     201  double *wtIRLS;             // IRLS weights (distance from model value weighted by standard error)
     202
     203  double **cArray;
     204  double  *sumVector;         // pre-allocated to mterm (2*order + 1)
     205
     206  double **bArray;
     207  double **bSaveArray;
     208  double **bBootArray;        // values generated by the bootstrap resampling
     209
     210  // output results:
     211  double *bSigma;             // 1 sigma range of parameters
     212
     213  double  min;                // min of bSigma[0] values
     214  double  max;                // max of bSigma[0] values
     215  double  sigma;              // (sample) standard deviation of bSigma[0] values
     216  double  chisq;              // chisq of fit (unmasked values only)
     217  int     Nmeas;              // number of unmasked values used in fit
     218} FitDataSet;
    165219
    166220typedef struct {
     
    311365double IMAGE_SCATTER;
    312366double IMAGE_OFFSET;
     367double NIGHT_SCATTER;
     368double NIGHT_OFFSET;
    313369double STAR_SCATTER;
    314370double STAR_CHISQ;
     
    497553int           liststats_irls      PROTO((StatDataSet *dataset, int Npoints, StatType *stats));
    498554int           liststats_fit1d     PROTO((double *value, double *err, double *x, int Npts, StatType *stats, double *dk));
     555double        weight_cauchy       PROTO((double x));
     556double        VectorFractionInterpolate PROTO((double *values, float fraction, int Npoints));
     557
     558// fit1d_irls:
     559int           fit1d_irls          PROTO((FitDataSet *dataset, int Npoints));
     560void          FitDataSetFree      PROTO((FitDataSet *dataset));
     561void          FitDataSetAlloc     PROTO((FitDataSet *dataset, int Nmax, int order, int Nbootstrap));
     562void          FitDataSetAddPriors PROTO((FitDataSet *dataset));
    499563
    500564unsigned int *ReadTGroupFile      PROTO((FILE *f, int *nelem));
     
    502566void          initTGroupsMcal     PROTO((void));
    503567TGroup       *getTGroupForImage   PROTO((off_t im));
    504 off_t         findTGroup          PROTO((unsigned int start, int photcode));
     568TGroup       *findTGroup          PROTO((unsigned int start, int photcode));
    505569
    506570Catalog      *load_catalogs       PROTO((SkyList *skylist, int *Ncatalog, int hostID, char *hostpath, char *syncfile));
     
    527591void          plot_star_coords    PROTO((Catalog *catalog, int Ncatalog));
    528592void          plot_stars          PROTO((Catalog *catalog, int Ncatalog));
     593void          plot_setMcal        PROTO((double *list, int Npts));
    529594
    530595void          plot_list_add       PROTO((Graphdata *graphdata, double *xlist, double *ylist, int N));
  • trunk/Ohana/src/relphot/src/ConfigInit.c

    r39478 r41453  
    11# include "relphot.h"
     2
     3// do not use with %s
     4# define DefConfig(NAME, FMT, DEF, VAR) {                               \
     5  char *status = ScanConfig (config, NAME, FMT, 0, &VAR);               \
     6  if (status == NULL) { VAR = DEF; }                                    \
     7  }
    28
    39void ConfigInit (int *argc, char **argv) {
     
    2026  GetConfig (config, "SIGMA_LIM",              "%lf", 0, &SIGMA_LIM);
    2127
    22   if (!ScanConfig (config, "RELPHOT_IMFIT_SYS_SIGMA_LIM", "%lf", 0, &IMFIT_SYS_SIGMA_LIM)) IMFIT_SYS_SIGMA_LIM = 0.01;
    2328
    2429  GetConfig (config, "STAR_SCATTER",           "%lf", 0, &STAR_SCATTER);
     30
    2531  GetConfig (config, "IMAGE_SCATTER",          "%lf", 0, &IMAGE_SCATTER);
    2632  GetConfig (config, "IMAGE_OFFSET",           "%lf", 0, &IMAGE_OFFSET);
     
    4753  snprintf (ImageCat, DVO_MAX_PATH, "%s/Images.dat", CATDIR);
    4854
    49   if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
    50     SKY_DEPTH = 2;
    51   }
     55  DefConfig ("RELPHOT_IMFIT_SYS_SIGMA_LIM", "%lf", 0.01, IMFIT_SYS_SIGMA_LIM);
     56  DefConfig ("NIGHT_SCATTER",               "%lf", 0.05, NIGHT_SCATTER);
     57  DefConfig ("NIGHT_OFFSET",                "%lf", 0.50, NIGHT_OFFSET);
     58  DefConfig ("SKY_DEPTH",                   "%d",     2, SKY_DEPTH);
     59
    5260  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
    5361    SKY_TABLE[0] = 0;
     
    9098  return;
    9199}
     100
  • trunk/Ohana/src/relphot/src/ImageOps.c

    r41428 r41453  
    11# include "relphot.h"
    22# define BASIC_STATS 0
    3 
    4 void plot_setMcal (double *list, int Npts, StatType *stats, float clouds);
    53
    64// the MeasureToImage, ImageToCatalog, and ImageToMeasure arrays are a substantial part of the memory footprint.
     
    588586  int mark, bad, Nfew, Nbad, Nmos, Ngrp, Nrel, Ngrid, Nsys;
    589587
    590   StatType stats;
    591   liststats_setmode (&stats, "INNER_WTMEAN");
    592 
    593588  // FREEZE_IMAGES only applies to mosaic data (eg, gpc1)
    594589
     
    608603  }
    609604
    610   StatDataSet *kronStars   = StatDataSetAlloc (1, Nmax);
    611   StatDataSet *psfStars    = StatDataSetAlloc (1, Nmax);
    612   StatDataSet *brightStars = StatDataSetAlloc (1, Nmax);
     605  // we are making a 0-order fit and not doing bootstrap analysis:
     606  FitDataSet psfStars, kronStars, brightStars;
     607  FitDataSetAlloc (&psfStars,    Nmax, 0, 0);
     608  FitDataSetAlloc (&kronStars,   Nmax, 0, 0);
     609  FitDataSetAlloc (&brightStars, Nmax, 0, 0);
    613610
    614611  Nfew = Nbad = Nmos = Ngrp = Ngrid = Nrel = Nsys = 0;
     
    713710
    714711    skip:
    715       psfStars->flxlist[Nref] = MsysPSF - MrelPSF - Mmos - Mgrp - Mgrid + Mflat;
    716       psfStars->errlist[Nref] = MAX (catalog[c].measureT[m].dM, MIN_ERROR);
    717       psfStars->wgtlist[Nref] = 1;
    718       psfStars->msklist[Nref] = 0;
    719       if (fabs(psfStars->flxlist[Nref]) > 0.03) {
    720         // fprintf (stderr, "deviant\n");
    721       }
     712      psfStars.alldata-> yVector[Nref] = MsysPSF - MrelPSF - Mmos - Mgrp - Mgrid + Mflat;
     713      psfStars.alldata->dyVector[Nref] = MAX (catalog[c].measureT[m].dM, MIN_ERROR);
    722714
    723715      float MrelKron = getMrel  (catalog, m, c, MAG_CLASS_KRON, MAG_SRC_CHP);
     
    725717
    726718      if (isfinite(MrelKron) && isfinite(MsysKron)) {
    727         kronStars->flxlist[Nkron] = MsysKron - MrelKron - Mmos - Mgrp - Mgrid + Mflat;
    728         kronStars->errlist[Nkron] = MAX (catalog[c].measureT[m].dM, MIN_ERROR);
    729         kronStars->wgtlist[Nkron] = 1;
    730         kronStars->msklist[Nkron] = 0;
     719        kronStars.alldata-> yVector[Nkron] = MsysKron - MrelKron - Mmos - Mgrp - Mgrid + Mflat;
     720        kronStars.alldata->dyVector[Nkron] = psfStars.alldata->dyVector[Nref];
    731721        Nkron ++;
    732722      }
    733723
    734724      if ((image[i].imageID == TEST_IMAGE1) || (image[i].imageID == TEST_IMAGE2)) {
    735         fprintf (stderr, "%1d, %3d : %3d, %3d : %10.6f %10.6f : %6.3f  %6.3f  %6.3f  %6.3f  %6.3f : %6.3f\n", (int) i, (int) j, (int) c, (int) m, catalog[c].averageT[n].R, catalog[c].averageT[n].D, MsysKron, MrelKron, Mmos, Mgrid, Mflat, kronStars->flxlist[Nref]);
     725        fprintf (stderr, "%1d, %3d : %3d, %3d : %10.6f %10.6f : %6.3f  %6.3f  %6.3f  %6.3f  %6.3f : %6.3f\n", (int) i, (int) j, (int) c, (int) m, catalog[c].averageT[n].R, catalog[c].averageT[n].D, MsysKron, MrelKron, Mmos, Mgrid, Mflat, kronStars.alldata->yVector[Nkron]);
    736726      }
    737727
    738728      if (catalog[c].measureT[m].dM < IMFIT_SYS_SIGMA_LIM) {
    739         brightStars->flxlist[Nbright] = psfStars->flxlist[Nref];
    740         brightStars->errlist[Nbright] = psfStars->errlist[Nref];
    741         brightStars->wgtlist[Nbright] = 1;
    742         brightStars->msklist[Nbright] = 0;
     729        brightStars.alldata-> yVector[Nbright] = psfStars.alldata-> yVector[Nref];
     730        brightStars.alldata->dyVector[Nbright] = psfStars.alldata->dyVector[Nref];
    743731        Nbright ++;
    744732      }
     
    762750
    763751    // no additional weight modification (we treat all stars on an image equally -- note an image is either ubercal-tied or not)
    764 # if (BASIC_STATS)
    765     liststats (psfStars->flxlist, psfStars->errlist, NULL, Nref, &stats);
    766 # else
    767     liststats_irls (psfStars, Nref, &stats);
    768 # endif
    769     image[i].McalPSF    = stats.mean;
    770     image[i].dMcal      = stats.error;
    771     image[i].nFitPhotom = Nref;
    772     image[i].McalChiSq  = stats.chisq;
     752    fit1d_irls (&psfStars, Nref);
     753    image[i].McalPSF    = psfStars.bSaveArray[0][0];
     754    image[i].dMcal      = psfStars.bSigma[0];
     755    image[i].nFitPhotom = psfStars.Nmeas;
     756    image[i].McalChiSq  = psfStars.chisq;
    773757    Ncalibrated ++;
    774758
    775759    // no additional weight modification (we treat all stars on an image equally -- note an image is either ubercal-tied or not)
    776 # if (BASIC_STATS)
    777     liststats (kronStars->flxlist, kronStars->errlist, NULL, Nkron, &stats);
    778 # else
    779     liststats_irls (kronStars, Nref, &stats);
    780 # endif
    781     image[i].McalAPER   = stats.mean;
    782 
    783     if ((image[i].imageID == TEST_IMAGE1) || (image[i].imageID == TEST_IMAGE2)) {
    784       for (j = 0; j < Nref; j++) {
    785         fprintf (stderr, "%1d, %8d : %6.3f  %6.3f  %6.3f  %d\n", (int) i, (int) image[i].imageID, kronStars->flxlist[j], kronStars->errlist[j], kronStars->wgtlist[j], kronStars->msklist[j]);
    786       }
    787     }
     760    // XXX: apply airmass from above and fit only zp?
     761    fit1d_irls (&kronStars, Nkron);
     762    image[i].McalAPER   = kronStars.bSaveArray[0][0];
    788763
    789764    if ((image[i].imageID == TEST_IMAGE1) || (image[i].imageID == TEST_IMAGE2)) {
     
    791766    }
    792767
    793     if (!mark && VERBOSE_IMAGE) {
    794       fprintf (stderr, "Mcal for : %s : %7.4f %7.4f\n", image[i].name, image[i].McalAPER, image[i].dMcal);
    795     }
    796 
    797768    if (PLOTSTUFF) {
    798769      fprintf (stderr, "Mcal for : %s : %7.4f %7.4f\n", image[i].name, image[i].McalAPER, image[i].dMcal);
    799       plot_setMcal (psfStars->flxlist, Nref, &stats, CLOUD_TOLERANCE);
     770      plot_setMcal (psfStars.alldata-> yVector, Nref);
    800771    }
    801772
    802773    // bright end scatter
    803     liststats (brightStars->flxlist, brightStars->errlist, NULL, Nbright, &stats);
    804     image[i].dMagSys = stats.sigma;
     774    // fit1d_irls (&brightStars, Nbright);
     775    // image[i].dMagSys = brightStars.sigma;
    805776
    806777    if (image[i].McalPSF < -CLOUD_TOLERANCE) {
     
    812783    image[i].ubercalDist = minUbercalDist + 1;
    813784  }
    814 
    815   StatDataSetFree (brightStars, 1);
    816   StatDataSetFree (kronStars, 1);
    817   StatDataSetFree (psfStars, 1);
    818785
    819786  fprintf (stderr, "%d images calibrated\n", Ncalibrated);
     
    825792    MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR_PHOTOM | ID_MEAS_SKIP_PHOTOM | ID_MEAS_AREA;
    826793  }
     794
     795  FitDataSetFree (&brightStars);
     796  FitDataSetFree (&kronStars);
     797  FitDataSetFree (&psfStars);
     798
    827799  return;
    828800}
     
    891863
    892864static int setMcal_init_done = FALSE;
    893 void plot_setMcal (double *list, int Npts, StatType *stats, float clouds) {
    894   OHANA_UNUSED_PARAM(stats);
    895   OHANA_UNUSED_PARAM(clouds);
     865void plot_setMcal (double *list, int Npts) {
    896866
    897867  off_t i;
  • trunk/Ohana/src/relphot/src/MosaicOps.c

    r41428 r41453  
    11# include "relphot.h"
    2 void plot_setMcal (double *list, int Npts, StatType *stats, float clouds);
    32off_t findMosaic (unsigned int *startTimes, off_t Nmosaic, unsigned int start);
    43
     
    12811280  if (PLOTSTUFF) {
    12821281    fprintf (stderr, "Mmos: %6.3f %6.3f +/- %6.3f %5d %5d | %s\n", stats.mean, stats.median, stats.sigma, stats.Nmeas, N, image[MosaicToImage[Nmos][0]].name);
    1283     plot_setMcal (psfMagList, N, &stats, CLOUD_TOLERANCE);
     1282    plot_setMcal (psfMagList, N);
    12841283  }
    12851284
  • trunk/Ohana/src/relphot/src/StarOps.c

    r41390 r41453  
    228228
    229229void SetMrelInfoFree (SetMrelInfo *results) {
     230
    230231  StatDataSetFree (results->psfData,  results->Nsecfilt);
    231232  StatDataSetFree (results->aperData, results->Nsecfilt);
    232233  StatDataSetFree (results->kronData, results->Nsecfilt);
     234
    233235  FREE (results->psfqf_list);
    234236  FREE (results->psfqfperf_list);
  • trunk/Ohana/src/relphot/src/TGroupOps.c

    r41404 r41453  
    11# include "relphot.h"
    22
    3 // XXX is this needed?
    4 void plot_setMcal (double *list, int Npts, StatType *stats, float clouds);
    5 
    6 // see discussion in ImagesOps.c re: IDX_T
    7 
    8 // array of tgroup definition structures
    9 static off_t  Ntgroup;
    10 static TGroup *tgroup;
    11 
    12 // tgroup index for given image : ImageToTGroup[ImageIndex] = TGroupIndex (ImageIndex : 0 < Nimage)
    13 static off_t   *ImageToTGroup;
     3// tgroupTimes carries the times of the tgroups (initially, just the photometric nights)
     4static     int  NtgroupTimes = 0;
     5static TGTimes **tgroupTimes = NULL;
     6
     7// TGroup pointers for each image
     8static TGroup **ImageToTGroup = NULL;
    149
    1510// elsewhere, we have loaded a set of catalogs with measures (catalog[cat].measure[meas])
    1611
    17 // each tgroup has N_onTGroup[TGroupIndex] measurements
    18 // static off_t    *N_onTGroup;   // actual number of measurements on tgroup     
    19 // static off_t    *N_ONTGROUP;   // allocated number of measurements on tgroup   
    20 
    21 // relationships between the measure,catalog set and the tgroups:
    22 static off_t   **MeasureToTGroup; // TGroup index from measure,catalog   : MeasureToTGroup[cat][meas] = TGroupIndex
    23 // static off_t   **TGroupToCatalog; // catalog for given measure on tgroup : TGroupCatalog[TGroupIndex][i] = cat (i : 0 < NonTGroup[TGroupIndex])
    24 // static off_t   **TGroupToMeasure; // measure for given measure on tgroup : TGroupMeasure[TGroupIndex][i] = cat (i : 0 < NonTGroup[TGroupIndex])
    25 
    26 // tgroupTimes carries the times of the photometric nights
    27 static          int NtgroupTimes;
    28 static unsigned int *tgroupTimes;
     12// TGroup pointers for each measure,catalog set
     13static TGroup  ***MeasureToTGroup = NULL;
    2914
    3015void sort_times (unsigned int *T, int N);
    3116
    32 /* find tgroups (unique time periods) (NOTE : we do NOT require matching photcodes...)
    33    we need to have a tgroup for each photcode available for a given photometric night
    34  */
     17void sort_tgtimes (TGTimes **T, int N) {
     18
     19# define SWAPFUNC(A,B){ TGTimes *tmp;           \
     20    tmp = T[A]; T[A] = T[B]; T[B] = tmp;        \
     21  }
     22# define COMPARE(A,B)(T[A][0].start < T[B][0].start)
     23
     24  OHANA_SORT (N, COMPARE, SWAPFUNC);
     25
     26# undef SWAPFUNC
     27# undef COMPARE
     28
     29}
    3530
    3631// load the photometric nights from a file : these will be used to define the tgroups
    37 // XXX call this in args.c where TGROUP_ZEROPT is set
    38 // XXX cannot call this in args.c : the Nphotcodes have not yet been loaded.
     32// this is called in args.c after TGROUP_ZEROPT is set
    3933void loadTGroups (char *filename) {
    4034
     
    4741    exit (4);
    4842  }
    49   tgroupTimes = ReadTGroupFile (f, &NtgroupTimes);
    50   if (!tgroupTimes) {
     43  // ReadTGroupFile returns a list of the time values (int)
     44  unsigned int *tgroupTimesRaw = ReadTGroupFile (f, &NtgroupTimes);
     45  if (!tgroupTimesRaw) {
    5146    fprintf (stderr, "error reading tgroup file %s\n", filename);
    5247    exit (4);
    5348  }
     49  fprintf (stderr, "loaded %d tgroups from file %s\n", NtgroupTimes, filename);
    5450
    5551  // sort the times for quick bisection
    56   sort_times (tgroupTimes, NtgroupTimes);
    57 
    58   // we define a tgroup for each photcode being considered
    59   // below, if there are no images in this tgroup with a given
    60   // photcode, it is left empty (no images)
    61   Ntgroup = NtgroupTimes*Nphotcodes;
    62 
    63   ALLOCATE (tgroup, TGroup, Ntgroup);
     52  sort_times (tgroupTimesRaw, NtgroupTimes);
     53
     54  // we first define the collection of times (TGTimes) then for each time, we define a tgroup for
     55  // each photcode being considered below, if there are no images in this tgroup with a
     56  // given photcode, it is left empty (no images)
     57
     58  ALLOCATE (tgroupTimes, TGTimes *, NtgroupTimes);
    6459
    6560  // the start of an MJD day is 14:00 HST, so the end time can be the start time + 23h 59m 59s (86399s)
     
    6762
    6863  for (int i = 0; i < NtgroupTimes; i++) {
     64    ALLOCATE (tgroupTimes[i], TGTimes, 1);
     65    tgroupTimes[i][0].start = tgroupTimesRaw[i];
     66    tgroupTimes[i][0].stop  = tgroupTimesRaw[i] + 86399;
     67
     68    ALLOCATE (tgroupTimes[i][0].byCode, TGroup, Nphotcodes);
     69    tgroupTimes[i][0].nCode = Nphotcodes;
     70    TGroup *tgroup = tgroupTimes[i][0].byCode;
     71
    6972    for (int j = 0; j < Nphotcodes; j++) {
    70       /* a new tgroup, define ranges */
    71       int Nt = i*Nphotcodes + j;
    72       tgroup[Nt].start     = tgroupTimes[i];
    73       tgroup[Nt].stop      = tgroupTimes[i] + 86399;
    74       tgroup[Nt].McalPSF   = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
    75       tgroup[Nt].McalAPER  = 0.0; // note : tgroup stores only offsets relative to the original image values
    76       tgroup[Nt].dKlam     = 0.0;
    77       tgroup[Nt].dMcal     = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
    78       tgroup[Nt].dMsys     = 0.0;
    79       tgroup[Nt].McalChiSq = 0.0; // NAN or 0.0?
    80       tgroup[Nt].flags     = 0;
    81       tgroup[Nt].photcode  = photcodes[j][0].code;
     73      tgroup[j].parent    = (void *) tgroupTimes[i];
     74      tgroup[j].McalPSF   = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     75      tgroup[j].McalAPER  = 0.0; // note : tgroup stores only offsets relative to the original image values
     76      tgroup[j].dKlam     = 0.0;
     77      tgroup[j].dMcal     = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     78      tgroup[j].dMsys     = 0.0;
     79      tgroup[j].McalChiSq = 0.0; // NAN or 0.0?
     80      tgroup[j].flags     = ID_IMAGE_PHOTOM_UBERCAL; // we start by treating the suspected photometric nights as photometric
     81      tgroup[j].photcode  = photcodes[j][0].code;
    8282   
    83       tgroup[Nt].NIMAGE    = 1000;
    84       tgroup[Nt].Nimage    = 0;
    85       ALLOCATE (tgroup[Nt].image, off_t, tgroup[Nt].NIMAGE);
    86       tgroup[Nt].image[0]  = -1;
    87 
    88       tgroup[Nt].Nmeasure  = 0;
    89       tgroup[Nt].NMEASURE  = 1000;
    90       ALLOCATE (tgroup[Nt].measure, off_t, tgroup[Nt].NMEASURE);
    91       ALLOCATE (tgroup[Nt].catalog, off_t, tgroup[Nt].NMEASURE);
    92     }
    93   }
     83      tgroup[j].NIMAGE    = 1000;
     84      tgroup[j].Nimage    = 0;
     85      ALLOCATE (tgroup[j].image, off_t, tgroup[j].NIMAGE);
     86      tgroup[j].image[0]  = -1;
     87
     88      tgroup[j].Nmeasure  = 0;
     89      tgroup[j].NMEASURE  = 1000;
     90      ALLOCATE (tgroup[j].measure, off_t, tgroup[j].NMEASURE);
     91      ALLOCATE (tgroup[j].catalog, off_t, tgroup[j].NMEASURE);
     92    }
     93  }
     94
     95  free (tgroupTimesRaw);
    9496  return;
    9597}
    9698
    97 // assign the images to the tgroups
     99// create a new TGroup based on the supplied time and photcode
     100void extendTGroups (unsigned int tzero) {
     101
     102  if (!TGROUP_ZEROPT) return;
     103  myAssert (tgroupTimes, "oops, tgroupTimes not allocated");
     104
     105  // index of the new entry
     106  int Ntgt = NtgroupTimes;
     107
     108  NtgroupTimes ++;
     109  REALLOCATE (tgroupTimes, TGTimes *, NtgroupTimes);
     110 
     111  double mjd = ohana_sec_to_mjd (tzero);
     112  double mjdInt = (int) mjd;
     113  time_t start = ohana_mjd_to_sec (mjdInt);
     114
     115  ALLOCATE (tgroupTimes[Ntgt], TGTimes, 1);
     116  tgroupTimes[Ntgt][0].start = start;
     117  tgroupTimes[Ntgt][0].stop  = start + 86399;
     118
     119  ALLOCATE (tgroupTimes[Ntgt][0].byCode, TGroup, Nphotcodes);
     120  tgroupTimes[Ntgt][0].nCode = Nphotcodes;
     121  TGroup *tgroup = tgroupTimes[Ntgt][0].byCode;
     122
     123  for (int j = 0; j < Nphotcodes; j++) {
     124    tgroup[j].parent    = (void *) tgroupTimes[Ntgt];
     125    tgroup[j].McalPSF   = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     126    tgroup[j].McalAPER  = 0.0; // note : tgroup stores only offsets relative to the original image values
     127    tgroup[j].dKlam     = 0.0;
     128    tgroup[j].dMcal     = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     129    tgroup[j].dMsys     = 0.0;
     130    tgroup[j].McalChiSq = 0.0; // NAN or 0.0?
     131    tgroup[j].flags     = 0;   // tgroups NOT in the original file are not suspected as photometric
     132    tgroup[j].photcode  = photcodes[j][0].code;
     133    tgroup[j].NIMAGE    = 1000;
     134    tgroup[j].Nimage    = 0;   // the new TGroup is not suspected to be photometric
     135    ALLOCATE (tgroup[j].image, off_t, tgroup[j].NIMAGE);
     136    tgroup[j].image[0]  = -1;
     137    tgroup[j].Nmeasure  = 0;
     138    tgroup[j].NMEASURE  = 1000;
     139    ALLOCATE (tgroup[j].measure, off_t, tgroup[j].NMEASURE);
     140    ALLOCATE (tgroup[j].catalog, off_t, tgroup[j].NMEASURE);
     141  }
     142
     143  // sort the times for quick bisection
     144  sort_tgtimes (tgroupTimes, NtgroupTimes);
     145  return;
     146}
     147
     148// Assign the images to the tgroups.  The initial tgroups table contains only suspected
     149// photometric nights.  As we find images which are not in the current tgroups list, add
     150// new non-photometric entries.
    98151void initTGroups (Image *subset, off_t Nsubset) {
    99152
     
    105158   */
    106159
    107   ALLOCATE (ImageToTGroup, off_t, Nsubset); // tgroup to which image belongs
     160  ALLOCATE (ImageToTGroup, TGroup *, Nsubset); // tgroup to which image belongs
    108161
    109162  // assign each image to a tgroup
    110163  int Nsimple = 0;
    111164  for (off_t i = 0; i < Nsubset; i++) {
    112     ImageToTGroup[i] = -1;
     165    ImageToTGroup[i] = NULL;
    113166
    114167    // ignore non-GPC1 images
     
    123176    }
    124177
    125     off_t j = findTGroup(subset[i].tzero, subset[i].photcode);
    126     if (j == -1) {
    127       // images which do not belong to a tgroup should be ignored in this analysis
    128       // XXX mark the images and the measurements somehow
    129       continue;
    130     }
    131 
    132     // add reference from image to tgroup
    133     ImageToTGroup[i] = j;
     178    TGroup *myGroup = findTGroup(subset[i].tzero, subset[i].photcode);
     179    if (!myGroup) {
     180      // generate a new TGroup which is not photometric
     181      extendTGroups (subset[i].tzero);
     182      myGroup = findTGroup(subset[i].tzero, subset[i].photcode);
     183      myAssert (myGroup, "oops, we just extended to include this");
     184    }
     185
     186    // add pointer to tgroup for this image
     187    ImageToTGroup[i] = myGroup;
    134188
    135189    // note the array 'subset' is registered in ImageOps.c:images by initImages
     
    137191
    138192    // add image to tgroup image list
    139     tgroup[j].image[tgroup[j].Nimage] = i; // reference to entry in 'subset'
    140     tgroup[j].Nimage ++;
    141     if (tgroup[j].Nimage == tgroup[j].NIMAGE) {
    142       tgroup[j].NIMAGE += 1000;
    143       REALLOCATE (tgroup[j].image, off_t, tgroup[j].NIMAGE);
     193    myGroup[0].image[myGroup[0].Nimage] = i; // reference to entry in 'subset'
     194    myGroup[0].Nimage ++;
     195    if (myGroup[0].Nimage == myGroup[0].NIMAGE) {
     196      myGroup[0].NIMAGE += 1000;
     197      REALLOCATE (myGroup[0].image, off_t, myGroup[0].NIMAGE);
    144198    }
    145199  }
     
    147201  initTGroupsMcal ();
    148202
    149   fprintf (stderr, "matched %d images to %d tgroups, %d simple chips not matched to tgroups\n", (int) (Nsubset - Nsimple), (int) Ntgroup, (int) Nsimple);
     203  fprintf (stderr, "matched %d images to %d tgroups, %d simple chips not matched to tgroups\n", (int) (Nsubset - Nsimple), (int) NtgroupTimes, (int) Nsimple);
    150204  return;
    151205}
     
    156210
    157211  free (ImageToTGroup);
     212
     213  for (int i = 0; i < NtgroupTimes; i++) {
     214    TGroup *tgroup = tgroupTimes[i][0].byCode;
     215    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     216      free (tgroup[j].image);
     217      free (tgroup[j].measure);
     218      free (tgroup[j].catalog);
     219    }
     220    free (tgroup);
     221    free (tgroupTimes[i]);
     222  }
    158223  free (tgroupTimes);
    159224
    160   for (int i = 0; i < Ntgroup; i++) {
    161     free (tgroup[i].image);
    162     free (tgroup[i].measure);
    163     free (tgroup[i].catalog);
    164   }
    165   free (tgroup);
     225  // free (ImageToGroup); why not?
    166226  return;
    167227}
     
    175235  if (!TGROUP_ZEROPT) return;
    176236
     237  // we use liststats to calculate the median Mcal for the input images
     238  // in each tgroup as a starting point.
    177239  StatType stats;
    178240  liststats_setmode (&stats, "MEDIAN");
    179241
    180242  // init the tgroup array values
    181   for (int i = 0; i < Ntgroup; i++) {
    182     tgroup[i].McalPSF   = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
    183     tgroup[i].McalAPER  = 0.0; // note : tgroup stores only offsets relative to the original image values
    184     tgroup[i].dMcal     = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
    185     tgroup[i].dMsys     = 0.0;
    186     tgroup[i].McalChiSq = 0.0;// NAN or 0.0?
    187 
    188     if (tgroup[i].Nimage == 0) continue; // no images, ignore the tgroup
    189 
    190     // calculate the median of the Mcal values for the images in this tgroup:
    191 
    192     ALLOCATE_PTR (McalPSF,  double, tgroup[i].Nimage);
    193     ALLOCATE_PTR (McalAPER, double, tgroup[i].Nimage);
    194     for (int j = 0; j < tgroup[i].Nimage; j++) {
    195       int Nsub = tgroup[i].image[j];
    196       McalPSF[j] = images[Nsub].McalPSF;
    197       McalAPER[j] = images[Nsub].McalAPER;
    198 
    199       // set these back to 0.0 to have no future effect
    200       images[Nsub].McalPSF = 0.0;
    201       images[Nsub].McalAPER = 0.0;
    202     }
     243  for (int i = 0; i < NtgroupTimes; i++) {
     244    TGroup *tgroup = tgroupTimes[i][0].byCode;
     245    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     246      tgroup[j].McalPSF   = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     247      tgroup[j].McalAPER  = 0.0; // note : tgroup stores only offsets relative to the original image values
     248      tgroup[j].dMcal     = 0.0; // note : at the end, tgroup.Mcal is added back to the input images
     249      tgroup[j].dMsys     = 0.0;
     250      tgroup[j].McalChiSq = 0.0;// NAN or 0.0?
     251
     252      if (tgroup[j].Nimage == 0) continue; // no images, ignore the tgroup
     253
     254      // calculate the median of the Mcal values for the images in this tgroup:
     255
     256      ALLOCATE_PTR (McalPSF,  double, tgroup[j].Nimage);
     257      ALLOCATE_PTR (McalAPER, double, tgroup[j].Nimage);
     258      for (int im = 0; im < tgroup[j].Nimage; im++) {
     259        int Nsub = tgroup[j].image[im];
     260        McalPSF[im] = images[Nsub].McalPSF;
     261        McalAPER[im] = images[Nsub].McalAPER;
     262
     263        // set these back to 0.0 to have no future effect
     264        images[Nsub].McalPSF = 0.0;
     265        images[Nsub].McalAPER = 0.0;
     266      }
    203267   
    204     liststats (McalPSF, NULL, NULL, tgroup[i].Nimage, &stats);
    205     tgroup[i].McalPSF = stats.median;
    206     FREE (McalPSF);
     268      liststats (McalPSF, NULL, NULL, tgroup[j].Nimage, &stats);
     269      tgroup[j].McalPSF = stats.median;
     270      FREE (McalPSF);
    207271 
    208     liststats (McalAPER, NULL, NULL, tgroup[i].Nimage, &stats);
    209     tgroup[i].McalAPER = stats.median;
    210     FREE (McalAPER);
     272      liststats (McalAPER, NULL, NULL, tgroup[j].Nimage, &stats);
     273      tgroup[j].McalAPER = stats.median;
     274      FREE (McalAPER);
     275    }
    211276  }
    212277  return;
     
    218283  if (!ImageToTGroup) return NULL;
    219284
    220   off_t m = ImageToTGroup[im];
    221   if (m < 0) return NULL;
    222   if (m >= Ntgroup) return NULL;
    223 
    224   return (&tgroup[m]);
     285  // test if im > Nimages / Nsubset?
     286  TGroup *myGroup = ImageToTGroup[im];
     287  return (myGroup);
    225288}
    226289
     
    228291// tgroupTimes is a sorted, unique list of times
    229292// assume a 1day range for now
    230 off_t findTGroup (unsigned int start, int photcode) {
    231 
    232   // first find the matching photcode
     293TGroup *findTGroup (unsigned int start, int photcode) {
     294
     295  // first find the matching photcode (our list of active secondary photcodes
     296  // does not necessarily match the list of all secondary photcodes)
    233297  int Ns = -1;
     298  int ecode = GetPhotcodeEquivCodebyCode (photcode);
    234299  for (int i = 0; (Ns < 0) && (i < Nphotcodes); i++) {
    235     int ecode = GetPhotcodeEquivCodebyCode (photcode);
    236300    if (photcodes[i][0].code != ecode) continue;
    237301    Ns = i;
    238302  }
    239   if (Ns < 0) return -1;
     303  if (Ns < 0) return NULL;
    240304
    241305  off_t Nlo, Nhi, N;
     
    243307  // find the last tgroup before start
    244308  Nlo = 0; // first valid tgroupTimes value
    245   Nhi = Ntgroup - 1; // last valid tgroupTimes value
    246 
    247   // if start is not in this range, return -1
    248   if (start < tgroupTimes[Nlo]) return (-1);
    249   if (start > tgroupTimes[Nhi] + 86399) return (-1); // 1-day range for tgroup for now
     309  Nhi = NtgroupTimes - 1; // last valid tgroupTimes value
     310
     311  // if start is not in this range, return NULL
     312  if (start < tgroupTimes[Nlo][0].start) return NULL;
     313  if (start > tgroupTimes[Nhi][0].start + 86399) return NULL; // 1-day range for tgroup for now
    250314
    251315  while (Nhi - Nlo > 4) {
    252316    N = 0.5*(Nlo + Nhi);
    253     if (tgroupTimes[N] < start) {
     317    if (tgroupTimes[N][0].start < start) {
    254318      Nlo = MAX(N, 0);
    255319    } else {
    256       Nhi = MIN(N, Ntgroup - 1);
     320      Nhi = MIN(N, NtgroupTimes - 1);
    257321    }
    258322  }
    259323  // we now have : tgroupTimes[Nlo] < start <= tgroupTimes[Nhi]
    260324
    261   // find a matched tgroup starting from Nlo, or return -1
     325  // find a matched tgroup starting from Nlo, or return NULL
    262326  // tgroupTimes is a lower bound, the upper bound is tgroupTimes + 86399 (1d)
    263327  for (N = Nlo; N <= Nhi; N++) {
    264     if (start < tgroupTimes[N]) continue;
    265     if (start > tgroupTimes[N] + 86399) continue; // XXX since they are sorted, probably do not need this check
    266     return (N*Nphotcodes + Ns); // we have the tgroupTime and photcodes, so we can construct the tgroup index
    267   }
    268   return (-1);
     328    if (start < tgroupTimes[N][0].start) continue;
     329    if (start > tgroupTimes[N][0].start + 86399) continue; // XXX since they are sorted, probably do not need this check
     330    // N is the tgroupTimes entry we want.
     331    // double-check that tgroupTimes[N][0].byCode[Ns].photcode = ecode?
     332    return &tgroupTimes[N][0].byCode[Ns];
     333  }
     334  return (NULL);
    269335}
    270336
    271337void setMcalFromTGroups () {
    272338
    273   off_t i, j, im, Nimage;
     339  off_t Nimage;
    274340  Image *image;
    275341
     
    282348  // copy the tgroup results to the images.  set the tgroup Mcal to 0.0 since we have moved its
    283349  // impact to the images
    284   for (i = 0; i < Ntgroup; i++) {
    285     for (j = 0; j < tgroup[i].Nimage; j++) {
    286       im = tgroup[i].image[j];
    287       double Mgrp = (TGROUP_FIT_AIRMASS) ? tgroup[i].McalPSF + tgroup[i].dKlam*(image[im].secz - 1.0) : tgroup[i].McalPSF;
    288       image[im].McalPSF    += Mgrp;
    289       image[im].McalAPER   += Mgrp;
    290       image[im].dMcal       = tgroup[i].dMcal;
    291       image[im].McalChiSq   = tgroup[i].McalChiSq;
    292       image[im].dMagSys     = tgroup[i].dMsys;
    293       image[im].nFitPhotom  = tgroup[i].nFitPhotom;
    294       image[im].flags      |= (tgroup[i].flags & ID_IMAGE_PHOTOM_FEW);
    295       image[im].flags      |= (tgroup[i].flags & ID_IMAGE_PHOTOM_POOR);
    296 
    297       fprintf (stderr, "TG to IMAGE: %f -> %f (%d)\n", tgroup[i].McalPSF, image[im].McalPSF, tgroup[i].nFitPhotom);
    298     }
    299     tgroup[i].McalPSF  = 0.0;
    300     tgroup[i].McalAPER = 0.0;
    301     tgroup[i].dKlam    = 0.0;
     350  for (off_t k = 0; k < NtgroupTimes; k++) {
     351    TGroup *tgroup = tgroupTimes[k][0].byCode;
     352    for (off_t i = 0; i < tgroupTimes[k][0].nCode; i++) {
     353      for (off_t j = 0; j < tgroup[i].Nimage; j++) {
     354        off_t im = tgroup[i].image[j];
     355        double Mgrp = (TGROUP_FIT_AIRMASS) ? tgroup[i].McalPSF + tgroup[i].dKlam*(image[im].secz - 1.0) : tgroup[i].McalPSF;
     356        image[im].McalPSF    += Mgrp;
     357        image[im].McalAPER   += Mgrp;
     358        image[im].dMcal       = tgroup[i].dMcal;
     359        image[im].McalChiSq   = tgroup[i].McalChiSq;
     360        image[im].dMagSys     = tgroup[i].dMsys;
     361        image[im].nFitPhotom  = tgroup[i].nFitPhotom;
     362        image[im].flags            |= (tgroup[i].flags & ID_IMAGE_PHOTOM_FEW);
     363        image[im].flags            |= (tgroup[i].flags & ID_IMAGE_PHOTOM_POOR);
     364        image[im].flags            |= (tgroup[i].flags & ID_IMAGE_PHOTOM_UBERCAL);
     365       
     366        fprintf (stderr, "TG to IMAGE: %f +/- %f -> %f (%d)\n", tgroup[i].McalPSF, tgroup[i].dMcal, image[im].McalPSF, tgroup[i].nFitPhotom);
     367      }
     368      tgroup[i].McalPSF  = 0.0;
     369      tgroup[i].McalAPER = 0.0;
     370      tgroup[i].dKlam    = 0.0;
     371    }
    302372  }     
    303373}
     
    310380  if (!TGROUP_ZEROPT) return;
    311381
    312   ALLOCATE (MeasureToTGroup, off_t *, Ncatalog);
     382  ALLOCATE (MeasureToTGroup, TGroup **, Ncatalog);
    313383  for (i = 0; i < Ncatalog; i++) {
    314     ALLOCATE (MeasureToTGroup[i], off_t, MAX (catalog[i].Nmeasure, 1));
    315     for (j = 0; j < catalog[i].Nmeasure; j++) MeasureToTGroup[i][j] = -1;
     384    ALLOCATE (MeasureToTGroup[i], TGroup *, MAX (catalog[i].Nmeasure, 1));
     385    for (j = 0; j < catalog[i].Nmeasure; j++) MeasureToTGroup[i][j] = NULL;
    316386  }
    317387}
     
    360430  }
    361431  fprintf (stderr, "Matched %d detections to tgroups\n", Nmatch);
    362   for (i = 0; i < Ntgroup; i++) {
    363     fprintf (stderr, "  TGROUP time %d, Nmeasure: %d, Nimage: %d\n", tgroup[i].start, (int) tgroup[i].Nmeasure, (int) tgroup[i].Nimage);
     432  for (i = 0; i < NtgroupTimes; i++) {
     433    TGroup *tgroup = tgroupTimes[i][0].byCode;
     434    for (off_t j = 0; j < tgroupTimes[i][0].nCode; j++) {
     435      fprintf (stderr, "  TGROUP time %.0f photcode %d, Nmeasure: %d, Nimage: %d\n", ohana_sec_to_mjd(tgroupTimes[i][0].start), tgroup[j].photcode, (int) tgroup[j].Nmeasure, (int) tgroup[j].Nimage);
     436    }
    364437  }
    365438  return (TRUE);
     
    377450  }
    378451
    379   off_t grpID = ImageToTGroup[idx];
    380   if (grpID < 0) {
     452  TGroup *myGroup = ImageToTGroup[idx];
     453  TGTimes *parent = (TGTimes *) myGroup->parent;
     454  if (!myGroup) {
    381455    // Image *image = getimage(idx);
    382456    // fprintf (stderr, "unmatched image %s\n", image[0].name);
     
    391465    // unsigned int imageStart = image[0].tzero - MAX(0.01*image[0].trate*image[0].NY, 1);
    392466    unsigned int imageStart = image[0].tzero;
    393     if ((imageStart < tgroup[grpID].start) || (imageStart > tgroup[grpID].stop)) {
     467    // XXX to do this check I need a pointer to the group master
     468    if ((imageStart < parent->start) || (imageStart > parent->stop)) {
    394469      fprintf (stderr, "error in image to tgroup match\n");
    395470      abort();
     
    399474  // this measurement is on one of my tgroups, mark it as mine.
    400475  catalog[cat].measureT[meas].myDet = TRUE;
    401   MeasureToTGroup[cat][meas] = grpID;
    402 
    403   tgroup[grpID].catalog[tgroup[grpID].Nmeasure] = cat;
    404   tgroup[grpID].measure[tgroup[grpID].Nmeasure] = meas;
    405   tgroup[grpID].Nmeasure ++;
    406 
    407   if (tgroup[grpID].Nmeasure == tgroup[grpID].NMEASURE) {
    408     tgroup[grpID].NMEASURE += 1000;
    409     REALLOCATE (tgroup[grpID].catalog, off_t, tgroup[grpID].NMEASURE);
    410     REALLOCATE (tgroup[grpID].measure, off_t, tgroup[grpID].NMEASURE);
     476  MeasureToTGroup[cat][meas] = myGroup;
     477
     478  myGroup->catalog[myGroup->Nmeasure] = cat;
     479  myGroup->measure[myGroup->Nmeasure] = meas;
     480  myGroup->Nmeasure ++;
     481
     482  if (myGroup->Nmeasure == myGroup->NMEASURE) {
     483    myGroup->NMEASURE += 1000;
     484    REALLOCATE (myGroup->catalog, off_t, myGroup->NMEASURE);
     485    REALLOCATE (myGroup->measure, off_t, myGroup->NMEASURE);
    411486  }
    412487  return;
     
    415490float getMgrp (off_t meas, int cat, float airmass) {
    416491
    417   off_t i;
    418492  float value;
    419493
     
    421495
    422496  // unassigned measurements belong to simple chips
    423   i = MeasureToTGroup[cat][meas];
    424   if (i == -1) return (0.0);
    425 
    426   // if (tgroup[i].flags & IMAGE_BAD) return (NAN); 
    427   value = tgroup[i].McalPSF + tgroup[i].dKlam*(airmass - 1.0);
     497  TGroup *myGroup = MeasureToTGroup[cat][meas];
     498  if (!myGroup) return (0.0);
     499
     500  // if (myGroup->flags & IMAGE_BAD) return (NAN); 
     501  value = myGroup->McalPSF + myGroup->dKlam*(airmass - 1.0);
    428502  return (value);
    429503}
     
    434508
    435509  // unassigned measurements belong to simple chips
    436   int i = MeasureToTGroup[cat][meas];
    437   if (i == -1) return (0);
    438 
    439   return (tgroup[i].flags);
    440 }
    441 
     510  TGroup *myGroup = MeasureToTGroup[cat][meas];
     511  if (!myGroup) return (0);
     512
     513  return (myGroup->flags);
     514}
     515
     516// XXX remove the lists and replace with StatDataSet structs?
     517// XXX move the StatDataSetAlloc up?
    442518typedef struct {
    443519  int Nfew;
     
    526602static int nextTGroup = 0;
    527603
    528 // we have an array of tgroups (tgroup, Ntgroup).  we need to hand out tgroups one at a time to
     604// we have an array of (tgroupTimes, NtgroupTimes).  we need to hand out tgroupTimes one at a time to
    529605// the worker threads as they need
    530606off_t getNextTGroupForThread () {
    531607
    532608  pthread_mutex_lock (&setMgrp_mutex);
    533   if (nextTGroup >= Ntgroup) {
     609  if (nextTGroup >= NtgroupTimes) {
    534610    pthread_mutex_unlock (&setMgrp_mutex);
    535611    return (-1);
     
    544620int setMgrp (Catalog *catalog, int PoorImages, FlatCorrectionTable *flatcorr) {
    545621
    546   off_t i, N, Nmax;
     622  off_t N;
    547623  Image *image;
    548624
     
    564640  }
    565641
    566   Nmax = 0;
    567   for (i = 0; i < Ntgroup; i++) {
    568     Nmax = MAX (Nmax, tgroup[i].Nmeasure);
     642  off_t Nmax = 0;
     643  for (off_t i = 0; i < NtgroupTimes; i++) {
     644    TGroup *tgroup = tgroupTimes[i][0].byCode;
     645    for (off_t j = 0; j < tgroupTimes[i][0].nCode; j++) {
     646      Nmax = MAX (Nmax, tgroup[j].Nmeasure);
     647    }
    569648  }
    570649
     
    575654  // if (PLOTSTUFF) PLOTDELAY = 0.0;
    576655
    577   for (i = 0; i < Ntgroup; i++) {
    578     setMgrp_tgroup (&tgroup[i], i, image, catalog, &info, flatcorr);
    579     fprintf (stderr, "TGROUP Mcal: %f, dK: %f, limiting negative clouds to %f\n", tgroup[i].McalPSF, tgroup[i].dKlam, CLOUD_TOLERANCE);
     656  for (off_t i = 0; i < NtgroupTimes; i++) {
     657    TGroup *tgroup = tgroupTimes[i][0].byCode;
     658    for (off_t j = 0; j < tgroupTimes[i][0].nCode; j++) {
     659      setMgrp_tgroup (&tgroup[j], i, image, catalog, &info, flatcorr);
     660      fprintf (stderr, "TGROUP time %.0f photcode %d Mcal: %f, dK: %f, dMcal: %f, limiting negative clouds to %f\n", ohana_sec_to_mjd(tgroupTimes[i][0].start), tgroup[j].photcode, tgroup[j].McalPSF, tgroup[j].dKlam, tgroup[j].dMcal, CLOUD_TOLERANCE);
     661    }
    580662  }
    581663  SetMgrpInfoFree (&info);
     
    601683# define NIGHT_GOOD_FRACTION 0.1
    602684
    603 // 'tgroup' is a pointer to the current tgroup of interest (Nmos)
     685// 'tgroup' is a pointer to the current tgroup of interest (entry Ngrp)
    604686int setMgrp_tgroup (TGroup *myTGroup, off_t Ngrp, Image *image, Catalog *catalog, SetMgrpInfo *info, FlatCorrectionTable *flatcorr) {
    605687
    606688  off_t j, NimageReal;
    607689
    608   StatType stats;
    609   liststats_setmode (&stats, "INNER_WTMEAN");
    610 
    611   double *psfMagList    = info->psfMagList;
    612   double *psfAirList    = info->psfAirList;
    613   double *psfErrList    = info->psfErrList;
    614   double *kronMagList   = info->kronMagList;
    615   double *kronErrList   = info->kronErrList;
    616   double *brightMagList = info->brightMagList;
    617   double *brightErrList = info->brightErrList;
     690  /* on PoorImages run, skip good images */
     691  if (info->PoorImages) {
     692    int bad = myTGroup->flags & (ID_IMAGE_PHOTOM_FEW | ID_IMAGE_PHOTOM_POOR | ID_IMAGE_PHOTOM_SKIP);
     693    if (!bad) return TRUE;
     694  }     
     695
     696  int fitOrder = TGROUP_FIT_AIRMASS ? 1 : 0;
     697
     698  // allocate the arrays used by the fit1d_irls analysis below.
     699  // the last 0 means we are NOT using bootstrap analysis here
     700
     701  FitDataSet psfStars, kronStars, brightStars;
     702  FitDataSetAlloc (&psfStars,    myTGroup->Nmeasure, fitOrder, 0);
     703  FitDataSetAlloc (&kronStars,   myTGroup->Nmeasure, fitOrder, 0);
     704  FitDataSetAlloc (&brightStars, myTGroup->Nmeasure, fitOrder, 0);
     705
     706  // add prior constraint on airmass:
     707  if (1) {
     708    FitDataSetAddPriors (&psfStars);
     709    psfStars.bPriorValue[1] = 0.0;  // note that we are fitting relative to the nominal slope
     710    psfStars.bPriorSigma[1] = 0.04; // XXX this prior sigma needs to be user-configured
     711  }
    618712
    619713  // Image *imageReal = getimages (&NimageReal, NULL); returned pointer is not used
    620714  getimages (&NimageReal, NULL);
    621715
    622   /* on PoorImages run, skip good images */
    623   if (info->PoorImages) {
    624     int bad = myTGroup[0].flags & (ID_IMAGE_PHOTOM_FEW | ID_IMAGE_PHOTOM_POOR | ID_IMAGE_PHOTOM_SKIP);
    625     if (!bad) return TRUE;
    626   }     
    627 
    628716  int Nsecfilt = GetPhotcodeNsecfilt ();
    629717
    630718  int testImage = FALSE;
    631   testImage |= (abs(myTGroup[0].start - 1245283200) < 10);
    632   // testImage |= (abs(myTGroup[0].start - 1324103823) < 10);
     719  TGTimes *tgroup = (TGTimes *) myTGroup->parent;
     720  testImage |= (abs(tgroup->start - 1245283200) < 10);
    633721
    634722  FILE *fout = NULL;
     
    732820    assert (Nbright >= 0);
    733821
    734     psfMagList[N]  = MsysPSF - MrelPSF - Mcal - Mgrid + Mflat;
    735     psfAirList[N]  = (catalog[c].measureT[m].airmass - 1.0);
    736     psfErrList[N]  = MAX (catalog[c].measureT[m].dM, MIN_ERROR);
    737     kronMagList[N] = MsysKron - MrelKron - Mcal - Mgrid + Mflat;
    738     kronErrList[N] = psfErrList[N];
     822    psfStars.alldata-> yVector[N] = MsysPSF - MrelPSF - Mcal - Mgrid + Mflat;
     823    psfStars.alldata-> xVector[N] = (catalog[c].measureT[m].airmass - 1.0);
     824    psfStars.alldata->dyVector[N] = MAX (catalog[c].measureT[m].dM, MIN_ERROR);
     825
     826    kronStars.alldata-> yVector[N] = MsysKron - MrelKron - Mcal - Mgrid + Mflat;
     827    kronStars.alldata-> xVector[N] = psfStars.alldata-> xVector[N];
     828    kronStars.alldata->dyVector[N] = psfStars.alldata->dyVector[N];
     829
    739830    if (catalog[c].measureT[m].dM < IMFIT_SYS_SIGMA_LIM) {
    740       brightMagList[Nbright] = psfMagList[N];
    741       brightErrList[Nbright] = psfErrList[N];
     831      brightStars.alldata-> yVector[Nbright] = psfStars.alldata-> yVector[N];
     832      brightStars.alldata-> xVector[Nbright] = psfStars.alldata-> xVector[N];
     833      brightStars.alldata->dyVector[Nbright] = psfStars.alldata->dyVector[N];
    742834      Nbright ++;
    743835    }
     
    750842    int mark = (N < NIGHT_TOOFEW) || (N < NIGHT_GOOD_FRACTION*myTGroup->Nmeasure);
    751843    if (mark) {
    752       // XXX is this right (effect of subset?) : image[tgroup[Ngrp].image[0]].name
    753       if (VERBOSE2) { fprintf (stderr, "marked tgroup %s ("OFF_T_FMT"), (%d < %d) || (%d < %f*"OFF_T_FMT")\n", image[tgroup[Ngrp].image[0]].name, Ngrp, N, NIGHT_TOOFEW, N, NIGHT_GOOD_FRACTION, myTGroup->Nmeasure); }
    754       myTGroup[0].flags |= ID_IMAGE_PHOTOM_FEW;
     844      if (VERBOSE2) {
     845        TGTimes *mygroup = (TGTimes *) myTGroup->parent;
     846        fprintf (stderr, "marked tgroup %f,%d, (%d < %d) || (%d < %f*"OFF_T_FMT")\n", ohana_sec_to_mjd(mygroup->start), myTGroup->photcode, N, NIGHT_TOOFEW, N, NIGHT_GOOD_FRACTION, myTGroup->Nmeasure);
     847      }
     848      myTGroup->flags |= ID_IMAGE_PHOTOM_FEW;
    755849      info->Nfew ++;
    756850      if (testImage) {
     
    758852      }
    759853    } else {
    760       myTGroup[0].flags &= ~ID_IMAGE_PHOTOM_FEW;
    761     }
    762   }
    763 
    764   double dk = 0.0;
    765   if (TGROUP_FIT_AIRMASS) {
    766     liststats_fit1d (psfMagList, psfErrList, psfAirList, N, &stats, &dk);
    767   } else {
    768     liststats (psfMagList, psfErrList, NULL, N, &stats);
    769   }
    770   if (VERBOSE2 && info->PoorImages) fprintf (stderr, "Mgrp: %f %f %d %d\n", stats.mean, stats.sigma, stats.Nmeas, N);
     854      myTGroup->flags &= ~ID_IMAGE_PHOTOM_FEW;
     855    }
     856  }
     857
     858  // do anything special with identified good nights?
     859  // (myTGroup->flags & ID_IMAGE_PHOTOM_UBERCAL)
     860
     861  fit1d_irls (&psfStars, N);
     862
     863  // if (VERBOSE2 && info->PoorImages) fprintf (stderr, "Mgrp: %f %f %d %d\n", stats.mean, stats.sigma, stats.Nmeas, N);
    771864
    772865  // for now, I have no reason to measure these separately for camera-level images
    773   myTGroup[0].McalPSF    = stats.mean;
    774   myTGroup[0].dMcal      = stats.error;
    775   myTGroup[0].McalChiSq  = stats.chisq;
    776   myTGroup[0].nFitPhotom = N;
    777   myTGroup[0].dKlam      = dk;
    778 
    779   // drop this for tgroups?
    780   liststats (kronMagList, kronErrList, NULL, N, &stats);
    781   myTGroup[0].McalAPER   = stats.mean;
     866  myTGroup->McalPSF    = psfStars.bSaveArray[0][0];
     867  myTGroup->dMcal      = psfStars.bSigma[0];
     868  myTGroup->McalChiSq  = psfStars.chisq;
     869  myTGroup->nFitPhotom = psfStars.Nmeas;
     870  myTGroup->dKlam      = psfStars.bSaveArray[1][0];
     871
     872  // XXX drop this for tgroups?
     873  // fit1d_irls (&kronStars, N);    // does it make sense to calculate a zero point based kron mags?
     874  // myTGroup->McalAPER   = stats.mean;
    782875
    783876  if (testImage) {
    784     fprintf (stderr, "test image %d (%d) %f %f %d ... ", (int) Ngrp, myTGroup[0].start, stats.mean, stats.error, myTGroup[0].nFitPhotom);
     877    TGTimes *parent = (TGTimes *) myTGroup->parent;
     878    fprintf (stderr, "test night %.0f aper: %f %f %d ... ", ohana_sec_to_mjd(parent->start), myTGroup->McalPSF, myTGroup->dMcal, myTGroup->nFitPhotom);
    785879  }
    786880
    787881  if (PLOTSTUFF) {
    788     fprintf (stderr, "Mgrp: %6.3f %6.3f +/- %6.3f %5d %5d | %s\n", stats.mean, stats.median, stats.sigma, stats.Nmeas, N, image[tgroup[Ngrp].image[0]].name);
    789     plot_setMcal (psfMagList, N, &stats, CLOUD_TOLERANCE);
     882    fprintf (stderr, "Mgrp: %6.3f +/- %6.3f %5d of %5d | %.0f\n", myTGroup->McalPSF, myTGroup->dMcal, myTGroup->nFitPhotom, N, ohana_sec_to_mjd(tgroup->start));
     883    plot_setMcal (psfStars.alldata->yVector, N);
    790884  }
    791885
    792886  // bright end scatter
    793   liststats (brightMagList, brightErrList, NULL, Nbright, &stats);
    794   myTGroup[0].dMsys = stats.sigma;
     887  // XXX this does not make sense: I need to apply the airmass slope calculated above first
     888  // redo this by calculating the corrected bright stars mags
     889  // fit1d_irls (&brightStars, N);  // does it make sense to calculate a separate bright star zero point?
     890  // myTGroup->dMsys = stats.sigma;
    795891
    796892  // keep this??
    797   if (myTGroup[0].McalPSF < -CLOUD_TOLERANCE) {
    798     myTGroup[0].McalPSF = 0.0;
     893  if (myTGroup->McalPSF < -CLOUD_TOLERANCE) {
     894    myTGroup->McalPSF = 0.0;
    799895  }
    800896
    801897  if (testImage) {
    802     fprintf (stderr, "%f %f  :  %f\n", myTGroup[0].McalPSF, myTGroup[0].dMsys, myTGroup[0].McalChiSq);
    803   }
     898    fprintf (stderr, "%f %f  :  %f\n", myTGroup->McalPSF, myTGroup->dMsys, myTGroup->McalChiSq);
     899  }
     900
     901  FitDataSetFree (&brightStars);
     902  FitDataSetFree (&kronStars);
     903  FitDataSetFree (&psfStars);
    804904
    805905  return TRUE;
     
    822922
    823923  off_t Nmax = 0;
    824   for (i = 0; i < Ntgroup; i++) {
    825     Nmax = MAX (Nmax, tgroup[i].Nmeasure);
     924  for (off_t i = 0; i < NtgroupTimes; i++) {
     925    TGroup *tgroup = tgroupTimes[i][0].byCode;
     926    for (off_t j = 0; j < tgroupTimes[i][0].nCode; j++) {
     927      Nmax = MAX (Nmax, tgroup[j].Nmeasure);
     928    }
    826929  }
    827930
     
    881984             threadinfo[i].info.Nrel,
    882985             threadinfo[i].info.Nsys,
    883              threadinfo[i].info.Nskip);
     986             threadinfo[i].info.Nskip);
    884987    SetMgrpInfoAccum (&summary, &threadinfo[i].info);
    885988  }
     
    9241027    Image *image = threadinfo->image;
    9251028
    926     setMgrp_tgroup (&tgroup[i], i, image, catalog, &results, flatcorr);
    927     SetMgrpInfoAccum (&threadinfo->info, &results);
     1029    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1030    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1031      setMgrp_tgroup (&tgroup[j], i, image, catalog, &results, flatcorr);
     1032      SetMgrpInfoAccum (&threadinfo->info, &results);
     1033    }
    9281034  }
    9291035
     
    9321038}
    9331039
     1040# if (0)
    9341041StatType statsTGroupM (Catalog *catalog) {
    9351042  OHANA_UNUSED_PARAM(catalog);
     
    9431050  if (!TGROUP_ZEROPT) return (stats);
    9441051
     1052  // XXX do this by time & photcode?
    9451053  ALLOCATE (list, double, Ntgroup);
    9461054  ALLOCATE (dlist, double, Ntgroup);
    9471055
    9481056  n = 0;
    949   for (i = 0; i < Ntgroup; i++) {
    950     if (tgroup[i].flags & IMAGE_BAD) continue;
    951     list[n] = tgroup[i].McalPSF;
    952     dlist[n] = 1;
    953     n++;
     1057  for (int i = 0; i < NtgroupTimes; i++) {
     1058    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1059    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1060      if (tgroup[j].flags & IMAGE_BAD) continue;
     1061      list[n] = tgroup[j].McalPSF;
     1062      dlist[n] = 1;
     1063      n++;
     1064    }
    9541065  }
    9551066
     
    10681179  return (stats);
    10691180}
     1181# endif
    10701182
    10711183/* mark tgroup if: abs(Mcal - <Mcal>) too large, dMcal too large */
     
    10801192  if (VERBOSE) fprintf (stderr, "marking poor tgroups\n");
    10811193
    1082   ALLOCATE (mlist, double, Ntgroup);
    1083   ALLOCATE (slist, double, Ntgroup);
    1084   ALLOCATE (dlist, double, Ntgroup);
    1085 
    1086   for (i = N = 0; i < Ntgroup; i++) {
    1087     if (tgroup[i].flags & IMAGE_BAD) continue;
    1088     mlist[N] = tgroup[i].McalPSF;
    1089     slist[N] = tgroup[i].dMcal;
    1090     dlist[N] = 1;
    1091     N++;
     1194  ALLOCATE (mlist, double, NtgroupTimes*Nphotcodes);
     1195  ALLOCATE (slist, double, NtgroupTimes*Nphotcodes);
     1196  ALLOCATE (dlist, double, NtgroupTimes*Nphotcodes);
     1197
     1198  for (i = N = 0; i < NtgroupTimes; i++) {
     1199    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1200    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1201      if (tgroup[j].flags & IMAGE_BAD) continue;
     1202      mlist[N] = tgroup[j].McalPSF;
     1203      slist[N] = tgroup[j].dMcal;
     1204      dlist[N] = 1;
     1205      N++;
     1206    }
    10921207  }
    10931208
     
    10961211
    10971212  liststats (mlist, dlist, NULL, N, &stats);
    1098   MaxOffset = MAX (IMAGE_OFFSET, 2*stats.sigma);
     1213  MaxOffset = MAX (NIGHT_OFFSET, 2*stats.sigma);
    10991214  MedOffset = stats.median;
    11001215
    11011216  liststats (slist, dlist, NULL, N, &stats);
    1102   MaxScatter = MAX (IMAGE_SCATTER, 2*stats.median);
     1217  MaxScatter = MAX (NIGHT_SCATTER, 2*stats.median);
    11031218  fprintf (stderr, "Mrel: %f, dMrel: %f, Max Scatter: %f, Max Offset: %f\n", MedOffset, stats.median, MaxScatter, MaxOffset);
    11041219 
    11051220  Nmark = Nscatter = Noffset = 0;
    1106   for (i = 0; i < Ntgroup; i++) {
    1107     // if we are keeping ubercal sacrosanct, then we should not be allowed to break them...
    1108     if (KEEP_UBERCAL && (tgroup[i].flags & ID_IMAGE_PHOTOM_UBERCAL)) continue;
    1109 
    1110     if (tgroup[i].flags & (ID_IMAGE_PHOTOM_FEW | ID_IMAGE_PHOTOM_SKIP)) continue;
    1111 
    1112     mark = FALSE;
    1113     if (tgroup[i].dMcal > MaxScatter) {
    1114       mark = TRUE;
    1115       Nscatter ++;
    1116     }
    1117     if (fabs(tgroup[i].McalPSF - MedOffset) > MaxOffset) {
    1118       mark = TRUE;
    1119       Noffset ++;
    1120     }
    1121     if (mark) {
    1122       Nmark ++;
    1123       tgroup[i].flags |= ID_IMAGE_PHOTOM_POOR;
    1124     } else {
    1125       tgroup[i].flags &= ~ID_IMAGE_PHOTOM_POOR;
     1221  for (i = 0; i < NtgroupTimes; i++) {
     1222    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1223    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1224      // if we are keeping ubercal sacrosanct, then we should not be allowed to break them...
     1225      if (KEEP_UBERCAL && (tgroup[i].flags & ID_IMAGE_PHOTOM_UBERCAL)) continue;
     1226     
     1227      if (tgroup[i].flags & (ID_IMAGE_PHOTOM_FEW | ID_IMAGE_PHOTOM_SKIP)) continue;
     1228     
     1229      mark = FALSE;
     1230      if (tgroup[i].dMcal > MaxScatter) {
     1231        mark = TRUE;
     1232        Nscatter ++;
     1233      }
     1234      if (fabs(tgroup[i].McalPSF - MedOffset) > MaxOffset) {
     1235        mark = TRUE;
     1236        Noffset ++;
     1237      }
     1238      if (mark) {
     1239        Nmark ++;
     1240        tgroup[i].flags |= ID_IMAGE_PHOTOM_POOR;
     1241      } else {
     1242        tgroup[i].flags &= ~ID_IMAGE_PHOTOM_POOR;
     1243      }
     1244      // XXX : unset the ubercal flag if we mark the night as bad?
    11261245    }
    11271246  }
     
    11361255void plot_tgroup_fields (Catalog *catalog) {
    11371256
    1138   off_t i, j, m, c, N, Nimage;
     1257  off_t m, c, Nimage;
    11391258  double *xlist, *ylist;
    11401259  char string[64];
     
    11461265  getimages (&Nimage, NULL);
    11471266
    1148   N = 0;
    1149   for (i = 0; i < Ntgroup; i++) {
    1150     N = MAX (N, tgroup[i].Nmeasure);
     1267  off_t N = 0;
     1268  for (off_t i = 0; i < NtgroupTimes; i++) {
     1269    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1270    for (off_t j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1271      N = MAX (N, tgroup[j].Nmeasure);
     1272    }
    11511273  }
    11521274
     
    11541276  ALLOCATE (ylist, double, N);
    11551277
    1156   for (i = 0; i < Ntgroup; i++) {
     1278  for (off_t k = 0; k < NtgroupTimes; k++) {
    11571279    N = 0;
    1158     for (j = 0; j < tgroup[i].Nmeasure; j++) {
     1280    TGroup *tgroup = tgroupTimes[k][0].byCode;
     1281    for (off_t i = 0; i < tgroupTimes[i][0].nCode; i++) {
     1282      for (off_t j = 0; j < tgroup[i].Nmeasure; j++) {
     1283       
     1284        m = tgroup[i].measure[j];
     1285        c = tgroup[i].catalog[j];
    11591286     
    1160       m = tgroup[i].measure[j];
    1161       c = tgroup[i].catalog[j];
    1162      
    1163       if (catalog[c].measureT[m].dbFlags & (ID_MEAS_AREA | ID_MEAS_NOCAL)) continue;
    1164 
    1165       // ave = catalog[c].measureT[m].averef;
    1166       xlist[N] = catalog[c].measureT[m].R;
    1167       ylist[N] = catalog[c].measureT[m].D;
    1168       N++;
    1169     }
    1170  
    1171     sprintf (string, "TGroup "OFF_T_FMT,  i);
     1287        if (catalog[c].measureT[m].dbFlags & (ID_MEAS_AREA | ID_MEAS_NOCAL)) continue;
     1288
     1289        // ave = catalog[c].measureT[m].averef;
     1290        xlist[N] = catalog[c].measureT[m].R;
     1291        ylist[N] = catalog[c].measureT[m].D;
     1292        N++;
     1293      }
     1294    }
     1295    sprintf (string, "TGroup "OFF_T_FMT,  k);
    11721296    plot_defaults (&graphdata);
    11731297    plot_list (&graphdata, xlist, ylist, N, string, NULL);
     
    11861310  if (!TGROUP_ZEROPT) return;
    11871311
    1188   ALLOCATE (xlist, double, Ntgroup);
    1189   ALLOCATE (dlist, double, Ntgroup);
    1190   ALLOCATE (Mlist, double, Ntgroup);
    1191 
    1192   for (i = 0; i < Ntgroup; i++) {
    1193     Mlist[i] = tgroup[i].McalPSF;
    1194     dlist[i] = tgroup[i].dMcal;
    1195     xlist[i] = tgroup[i].start;
     1312  ALLOCATE (xlist, double, NtgroupTimes*Nphotcodes);
     1313  ALLOCATE (dlist, double, NtgroupTimes*Nphotcodes);
     1314  ALLOCATE (Mlist, double, NtgroupTimes*Nphotcodes);
     1315
     1316  int Npts = 0;
     1317  for (i = 0; i < NtgroupTimes; i++) {
     1318    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1319    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1320      Mlist[Npts] = tgroup[j].McalPSF;
     1321      dlist[Npts] = tgroup[j].dMcal;
     1322      xlist[Npts] = tgroupTimes[i][0].start;
     1323      Npts ++;
     1324    }
    11961325  }
    11971326
     
    12011330  graphdata.ymin = PlotdMmin;
    12021331  graphdata.ymax = PlotdMmax;
    1203   plot_list (&graphdata, xlist, Mlist, Ntgroup, "airmass vs Mcal", "%s.airmass.png", OUTROOT);
     1332  plot_list (&graphdata, xlist, Mlist, Npts, "airmass vs Mcal", "%s.airmass.png", OUTROOT);
    12041333  plot_defaults (&graphdata);
    12051334  graphdata.size = 1.5;
    12061335  graphdata.ptype = 7;
    1207   plot_list (&graphdata, Mlist, dlist, Ntgroup, "Mcal vs dMcal", "%s.MdM.png", OUTROOT);
     1336  plot_list (&graphdata, Mlist, dlist, Npts, "Mcal vs dMcal", "%s.MdM.png", OUTROOT);
    12081337
    12091338# define NBIN 200
     
    12141343  for (i = 0; i < NBIN; i++) xlist[i] = 0.00005*i;
    12151344  bzero (Mlist, NBIN*sizeof(double));
    1216   for (i = 0; i < Ntgroup; i++) {
    1217     bin = tgroup[i].dMcal / 0.00005;
    1218     bin = MAX (0, MIN (NBIN - 1, bin));
    1219     Mlist[bin] += 1.0;
     1345
     1346  for (i = 0; i < NtgroupTimes; i++) {
     1347    TGroup *tgroup = tgroupTimes[i][0].byCode;
     1348    for (int j = 0; j < tgroupTimes[i][0].nCode; j++) {
     1349      bin = tgroup[j].dMcal / 0.00005;
     1350      bin = MAX (0, MIN (NBIN - 1, bin));
     1351      Mlist[bin] += 1.0;
     1352    }
    12201353  }
    12211354  plot_defaults (&graphdata);
  • trunk/Ohana/src/relphot/src/args.c

    r41390 r41453  
    579579 
    580580  freeTGroups();
     581  free_error();
    581582
    582583  ohana_memcheck (VERBOSE);
  • trunk/Ohana/src/relphot/src/initialize.c

    r39478 r41453  
    33RelphotMode initialize (int argc, char **argv) {
    44
     5  init_error();
    56  relphot_help (argc, argv);
    67  ConfigInit (&argc, argv);
  • trunk/Ohana/src/relphot/src/liststats.c

    r41390 r41453  
    209209
    210210  double zp = (M*Z2 - Z1*MZ)*Det;
    211   *dk = (MZ*R - M*Z1)*Det;
    212 
     211  double dK = (MZ*R - M*Z1)*Det;
     212
     213  /* find sigma and chisq */
     214  double Mo = 0.0, dM = 0.0;
     215  double X2 = 0.0, dS = 0.0;
     216  for (int i = 0; i < Npts; i++) {
     217    Mo = zp + dK*x[i];
     218    M  = SQ (value[i] - Mo);
     219    dM = SQ (err[i]);
     220    X2 += M / dM;
     221    dS += M;
     222  }
     223  X2 = X2 / (Npts - 1);
     224  dS = sqrt (dS / (Npts - 1));
     225
     226  *dk = dK;
    213227  stats->mean = zp;
    214   stats->chisq = NAN;
     228  stats->chisq = X2;
     229  stats->error = dS;
    215230  return TRUE;
    216231}
    217 
    218232
    219233// These should probably be tunable:
     
    224238
    225239int fit_least_squares (double *fit, double *err, double *y, double *dy, double *wgt, double *wt, int Npts);
    226 double VectorFractionInterpolate (double *values, float fraction, int Npts);
    227 double weight_cauchy (double x);
    228240
    229241// this is a zero-order fit (constant value only)
     
    433445// \sigma^2 = (1/R) \sum (weight_i^2 \sigma_i^2)
    434446// R = \sum (weight_i^2)
     447
  • trunk/Ohana/src/relphot/src/setMrelCatalog.c

    r41390 r41453  
    6565  liststats_setmode (&results->kronstats, STATMODE);
    6666
    67   SetMrelInfoReset (results); // reset the countesrs
     67  SetMrelInfoReset (results); // reset the counters
    6868
    6969  for (j = 0; j < catalog[Nc].Naverage; j++) {
     
    9494// eg, -refcode g_SDSS
    9595// this probably makes no sense in the context of multifilter analysis
    96 // XXX probably need to use the photocde table to assign reference mag weights.
     96// XXX probably need to use the photcode table to assign reference mag weights.
    9797
    9898// dlist gives the error per measurement, wlist gives the weight
  • trunk/Ohana/src/relphot/test/relphot.tgroups.dvo

    r41390 r41453  
    5252  # generate the basic images and check they were correctly ingested by dvo
    5353  for i 0 mjd_uc[]
    54     sprintf filerootout "%s.%02d" $fileroot $i
     54    sprintf filerootout "%s.uc.%02d" $fileroot $i
    5555    mkexposure $catdir mjd_uc[$i] zpt_uc[$i] exptime_uc[$i] secz_uc[$i] $FILTER $filerootout $RA_CENTER $DEC_CENTER
    5656    ckexposure $catdir mjd_uc[$i] zpt_uc[$i] exptime_uc[$i] secz_uc[$i] $FILTER raw
    5757  end
    5858
     59  for i 0 mjd_nc[]
     60    sprintf filerootout "%s.nc.%02d" $fileroot $i
     61    mkexposure $catdir mjd_nc[$i] zpt_nc[$i] exptime_nc[$i] secz_nc[$i] $FILTER $filerootout $RA_CENTER $DEC_CENTER
     62    ckexposure $catdir mjd_nc[$i] zpt_nc[$i] exptime_nc[$i] secz_nc[$i] $FILTER raw
     63  end
     64
    5965  break
    60  
     66
    6167  # run relphot on the db and check that the images now match the expected values
    6268  tapEXEC relphot -tgroup-fit-airmass -tgroups tgroups.dat -images g -v -region $RA_MIN $RA_MAX $DEC_MIN $DEC_MAX -D CATDIR $catdir -D STAR_TOOFEW 1 -statmode WT_MEAN -cloud-limit 0.5 -update -nloop 12
Note: See TracChangeset for help on using the changeset viewer.