IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40779


Ignore:
Timestamp:
Jun 2, 2019, 5:38:05 PM (7 years ago)
Author:
eugene
Message:

add variance and IRLS to fitslit

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ohana.20190329/src/opihi/mana/deimos_fitslit.c

    r40773 r40779  
    11# include "data.h"
     2# define IRLS_TOLERANCE 1e-4
     3
     4float weight_cauchy_square_flt (float x2);
     5static void fitflux (float *Fwind, float *Fprof, float *weight, int Nx, double *flux, double *sky);
    26
    37int deimos_fitslit (int argc, char **argv) {
    48
    5   // fitslit (window) (slit) (flux) (sky)
    6 
    7   // int N;
     9  // fitslit (window) (vari) (slit) (flux) (sky)
    810
    911  Vector *flux    = NULL;
     
    1113
    1214  Buffer *wind    = NULL;
     15  Buffer *vari    = NULL;
    1316  Buffer *slit    = NULL;
    1417
    15   if (argc != 5) {
    16     gprint (GP_ERR, "USAGE: deimos fitslit (window) (slit) (flux) (sky)\n");
    17     gprint (GP_ERR, "  inputs:  window (observed 2D flux), slit (model 2D flux)\n");
     18  int N;
     19  int Niter = 10;
     20  if ((N = get_argument (argc, argv, "-irls-iter"))) {
     21    remove_argument (N, &argc, argv);
     22    Niter = atoi (argv[N]);
     23    remove_argument (N, &argc, argv);
     24  }
     25
     26  Buffer *model = NULL;
     27  if ((N = get_argument (argc, argv, "-model"))) {
     28    remove_argument (N, &argc, argv);
     29    if ((model = SelectBuffer (argv[N], ANYBUFFER, TRUE)) == NULL) return (FALSE);
     30    remove_argument (N, &argc, argv);
     31  }
     32
     33  if (argc != 6) {
     34    gprint (GP_ERR, "USAGE: deimos fitslit (window) (variance) (slit) (flux) (sky)\n");
     35    gprint (GP_ERR, "  inputs:  window (observed 2D flux), variance (on 2D flux), slit (model 2D flux)\n");
    1836    gprint (GP_ERR, "  outputs: flux (best-fit 1D flux), sky (best-fit 1D background)\n");
    1937    return FALSE;
     
    2240  // XXX I probably should rename FindSpline as SelectSpline and give it the same behavior
    2341  if ((wind = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
    24   if ((slit = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
    25   if ((flux = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
    26   if ((sky  = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
    27 
    28   // XXX confirm slit and wind have same dimensions
     42  if ((vari = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
     43  if ((slit = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
     44  if ((flux = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
     45  if ((sky  = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
    2946
    3047  // define the output window
     
    3249  int Ny = wind[0].matrix.Naxis[1];
    3350 
     51  // confirm wind, vari, slit have same dimensions
    3452  if (Nx != slit[0].matrix.Naxis[0]) { gprint (GP_ERR, "size mismatch in fitslit for window and slit\n"); return FALSE; }
    3553  if (Ny != slit[0].matrix.Naxis[1]) { gprint (GP_ERR, "size mismatch in fitslit for window and slit\n"); return FALSE; }
     54  if (Nx != vari[0].matrix.Naxis[0]) { gprint (GP_ERR, "size mismatch in fitslit for window and variance\n"); return FALSE; }
     55  if (Ny != vari[0].matrix.Naxis[1]) { gprint (GP_ERR, "size mismatch in fitslit for window and variance\n"); return FALSE; }
    3656
    3757  ResetVector (flux, OPIHI_FLT, Ny);
    3858  ResetVector (sky,  OPIHI_FLT, Ny);
    3959
     60  if (model) {
     61    if (!CreateBuffer (model, Nx, Ny, -32, 1.0, 0.0)) { gprint (GP_ERR, "error generating output model buffer\n"); return FALSE; }
     62  }
     63
    4064  float *Fwind = (float *) wind[0].matrix.buffer;
     65  float *Fvari = (float *) vari[0].matrix.buffer;
    4166  float *Fprof = (float *) slit[0].matrix.buffer;
     67  float *FmodOut = model ? (float *) model[0].matrix.buffer : NULL;
     68
     69  ALLOCATE_PTR (weight, float, Nx);
     70  ALLOCATE_PTR (rawwgt, float, Nx);
    4271
    4372  // loop over the rows
    4473  for (int iy = 0; iy < Ny; iy++) {
    4574
    46     // calculate elements of the chi-square for this row:
     75    double F = 0.0, S = 0.0;
    4776
    48     double R = 0.0, P = 0.0, P2 = 0.0, f = 0.0, fp = 0.0;
    49     double wt = 1.0;
    50 
     77    // set weight based on the variance
    5178    for (int ix = 0; ix < Nx; ix++) {
    52      
    53       // skip NAN / Inf pixels in either window or slit
    54       if (!isfinite(Fwind[ix + iy*Nx])) continue;
    55       if (!isfinite(Fprof[ix + iy*Nx])) continue;
    56 
    57       float fxy = Fwind[ix + iy*Nx];
    58       float pxy = Fprof[ix + iy*Nx];
    59 
    60       R  += wt;
    61       P  += pxy*wt;
    62       P2 += pxy*pxy*wt;
    63       f  += fxy*wt;
    64       fp += fxy*pxy*wt;
     79      float vari = Fvari[ix + iy*Nx];
     80      weight[ix] = !isfinite(vari) || (fabs(vari) < 1e-6) ? 1.0 : 1.0 / vari;
     81      rawwgt[ix] = weight[ix];
    6582    }
    6683
    67     double det = R*P2 - P*P;
    68     double S = (P2*f - P*fp) / det;
    69     double F = (R*fp - P*f) / det;
     84    // calculate elements of the chi-square for this row:
     85    fitflux (&Fwind[iy*Nx], &Fprof[iy*Nx], weight, Nx, &F, &S);
     86
     87    // do an IRLS loop here to reject outliers
     88    int converged = FALSE;
     89    for (int iter = 0; (iter < Niter) && !converged; iter++) {
     90
     91      double Flast = F;
     92      double Slast = S;
     93
     94      // calculate weight modification based on distances (squared).
     95      // use modifier to calculate new weighted mean
     96      for (int ix = 0; ix < Nx; ix++) {
     97
     98        // F & S are model parameters; compare the model and observed values for each pixel
     99        float Fmodel = S + F*Fprof[ix + iy*Nx];
     100        float dV = (Fwind[ix + iy*Nx] - Fmodel);
     101        float d2 = SQ(dV) * rawwgt[ix];
     102       
     103        float Mod = weight_cauchy_square_flt (d2);
     104        weight[ix] = Mod * rawwgt[ix];
     105      }
     106      fitflux (&Fwind[iy*Nx], &Fprof[iy*Nx], weight, Nx, &F, &S);
     107
     108      float dF = fabs(F - Flast);
     109      float dS = fabs(S - Slast);
     110
     111      if ((dF < F * IRLS_TOLERANCE) && (dS < S * IRLS_TOLERANCE)) converged = TRUE;
     112    }
     113
     114    if (FmodOut) {
     115      for (int ix = 0; ix < Nx; ix++) {
     116        // F & S are model parameters; compare the model and observed values for each pixel
     117        float Fmodel = S + F*Fprof[ix + iy*Nx];
     118        float dV = (Fwind[ix + iy*Nx] - Fmodel);
     119        float d2 = SQ(dV) * rawwgt[ix];
     120        float Mod = weight_cauchy_square_flt (d2);
     121        if (Mod < 0.1) {
     122          FmodOut[ix + iy*Nx] = NAN;
     123        } else {
     124          FmodOut[ix + iy*Nx] = Fmodel;
     125        }
     126      }
     127    }
    70128
    71129    flux->elements.Flt[iy] = F;
    72130    sky->elements.Flt[iy] = S;
    73131  }
    74 
    75132  return TRUE;
    76133}
    77134
    78 void fitflux () {
    79     // calculate elements of the chi-square for this row:
     135// weight is 1 / variance
     136// Fwind, Fprof are pointers to the start of a single row
     137// Fwind is the observed flux in the window
     138// Fprof is the slit profile
     139void fitflux (float *Fwind, float *Fprof, float *weight, int Nx, double *flux, double *sky) {
    80140
    81     double R = 0.0, P = 0.0, P2 = 0.0, f = 0.0, fp = 0.0;
    82     double wt = 1.0;
     141  // calculate elements of the chi-square fit for this row:
    83142
    84     for (int ix = 0; ix < Nx; ix++) {
     143  double R = 0.0, P = 0.0, P2 = 0.0, f = 0.0, fp = 0.0;
     144
     145  for (int ix = 0; ix < Nx; ix++) {
    85146     
    86       // skip NAN / Inf pixels in either window or slit
    87       if (!isfinite(Fwind[ix + iy*Nx])) continue;
    88       if (!isfinite(Fprof[ix + iy*Nx])) continue;
     147    double fxy = Fwind[ix];
     148    double pxy = Fprof[ix];
    89149
    90       float fxy = Fwind[ix + iy*Nx];
    91       float pxy = Fprof[ix + iy*Nx];
     150    // skip NAN / Inf pixels in either window or slit
     151    if (!isfinite(fxy)) continue;
     152    if (!isfinite(pxy)) continue;
    92153
    93       R  += wt;
    94       P  += pxy*wt;
    95       P2 += pxy*pxy*wt;
    96       f  += fxy*wt;
    97       fp += fxy*pxy*wt;
    98     }
     154    double wt = (weight == NULL) ? 1.0 : weight[ix];
     155    R  += wt;
     156    P  += pxy*wt;
     157    P2 += pxy*pxy*wt;
     158    f  += fxy*wt;
     159    fp += fxy*pxy*wt;
     160  }
    99161
    100     double det = R*P2 - P*P;
    101     double S = (P2*f - P*fp) / det;
    102     double F = (R*fp - P*f) / det;
     162  double det = R*P2 - P*P;
     163  *sky = (P2*f - P*fp) / det;
     164  *flux = (R*fp - P*f) / det;
    103165}
Note: See TracChangeset for help on using the changeset viewer.