IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40754


Ignore:
Timestamp:
May 25, 2019, 3:28:51 PM (7 years ago)
Author:
eugene
Message:

add irls to fitprofile

File:
1 edited

Legend:

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

    r40753 r40754  
    44typedef enum {MODE_UPPER, MODE_LOWER} SigmoidMode;
    55
    6 void sigmoid_fit (Vector *xprofile, Vector *fprofile, Vector *oprofile, double *par, int Npar, SigmoidMode mode, double limit);
     6void sigmoid_fit (opihi_flt *xprofile, opihi_flt *fprofile, opihi_flt *wprofile, opihi_flt *oprofile, int Npts, opihi_flt *par, int Npar, FitFunc *FUNC);
     7void sigmoid_fit_irls (opihi_flt *xprofile, opihi_flt *fprofile, opihi_flt *wprofile, opihi_flt *oprofile, int NptsAll, opihi_flt *par, int Npar, SigmoidMode mode, double limit);
    78
    89opihi_flt fsigmoidDeimos (opihi_flt, opihi_flt *, int, opihi_flt *);
    910opihi_flt rsigmoidDeimos (opihi_flt, opihi_flt *, int, opihi_flt *);
     11
     12double deimos_weight_cauchy (double x);
    1013
    1114// use these globals to carry into sigmoid_fit
    1215int VERBOSE = FALSE;
    1316int QUIET   = FALSE;
     17int MaxIterations = 10;
    1418
    1519int deimos_fitprofile (int argc, char **argv) {
     
    2933  Vector *xprofile = NULL;
    3034  Vector *fprofile = NULL;
     35  Vector *wprofile = NULL;
    3136
    3237  QUIET = FALSE;
     
    4449    remove_argument (N, &argc, argv);
    4550  }
    46 
    47   if (argc != 5) goto usage;
     51  MaxIterations = 10;
     52  if ((N = get_argument (argc, argv, "-max-iterations"))) {
     53    remove_argument (N, &argc, argv);
     54    MaxIterations = atof(argv[N]);
     55    remove_argument (N, &argc, argv);
     56  }
     57
     58  if (argc != 6) goto usage;
    4859  if ((xprofile = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
    4960  if ((fprofile = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
     61  if ((wprofile = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
    5062  if (xprofile->Nelements != fprofile->Nelements) goto usage;
     63  if (xprofile->Nelements != wprofile->Nelements) goto usage;
    5164
    5265  // supplied guess for boundaries
    53   double Xs = atof(argv[3]);
    54   double Xe = atof(argv[4]);
     66  double Xs = atof(argv[4]);
     67  double Xe = atof(argv[5]);
    5568
    5669  // output vectors of fits
     
    94107  par[2] = Sky;
    95108  par[3] = BckL;
    96 
    97   sigmoid_fit (xprofile, fprofile, Lprofile, par, Npar, MODE_LOWER, Xmid);
     109  sigmoid_fit_irls (xprofile->elements.Flt, fprofile->elements.Flt, wprofile->elements.Flt, Lprofile->elements.Flt, xprofile->Nelements, par, Npar, MODE_LOWER, Xmid);
     110  set_variable ("sigmoid_left_center", par[0]);
     111  set_variable ("sigmoid_left_sigma",  par[1]);
     112  set_variable ("sigmoid_left_top",    par[2]);
     113  set_variable ("sigmoid_left_bottom", par[3]);
    98114
    99115  par[0] = Xe;
     
    101117  par[2] = Sky;
    102118  par[3] = BckR;
    103 
    104   sigmoid_fit (xprofile, fprofile, Rprofile, par, Npar, MODE_UPPER, Xmid);
     119  sigmoid_fit_irls (xprofile->elements.Flt, fprofile->elements.Flt, wprofile->elements.Flt, Rprofile->elements.Flt, xprofile->Nelements, par, Npar, MODE_UPPER, Xmid);
     120  set_variable ("sigmoid_right_center", par[0]);
     121  set_variable ("sigmoid_right_sigma",  par[1]);
     122  set_variable ("sigmoid_right_top",    par[2]);
     123  set_variable ("sigmoid_right_bottom", par[3]);
    105124 
    106125  return TRUE;
    107126 
    108127usage:
    109   gprint (GP_ERR, "USAGE: deimos fitprofile xprof fprof Xs Xe\n");
     128  gprint (GP_ERR, "USAGE: deimos fitprofile xprof fprof wprof Xs Xe\n");
    110129  return FALSE;
    111130}
     
    173192}
    174193
    175 void sigmoid_fit (Vector *xprofile, Vector *fprofile, Vector *oprofile, double *par, int Npar, SigmoidMode mode, double limit) {
    176 
    177   int Nelements = xprofile->Nelements;
    178 
    179   ALLOCATE_PTR (xtemp, opihi_flt, Nelements);
    180   ALLOCATE_PTR (ytemp, opihi_flt, Nelements);
    181   ALLOCATE_PTR (wtemp, opihi_flt, Nelements);
     194# define FIT_TOLERANCE 1e-4
     195# define FLT_TOLERANCE 1e-6
     196
     197// wprofile is the true poisson error
     198void sigmoid_fit_irls (opihi_flt *xprofile, opihi_flt *fprofile, opihi_flt *wprofile, opihi_flt *oprofile, int NptsAll, opihi_flt *par, int Npar, SigmoidMode mode, double limit) {
     199
     200  FitFunc *FUNC = (mode == MODE_LOWER) ? fsigmoidDeimos : rsigmoidDeimos;
     201
     202  ALLOCATE_PTR (par_old, opihi_flt, Npar);
     203
     204  // allocate these as global static in this file?
     205  ALLOCATE_PTR (xtemp, opihi_flt, NptsAll);
     206  ALLOCATE_PTR (ytemp, opihi_flt, NptsAll);
     207  ALLOCATE_PTR (wtemp, opihi_flt, NptsAll);
     208  ALLOCATE_PTR (otemp, opihi_flt, NptsAll);
    182209
    183210  // extract the points on the right side and fit
    184   // XXX error model is pure poisson (allow external errors)
    185 
    186211  int Npts = 0;
    187   for (int i = 0; i < Nelements; i++) {
    188     int keep = (mode == MODE_UPPER) ^ (xprofile->elements.Flt[i] < limit);
     212  for (int i = 0; i < NptsAll; i++) {
     213    int keep = (mode == MODE_UPPER) ^ (xprofile[i] < limit);
    189214    if (keep) {
    190       xtemp[Npts] = xprofile->elements.Flt[i];
    191       ytemp[Npts] = fprofile->elements.Flt[i];
    192       wtemp[Npts] = 1.0 / (fabs(fprofile->elements.Flt[i] + 0.01));
     215      xtemp[Npts] = xprofile[i];
     216      ytemp[Npts] = fprofile[i];
     217      wtemp[Npts] = (wprofile[i] == 0.0) ? 1.0 : wprofile[i]; // crude
    193218      Npts ++;
    194219    }
    195220  }
    196221
    197   FitFunc *FUNC = (mode == MODE_LOWER) ? fsigmoidDeimos : rsigmoidDeimos;
    198 
    199   double ochisq = mrqinit (xtemp, ytemp, wtemp, Npts, par, Npar, FUNC, VERBOSE);
     222  // define initial weights as 1.0
     223  ALLOCATE_PTR (wt, opihi_flt, Npts);
     224  for (int i = 0; i < Npts; i++) {
     225    wt[i] = 1.0 / SQ(wtemp[i]);
     226  }
     227
     228  // initial fit with ordinary least-squares
     229  // otemp is the fitted value of the function at xtemp
     230  sigmoid_fit (xtemp, ytemp, wt, otemp, Npts, par, Npar, FUNC);
     231
     232  int converged = FALSE;
     233  for (int iterations = 0; !converged && (iterations < MaxIterations); iterations++) {
     234
     235    for (int i = 0; i < Npts; i++) {
     236      wt[i] = deimos_weight_cauchy ((ytemp[i] - otemp[i]) / wtemp[i]) / SQ(wtemp[i]);
     237    }
     238
     239    sigmoid_fit (xtemp, ytemp, wt, otemp, Npts, par, Npar, FUNC);
     240
     241    // save this solution
     242    for (int i = 0; i < Npar; i++) {
     243      par_old[i] = par[i];
     244    }
     245
     246    converged = TRUE;
     247    for (int i = 0; i < Npts; i++) {
     248      if ((fabs(par[i] - par_old[i]) > FIT_TOLERANCE * fabs(par[i])) &&
     249          (fabs(par[i] - par_old[i]) > FLT_TOLERANCE))
     250        converged = FALSE;
     251    }
     252  }
     253
     254  for (int i = 0; i < NptsAll; i++) {
     255    oprofile[i] = FUNC (xprofile[i], par, Npar, NULL);
     256  }
     257
     258  FREE (xtemp);
     259  FREE (ytemp);
     260  FREE (wtemp);
     261  FREE (otemp);
     262
     263  FREE (par_old);
     264  FREE (wt);
     265}
     266
     267void sigmoid_fit (opihi_flt *xprofile, opihi_flt *yprofile, opihi_flt *wprofile, opihi_flt *oprofile, int Npts, opihi_flt *par, int Npar, FitFunc *FUNC) {
     268
     269  double ochisq = mrqinit (xprofile, yprofile, wprofile, Npts, par, Npar, FUNC, VERBOSE);
    200270  double dchisq = ochisq + 2*Npts;
    201271
    202272  int Niter;
    203273  for (Niter = 0; (Niter < 20) && ((dchisq > 0.1*(Npts - Npar)) || (dchisq <= 0.0)); Niter++) {
    204     double chisq = mrqmin (xtemp, ytemp, wtemp, Npts, par, Npar, FUNC, VERBOSE);
     274    double chisq = mrqmin (xprofile, yprofile, wprofile, Npts, par, Npar, FUNC, VERBOSE);
    205275    dchisq = ochisq - chisq;
    206276    ochisq = chisq;
     
    210280
    211281  if (!QUIET) gprint (GP_LOG, "sigmoid @ %f (%f) : top %f bottom %f\n", par[0], par[1], par[2], par[3]);
    212   for (int i = 0; i < Nelements; i++) {
    213     oprofile[0].elements.Flt[i] = FUNC (xprofile[0].elements.Flt[i], par, Npar, NULL);
    214   }
    215 
    216   if (mode == MODE_LOWER) {
    217     set_variable ("sigmoid_left_center", par[0]);
    218     set_variable ("sigmoid_left_sigma",  par[1]);
    219     set_variable ("sigmoid_left_top",    par[2]);
    220     set_variable ("sigmoid_left_bottom", par[3]);
    221   } else {
    222     set_variable ("sigmoid_right_center", par[0]);
    223     set_variable ("sigmoid_right_sigma",  par[1]);
    224     set_variable ("sigmoid_right_top",    par[2]);
    225     set_variable ("sigmoid_right_bottom", par[3]);
    226   }
     282
     283  for (int i = 0; i < Npts; i++) {
     284    oprofile[i] = FUNC (xprofile[i], par, Npar, NULL);
     285  }
     286
    227287  mrqfree (Npar);
    228 
    229   FREE (xtemp);
    230   FREE (ytemp);
    231   FREE (wtemp);
    232 
    233288
     289
     290double deimos_weight_cauchy (double x) {
     291  double r = x / 2.385;
     292  return (1.0 / (1.0 + SQ(r)));
     293}
     294
Note: See TracChangeset for help on using the changeset viewer.