IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 36375


Ignore:
Timestamp:
Dec 10, 2013, 2:55:11 PM (12 years ago)
Author:
eugene
Message:

merge changes from eam_branches/ipp-20130904

Location:
trunk
Files:
116 edited
17 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/Nebulous

  • trunk/Nebulous-Server

  • trunk/Ohana

  • trunk/Ohana/src/dvomerge

  • trunk/Ohana/src/dvopsps/src/insert_detections_dvopsps_catalog.c

    r36188 r36375  
    202202
    203203  // PrintIOBuffer (buffer, "INSERT INTO dvoDetectionFull (imageID, ippDetectID, detectID, ippObjID, objID, photcode, flags, zp, zpErr, airMass, expTime, ra, dec_, raErr, decErr) VALUES \n");
    204   PrintIOBuffer (buffer, "INSERT IGNORE INTO dvoDetectionFull (imageID, ippDetectID, detectID, ippObjID, objID, flags, zp, zpErr, airMass, expTime, ra, dec_, raErr, decErr) VALUES \n");
     204  PrintIOBuffer (buffer, "INSERT INTO dvoDetectionFull (imageID, ippDetectID, detectID, ippObjID, objID, flags, zp, zpErr, airMass, expTime, ra, dec_, raErr, decErr) VALUES \n");
    205205
    206206  return TRUE;
  • trunk/Ohana/src/libohana/src

  • trunk/Ohana/src/opihi

  • trunk/Ohana/src/opihi/cmd.astro

  • trunk/Ohana/src/opihi/cmd.astro/fitplx.c

    r35416 r36375  
    4141    remove_argument (N, &argc, argv);
    4242    VERBOSE = TRUE;
     43  }
     44  if ((N = get_argument (argc, argv, "-vv"))) {
     45    remove_argument (N, &argc, argv);
     46    VERBOSE = 2;
    4347  }
    4448
     
    145149
    146150  PlxFit fit;
    147   FitPMandPar (&fit, X, dX, Y, dY, t, pX, pY, n, VERBOSE);
     151  if (!FitPMandPar (&fit, X, dX, Y, dY, t, pX, pY, n, VERBOSE)) {
     152    return FALSE;
     153  }
    148154
    149155  // fprintf (stderr, "Roff, Doff: %f, %f; dRo, dDo: %f, %f\n", fit.Ro, fit.Do, fit.dRo, fit.dDo);
     
    204210  for (i = 0; i < Npts; i++) {
    205211
    206     if (VERBOSE) fprintf (stderr, "%f %f : %f %f : %f : %f %f\n", X[i], dX[i], Y[i], dY[i], T[i], pR[i], pD[i]);
     212    if (VERBOSE == 2) fprintf (stderr, "%f %f : %f %f : %f : %f %f\n", X[i], dX[i], Y[i], dY[i], T[i], pR[i], pD[i]);
    207213
    208214    /* handle case where dX or dY = 0.0 */
    209     wx = 1.0 / SQ(dX[i]);
    210     wy = 1.0 / SQ(dY[i]);
     215    wx = (fabs(dX[i]) < 0.0001) ? 1.0 : 1.0 / SQ(dX[i]);
     216    wy = (fabs(dY[i]) < 0.0001) ? 1.0 : 1.0 / SQ(dY[i]);
    211217
    212218    Wx += wx;
     
    266272  B[4][0] = PRX + PDY;
    267273
    268   dgaussjordan ((double **)A, (double **)B, 5, 1);
     274  if (!dgaussjordan ((double **)A, (double **)B, 5, 1)) {
     275    if (VERBOSE) fprintf (stderr, "error in fit\n");
     276    if (VERBOSE == 2) {
     277      int j;
     278      for (i = 0; i < 5; i++) {
     279        for (j = 0; j < 5; j++) {
     280          fprintf (stderr, "%e ", A[i][j]);
     281        }
     282        fprintf (stderr, " : %e\n", A[i][0]);
     283      }
     284    }
     285    return FALSE;
     286  }
    269287
    270288  fit[0].Ro = B[0][0];
     
    285303    Xf = fit[0].Ro + fit[0].uR*T[i] + fit[0].p*pR[i];
    286304    Yf = fit[0].Do + fit[0].uD*T[i] + fit[0].p*pD[i];
    287     chisq += SQ(X[i] - Xf) / SQ(dX[i]);
    288     chisq += SQ(Y[i] - Yf) / SQ(dY[i]);
    289     if (VERBOSE) fprintf (stderr, "chisq contrib : %f %f : %f %f : %f %f : %f %f : %f\n", Xf, Yf, X[i] - Xf, Y[i] - Yf, dX[i], dY[i], (X[i] - Xf) / dX[i], (Y[i] - Yf) / dY[i], chisq);
     305    wx = (fabs(dX[i]) < 0.0001) ? 1.0 : 1.0 / SQ(dX[i]);
     306    wy = (fabs(dY[i]) < 0.0001) ? 1.0 : 1.0 / SQ(dY[i]);
     307    chisq += SQ(X[i] - Xf) * wx;
     308    chisq += SQ(Y[i] - Yf) * wy;
     309    // if (VERBOSE) fprintf (stderr, "chisq contrib : %f %f : %f %f : %f %f : %f %f : %f\n", Xf, Yf, X[i] - Xf, Y[i] - Yf, dX[i], dY[i], (X[i] - Xf) / dX[i], (Y[i] - Yf) / dY[i], chisq);
    290310  }
    291311  fit[0].Nfit = Npts;
  • trunk/Ohana/src/opihi/cmd.data

  • trunk/Ohana/src/opihi/cmd.data/Makefile

    r36084 r36375  
    6464$(SRC)/imhist.$(ARCH).o \
    6565$(SRC)/imsmooth.$(ARCH).o       \
     66$(SRC)/imsmooth.generic.$(ARCH).o       \
     67$(SRC)/imsmooth.2d.$(ARCH).o    \
    6668$(SRC)/integrate.$(ARCH).o      \
    6769$(SRC)/interpolate.$(ARCH).o    \
  • trunk/Ohana/src/opihi/cmd.data/init.c

    r36084 r36375  
    5353int imhist           PROTO((int, char **));
    5454int imsmooth         PROTO((int, char **));
     55int imsmooth_generic PROTO((int, char **));
     56int imsmooth_2d      PROTO((int, char **));
    5557int integrate        PROTO((int, char **));
    5658int interpolate      PROTO((int, char **));
     
    208210  {1, "imhistogram",  imhist,           "histogram of an image region"},
    209211  {1, "imsmooth",     imsmooth,         "circular gaussian smoothing"},
     212  {1, "imsmooth.generic", imsmooth_generic, "circular non-gaussian smoothing"},
     213  {1, "imsmooth.2d",  imsmooth_2d,      "circular non-gaussian smoothing"},
    210214  {1, "imstats",      imstats,          "statistics on a portion of an image"},
    211215  {1, "integrate",    integrate,        "integrate a vector"},
  • trunk/Ohana/src/opihi/cmd.data/read_vectors.c

    r34753 r36375  
    2323// vector types
    2424enum {COLTYPE_NONE, COLTYPE_FLT, COLTYPE_INT, COLTYPE_TIME, COLTYPE_CHAR};
     25static int FITS_TRANSPOSE;
    2526
    2627int read_vectors (int argc, char **argv) {
     
    3435
    3536  char *buffer = NULL;
     37
     38  FITS_TRANSPOSE = FALSE;
     39  if ((Narg = get_argument (argc, argv, "-transpose"))) {
     40    remove_argument (Narg, &argc, argv);
     41    FITS_TRANSPOSE = TRUE;
     42  }
    3643
    3744  /* auto-sense table type */
     
    410417    }
    411418       
    412     // define the multifield vector names
    413     ALLOCATE (vec, Vector *, Nval);
    414     for (j = 0; j < Nval; j++) {
    415       if (Nval == 1)
    416         sprintf (name, "%s", argv[i]);
    417       else
    418         sprintf (name, "%s:%d", argv[i], j);
    419       if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) ESCAPE ("bad vector name");
    420       ResetVector (vec[j], vecType, Ny);
    421     }
    422 
    423     if (!strcmp (type, "char")) {
    424       char *Ptr = data;
     419    if (!FITS_TRANSPOSE) {
     420      // define the multifield vector names (Nval vectors x Ny elements)
     421      ALLOCATE (vec, Vector *, Nval);
     422      for (j = 0; j < Nval; j++) {
     423        if (Nval == 1)
     424          sprintf (name, "%s", argv[i]);
     425        else
     426          sprintf (name, "%s:%d", argv[i], j);
     427        if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) ESCAPE ("bad vector name");
     428        ResetVector (vec[j], vecType, Ny);
     429      }
     430
     431      if (!strcmp (type, "char")) {
     432        char *Ptr = data;
     433        for (j = 0; j < Ny; j++) {
     434          for (k = 0; k < Nval; k++, Ptr++) {
     435            vec[k][0].elements.Int[j] = *Ptr;
     436          }
     437        }
     438      }
     439      if (!strcmp (type, "short")) {
     440        short *Ptr = data;
     441        for (j = 0; j < Ny; j++) {
     442          for (k = 0; k < Nval; k++, Ptr++) {
     443            vec[k][0].elements.Int[j] = *Ptr;
     444          }
     445        }
     446      }
     447      if (!strcmp (type, "int")) {
     448        int *Ptr = data;
     449        for (j = 0; j < Ny; j++) {
     450          for (k = 0; k < Nval; k++, Ptr++) {
     451            vec[k][0].elements.Int[j] = *Ptr;
     452          }
     453        }
     454      }
     455      if (!strcmp (type, "int64_t")) {
     456        int64_t *Ptr = data;
     457        for (j = 0; j < Ny; j++) {
     458          for (k = 0; k < Nval; k++, Ptr++) {
     459            vec[k][0].elements.Int[j] = *Ptr;
     460          }
     461        }
     462      }
     463      if (!strcmp (type, "float")) {
     464        float *Ptr = data;
     465        for (j = 0; j < Ny; j++) {
     466          for (k = 0; k < Nval; k++, Ptr++) {
     467            vec[k][0].elements.Flt[j] = *Ptr;
     468          }
     469        }
     470      }
     471      if (!strcmp (type, "double")) {
     472        double *Ptr = data;
     473        for (j = 0; j < Ny; j++) {
     474          for (k = 0; k < Nval; k++, Ptr++) {
     475            vec[k][0].elements.Flt[j] = *Ptr;
     476          }
     477        }
     478      }
     479    } else {
     480      // define the multifield vector names (Ny vectors x Nval elements)
     481      ALLOCATE (vec, Vector *, Ny);
    425482      for (j = 0; j < Ny; j++) {
    426         for (k = 0; k < Nval; k++, Ptr++) {
    427           vec[k][0].elements.Int[j] = *Ptr;
    428         }
    429       }
    430     }
    431     if (!strcmp (type, "short")) {
    432       short *Ptr = data;
    433       for (j = 0; j < Ny; j++) {
    434         for (k = 0; k < Nval; k++, Ptr++) {
    435           vec[k][0].elements.Int[j] = *Ptr;
    436         }
    437       }
    438     }
    439     if (!strcmp (type, "int")) {
    440       int *Ptr = data;
    441       for (j = 0; j < Ny; j++) {
    442         for (k = 0; k < Nval; k++, Ptr++) {
    443           vec[k][0].elements.Int[j] = *Ptr;
    444         }
    445       }
    446     }
    447     if (!strcmp (type, "int64_t")) {
    448       int64_t *Ptr = data;
    449       for (j = 0; j < Ny; j++) {
    450         for (k = 0; k < Nval; k++, Ptr++) {
    451           vec[k][0].elements.Int[j] = *Ptr;
    452         }
    453       }
    454     }
    455     if (!strcmp (type, "float")) {
    456       float *Ptr = data;
    457       for (j = 0; j < Ny; j++) {
    458         for (k = 0; k < Nval; k++, Ptr++) {
    459           vec[k][0].elements.Flt[j] = *Ptr;
    460         }
    461       }
    462     }
    463     if (!strcmp (type, "double")) {
    464       double *Ptr = data;
    465       for (j = 0; j < Ny; j++) {
    466         for (k = 0; k < Nval; k++, Ptr++) {
    467           vec[k][0].elements.Flt[j] = *Ptr;
     483        if (Ny == 1)
     484          sprintf (name, "%s", argv[i]);
     485        else
     486          sprintf (name, "%s:%d", argv[i], j);
     487        if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) ESCAPE ("bad vector name");
     488        ResetVector (vec[j], vecType, Nval);
     489      }
     490
     491      if (!strcmp (type, "char")) {
     492        char *Ptr = data;
     493        for (j = 0; j < Ny; j++) {
     494          for (k = 0; k < Nval; k++, Ptr++) {
     495            vec[j][0].elements.Int[k] = *Ptr;
     496          }
     497        }
     498      }
     499      if (!strcmp (type, "short")) {
     500        short *Ptr = data;
     501        for (j = 0; j < Ny; j++) {
     502          for (k = 0; k < Nval; k++, Ptr++) {
     503            vec[j][0].elements.Int[k] = *Ptr;
     504          }
     505        }
     506      }
     507      if (!strcmp (type, "int")) {
     508        int *Ptr = data;
     509        for (j = 0; j < Ny; j++) {
     510          for (k = 0; k < Nval; k++, Ptr++) {
     511            vec[j][0].elements.Int[k] = *Ptr;
     512          }
     513        }
     514      }
     515      if (!strcmp (type, "int64_t")) {
     516        int64_t *Ptr = data;
     517        for (j = 0; j < Ny; j++) {
     518          for (k = 0; k < Nval; k++, Ptr++) {
     519            vec[j][0].elements.Int[k] = *Ptr;
     520          }
     521        }
     522      }
     523      if (!strcmp (type, "float")) {
     524        float *Ptr = data;
     525        for (j = 0; j < Ny; j++) {
     526          for (k = 0; k < Nval; k++, Ptr++) {
     527            vec[j][0].elements.Flt[k] = *Ptr;
     528          }
     529        }
     530      }
     531      if (!strcmp (type, "double")) {
     532        double *Ptr = data;
     533        for (j = 0; j < Ny; j++) {
     534          for (k = 0; k < Nval; k++, Ptr++) {
     535            vec[j][0].elements.Flt[k] = *Ptr;
     536          }
    468537        }
    469538      }
  • trunk/Ohana/src/opihi/dvo/Makefile

    r34461 r36375  
    4040$(SRC)/cmpload.$(ARCH).o                \
    4141$(SRC)/cmpread.$(ARCH).o                \
     42$(SRC)/coordimage.$(ARCH).o             \
    4243$(SRC)/ddmags.$(ARCH).o         \
    4344$(SRC)/detrend.$(ARCH).o                \
  • trunk/Ohana/src/opihi/dvo/init.c

    r34461 r36375  
    1313int cmpload         PROTO((int, char **));
    1414int cmpread         PROTO((int, char **));
     15int coordimage      PROTO((int, char **));
    1516int ddmags          PROTO((int, char **));
    1617int detrend         PROTO((int, char **));
     
    7172  {1, "cmpload",     cmpload,      "load cmp file into ?"},
    7273  {1, "cmpread",     cmpread,      "read data from cmp format files"},
     74  {1, "coordimage",  coordimage,   "generate a map of the transformation residuals"},
    7375  {1, "ddmags",      ddmags,       "plot magnitude differences"},
    7476  {1, "detrend",     detrend,      "extract from detrend database?"},
  • trunk/Ohana/src/opihi/include/dvomath.h

    r33662 r36375  
    5555} Buffer;
    5656
     57typedef enum {
     58  ST_NONE,
     59  ST_LEFT,
     60  ST_RIGHT,
     61  ST_COMMA,
     62  ST_TRINARY,
     63  ST_OR,
     64  ST_AND,
     65  ST_LOGIC,
     66  ST_BITWISE,
     67  ST_ADD,
     68  ST_TIMES,
     69  ST_POWER,
     70  ST_UNARY,
     71  ST_BINARY,
     72
     73  ST_VALUE,
     74  ST_SCALAR_INT,
     75  ST_SCALAR_FLT,
     76  ST_VECTOR,
     77  ST_VECTOR_TMP,
     78  ST_MATRIX,
     79  ST_MATRIX_TMP,
     80
     81  ST_STRING,
     82  ST_STRING_TMP,
     83} StackVarType;
     84
    5785typedef struct {                        /* math stack structure */
    5886  char   *name;
    59   char    type;
     87  StackVarType type;
    6088  Buffer *buffer;
    6189  Vector *vector;
     
    77105void          delete_stack          PROTO((StackVar *stack, int Nstack));
    78106void          clear_stack           PROTO((StackVar *stack));
    79 void          assign_stack          PROTO((StackVar *stack, char *name, int type));
     107void          assign_stack          PROTO((StackVar *stack, char *name, StackVarType type));
     108
     109int           SSS_trinary           PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op));
     110int           VVV_trinary           PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op));
     111int           MMM_trinary           PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op));
    80112
    81113int           VV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
  • trunk/Ohana/src/opihi/include/pcontrol.h

    r33662 r36375  
    88/** job status values **/
    99typedef enum {
     10  PCONTROL_JOB_NONE, // XXX OK?
    1011  PCONTROL_JOB_ALLJOBS,
    1112  PCONTROL_JOB_PENDING,
     
    309310char  *GetJobStackName (int StackID);
    310311Stack *GetJobStackByName (char *name);
     312int GetJobStackIDbyName (char *name);
    311313int    PutJob (Job *job, int StackID, int where);
    312314int    PutJobSetState (Job *job, int StackID, int where, int state);
  • trunk/Ohana/src/opihi/lib.shell/check_stack.c

    r34260 r36375  
    1212
    1313  for (i = 0; i < Nstack; i++) {
    14     if (stack[i].type == 'X') {
     14    if (stack[i].type == ST_VALUE) {
    1515
    1616      /** if this is a number, put it on the list of scalars and move on.  assume value is
     
    2727      stack[i].IntValue = strtol (stack[i].name, &c2, 0);
    2828      if ((fabs(stack[i].FltValue) > MAX_INT) && (c1 == stack[i].name + strlen (stack[i].name))) {
    29         stack[i].type  = 'S'; // 'S' == (float)
     29        stack[i].type  = ST_SCALAR_FLT; // (float)
    3030        continue;
    3131      }
    3232      if (c2 == stack[i].name + strlen (stack[i].name)) {
    33         stack[i].type  = 's'; // 's' == (int)
     33        stack[i].type  = ST_SCALAR_INT; // (int)
    3434        continue;
    3535      }
    3636      if (c1 == stack[i].name + strlen (stack[i].name)) {
    37         stack[i].type  = 'S'; // 'S' == (float)
     37        stack[i].type  = ST_SCALAR_FLT; // (float)
    3838        continue;
    3939      }
     
    4242      if (IsBuffer (stack[i].name)) {
    4343        stack[i].buffer = SelectBuffer (stack[i].name, OLDBUFFER, TRUE);
    44         stack[i].type   = 'M';
     44        stack[i].type   = ST_MATRIX;
    4545        if (Nx == -1) {
    4646          Nx = stack[i].buffer[0].matrix.Naxis[0];
     
    6363      if (IsVector (stack[i].name)) {
    6464        stack[i].vector = SelectVector (stack[i].name, OLDVECTOR, FALSE);
    65         stack[i].type   = 'V';
     65        stack[i].type   = ST_VECTOR;
    6666
    6767        if (Nv == -1) Nv = stack[i].vector[0].Nelements;
     
    8080
    8181      /* this is not a scalar, vector, or matrix.  must be string */
    82       stack[i].type  = 'W';
     82      stack[i].type  = ST_STRING;
    8383    }
    8484  }
  • trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c

    r34088 r36375  
    44StackVar *convert_to_RPN (int argc, char **argv, int *nstack) {
    55 
    6   int type;
     6 StackVarType type;
    77  int i, j, Nstack, Nop_stack, NSTACK;
    88  StackVar *stack, *op_stack;
     
    2121   
    2222    /* decide on priority of object */
    23     type = 0;
     23    type = ST_NONE;
     24
     25    /* trinary operations */
     26    if (!strcmp (argv[i], "?"))      { type = ST_TRINARY; goto gotit; }
     27    if (!strcmp (argv[i], ":"))      { type = ST_COMMA; goto gotit; }
     28
    2429    /* unary operations */
    25     if (!strcmp (argv[i], "abs"))    { type = 9; goto gotit; }
    26     if (!strcmp (argv[i], "int"))    { type = 9; goto gotit; }
    27     if (!strcmp (argv[i], "exp"))    { type = 9; goto gotit; }
    28     if (!strcmp (argv[i], "ten"))    { type = 9; goto gotit; }
    29     if (!strcmp (argv[i], "log"))    { type = 9; goto gotit; }
    30     if (!strcmp (argv[i], "ln"))     { type = 9; goto gotit; }
    31     if (!strcmp (argv[i], "sqrt"))   { type = 9; goto gotit; }
    32     if (!strcmp (argv[i], "erf"))    { type = 9; goto gotit; }
    33 
    34     if (!strcmp (argv[i], "sinh"))   { type = 9; goto gotit; }
    35     if (!strcmp (argv[i], "cosh"))   { type = 9; goto gotit; }
    36     if (!strcmp (argv[i], "asinh"))  { type = 9; goto gotit; }
    37     if (!strcmp (argv[i], "acosh"))  { type = 9; goto gotit; }
    38 
    39     if (!strcmp (argv[i], "sin"))    { type = 9; goto gotit; }
    40     if (!strcmp (argv[i], "cos"))    { type = 9; goto gotit; }
    41     if (!strcmp (argv[i], "tan"))    { type = 9; goto gotit; }
    42     if (!strcmp (argv[i], "dsin"))   { type = 9; goto gotit; }
    43     if (!strcmp (argv[i], "dcos"))   { type = 9; goto gotit; }
    44     if (!strcmp (argv[i], "dtan"))   { type = 9; goto gotit; }
    45     if (!strcmp (argv[i], "asin"))   { type = 9; goto gotit; }
    46     if (!strcmp (argv[i], "acos"))   { type = 9; goto gotit; }
    47     if (!strcmp (argv[i], "atan"))   { type = 9; goto gotit; }
    48     if (!strcmp (argv[i], "dasin"))  { type = 9; goto gotit; }
    49     if (!strcmp (argv[i], "dacos"))  { type = 9; goto gotit; }
    50     if (!strcmp (argv[i], "datan"))  { type = 9; goto gotit; }
    51 
    52     if (!strcmp (argv[i], "lgamma")) { type = 9; goto gotit; }
    53 
    54     if (!strcmp (argv[i], "rnd"))    { type = 9; goto gotit; }
    55     if (!strcmp (argv[i], "xramp"))  { type = 9; goto gotit; }
    56     if (!strcmp (argv[i], "yramp"))  { type = 9; goto gotit; }
    57     if (!strcmp (argv[i], "ramp"))   { type = 9; goto gotit; }
    58     if (!strcmp (argv[i], "zero"))   { type = 9; goto gotit; }
    59     if (!strcmp (argv[i], "--"))     { type = 9; goto gotit; }
    60     if (!strcmp (argv[i], "not"))    { type = 9; goto gotit; }
    61     if (!strcmp (argv[i], "isinf"))  { type = 9; goto gotit; }
    62     if (!strcmp (argv[i], "isnan"))  { type = 9; goto gotit; }
     30    if (!strcmp (argv[i], "abs"))    { type = ST_UNARY; goto gotit; }
     31    if (!strcmp (argv[i], "int"))    { type = ST_UNARY; goto gotit; }
     32    if (!strcmp (argv[i], "exp"))    { type = ST_UNARY; goto gotit; }
     33    if (!strcmp (argv[i], "ten"))    { type = ST_UNARY; goto gotit; }
     34    if (!strcmp (argv[i], "log"))    { type = ST_UNARY; goto gotit; }
     35    if (!strcmp (argv[i], "ln"))     { type = ST_UNARY; goto gotit; }
     36    if (!strcmp (argv[i], "sqrt"))   { type = ST_UNARY; goto gotit; }
     37    if (!strcmp (argv[i], "erf"))    { type = ST_UNARY; goto gotit; }
     38    if (!strcmp (argv[i], "sinh"))   { type = ST_UNARY; goto gotit; }
     39    if (!strcmp (argv[i], "cosh"))   { type = ST_UNARY; goto gotit; }
     40    if (!strcmp (argv[i], "asinh"))  { type = ST_UNARY; goto gotit; }
     41    if (!strcmp (argv[i], "acosh"))  { type = ST_UNARY; goto gotit; }
     42    if (!strcmp (argv[i], "sin"))    { type = ST_UNARY; goto gotit; }
     43    if (!strcmp (argv[i], "cos"))    { type = ST_UNARY; goto gotit; }
     44    if (!strcmp (argv[i], "tan"))    { type = ST_UNARY; goto gotit; }
     45    if (!strcmp (argv[i], "dsin"))   { type = ST_UNARY; goto gotit; }
     46    if (!strcmp (argv[i], "dcos"))   { type = ST_UNARY; goto gotit; }
     47    if (!strcmp (argv[i], "dtan"))   { type = ST_UNARY; goto gotit; }
     48    if (!strcmp (argv[i], "asin"))   { type = ST_UNARY; goto gotit; }
     49    if (!strcmp (argv[i], "acos"))   { type = ST_UNARY; goto gotit; }
     50    if (!strcmp (argv[i], "atan"))   { type = ST_UNARY; goto gotit; }
     51    if (!strcmp (argv[i], "dasin"))  { type = ST_UNARY; goto gotit; }
     52    if (!strcmp (argv[i], "dacos"))  { type = ST_UNARY; goto gotit; }
     53    if (!strcmp (argv[i], "datan"))  { type = ST_UNARY; goto gotit; }
     54    if (!strcmp (argv[i], "lgamma")) { type = ST_UNARY; goto gotit; }
     55    if (!strcmp (argv[i], "rnd"))    { type = ST_UNARY; goto gotit; }
     56    if (!strcmp (argv[i], "xramp"))  { type = ST_UNARY; goto gotit; }
     57    if (!strcmp (argv[i], "yramp"))  { type = ST_UNARY; goto gotit; }
     58    if (!strcmp (argv[i], "ramp"))   { type = ST_UNARY; goto gotit; }
     59    if (!strcmp (argv[i], "zero"))   { type = ST_UNARY; goto gotit; }
     60    if (!strcmp (argv[i], "--"))     { type = ST_UNARY; goto gotit; }
     61    if (!strcmp (argv[i], "not"))    { type = ST_UNARY; goto gotit; }
     62    if (!strcmp (argv[i], "isinf"))  { type = ST_UNARY; goto gotit; }
     63    if (!strcmp (argv[i], "isnan"))  { type = ST_UNARY; goto gotit; }
    6364
    6465    /* binary operations */
    65     if (!strcmp (argv[i], "^"))      { type = 8; goto gotit; }
    66 
    67     if (!strcmp (argv[i], "@"))      { type = 7; goto gotit; }
    68     if (!strcmp (argv[i], "/"))      { type = 7; goto gotit; }
    69     if (!strcmp (argv[i], "*"))      { type = 7; goto gotit; }
    70     if (!strcmp (argv[i], "%"))      { type = 7; goto gotit; }
    71 
    72     if (!strcmp (argv[i], "+"))      { type = 6; goto gotit; }
    73     if (!strcmp (argv[i], "-"))      { type = 6; goto gotit; }
     66    if (!strcmp (argv[i], "^"))      { type = ST_POWER; goto gotit; }
     67
     68    if (!strcmp (argv[i], "atan2"))  { type = ST_BINARY; goto gotit; }
     69    if (!strcmp (argv[i], ","))      { type = ST_COMMA; goto gotit; }
     70
     71    if (!strcmp (argv[i], "@"))      { type = ST_TIMES; goto gotit; }
     72    if (!strcmp (argv[i], "/"))      { type = ST_TIMES; goto gotit; }
     73    if (!strcmp (argv[i], "*"))      { type = ST_TIMES; goto gotit; }
     74    if (!strcmp (argv[i], "%"))      { type = ST_TIMES; goto gotit; }
     75
     76    if (!strcmp (argv[i], "+"))      { type = ST_ADD; goto gotit; }
     77    if (!strcmp (argv[i], "-"))      { type = ST_ADD; goto gotit; }
    7478       
    75     if (!strcmp (argv[i], "&"))      { type = 5; goto gotit; }
    76     if (!strcmp (argv[i], "|"))      { type = 5; goto gotit; }
    77 
    78     if (!strcmp (argv[i], "<"))      { type = 4; goto gotit; }
    79     if (!strcmp (argv[i], ">"))      { type = 4; goto gotit; }
    80     if (!strcmp (argv[i], "=="))     { type = 4; strcpy (argv[i], "E"); goto gotit; }
    81     if (!strcmp (argv[i], "!="))     { type = 4; strcpy (argv[i], "N"); goto gotit; }
    82     if (!strcmp (argv[i], "<="))     { type = 4; strcpy (argv[i], "L"); goto gotit; }
    83     if (!strcmp (argv[i], ">="))     { type = 4; strcpy (argv[i], "G"); goto gotit; }
    84     if (!strcmp (argv[i], ">>"))     { type = 4; strcpy (argv[i], "U"); goto gotit; }
    85     if (!strcmp (argv[i], "<<"))     { type = 4; strcpy (argv[i], "D"); goto gotit; }
    86 
    87     if (!strcmp (argv[i], "&&"))     { type = 3; strcpy (argv[i], "A"); goto gotit; }
    88     if (!strcmp (argv[i], "||"))     { type = 3; strcpy (argv[i], "O"); goto gotit; }
    89 
    90     if (!strcmp (argv[i], "("))      { type = 2; goto gotit; }
    91     if (!strcmp (argv[i], ")"))      { type = 1; goto gotit; }
     79    if (!strcmp (argv[i], "&"))      { type = ST_BITWISE; goto gotit; }
     80    if (!strcmp (argv[i], "|"))      { type = ST_BITWISE; goto gotit; }
     81
     82    if (!strcmp (argv[i], "<"))      { type = ST_LOGIC; goto gotit; }
     83    if (!strcmp (argv[i], ">"))      { type = ST_LOGIC; goto gotit; }
     84    if (!strcmp (argv[i], "=="))     { type = ST_LOGIC; strcpy (argv[i], "E"); goto gotit; }
     85    if (!strcmp (argv[i], "!="))     { type = ST_LOGIC; strcpy (argv[i], "N"); goto gotit; }
     86    if (!strcmp (argv[i], "<="))     { type = ST_LOGIC; strcpy (argv[i], "L"); goto gotit; }
     87    if (!strcmp (argv[i], ">="))     { type = ST_LOGIC; strcpy (argv[i], "G"); goto gotit; }
     88    if (!strcmp (argv[i], ">>"))     { type = ST_LOGIC; strcpy (argv[i], "U"); goto gotit; }
     89    if (!strcmp (argv[i], "<<"))     { type = ST_LOGIC; strcpy (argv[i], "D"); goto gotit; }
     90
     91    if (!strcmp (argv[i], "&&"))     { type = ST_AND; strcpy (argv[i], "A"); goto gotit; }
     92    if (!strcmp (argv[i], "||"))     { type = ST_OR ; strcpy (argv[i], "O"); goto gotit; }
     93
     94    if (!strcmp (argv[i], "("))      { type = ST_LEFT; goto gotit; }
     95    if (!strcmp (argv[i], ")"))      { type = ST_RIGHT; goto gotit; }
    9296
    9397  gotit:
    9498    /* choose how to deal with object */
    9599    switch (type) {
    96       case 8:  /* exponentiation: 2^2^3 = 64 != 256 (precedence is right-to-left, not left-to-right!) */
     100      case ST_POWER:  /* exponentiation: 2^2^3 = 64 != 256 (precedence is right-to-left, not left-to-right!) */
    97101        /* pop previous, higher operators from OP stack to stack */
    98102        for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type > type); j--) {
     
    105109        Nop_stack ++;
    106110        break;
    107       case 9: /* unary OPs */
    108       case 7: /* binary OPs */
    109       case 6:
    110       case 5:
    111       case 4:
    112       case 3:
     111      case ST_UNARY:
     112      case ST_BINARY:
     113      case ST_TRINARY:
     114      case ST_TIMES:
     115      case ST_ADD:
     116      case ST_BITWISE:
     117      case ST_LOGIC:
     118      case ST_AND:
     119      case ST_OR:
    113120        /* pop previous, higher or equal operators from OP stack to stack */
    114121        for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type >= type); j--) {
     
    121128        Nop_stack ++;
    122129        break;
    123       case 2
     130      case ST_LEFT
    124131        /* push operator on OP stack */
    125132        assign_stack (&op_stack[Nop_stack], argv[i], type);
     
    127134        Nop_stack ++;
    128135        break;
    129       case 1:
     136      case ST_RIGHT:
    130137        /* pop rest of operators from OP stack to stack, looking for '(' */
    131         for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != 2); j--) {
    132           move_stack (&stack[Nstack], &op_stack[j]);
    133           Nstack ++;
    134           Nop_stack --;
    135         }
    136         if ((j == -1) || (op_stack[j].type != 2)) {
     138        for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != ST_LEFT); j--) {
     139          move_stack (&stack[Nstack], &op_stack[j]);
     140          Nstack ++;
     141          Nop_stack --;
     142        }
     143        if ((j == -1) || (op_stack[j].type != ST_LEFT)) {
    137144          push_error ("syntax error: mismatched parenthesis");
    138145          Nstack = 0;
     
    144151        Nop_stack --;
    145152        break;
    146       case 0:
     153      case ST_COMMA:
     154        /* pop rest of operators from OP stack to stack, looking for '(' (but do not pop the '(')*/
     155        for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != ST_LEFT) && (op_stack[j].type != ST_TRINARY); j--) {
     156          move_stack (&stack[Nstack], &op_stack[j]);
     157          Nstack ++;
     158          Nop_stack --;
     159        }
     160        break;
     161      case ST_NONE:
    147162        /* place the value (number or vector/matrix name) on stack */
    148163        /* value of 'X' is used as sentinel until we sort out values */
    149         assign_stack (&stack[Nstack], argv[i], 'X');
     164        assign_stack (&stack[Nstack], argv[i], ST_VALUE);
    150165        Nstack ++;
    151166        break;
     167
     168      default:
     169        push_error ("invalid stack typ");
     170        Nstack = 0;
     171        goto cleanup;
    152172    }
    153173  }
    154174
    155   /* dump remaining operators on stack, checking for ')' */
     175  /* dump remaining operators on stack, checking for '(' */
    156176  for (j = Nop_stack - 1; j >= 0; j--) {
    157     if (op_stack[j].type == 2) {
     177    if (op_stack[j].type == ST_LEFT) {
    158178      push_error ("syntax error: mismatched parenthesis");
    159179      Nstack = 0;
  • trunk/Ohana/src/opihi/lib.shell/dvomath.c

    r31635 r36375  
    8080        sprintf (outname, "%s", stack[0].name);
    8181      } else {
    82         if (stack[0].type == 's') {
     82        if (stack[0].type == ST_SCALAR_INT) {
    8383          sprintf (outname, "%d", stack[0].IntValue);
    8484        } else {
  • trunk/Ohana/src/opihi/lib.shell/evaluate_stack.c

    r34088 r36375  
    22# define VERBOSE 0
    33
    4 # define TWO_OP(A,B,FUNC) \
    5   if (!strncasecmp (&stack[i - 2].type, A, 1) && !strncasecmp (&stack[i - 1].type, B, 1)) \
    6     status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name);
    7 
    8 # define ONE_OP(A,FUNC) \
    9   if (!strncasecmp (&stack[i - 1].type, A, 1)) \
    10     status = FUNC (&tmp_stack, &stack[i - 1], stack[i].name);
     4// all three operands must have the same type
     5# define THREE_OP(A,FUNC)                                               \
     6  if ((stack[i - 3].type == A) && (stack[i - 2].type == A) && (stack[i - 1].type == A)) { \
     7    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     8    goto got_three_op; } \
     9  if ((stack[i - 3].type == A+1) && (stack[i - 2].type == A) && (stack[i - 1].type == A)) { \
     10    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     11    goto got_three_op; } \
     12  if ((stack[i - 3].type == A) && (stack[i - 2].type == A+1) && (stack[i - 1].type == A)) { \
     13    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     14    goto got_three_op; } \
     15  if ((stack[i - 3].type == A+1) && (stack[i - 2].type == A+1) && (stack[i - 1].type == A)) { \
     16    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     17    goto got_three_op; } \
     18  if ((stack[i - 3].type == A) && (stack[i - 2].type == A) && (stack[i - 1].type == A+1)) { \
     19    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     20    goto got_three_op; } \
     21  if ((stack[i - 3].type == A+1) && (stack[i - 2].type == A) && (stack[i - 1].type == A+1)) { \
     22    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     23    goto got_three_op; } \
     24  if ((stack[i - 3].type == A) && (stack[i - 2].type == A+1) && (stack[i - 1].type == A+1)) { \
     25    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     26    goto got_three_op; } \
     27  if ((stack[i - 3].type == A+1) && (stack[i - 2].type == A+1) && (stack[i - 1].type == A+1)) { \
     28    status = FUNC (&tmp_stack, &stack[i - 3], &stack[i - 2], &stack[i - 1], stack[i].name); \
     29    goto got_three_op; } \
     30
     31// A & B value types all have 2 possible values
     32# define TWO_OP(A,B,FUNC) {                                             \
     33    if ((stack[i - 2].type == A) && (stack[i - 1].type == B)) {         \
     34      status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); \
     35      goto got_two_op; }                                                \
     36    if ((stack[i - 2].type == A+1) && (stack[i - 1].type == B)) {       \
     37      status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); \
     38      goto got_two_op; }                                                \
     39    if ((stack[i - 2].type == A) && (stack[i - 1].type == B+1)) {       \
     40      status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); \
     41      goto got_two_op; }                                                \
     42    if ((stack[i - 2].type == A+1) && (stack[i - 1].type == B+1)) {     \
     43      status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); \
     44      goto got_two_op; } \
     45  }
     46
     47# define ONE_OP(A,FUNC)                                         \
     48  if (stack[i - 1].type == A) {                                 \
     49    status = FUNC (&tmp_stack, &stack[i - 1], stack[i].name);   \
     50    goto got_one_op; }
    1151
    1252int evaluate_stack (StackVar *stack, int *Nstack) {
     
    2060
    2161  if (*Nstack == 1) {
    22     if ((stack[0].type == 'S') || (stack[0].type == 's')) {
     62    if ((stack[0].type == ST_SCALAR_INT) || (stack[0].type == ST_SCALAR_FLT)) {
    2363      clear_stack (&tmp_stack);
    2464      return (TRUE);
    2565    }
    26     if (stack[0].type == 'V') {
     66    if (stack[0].type == ST_VECTOR) {
    2767      /* need to make a copy so we set output value? */
    2868      V_unary (&tmp_stack, &stack[0], "=");
     
    3070      return (TRUE);
    3171    }
    32     if (stack[0].type == 'M') {
     72    if (stack[0].type == ST_MATRIX) {
    3373      /* need to make a copy so we set output value? */
    3474      M_unary (&tmp_stack, &stack[0], "=");
     
    5696    }
    5797
    58     /***** binary operators *****/
    59     if ((stack[i].type >= 3) && (stack[i].type <= 8)) {
    60 
    61       if (i < 2) {  /* need two variables to operate on */
    62         sprintf (line, "syntax error: binary operator with one operand: %s\n", stack[i].name);
     98    /***** trinary operators *****/
     99    switch (stack[i].type) {
     100      case ST_TRINARY:
     101
     102        if (i < 3) {  /* need two variables to operate on */
     103          snprintf (line, 512, "syntax error: trinary operator without three operands: %s\n", stack[i].name);
     104          push_error (line);
     105          clear_stack (&tmp_stack);
     106          return (FALSE);
     107        }
     108
     109        status = FALSE;
     110        THREE_OP (ST_MATRIX,MMM_trinary);
     111        THREE_OP (ST_VECTOR,VVV_trinary);
     112
     113        THREE_OP (ST_SCALAR_FLT,SSS_trinary);
     114        THREE_OP (ST_SCALAR_INT,SSS_trinary);
     115
     116        /* there are no valid unary string operators */
     117        push_error ("invalid operands for trinary operator (mismatch types?)");
     118        clear_stack (&tmp_stack);
     119        return (FALSE);
     120
     121      got_three_op:
     122        if (!status) {
     123          snprintf (line, 512, "syntax error: invalid operand for binary operation: %s or %s or %s\n", stack[i-1].name, stack[i-2].name, stack[i-3].name);
     124          push_error (line);
     125          clear_stack (&tmp_stack);
     126          return (FALSE);
     127        }
     128        move_stack (&stack[i-3], &tmp_stack);
     129        delete_stack (&stack[i-2], 3);
     130        for (j = i + 1; j < *Nstack; j++) {
     131          move_stack (&stack[j-3], &stack[j]);
     132        }
     133        *Nstack -= 3;
     134        i -= 3;
     135        init_stack (&tmp_stack);
     136        continue;
     137
     138        /***** binary operators *****/
     139      case ST_OR:
     140      case ST_AND:
     141      case ST_LOGIC:
     142      case ST_BITWISE:
     143      case ST_ADD:
     144      case ST_TIMES:
     145      case ST_POWER:
     146      case ST_BINARY:
     147
     148        if (i < 2) {  /* need two variables to operate on */
     149          snprintf (line, 512, "syntax error: binary operator with one operand: %s\n", stack[i].name);
     150          push_error (line);
     151          clear_stack (&tmp_stack);
     152          return (FALSE);
     153        }
     154
     155        status = FALSE;
     156        TWO_OP (ST_MATRIX,ST_MATRIX,MM_binary);
     157        TWO_OP (ST_MATRIX,ST_VECTOR,MV_binary);
     158        TWO_OP (ST_MATRIX,ST_SCALAR_INT,MS_binary);
     159
     160        TWO_OP (ST_VECTOR,ST_MATRIX,VM_binary);
     161        TWO_OP (ST_VECTOR,ST_VECTOR,VV_binary);
     162        TWO_OP (ST_VECTOR,ST_SCALAR_INT,VS_binary);
     163
     164        TWO_OP (ST_SCALAR_INT,ST_MATRIX,SM_binary);
     165        TWO_OP (ST_SCALAR_INT,ST_VECTOR,SV_binary);
     166        TWO_OP (ST_SCALAR_INT,ST_SCALAR_INT,SS_binary);     
     167
     168        TWO_OP (ST_SCALAR_FLT,ST_MATRIX,SM_binary);
     169        TWO_OP (ST_SCALAR_FLT,ST_VECTOR,SV_binary);
     170        TWO_OP (ST_SCALAR_FLT,ST_SCALAR_INT,SS_binary);     
     171
     172        TWO_OP (ST_STRING,ST_STRING,WW_binary);     
     173        TWO_OP (ST_STRING,ST_SCALAR_INT,WW_binary);     
     174        TWO_OP (ST_SCALAR_INT,ST_STRING,WW_binary);     
     175     
     176      got_two_op:
     177        if (!status) {
     178          snprintf (line, 512, "syntax error: invalid operand for binary operation: %s or %s\n", stack[i-1].name, stack[i-2].name);
     179          push_error (line);
     180          clear_stack (&tmp_stack);
     181          return (FALSE);
     182        }
     183        move_stack (&stack[i-2], &tmp_stack);
     184        delete_stack (&stack[i-1], 2);
     185        for (j = i + 1; j < *Nstack; j++) {
     186          move_stack (&stack[j - 2], &stack[j]);
     187        }
     188        *Nstack -= 2;
     189        i -= 2;
     190        init_stack (&tmp_stack);
     191        continue;
     192
     193        /***** unary operators **/
     194      case ST_UNARY:
     195
     196        if (i < 1) {  /* need one variable to operate on */
     197          push_error ("syntax error: unary operator with no operand");
     198          clear_stack (&tmp_stack);
     199          return (FALSE);
     200        }
     201
     202        ONE_OP (ST_MATRIX, M_unary);
     203        ONE_OP (ST_MATRIX_TMP, M_unary);
     204
     205        ONE_OP (ST_VECTOR, V_unary);
     206        ONE_OP (ST_VECTOR_TMP, V_unary);
     207
     208        ONE_OP (ST_SCALAR_INT, S_unary);
     209        ONE_OP (ST_SCALAR_FLT, S_unary);
     210
     211        /* there are no valid unary string operators */
     212        push_error ("syntax error: no valid string unary ops");
     213        clear_stack (&tmp_stack);
     214        return (FALSE);
     215
     216      got_one_op:
     217        move_stack (&stack[i-1], &tmp_stack);
     218        delete_stack (&stack[i], 1);
     219        for (j = i + 1; j < *Nstack; j++) {
     220          move_stack (&stack[j - 1], &stack[j]);
     221        }
     222        init_stack (&tmp_stack);
     223        *Nstack -= 1;
     224        i -= 1;
     225        continue;
     226
     227      case ST_SCALAR_INT:
     228      case ST_SCALAR_FLT:
     229      case ST_VECTOR:
     230      case ST_VECTOR_TMP:
     231      case ST_MATRIX:
     232      case ST_MATRIX_TMP:
     233      case ST_STRING:
     234        continue;
     235
     236      default:
     237        snprintf (line, 512, "syntax error: unexpected operator type %s", stack[i].name);
    63238        push_error (line);
    64239        clear_stack (&tmp_stack);
    65240        return (FALSE);
    66       }
    67 
    68       status = FALSE;
    69       TWO_OP ("M","M",MM_binary);
    70       TWO_OP ("M","V",MV_binary);
    71       TWO_OP ("M","S",MS_binary);
    72       TWO_OP ("V","M",VM_binary);
    73       TWO_OP ("V","V",VV_binary);
    74       TWO_OP ("V","S",VS_binary);
    75       TWO_OP ("S","M",SM_binary);
    76       TWO_OP ("S","V",SV_binary);
    77       TWO_OP ("S","S",SS_binary);     
    78       TWO_OP ("W","W",WW_binary);     
    79       TWO_OP ("W","S",WW_binary);     
    80       TWO_OP ("S","W",WW_binary);     
    81      
    82       if (!status) {
    83         sprintf (line, "syntax error: invalid operand for binary operation: %s or %s\n", stack[i-1].name, stack[i-2].name);
    84         push_error (line);
    85         clear_stack (&tmp_stack);
    86         return (FALSE);
    87       }
    88       move_stack (&stack[i-2], &tmp_stack);
    89       delete_stack (&stack[i-1], 2);
    90       for (j = i + 1; j < *Nstack; j++) {
    91         move_stack (&stack[j - 2], &stack[j]);
    92       }
    93       *Nstack -= 2;
    94       i -= 2;
    95       init_stack (&tmp_stack);
    96       continue;
    97     }
    98 
    99     /***** unary operators **/
    100     if (stack[i].type == 9) {
    101 
    102       if (i < 1) {  /* need one variable to operate on */
    103         push_error ("syntax error: unary operator with no operand");
    104         clear_stack (&tmp_stack);
    105         return (FALSE);
    106       }
    107 
    108       ONE_OP ("M", M_unary);
    109       ONE_OP ("V", V_unary);
    110       ONE_OP ("S", S_unary);
    111 
    112       /* there are no valid unary string operators */
    113       if (!strncasecmp (&stack[i - 1].type, "W", 1)) {
    114         push_error ("syntax error: no valid string unary ops");
    115         clear_stack (&tmp_stack);
    116         return (FALSE);
    117       }
    118 
    119       move_stack (&stack[i-1], &tmp_stack);
    120       delete_stack (&stack[i], 1);
    121       for (j = i + 1; j < *Nstack; j++) {
    122         move_stack (&stack[j - 1], &stack[j]);
    123       }
    124       init_stack (&tmp_stack);
    125       *Nstack -= 1;
    126       i -= 1;
    127       continue;
    128     }
     241    }
    129242  }
    130243  clear_stack (&tmp_stack);
     
    160273
    161274  for (i = 0; i < Nstack; i++) {
    162     if (IsBufferPtr (stack[i].buffer) && (stack[i].type == 'm')) {
     275    if (IsBufferPtr (stack[i].buffer) && (stack[i].type == ST_MATRIX_TMP)) {
    163276      if (VERBOSE) gprint (GP_ERR, "free %s (buff) (%lx)\n", stack[i].name, (long) stack[i].buffer);
    164277      free (stack[i].buffer[0].header.buffer);
     
    167280      stack[i].buffer = NULL;
    168281    }   
    169     if (IsVectorPtr (stack[i].vector) && (stack[i].type == 'v')) {
     282    if (IsVectorPtr (stack[i].vector) && (stack[i].type == ST_VECTOR_TMP)) {
    170283      if (VERBOSE) gprint (GP_ERR, "free %s (vect) (%lx)\n", stack[i].name, (long) stack[i].vector);
    171284      free (stack[i].vector[0].elements.Ptr);
     
    193306}
    194307
    195 void assign_stack (StackVar *stack, char *name, int type) {
     308void assign_stack (StackVar *stack, char *name, StackVarType type) {
    196309  stack->name = strcreate (name);
    197310  stack->type = type;
  • trunk/Ohana/src/opihi/lib.shell/stack_math.c

    r34342 r36375  
    66*/
    77
    8 // XXX we temporarily drop the concept of using one of the temporary input vectors for
    9 // the output vector (thus saving an ALLOC): we have to juggle the size of the input vectors
    10 // as well as their temporary state
    11 
    12 int VV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
     8int SSS_trinary (StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op) {
     9
     10  char line[512]; // this is only used to report an error
     11 
     12  // set up the possible operations : int OP int -> int, all else yield float
     13  // OP is the operation performed on *M1 and *M2
     14# define SSS_FUNC(OP) {                                         \
     15    if ((V1->type == ST_SCALAR_FLT) && (V2->type == ST_SCALAR_FLT) && (V3->type == ST_SCALAR_FLT)) { \
     16      opihi_flt M1  =  V1[0].FltValue;                  \
     17      opihi_flt M2  =  V2[0].FltValue;                  \
     18      opihi_flt M3  =  V3[0].FltValue;                  \
     19      OUT[0].type = ST_SCALAR_FLT;                      \
     20      OUT[0].FltValue = OP;                                                     \
     21      break;                                                            \
     22    }                                                                   \
     23    if ((V1->type == ST_SCALAR_INT) && (V2->type == ST_SCALAR_INT) && (V3->type == ST_SCALAR_INT)) { \
     24      opihi_int M1  =  V1[0].IntValue;                  \
     25      opihi_int M2  =  V2[0].IntValue;                  \
     26      opihi_int M3  =  V3[0].IntValue;                  \
     27      OUT[0].type = ST_SCALAR_INT;                      \
     28      OUT[0].IntValue = OP;                                                     \
     29      break;                                                            \
     30    }                                                                   \
     31  }
     32
     33  switch (op[0]) {
     34    case '?': SSS_FUNC(M1 ? M2: M3);
     35    default:
     36      snprintf (line, 512, "error: op %c not defined!", op[0]);
     37      push_error (line);
     38      return (FALSE);
     39  }
     40# undef SSS_FUNC
     41
     42  clear_stack (V1);
     43  clear_stack (V2);
     44  clear_stack (V3);
     45  return (TRUE);
     46
     47}
     48
     49int VVV_trinary (StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op) {
    1350
    1451  int i, Nx;
     
    1956    return (FALSE);
    2057  }
     58  if (V1[0].vector[0].Nelements != V3[0].vector[0].Nelements) {
     59    return (FALSE);
     60  }
    2161
    2262  Nx = V1[0].vector[0].Nelements;
     
    2464  // create the output vector guaranteed to be temporary until the very end
    2565  OUT[0].vector = InitVector ();
    26   OUT[0].type = 'v';
     66  OUT[0].type = ST_VECTOR_TMP;
     67
     68  // set up the possible operations : int OP int -> int, all else yield float
     69  // OP is the operation performed on *M1 and *M2
     70# define VVV_FUNC(OP) {                                         \
     71    if ((V1->vector->type == OPIHI_FLT) && (V2->vector->type == OPIHI_FLT) && (V3->vector->type == OPIHI_FLT)) { \
     72      CopyVector (OUT[0].vector, V1[0].vector);                         \
     73      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     74      opihi_flt *M2  =  V2[0].vector[0].elements.Flt;                   \
     75      opihi_flt *M3  =  V3[0].vector[0].elements.Flt;                   \
     76      opihi_flt *out = OUT[0].vector[0].elements.Flt;                   \
     77      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {               \
     78        *out = OP;                                                      \
     79      }                                                                 \
     80      break;                                                            \
     81    }                                                                   \
     82    if ((V1->vector->type == OPIHI_INT) && (V2->vector->type == OPIHI_INT) && (V3->vector->type == OPIHI_INT)) { \
     83      CopyVector (OUT[0].vector, V1[0].vector);                         \
     84      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     85      opihi_int *M2  =  V2[0].vector[0].elements.Int;                   \
     86      opihi_int *M3  =  V3[0].vector[0].elements.Int;                   \
     87      opihi_int *out = OUT[0].vector[0].elements.Int;                   \
     88      for (i = 0; i < Nx; i++, out++, M1++, M2++, M3++) {               \
     89        *out = OP;                                                      \
     90      }                                                                 \
     91      break;                                                            \
     92    }                                                                   \
     93  }
     94
     95  switch (op[0]) {
     96    case '?': VVV_FUNC(*M1 ? *M2: *M3);
     97    default:
     98      snprintf (line, 512, "error: op %c not defined!", op[0]);
     99      push_error (line);
     100      return (FALSE);
     101  }
     102# undef VVV_FUNC
     103
     104  /** free up any temporary buffers: **/
     105
     106  if (V1[0].type == ST_VECTOR_TMP) {
     107    free (V1[0].vector[0].elements.Ptr);
     108    free (V1[0].vector);
     109  }
     110  if (V2[0].type == ST_VECTOR_TMP) {
     111    free (V2[0].vector[0].elements.Ptr);
     112    free (V2[0].vector);
     113  }
     114  if (V3[0].type == ST_VECTOR_TMP) {
     115    free (V3[0].vector[0].elements.Ptr);
     116    free (V3[0].vector);
     117  }
     118  /* at the end, V1 and V2 are deleted only if they were temporary */
     119
     120  clear_stack (V1);
     121  clear_stack (V2);
     122  clear_stack (V3);
     123  return (TRUE);
     124
     125}
     126
     127int MMM_trinary (StackVar *OUT, StackVar *V1, StackVar *V2, StackVar *V3, char *op) {
     128
     129  int i, Nx, Ny;
     130  float *out, *M1, *M2, *M3;
     131  char line[512]; // this is only used to report an error
     132 
     133  Nx = V1[0].buffer[0].matrix.Naxis[0];
     134  Ny = V1[0].buffer[0].matrix.Naxis[1];
     135
     136  if (V1[0].type == ST_MATRIX_TMP) {  /** use V1 as temp buffer **/
     137    OUT[0].buffer = V1[0].buffer;
     138    V1[0].type = ST_MATRIX; /* prevent it from being freed below */
     139  } else {
     140    if (V2[0].type == ST_MATRIX_TMP) { /** use V2 as temp buffer, but header of V1 **/
     141      OUT[0].buffer = V2[0].buffer;
     142      V2[0].type = ST_MATRIX; /* prevent it from being freed below */
     143    } else {  /* no spare temp buffer */
     144      OUT[0].buffer = InitBuffer ();
     145      CopyBuffer (OUT[0].buffer, V1[0].buffer);
     146    }
     147  }
     148  OUT[0].type = ST_MATRIX_TMP; /*** <<--- says this is a temporary matrix ***/
     149
     150  M1  = (float *)V1[0].buffer[0].matrix.buffer;
     151  M2  = (float *)V2[0].buffer[0].matrix.buffer;
     152  M3  = (float *)V3[0].buffer[0].matrix.buffer;
     153  out = (float *)OUT[0].buffer[0].matrix.buffer;
     154
     155# define MMM_FUNC(OP)                                   \
     156  for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++, M3++) {        \
     157    *out = OP;                                          \
     158  }                                                     \
     159  break;
     160
     161  switch (op[0]) {
     162    case '?': MMM_FUNC(*M1 ? *M2: *M3);
     163    default:
     164      snprintf (line, 512, "error: op %c not defined!", op[0]);
     165      push_error (line);
     166      return (FALSE);
     167  }
     168# undef MMM_FUNC
     169
     170  /** free up any temporary buffers: **/
     171
     172  if (V1[0].type == ST_MATRIX_TMP) {
     173    free (V1[0].buffer[0].header.buffer);
     174    free (V1[0].buffer[0].matrix.buffer);
     175    free (V1[0].buffer);
     176  }
     177  if (V2[0].type == ST_MATRIX_TMP) {
     178    free (V2[0].buffer[0].header.buffer);
     179    free (V2[0].buffer[0].matrix.buffer);
     180    free (V2[0].buffer);
     181  }
     182  if (V3[0].type == ST_MATRIX_TMP) {
     183    free (V3[0].buffer[0].header.buffer);
     184    free (V3[0].buffer[0].matrix.buffer);
     185    free (V3[0].buffer);
     186  }
     187
     188  /* at the end, V1 and V2 are deleted only if they were temporary */
     189
     190  clear_stack (V1);
     191  clear_stack (V2);
     192  clear_stack (V3);
     193  return (TRUE);
     194
     195}
     196
     197// XXX we temporarily drop the concept of using one of the temporary input vectors for
     198// the output vector (thus saving an ALLOC): we have to juggle the size of the input vectors
     199// as well as their temporary state
     200
     201int VV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
     202
     203  int i, Nx;
     204  char line[512]; // this is only used to report an error
     205 
     206  // the vectors have to match in length
     207  if (V1[0].vector[0].Nelements != V2[0].vector[0].Nelements) {
     208    return (FALSE);
     209  }
     210
     211  Nx = V1[0].vector[0].Nelements;
     212
     213  // create the output vector guaranteed to be temporary until the very end
     214  OUT[0].vector = InitVector ();
     215  OUT[0].type = ST_VECTOR_TMP;
    27216
    28217  // set up the possible operations : int OP int -> int, all else yield float
     
    59248      break;                                                            \
    60249    }                                                                   \
    61     if ((FTYPE == 'S') && (V1->vector->type != OPIHI_FLT) && (V2->vector->type != OPIHI_FLT)) { \
     250    if ((FTYPE == ST_SCALAR_FLT) && (V1->vector->type != OPIHI_FLT) && (V2->vector->type != OPIHI_FLT)) { \
    62251      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);             \
    63252      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     
    82271
    83272  switch (op[0]) {
    84     case '+': VV_FUNC('s', *M1 + *M2);
    85     case '-': VV_FUNC('s', *M1 - *M2);
    86     case '*': VV_FUNC('s', *M1 * *M2);
    87     case '/': VV_FUNC('S', *M1 / (opihi_flt) *M2);
    88     case '%': VV_FUNC('s', (long long)*M1 % (long long)*M2);
    89     case '^': VV_FUNC('S', pow (*M1, *M2));
    90     case '@': VV_FUNC('S', DEG_RAD*atan2 (*M1, *M2));
    91     case 'D': VV_FUNC('s', MIN (*M1, *M2));
    92     case 'U': VV_FUNC('s', MAX (*M1, *M2));
    93     case '<': VV_FUNC('s', (*M1 < *M2) ? 1 : 0);
    94     case '>': VV_FUNC('s', (*M1 > *M2) ? 1 : 0);
    95     case '&': VV_FUNC('s', ((long long)*M1 & (long long)*M2));
    96     case '|': VV_FUNC('s', ((long long)*M1 | (long long)*M2));
    97     case 'E': VV_FUNC('s', (*M1 == *M2) ? 1 : 0);
    98     case 'N': VV_FUNC('s', (*M1 != *M2) ? 1 : 0);
    99     case 'L': VV_FUNC('s', (*M1 <= *M2) ? 1 : 0);
    100     case 'G': VV_FUNC('s', (*M1 >= *M2) ? 1 : 0);
    101     case 'A': VV_FUNC('s', (*M1 && *M2) ? 1 : 0);
    102     case 'O': VV_FUNC('s', (*M1 || *M2) ? 1 : 0);
     273    case '+': VV_FUNC(ST_SCALAR_INT, *M1 + *M2);
     274    case '-': VV_FUNC(ST_SCALAR_INT, *M1 - *M2);
     275    case '*': VV_FUNC(ST_SCALAR_INT, *M1 * *M2);
     276    case '/': VV_FUNC(ST_SCALAR_FLT, *M1 / (opihi_flt) *M2);
     277    case '%': VV_FUNC(ST_SCALAR_INT, (long long)*M1 % (long long)*M2);
     278    case '^': VV_FUNC(ST_SCALAR_FLT, pow (*M1, *M2));
     279    case '@': VV_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (*M1, *M2));
     280    case 'a': VV_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (*M1, *M2));
     281    case 'D': VV_FUNC(ST_SCALAR_INT, MIN (*M1, *M2));
     282    case 'U': VV_FUNC(ST_SCALAR_INT, MAX (*M1, *M2));
     283    case '<': VV_FUNC(ST_SCALAR_INT, (*M1 < *M2) ? 1 : 0);
     284    case '>': VV_FUNC(ST_SCALAR_INT, (*M1 > *M2) ? 1 : 0);
     285    case '&': VV_FUNC(ST_SCALAR_INT, ((long long)*M1 & (long long)*M2));
     286    case '|': VV_FUNC(ST_SCALAR_INT, ((long long)*M1 | (long long)*M2));
     287    case 'E': VV_FUNC(ST_SCALAR_INT, (*M1 == *M2) ? 1 : 0);
     288    case 'N': VV_FUNC(ST_SCALAR_INT, (*M1 != *M2) ? 1 : 0);
     289    case 'L': VV_FUNC(ST_SCALAR_INT, (*M1 <= *M2) ? 1 : 0);
     290    case 'G': VV_FUNC(ST_SCALAR_INT, (*M1 >= *M2) ? 1 : 0);
     291    case 'A': VV_FUNC(ST_SCALAR_INT, (*M1 && *M2) ? 1 : 0);
     292    case 'O': VV_FUNC(ST_SCALAR_INT, (*M1 || *M2) ? 1 : 0);
    103293    default:
    104       sprintf (line, "error: op %c not defined!", op[0]);
     294      snprintf (line, 512, "error: op %c not defined!", op[0]);
    105295      push_error (line);
    106296      return (FALSE);
     
    110300  /** free up any temporary buffers: **/
    111301
    112   if (V1[0].type == 'v') {
     302  if (V1[0].type == ST_VECTOR_TMP) {
    113303    free (V1[0].vector[0].elements.Ptr);
    114304    free (V1[0].vector);
    115305  }
    116   if (V2[0].type == 'v') {
     306  if (V2[0].type == ST_VECTOR_TMP) {
    117307    free (V2[0].vector[0].elements.Ptr);
    118308    free (V2[0].vector);
     
    134324
    135325  OUT[0].vector = InitVector ();
    136   OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
     326  OUT[0].type = ST_VECTOR_TMP;   /*** <<--- says this is a temporary matrix ***/
    137327
    138328  // set up the possible operations : int OP int -> int, all else yield float
    139329  // OP is the operation performed on *M1 and *M2
    140330# define SV_FUNC(FTYPE,OP) {                                            \
    141     if ((V1->type == 'S') && (V2->vector->type == OPIHI_FLT)) {         \
     331    if ((V1->type == ST_SCALAR_FLT) && (V2->vector->type == OPIHI_FLT)) {               \
    142332      CopyVector (OUT[0].vector, V2[0].vector);                         \
    143333      opihi_flt  M1  =  V1[0].FltValue;                                 \
     
    149339      break;                                                            \
    150340    }                                                                   \
    151     if ((V1->type == 'S') && (V2->vector->type != OPIHI_FLT)) {         \
     341    if ((V1->type == ST_SCALAR_FLT) && (V2->vector->type != OPIHI_FLT)) {               \
    152342      MatchVector (OUT[0].vector, V2[0].vector, OPIHI_FLT);             \
    153343      opihi_flt  M1  =  V1[0].FltValue;                                 \
     
    159349      break;                                                            \
    160350    }                                                                   \
    161     if ((V1->type == 's') && (V2->vector->type == OPIHI_FLT)) {         \
     351    if ((V1->type == ST_SCALAR_INT) && (V2->vector->type == OPIHI_FLT)) {               \
    162352      CopyVector (OUT[0].vector, V2[0].vector);                         \
    163353      opihi_int  M1  =  V1[0].IntValue;                                 \
     
    169359      break;                                                            \
    170360    }                                                                   \
    171     if ((FTYPE == 'S') && (V1->type == 's') && (V2->vector->type != OPIHI_FLT)) { \
     361    if ((FTYPE == ST_SCALAR_FLT) && (V1->type == ST_SCALAR_INT) && (V2->vector->type != OPIHI_FLT)) { \
    172362      MatchVector (OUT[0].vector, V2[0].vector, OPIHI_FLT);             \
    173363      opihi_int  M1  =  V1[0].IntValue;                                 \
     
    179369      break;                                                            \
    180370    }                                                                   \
    181     if ((V1->type == 's') && (V2->vector->type != OPIHI_FLT)) {         \
     371    if ((V1->type == ST_SCALAR_INT) && (V2->vector->type != OPIHI_FLT)) {               \
    182372      CopyVector (OUT[0].vector, V2[0].vector);                         \
    183373      opihi_int  M1  =  V1[0].IntValue;                                 \
     
    192382
    193383  switch (op[0]) {
    194     case '+': SV_FUNC('s', M1 + *M2);
    195     case '-': SV_FUNC('s', M1 - *M2);
    196     case '*': SV_FUNC('s', M1 * *M2);
    197     case '/': SV_FUNC('S', M1 / (opihi_flt) *M2);
    198     case '%': SV_FUNC('s', (long long) M1 % (long long) *M2);
    199     case '^': SV_FUNC('S', pow (M1, *M2));
    200     case '@': SV_FUNC('S', DEG_RAD*atan2 (M1, *M2));
    201     case 'D': SV_FUNC('s', MIN (M1, *M2));
    202     case 'U': SV_FUNC('s', MAX (M1, *M2));
    203     case '<': SV_FUNC('s', (M1 < *M2) ? 1 : 0);
    204     case '>': SV_FUNC('s', (M1 > *M2) ? 1 : 0);
    205     case '&': SV_FUNC('s', ((long long)M1 & (long long)*M2));
    206     case '|': SV_FUNC('s', ((long long)M1 | (long long)*M2));
    207     case 'E': SV_FUNC('s', (M1 == *M2) ? 1 : 0);
    208     case 'N': SV_FUNC('s', (M1 != *M2) ? 1 : 0);
    209     case 'L': SV_FUNC('s', (M1 <= *M2) ? 1 : 0);
    210     case 'G': SV_FUNC('s', (M1 >= *M2) ? 1 : 0);
    211     case 'A': SV_FUNC('s', (M1 && *M2) ? 1 : 0);
    212     case 'O': SV_FUNC('s', (M1 || *M2) ? 1 : 0);
     384    case '+': SV_FUNC(ST_SCALAR_INT, M1 + *M2);
     385    case '-': SV_FUNC(ST_SCALAR_INT, M1 - *M2);
     386    case '*': SV_FUNC(ST_SCALAR_INT, M1 * *M2);
     387    case '/': SV_FUNC(ST_SCALAR_FLT, M1 / (opihi_flt) *M2);
     388    case '%': SV_FUNC(ST_SCALAR_INT, (long long) M1 % (long long) *M2);
     389    case '^': SV_FUNC(ST_SCALAR_FLT, pow (M1, *M2));
     390    case '@': SV_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (M1, *M2));
     391    case 'a': SV_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (M1, *M2));
     392    case 'D': SV_FUNC(ST_SCALAR_INT, MIN (M1, *M2));
     393    case 'U': SV_FUNC(ST_SCALAR_INT, MAX (M1, *M2));
     394    case '<': SV_FUNC(ST_SCALAR_INT, (M1 < *M2) ? 1 : 0);
     395    case '>': SV_FUNC(ST_SCALAR_INT, (M1 > *M2) ? 1 : 0);
     396    case '&': SV_FUNC(ST_SCALAR_INT, ((long long)M1 & (long long)*M2));
     397    case '|': SV_FUNC(ST_SCALAR_INT, ((long long)M1 | (long long)*M2));
     398    case 'E': SV_FUNC(ST_SCALAR_INT, (M1 == *M2) ? 1 : 0);
     399    case 'N': SV_FUNC(ST_SCALAR_INT, (M1 != *M2) ? 1 : 0);
     400    case 'L': SV_FUNC(ST_SCALAR_INT, (M1 <= *M2) ? 1 : 0);
     401    case 'G': SV_FUNC(ST_SCALAR_INT, (M1 >= *M2) ? 1 : 0);
     402    case 'A': SV_FUNC(ST_SCALAR_INT, (M1 && *M2) ? 1 : 0);
     403    case 'O': SV_FUNC(ST_SCALAR_INT, (M1 || *M2) ? 1 : 0);
    213404    default:
    214       sprintf (line, "error: op %c not defined!", op[0]);
     405      snprintf (line, 512, "error: op %c not defined!", op[0]);
    215406      push_error (line);
    216407      return (FALSE);
     
    219410
    220411  /** free up any temporary buffers: **/
    221   if (V2[0].type == 'v') {
     412  if (V2[0].type == ST_VECTOR_TMP) {
    222413    free (V2[0].vector[0].elements.Ptr);
    223414    free (V2[0].vector);
     
    240431
    241432  OUT[0].vector = InitVector ();
    242   OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
     433  OUT[0].type = ST_VECTOR_TMP;   /*** <<--- says this is a temporary matrix ***/
    243434
    244435  // set up the possible operations : int OP int -> int, all else yield float
    245436  // OP is the operation performed on *M1 and *M2
    246437# define VS_FUNC(FTYPE,OP) {                                            \
    247     if ((V2->type == 'S') && (V1->vector->type == OPIHI_FLT)) {         \
     438    if ((V2->type == ST_SCALAR_FLT) && (V1->vector->type == OPIHI_FLT)) {               \
    248439      CopyVector (OUT[0].vector, V1[0].vector);                         \
    249440      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     
    255446      break;                                                            \
    256447    }                                                                   \
    257     if ((V2->type == 'S') && (V1->vector->type != OPIHI_FLT)) {         \
     448    if ((V2->type == ST_SCALAR_FLT) && (V1->vector->type != OPIHI_FLT)) {               \
    258449      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);             \
    259450      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     
    265456      break;                                                            \
    266457    }                                                                   \
    267     if ((V2->type == 's') && (V1->vector->type == OPIHI_FLT)) {         \
     458    if ((V2->type == ST_SCALAR_INT) && (V1->vector->type == OPIHI_FLT)) {               \
    268459      CopyVector (OUT[0].vector, V1[0].vector);                         \
    269460      opihi_flt *M1  =  V1[0].vector[0].elements.Flt;                   \
     
    275466      break;                                                            \
    276467    }                                                                   \
    277     if ((FTYPE == 'S') && (V2->type == 's') && (V1->vector->type != OPIHI_FLT)) { \
     468    if ((FTYPE == ST_SCALAR_FLT) && (V2->type == ST_SCALAR_INT) && (V1->vector->type != OPIHI_FLT)) { \
    278469      CopyVector (OUT[0].vector, V1[0].vector);                         \
    279470      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     
    285476      break;                                                            \
    286477    }                                                                   \
    287     if ((V2->type == 's') && (V1->vector->type != OPIHI_FLT)) {         \
     478    if ((V2->type == ST_SCALAR_INT) && (V1->vector->type != OPIHI_FLT)) {               \
    288479      CopyVector (OUT[0].vector, V1[0].vector);                         \
    289480      opihi_int *M1  =  V1[0].vector[0].elements.Int;                   \
     
    298489
    299490  switch (op[0]) {
    300     case '+': VS_FUNC('s', *M1 + M2);
    301     case '-': VS_FUNC('s', *M1 - M2);
    302     case '*': VS_FUNC('s', *M1 * M2);
    303     case '/': VS_FUNC('S', *M1 / (opihi_flt) M2);
    304     case '%': VS_FUNC('s', (long long) *M1 % (long long) M2);
    305     case '^': VS_FUNC('S', pow (*M1, M2));
    306     case '@': VS_FUNC('S', DEG_RAD*atan2 (*M1, M2));
    307     case 'D': VS_FUNC('s', MIN (*M1, M2));
    308     case 'U': VS_FUNC('s', MAX (*M1, M2));
    309     case '<': VS_FUNC('s', (*M1 < M2) ? 1 : 0);
    310     case '>': VS_FUNC('s', (*M1 > M2) ? 1 : 0);
    311     case '&': VS_FUNC('s', ((long long)*M1 & (long long)M2));
    312     case '|': VS_FUNC('s', ((long long)*M1 | (long long)M2));
    313     case 'E': VS_FUNC('s', (*M1 == M2) ? 1 : 0);
    314     case 'N': VS_FUNC('s', (*M1 != M2) ? 1 : 0);
    315     case 'L': VS_FUNC('s', (*M1 <= M2) ? 1 : 0);
    316     case 'G': VS_FUNC('s', (*M1 >= M2) ? 1 : 0);
    317     case 'A': VS_FUNC('s', (*M1 && M2) ? 1 : 0);
    318     case 'O': VS_FUNC('s', (*M1 || M2) ? 1 : 0);
     491    case '+': VS_FUNC(ST_SCALAR_INT, *M1 + M2);
     492    case '-': VS_FUNC(ST_SCALAR_INT, *M1 - M2);
     493    case '*': VS_FUNC(ST_SCALAR_INT, *M1 * M2);
     494    case '/': VS_FUNC(ST_SCALAR_FLT, *M1 / (opihi_flt) M2);
     495    case '%': VS_FUNC(ST_SCALAR_INT, (long long) *M1 % (long long) M2);
     496    case '^': VS_FUNC(ST_SCALAR_FLT, pow (*M1, M2));
     497    case '@': VS_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (*M1, M2));
     498    case 'a': VS_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (*M1, M2));
     499    case 'D': VS_FUNC(ST_SCALAR_INT, MIN (*M1, M2));
     500    case 'U': VS_FUNC(ST_SCALAR_INT, MAX (*M1, M2));
     501    case '<': VS_FUNC(ST_SCALAR_INT, (*M1 < M2) ? 1 : 0);
     502    case '>': VS_FUNC(ST_SCALAR_INT, (*M1 > M2) ? 1 : 0);
     503    case '&': VS_FUNC(ST_SCALAR_INT, ((long long)*M1 & (long long)M2));
     504    case '|': VS_FUNC(ST_SCALAR_INT, ((long long)*M1 | (long long)M2));
     505    case 'E': VS_FUNC(ST_SCALAR_INT, (*M1 == M2) ? 1 : 0);
     506    case 'N': VS_FUNC(ST_SCALAR_INT, (*M1 != M2) ? 1 : 0);
     507    case 'L': VS_FUNC(ST_SCALAR_INT, (*M1 <= M2) ? 1 : 0);
     508    case 'G': VS_FUNC(ST_SCALAR_INT, (*M1 >= M2) ? 1 : 0);
     509    case 'A': VS_FUNC(ST_SCALAR_INT, (*M1 && M2) ? 1 : 0);
     510    case 'O': VS_FUNC(ST_SCALAR_INT, (*M1 || M2) ? 1 : 0);
    319511    default:
    320       sprintf (line, "error: op %c not defined!", op[0]);
     512      snprintf (line, 512, "error: op %c not defined!", op[0]);
    321513      push_error (line);
    322514      return (FALSE);
     
    326518  /** free up any temporary buffers: **/
    327519
    328   if (V1[0].type == 'v') {
     520  if (V1[0].type == ST_VECTOR_TMP) {
    329521    free (V1[0].vector[0].elements.Ptr);
    330522    free (V1[0].vector);
     
    353545
    354546  /* if possible, use V1 as temp buffer, otherwise create new one */
    355   if (V1[0].type == 'm') { 
     547  if (V1[0].type == ST_MATRIX_TMP) { 
    356548    OUT[0].buffer = V1[0].buffer;
    357     V1[0].type = 'M'; /* prevent it from being freed below */
     549    V1[0].type = ST_MATRIX; /* prevent it from being freed below */
    358550  } else { 
    359551    /* do buffer.matrix.buffer and buffer.header.buffer get correctly zeroed? */
     
    361553    CopyBuffer (OUT[0].buffer, V1[0].buffer);
    362554  }
    363   OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
     555  OUT[0].type = ST_MATRIX_TMP; /*** <<--- says this is a temporary matrix ***/
    364556
    365557  float     *M1  = (float *) V1[0].buffer[0].matrix.buffer;
     
    395587    case '^': MV_FUNC(pow (*M1, *M2));
    396588    case '@': MV_FUNC(DEG_RAD*atan2 (*M1, *M2));
     589    case 'a': MV_FUNC(DEG_RAD*atan2 (*M1, *M2));
    397590    case 'D': MV_FUNC(MIN (*M1, *M2));
    398591    case 'U': MV_FUNC(MAX (*M1, *M2));
     
    408601    case 'O': MV_FUNC((*M1 || *M2) ? 1 : 0);
    409602    default:
    410       sprintf (line, "error: op %c not defined!", op[0]);
     603      snprintf (line, 512, "error: op %c not defined!", op[0]);
    411604      push_error (line);
    412605      return (FALSE);
     
    416609  /** free up any temporary buffers: **/
    417610
    418   if (V1[0].type == 'm') {
     611  if (V1[0].type == ST_MATRIX_TMP) {
    419612    free (V1[0].buffer[0].header.buffer);
    420613    free (V1[0].buffer[0].matrix.buffer);
    421614    free (V1[0].buffer);
    422615  }
    423   if (V2[0].type == 'v') {
     616  if (V2[0].type == ST_VECTOR_TMP) {
    424617    free (V2[0].vector[0].elements.Ptr);
    425618    free (V2[0].vector);
     
    446639
    447640  /* if possible, use V2 as temp buffer, otherwise create new one */
    448   if (V2[0].type == 'm') {
     641  if (V2[0].type == ST_MATRIX_TMP) {
    449642    OUT[0].buffer = V2[0].buffer;
    450     V2[0].type = 'M'; /* prevent it from being freed below */
     643    V2[0].type = ST_MATRIX; /* prevent it from being freed below */
    451644  } else {  /* no spare temp buffer */
    452645    OUT[0].buffer = InitBuffer ();
    453646    CopyBuffer (OUT[0].buffer, V2[0].buffer);
    454647  }
    455   OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
     648  OUT[0].type = ST_MATRIX_TMP; /*** <<--- says this is a temporary matrix ***/
    456649
    457650  float     *M2  = (float *) V2[0].buffer[0].matrix.buffer;
     
    487680    case '^': VM_FUNC(pow (*M1, *M2));
    488681    case '@': VM_FUNC(DEG_RAD*atan2 (*M1, *M2));
     682    case 'a': VM_FUNC(DEG_RAD*atan2 (*M1, *M2));
    489683    case 'D': VM_FUNC(MIN (*M1, *M2));
    490684    case 'U': VM_FUNC(MAX (*M1, *M2));
     
    500694    case 'O': VM_FUNC((*M1 || *M2) ? 1 : 0);
    501695    default:
    502       sprintf (line, "error: op %c not defined!", op[0]);
     696      snprintf (line, 512, "error: op %c not defined!", op[0]);
    503697      push_error (line);
    504698      return (FALSE);
     
    508702  /** free up any temporary buffers: **/
    509703
    510   if (V1[0].type == 'v') {
     704  if (V1[0].type == ST_VECTOR_TMP) {
    511705    free (V1[0].vector[0].elements.Ptr);
    512706    free (V1[0].vector);
    513707  }
    514   if (V2[0].type == 'm') {
     708  if (V2[0].type == ST_MATRIX_TMP) {
    515709    free (V2[0].buffer[0].header.buffer);
    516710    free (V2[0].buffer[0].matrix.buffer);
     
    535729  Ny = V1[0].buffer[0].matrix.Naxis[1];
    536730
    537   if (V1[0].type == 'm') {  /** use V1 as temp buffer **/
     731  if (V1[0].type == ST_MATRIX_TMP) {  /** use V1 as temp buffer **/
    538732    OUT[0].buffer = V1[0].buffer;
    539     V1[0].type = 'M'; /* prevent it from being freed below */
     733    V1[0].type = ST_MATRIX; /* prevent it from being freed below */
    540734  } else {
    541     if (V2[0].type == 'm') { /** use V2 as temp buffer, but header of V1 **/
     735    if (V2[0].type == ST_MATRIX_TMP) { /** use V2 as temp buffer, but header of V1 **/
    542736      OUT[0].buffer = V2[0].buffer;
    543       V2[0].type = 'M'; /* prevent it from being freed below */
     737      V2[0].type = ST_MATRIX; /* prevent it from being freed below */
    544738    } else {  /* no spare temp buffer */
    545739      OUT[0].buffer = InitBuffer ();
     
    547741    }
    548742  }
    549   OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
     743  OUT[0].type = ST_MATRIX_TMP; /*** <<--- says this is a temporary matrix ***/
    550744
    551745  M1  = (float *)V1[0].buffer[0].matrix.buffer;
     
    567761    case '^': MM_FUNC(pow (*M1, *M2));
    568762    case '@': MM_FUNC(DEG_RAD*atan2 (*M1, *M2));
     763    case 'a': MM_FUNC(DEG_RAD*atan2 (*M1, *M2));
    569764    case 'D': MM_FUNC(MIN (*M1, *M2));
    570765    case 'U': MM_FUNC(MAX (*M1, *M2));
     
    580775    case 'O': MM_FUNC((*M1 || *M2) ? 1 : 0);
    581776    default:
    582       sprintf (line, "error: op %c not defined!", op[0]);
     777      snprintf (line, 512, "error: op %c not defined!", op[0]);
    583778      push_error (line);
    584779      return (FALSE);
     
    588783  /** free up any temporary buffers: **/
    589784
    590   if (V1[0].type == 'm') {
     785  if (V1[0].type == ST_MATRIX_TMP) {
    591786    free (V1[0].buffer[0].header.buffer);
    592787    free (V1[0].buffer[0].matrix.buffer);
    593788    free (V1[0].buffer);
    594789  }
    595   if (V2[0].type == 'm') {
     790  if (V2[0].type == ST_MATRIX_TMP) {
    596791    free (V2[0].buffer[0].header.buffer);
    597792    free (V2[0].buffer[0].matrix.buffer);
     
    615810
    616811  /* if possible, use V1 as temp buffer, otherwise create new one */
    617   if (V1[0].type == 'm') {
     812  if (V1[0].type == ST_MATRIX_TMP) {
    618813    OUT[0].buffer = V1[0].buffer;
    619     V1[0].type = 'M'; /* prevent it from being freed below */
     814    V1[0].type = ST_MATRIX; /* prevent it from being freed below */
    620815  } else {
    621816    OUT[0].buffer = InitBuffer ();
    622817    CopyBuffer (OUT[0].buffer, V1[0].buffer);
    623818  }
    624   OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
     819  OUT[0].type = ST_MATRIX_TMP;      /*** <<--- says this is a temporary matrix ***/
    625820
    626821  float *M1    = (float *)V1[0].buffer[0].matrix.buffer;
     
    628823
    629824# define MS_FUNC(OP) {                                  \
    630     if (V2->type == 'S')  {                             \
     825    if (V2->type == ST_SCALAR_FLT)  {                           \
    631826      opihi_flt M2 = V2[0].FltValue;                    \
    632827      for (i = 0; i < Nx*Ny; i++, out++, M1++) {        \
     
    635830      break;                                            \
    636831    }                                                   \
    637     if (V2->type == 's')  {                             \
     832    if (V2->type == ST_SCALAR_INT)  {                           \
    638833      opihi_int M2 = V2[0].IntValue;                    \
    639834      for (i = 0; i < Nx*Ny; i++, out++, M1++) {        \
     
    652847    case '^': MS_FUNC(pow (*M1, M2));
    653848    case '@': MS_FUNC(DEG_RAD*atan2 (*M1, M2));
     849    case 'a': MS_FUNC(DEG_RAD*atan2 (*M1, M2));
    654850    case 'D': MS_FUNC(MIN (*M1, M2));
    655851    case 'U': MS_FUNC(MAX (*M1, M2));
     
    665861    case 'O': MS_FUNC((*M1 || M2) ? 1 : 0);
    666862    default:
    667       sprintf (line, "error: op %c not defined!", op[0]);
     863      snprintf (line, 512, "error: op %c not defined!", op[0]);
    668864      push_error (line);
    669865      return (FALSE);
     
    671867# undef MS_FUNC
    672868
    673   if (V1[0].type == 'm') {
     869  if (V1[0].type == ST_MATRIX_TMP) {
    674870    free (V1[0].buffer[0].header.buffer);
    675871    free (V1[0].buffer[0].matrix.buffer);
     
    691887  Ny = V2[0].buffer[0].matrix.Naxis[1];
    692888
    693   if (V2[0].type == 'm') {  /* V2[0] is NOT temporary, we can't use it for storage */
     889  if (V2[0].type == ST_MATRIX_TMP) {  /* V2[0] is NOT temporary, we can't use it for storage */
    694890    OUT[0].buffer = V2[0].buffer;
    695     V2[0].type = 'M'; /* prevent it from being freed below */
     891    V2[0].type = ST_MATRIX; /* prevent it from being freed below */
    696892  } else {
    697893    OUT[0].buffer = InitBuffer ();
    698894    CopyBuffer (OUT[0].buffer, V2[0].buffer);
    699895  }
    700   OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
     896  OUT[0].type = ST_MATRIX_TMP; /*** <<--- says this is a temporary matrix ***/
    701897
    702898  float *M2    = (float *)V2[0].buffer[0].matrix.buffer;
     
    704900
    705901# define SM_FUNC(OP) {                                  \
    706     if (V1->type == 'S')  {                             \
     902    if (V1->type == ST_SCALAR_FLT)  {                           \
    707903      opihi_flt M1 = V1[0].FltValue;                    \
    708904      for (i = 0; i < Nx*Ny; i++, out++, M2++) {        \
     
    711907      break;                                            \
    712908    }                                                   \
    713     if (V1->type == 's')  {                             \
     909    if (V1->type == ST_SCALAR_INT)  {                           \
    714910      opihi_int M1 = V1[0].IntValue;                    \
    715911      for (i = 0; i < Nx*Ny; i++, out++, M2++) {        \
     
    728924    case '^': SM_FUNC(pow (M1, *M2));
    729925    case '@': SM_FUNC(DEG_RAD*atan2 (M1, *M2));
     926    case 'a': SM_FUNC(DEG_RAD*atan2 (M1, *M2));
    730927    case 'D': SM_FUNC(MIN (M1, *M2));
    731928    case 'U': SM_FUNC(MAX (M1, *M2));
     
    741938    case 'O': SM_FUNC((M1 || *M2) ? 1 : 0);
    742939    default:
    743       sprintf (line, "error: op %c not defined!", op[0]);
     940      snprintf (line, 512, "error: op %c not defined!", op[0]);
    744941      push_error (line);
    745942      return (FALSE);
     
    747944# undef SM_FUNC
    748945
    749   if (V2[0].type == 'm') {
     946  if (V2[0].type == ST_MATRIX_TMP) {
    750947    free (V2[0].buffer[0].header.buffer);
    751948    free (V2[0].buffer[0].matrix.buffer);
     
    764961
    765962# define SS_FUNC(FTYPE,OP) {                                            \
    766     if ((V1->type == 'S') && (V2->type == 'S')) {                       \
     963    if ((V1->type == ST_SCALAR_FLT) && (V2->type == ST_SCALAR_FLT)) {                   \
    767964      opihi_flt M1 = V1[0].FltValue;                                    \
    768965      opihi_flt M2 = V2[0].FltValue;                                    \
    769       OUT[0].type = 'S';                                                \
     966      OUT[0].type = ST_SCALAR_FLT;                                              \
    770967      OUT[0].FltValue = OP;                                             \
    771968      break;                                                            \
    772969    }                                                                   \
    773     if ((V1->type == 'S') && (V2->type == 's')) {                       \
     970    if ((V1->type == ST_SCALAR_FLT) && (V2->type == ST_SCALAR_INT)) {                   \
    774971      opihi_flt M1 = V1[0].FltValue;                                    \
    775972      opihi_int M2 = V2[0].IntValue;                                    \
    776       OUT[0].type = 'S';                                                \
     973      OUT[0].type = ST_SCALAR_FLT;                                              \
    777974      OUT[0].FltValue = OP;                                             \
    778975      break;                                                            \
    779976    }                                                                   \
    780     if ((V1->type == 's') && (V2->type == 'S')) {                       \
     977    if ((V1->type == ST_SCALAR_INT) && (V2->type == ST_SCALAR_FLT)) {                   \
    781978      opihi_int M1 = V1[0].IntValue;                                    \
    782979      opihi_flt M2 = V2[0].FltValue;                                    \
    783       OUT[0].type = 'S';                                                \
     980      OUT[0].type = ST_SCALAR_FLT;                                              \
    784981      OUT[0].FltValue = OP;                                             \
    785982      break;                                                            \
    786983    }                                                                   \
    787     if ((FTYPE == 'S') && (V1->type == 's') && (V2->type == 's')) {     \
     984    if ((FTYPE == ST_SCALAR_FLT) && (V1->type == ST_SCALAR_INT) && (V2->type == ST_SCALAR_INT)) {       \
    788985      opihi_int M1 = V1[0].IntValue;                                    \
    789986      opihi_int M2 = V2[0].IntValue;                                    \
    790       OUT[0].type = 'S';                                                \
     987      OUT[0].type = ST_SCALAR_FLT;                                              \
    791988      OUT[0].FltValue = OP;                                             \
    792989      break;                                                            \
    793990    }                                                                   \
    794     if ((V1->type == 's') && (V2->type == 's')) {                       \
     991    if ((V1->type == ST_SCALAR_INT) && (V2->type == ST_SCALAR_INT)) {                   \
    795992      opihi_int M1 = V1[0].IntValue;                                    \
    796993      opihi_int M2 = V2[0].IntValue;                                    \
    797       OUT[0].type = 's';                                                \
     994      OUT[0].type = ST_SCALAR_INT;                                              \
    798995      OUT[0].IntValue = OP;                                             \
    799996      break;                                                            \
     
    802999
    8031000  switch (op[0]) {
    804     case '+': SS_FUNC('s', M1 + M2);
    805     case '-': SS_FUNC('s', M1 - M2);
    806     case '*': SS_FUNC('s', M1 * M2);
    807     case '/': SS_FUNC('S', M1 / (opihi_flt) M2);
    808     case '%': SS_FUNC('s', (long long) M1 % (long long) M2);
    809     case '^': SS_FUNC('S', pow (M1, M2));
    810     case '@': SS_FUNC('S', DEG_RAD*atan2 (M1, M2));
    811     case 'D': SS_FUNC('s', MIN (M1, M2));
    812     case 'U': SS_FUNC('s', MAX (M1, M2));
    813     case '<': SS_FUNC('s', (M1 < M2) ? 1 : 0);
    814     case '>': SS_FUNC('s', (M1 > M2) ? 1 : 0);
    815     case '&': SS_FUNC('s', ((long long)M1 & (long long)M2));
    816     case '|': SS_FUNC('s', ((long long)M1 | (long long)M2));
    817     case 'E': SS_FUNC('s', (M1 == M2) ? 1 : 0);
    818     case 'N': SS_FUNC('s', (M1 != M2) ? 1 : 0);
    819     case 'L': SS_FUNC('s', (M1 <= M2) ? 1 : 0);
    820     case 'G': SS_FUNC('s', (M1 >= M2) ? 1 : 0);
    821     case 'A': SS_FUNC('s', (M1 && M2) ? 1 : 0);
    822     case 'O': SS_FUNC('s', (M1 || M2) ? 1 : 0);
     1001    case '+': SS_FUNC(ST_SCALAR_INT, M1 + M2);
     1002    case '-': SS_FUNC(ST_SCALAR_INT, M1 - M2);
     1003    case '*': SS_FUNC(ST_SCALAR_INT, M1 * M2);
     1004    case '/': SS_FUNC(ST_SCALAR_FLT, M1 / (opihi_flt) M2);
     1005    case '%': SS_FUNC(ST_SCALAR_INT, (long long) M1 % (long long) M2);
     1006    case '^': SS_FUNC(ST_SCALAR_FLT, pow (M1, M2));
     1007    case '@': SS_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (M1, M2));
     1008    case 'a': SS_FUNC(ST_SCALAR_FLT, DEG_RAD*atan2 (M1, M2));
     1009    case 'D': SS_FUNC(ST_SCALAR_INT, MIN (M1, M2));
     1010    case 'U': SS_FUNC(ST_SCALAR_INT, MAX (M1, M2));
     1011    case '<': SS_FUNC(ST_SCALAR_INT, (M1 < M2) ? 1 : 0);
     1012    case '>': SS_FUNC(ST_SCALAR_INT, (M1 > M2) ? 1 : 0);
     1013    case '&': SS_FUNC(ST_SCALAR_INT, ((long long)M1 & (long long)M2));
     1014    case '|': SS_FUNC(ST_SCALAR_INT, ((long long)M1 | (long long)M2));
     1015    case 'E': SS_FUNC(ST_SCALAR_INT, (M1 == M2) ? 1 : 0);
     1016    case 'N': SS_FUNC(ST_SCALAR_INT, (M1 != M2) ? 1 : 0);
     1017    case 'L': SS_FUNC(ST_SCALAR_INT, (M1 <= M2) ? 1 : 0);
     1018    case 'G': SS_FUNC(ST_SCALAR_INT, (M1 >= M2) ? 1 : 0);
     1019    case 'A': SS_FUNC(ST_SCALAR_INT, (M1 && M2) ? 1 : 0);
     1020    case 'O': SS_FUNC(ST_SCALAR_INT, (M1 || M2) ? 1 : 0);
    8231021    default:
    824       sprintf (line, "error: op %c not defined!", op[0]);
     1022      snprintf (line, 512, "error: op %c not defined!", op[0]);
    8251023      push_error (line);
    8261024      return (FALSE);
     
    8441042
    8451043  if ((op[0] != 'N') && (op[0] != 'E')) {
    846     sprintf (line, "error: op %c not defined for string operations!", op[0]);
     1044    snprintf (line, 512, "error: op %c not defined for string operations!", op[0]);
    8471045    push_error (line);
    8481046    return (FALSE);
     
    8531051     thus: string == number -> false */
    8541052
    855   if (!strncasecmp (&V1[0].type, "S", 1)) {
     1053  if (V1[0].type == ST_SCALAR_INT) {
    8561054    value = (op[0] == 'N');
    8571055    goto escape;
    8581056  }
    859   if (!strncasecmp (&V2[0].type, "S", 1)) {
     1057  if (V1[0].type == ST_SCALAR_FLT) {
     1058    value = (op[0] == 'N');
     1059    goto escape;
     1060  }
     1061  if (V2[0].type == ST_SCALAR_INT) {
     1062    value = (op[0] == 'N');
     1063    goto escape;
     1064  }
     1065  if (V2[0].type == ST_SCALAR_FLT) {
    8601066    value = (op[0] == 'N');
    8611067    goto escape;
     
    8701076    break;
    8711077    default:
    872       sprintf (line, "error: op %c not defined for string operations!", op[0]);
     1078      snprintf (line, 512, "error: op %c not defined for string operations!", op[0]);
    8731079      push_error (line);
    8741080      return (FALSE);
     
    8771083escape:
    8781084  OUT[0].FltValue = value;
    879   OUT[0].type = 'S';
     1085  OUT[0].type = ST_SCALAR_FLT;
    8801086
    8811087  clear_stack (V1);
     
    8911097 
    8921098# define S_FUNC(OP,FTYPE) {                     \
    893     if (V1->type == 'S') {                      \
     1099    if (V1->type == ST_SCALAR_FLT) {                    \
    8941100      opihi_flt M1  = V1[0].FltValue;           \
    895       OUT[0].type = 'S';                        \
     1101      OUT[0].type = ST_SCALAR_FLT;                      \
    8961102      OUT[0].FltValue = OP;                     \
    8971103      clear_stack (V1);                         \
    8981104      return (TRUE);                            \
    8991105    }                                           \
    900     if ((FTYPE == 'S') && (V1->type == 's')) {  \
     1106    if ((FTYPE == ST_SCALAR_FLT) && (V1->type == ST_SCALAR_INT)) {      \
    9011107      opihi_int M1  = V1[0].IntValue;           \
    902       OUT[0].type = 'S';                        \
     1108      OUT[0].type = ST_SCALAR_FLT;                      \
    9031109      OUT[0].FltValue = OP;                     \
    9041110      clear_stack (V1);                         \
    9051111      return (TRUE);                            \
    9061112    }                                           \
    907     if ((FTYPE == 's') && (V1->type == 's')) {  \
     1113    if ((FTYPE == ST_SCALAR_INT) && (V1->type == ST_SCALAR_INT)) {      \
    9081114      opihi_int M1  = V1[0].IntValue;           \
    909       OUT[0].type = 's';                        \
     1115      OUT[0].type = ST_SCALAR_INT;                      \
    9101116      OUT[0].IntValue = OP;                     \
    9111117      clear_stack (V1);                         \
     
    9141120  }
    9151121
    916   if (!strcmp (op, "="))      S_FUNC(M1, 's');
    917   if (!strcmp (op, "abs"))    S_FUNC(fabs(M1), 's');
    918   if (!strcmp (op, "int"))    S_FUNC((long long)(M1), 's');
    919   if (!strcmp (op, "exp"))    S_FUNC(exp (M1), 'S');
    920   if (!strcmp (op, "ten"))    S_FUNC(pow (10.0,M1), 'S');
    921   if (!strcmp (op, "log"))    S_FUNC(log10 (M1), 'S');
    922   if (!strcmp (op, "ln"))     S_FUNC(log (M1), 'S');
    923   if (!strcmp (op, "sqrt"))   S_FUNC(sqrt (M1), 'S');
    924   if (!strcmp (op, "erf"))    S_FUNC(erf (M1), 'S');
    925   if (!strcmp (op, "sinh"))   S_FUNC(sinh (M1), 'S');
    926   if (!strcmp (op, "cosh"))   S_FUNC(cosh (M1), 'S');
    927   if (!strcmp (op, "asinh"))  S_FUNC(asinh (M1), 'S');
    928   if (!strcmp (op, "acosh"))  S_FUNC(acosh (M1), 'S');
    929   if (!strcmp (op, "lgamma")) S_FUNC(lgamma (M1), 'S');
    930   if (!strcmp (op, "sin"))    S_FUNC(sin (M1), 'S');
    931   if (!strcmp (op, "cos"))    S_FUNC(cos (M1), 'S');
    932   if (!strcmp (op, "tan"))    S_FUNC(tan (M1), 'S');
    933   if (!strcmp (op, "dsin"))   S_FUNC(sin (M1*RAD_DEG), 'S');
    934   if (!strcmp (op, "dcos"))   S_FUNC(cos (M1*RAD_DEG), 'S');
    935   if (!strcmp (op, "dtan"))   S_FUNC(tan (M1*RAD_DEG), 'S');
    936   if (!strcmp (op, "asin"))   S_FUNC(asin (M1), 'S');
    937   if (!strcmp (op, "acos"))   S_FUNC(acos (M1), 'S');
    938   if (!strcmp (op, "atan"))   S_FUNC(atan (M1), 'S');
    939   if (!strcmp (op, "dasin"))  S_FUNC(asin (M1)*DEG_RAD, 'S');
    940   if (!strcmp (op, "dacos"))  S_FUNC(acos (M1)*DEG_RAD, 'S');
    941   if (!strcmp (op, "datan"))  S_FUNC(atan (M1)*DEG_RAD, 'S');
    942   if (!strcmp (op, "rnd"))    S_FUNC(M1*0.0 + drand48(), 'S');
    943   if (!strcmp (op, "not"))    S_FUNC(!(M1), 's');
    944   if (!strcmp (op, "--"))     S_FUNC(-1*M1, 's'); // NOTE: opihi_int is signed,
    945   if (!strcmp (op, "isinf"))  S_FUNC(!finite(M1), 'S'); // XXX modify in future
    946   if (!strcmp (op, "isnan"))  S_FUNC(isnan(M1), 'S'); // XXX modify in future   
     1122  if (!strcmp (op, "="))      S_FUNC(M1, ST_SCALAR_INT);
     1123  if (!strcmp (op, "abs"))    S_FUNC(fabs(M1), ST_SCALAR_INT);
     1124  if (!strcmp (op, "int"))    S_FUNC((long long)(M1), ST_SCALAR_INT);
     1125  if (!strcmp (op, "exp"))    S_FUNC(exp (M1), ST_SCALAR_FLT);
     1126  if (!strcmp (op, "ten"))    S_FUNC(pow (10.0,M1), ST_SCALAR_FLT);
     1127  if (!strcmp (op, "log"))    S_FUNC(log10 (M1), ST_SCALAR_FLT);
     1128  if (!strcmp (op, "ln"))     S_FUNC(log (M1), ST_SCALAR_FLT);
     1129  if (!strcmp (op, "sqrt"))   S_FUNC(sqrt (M1), ST_SCALAR_FLT);
     1130  if (!strcmp (op, "erf"))    S_FUNC(erf (M1), ST_SCALAR_FLT);
     1131  if (!strcmp (op, "sinh"))   S_FUNC(sinh (M1), ST_SCALAR_FLT);
     1132  if (!strcmp (op, "cosh"))   S_FUNC(cosh (M1), ST_SCALAR_FLT);
     1133  if (!strcmp (op, "asinh"))  S_FUNC(asinh (M1), ST_SCALAR_FLT);
     1134  if (!strcmp (op, "acosh"))  S_FUNC(acosh (M1), ST_SCALAR_FLT);
     1135  if (!strcmp (op, "lgamma")) S_FUNC(lgamma (M1), ST_SCALAR_FLT);
     1136  if (!strcmp (op, "sin"))    S_FUNC(sin (M1), ST_SCALAR_FLT);
     1137  if (!strcmp (op, "cos"))    S_FUNC(cos (M1), ST_SCALAR_FLT);
     1138  if (!strcmp (op, "tan"))    S_FUNC(tan (M1), ST_SCALAR_FLT);
     1139  if (!strcmp (op, "dsin"))   S_FUNC(sin (M1*RAD_DEG), ST_SCALAR_FLT);
     1140  if (!strcmp (op, "dcos"))   S_FUNC(cos (M1*RAD_DEG), ST_SCALAR_FLT);
     1141  if (!strcmp (op, "dtan"))   S_FUNC(tan (M1*RAD_DEG), ST_SCALAR_FLT);
     1142  if (!strcmp (op, "asin"))   S_FUNC(asin (M1), ST_SCALAR_FLT);
     1143  if (!strcmp (op, "acos"))   S_FUNC(acos (M1), ST_SCALAR_FLT);
     1144  if (!strcmp (op, "atan"))   S_FUNC(atan (M1), ST_SCALAR_FLT);
     1145  if (!strcmp (op, "dasin"))  S_FUNC(asin (M1)*DEG_RAD, ST_SCALAR_FLT);
     1146  if (!strcmp (op, "dacos"))  S_FUNC(acos (M1)*DEG_RAD, ST_SCALAR_FLT);
     1147  if (!strcmp (op, "datan"))  S_FUNC(atan (M1)*DEG_RAD, ST_SCALAR_FLT);
     1148  if (!strcmp (op, "rnd"))    S_FUNC(M1*0.0 + drand48(), ST_SCALAR_FLT);
     1149  if (!strcmp (op, "not"))    S_FUNC(!(M1), ST_SCALAR_INT);
     1150  if (!strcmp (op, "--"))     S_FUNC(-1*M1, ST_SCALAR_INT); // NOTE: opihi_int is signed,
     1151  if (!strcmp (op, "isinf"))  S_FUNC(!finite(M1), ST_SCALAR_FLT); // XXX modify in future
     1152  if (!strcmp (op, "isnan"))  S_FUNC(isnan(M1), ST_SCALAR_FLT); // XXX modify in future   
    9471153
    9481154# undef S_FUNC
    9491155
    9501156  clear_stack (V1);
    951   sprintf (line, "error: op %s not defined!", op);
     1157  snprintf (line, 512, "error: op %s not defined!", op);
    9521158  push_error (line);
    9531159  return (FALSE);
     
    9621168
    9631169  OUT[0].vector = InitVector ();
    964   OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
     1170  OUT[0].type = ST_VECTOR_TMP; /*** <<--- says this is a temporary matrix ***/
    9651171
    9661172# define V_FUNC(OP,FTYPE) {                                     \
     
    9741180      goto escape;                                              \
    9751181    }                                                           \
    976     if ((V1->vector->type == OPIHI_INT) && (FTYPE == 'S')) {    \
     1182    if ((V1->vector->type == OPIHI_INT) && (FTYPE == ST_SCALAR_FLT)) {  \
    9771183      MatchVector (OUT[0].vector, V1[0].vector, OPIHI_FLT);     \
    9781184      opihi_int *M1  = V1[0].vector[0].elements.Int;            \
     
    9831189      goto escape;                                              \
    9841190    }                                                           \
    985     if ((V1->vector->type == OPIHI_INT) && (FTYPE == 's')) {    \
     1191    if ((V1->vector->type == OPIHI_INT) && (FTYPE == ST_SCALAR_INT)) {  \
    9861192      CopyVector (OUT[0].vector, V1[0].vector);                 \
    9871193      opihi_int *M1  = V1[0].vector[0].elements.Int;            \
     
    9931199    } }                                                 
    9941200
    995   if (!strcmp (op, "="))      V_FUNC(*M1, 's');
    996   if (!strcmp (op, "abs"))    V_FUNC(fabs(*M1), 's');
    997   if (!strcmp (op, "int"))    V_FUNC((long long)(*M1), 's');
    998   if (!strcmp (op, "exp"))    V_FUNC(exp(*M1), 'S');
    999   if (!strcmp (op, "ten"))    V_FUNC(pow(10.0,*M1), 'S');
    1000   if (!strcmp (op, "log"))    V_FUNC(log10(*M1), 'S');
    1001   if (!strcmp (op, "ln"))     V_FUNC(log(*M1), 'S');
    1002   if (!strcmp (op, "sqrt"))   V_FUNC(sqrt(*M1), 'S');
    1003   if (!strcmp (op, "erf"))    V_FUNC(erf(*M1), 'S');
    1004   if (!strcmp (op, "sinh"))   V_FUNC(sinh(*M1), 'S');
    1005   if (!strcmp (op, "cosh"))   V_FUNC(cosh(*M1), 'S');
    1006   if (!strcmp (op, "asinh"))  V_FUNC(asinh(*M1), 'S');
    1007   if (!strcmp (op, "acosh"))  V_FUNC(acosh(*M1), 'S');
    1008   if (!strcmp (op, "lgamma")) V_FUNC(lgamma(*M1), 'S');
    1009   if (!strcmp (op, "sin"))    V_FUNC(sin(*M1), 'S');
    1010   if (!strcmp (op, "cos"))    V_FUNC(cos(*M1), 'S');
    1011   if (!strcmp (op, "tan"))    V_FUNC(tan(*M1), 'S');
    1012   if (!strcmp (op, "dsin"))   V_FUNC(sin(*M1*RAD_DEG), 'S');
    1013   if (!strcmp (op, "dcos"))   V_FUNC(cos(*M1*RAD_DEG), 'S');
    1014   if (!strcmp (op, "dtan"))   V_FUNC(tan(*M1*RAD_DEG), 'S');
    1015   if (!strcmp (op, "asin"))   V_FUNC(asin(*M1), 'S');
    1016   if (!strcmp (op, "acos"))   V_FUNC(acos(*M1), 'S');
    1017   if (!strcmp (op, "atan"))   V_FUNC(atan(*M1), 'S');
    1018   if (!strcmp (op, "dasin"))  V_FUNC(asin(*M1)*DEG_RAD, 'S');
    1019   if (!strcmp (op, "dacos"))  V_FUNC(acos(*M1)*DEG_RAD, 'S');
    1020   if (!strcmp (op, "datan"))  V_FUNC(atan(*M1)*DEG_RAD, 'S');
    1021   if (!strcmp (op, "rnd"))    V_FUNC(drand48(), 'S');
    1022   if (!strcmp (op, "ramp"))   V_FUNC(i, 's');
    1023   if (!strcmp (op, "zero"))   V_FUNC(0, 's');
    1024   if (!strcmp (op, "not"))    V_FUNC(!(*M1), 's');
    1025   if (!strcmp (op, "--"))     V_FUNC(-1*(*M1), 's'); // NOTE: opihi_int is signed
    1026   if (!strcmp (op, "isinf"))  V_FUNC(!finite(*M1), 'S');
    1027   if (!strcmp (op, "isnan"))  V_FUNC(isnan(*M1), 'S');
    1028   if (!strcmp (op, "xramp"))  V_FUNC(i, 's');
    1029   if (!strcmp (op, "yramp"))  V_FUNC(0, 's');
     1201  if (!strcmp (op, "="))      V_FUNC(*M1, ST_SCALAR_INT);
     1202  if (!strcmp (op, "abs"))    V_FUNC(fabs(*M1), ST_SCALAR_INT);
     1203  if (!strcmp (op, "int"))    V_FUNC((long long)(*M1), ST_SCALAR_INT);
     1204  if (!strcmp (op, "exp"))    V_FUNC(exp(*M1), ST_SCALAR_FLT);
     1205  if (!strcmp (op, "ten"))    V_FUNC(pow(10.0,*M1), ST_SCALAR_FLT);
     1206  if (!strcmp (op, "log"))    V_FUNC(log10(*M1), ST_SCALAR_FLT);
     1207  if (!strcmp (op, "ln"))     V_FUNC(log(*M1), ST_SCALAR_FLT);
     1208  if (!strcmp (op, "sqrt"))   V_FUNC(sqrt(*M1), ST_SCALAR_FLT);
     1209  if (!strcmp (op, "erf"))    V_FUNC(erf(*M1), ST_SCALAR_FLT);
     1210  if (!strcmp (op, "sinh"))   V_FUNC(sinh(*M1), ST_SCALAR_FLT);
     1211  if (!strcmp (op, "cosh"))   V_FUNC(cosh(*M1), ST_SCALAR_FLT);
     1212  if (!strcmp (op, "asinh"))  V_FUNC(asinh(*M1), ST_SCALAR_FLT);
     1213  if (!strcmp (op, "acosh"))  V_FUNC(acosh(*M1), ST_SCALAR_FLT);
     1214  if (!strcmp (op, "lgamma")) V_FUNC(lgamma(*M1), ST_SCALAR_FLT);
     1215  if (!strcmp (op, "sin"))    V_FUNC(sin(*M1), ST_SCALAR_FLT);
     1216  if (!strcmp (op, "cos"))    V_FUNC(cos(*M1), ST_SCALAR_FLT);
     1217  if (!strcmp (op, "tan"))    V_FUNC(tan(*M1), ST_SCALAR_FLT);
     1218  if (!strcmp (op, "dsin"))   V_FUNC(sin(*M1*RAD_DEG), ST_SCALAR_FLT);
     1219  if (!strcmp (op, "dcos"))   V_FUNC(cos(*M1*RAD_DEG), ST_SCALAR_FLT);
     1220  if (!strcmp (op, "dtan"))   V_FUNC(tan(*M1*RAD_DEG), ST_SCALAR_FLT);
     1221  if (!strcmp (op, "asin"))   V_FUNC(asin(*M1), ST_SCALAR_FLT);
     1222  if (!strcmp (op, "acos"))   V_FUNC(acos(*M1), ST_SCALAR_FLT);
     1223  if (!strcmp (op, "atan"))   V_FUNC(atan(*M1), ST_SCALAR_FLT);
     1224  if (!strcmp (op, "dasin"))  V_FUNC(asin(*M1)*DEG_RAD, ST_SCALAR_FLT);
     1225  if (!strcmp (op, "dacos"))  V_FUNC(acos(*M1)*DEG_RAD, ST_SCALAR_FLT);
     1226  if (!strcmp (op, "datan"))  V_FUNC(atan(*M1)*DEG_RAD, ST_SCALAR_FLT);
     1227  if (!strcmp (op, "rnd"))    V_FUNC(drand48(), ST_SCALAR_FLT);
     1228  if (!strcmp (op, "ramp"))   V_FUNC(i, ST_SCALAR_INT);
     1229  if (!strcmp (op, "zero"))   V_FUNC(0, ST_SCALAR_INT);
     1230  if (!strcmp (op, "not"))    V_FUNC(!(*M1), ST_SCALAR_INT);
     1231  if (!strcmp (op, "--"))     V_FUNC(-1*(*M1), ST_SCALAR_INT); // NOTE: opihi_int is signed
     1232  if (!strcmp (op, "isinf"))  V_FUNC(!finite(*M1), ST_SCALAR_FLT);
     1233  if (!strcmp (op, "isnan"))  V_FUNC(isnan(*M1), ST_SCALAR_FLT);
     1234  if (!strcmp (op, "xramp"))  V_FUNC(i, ST_SCALAR_INT);
     1235  if (!strcmp (op, "yramp"))  V_FUNC(0, ST_SCALAR_INT);
    10301236  /* xramp and yramp above only make sense for matrices. for vectors, xramp = ramp, yramp = zero */
    10311237
     
    10341240escape:
    10351241
    1036   if (V1[0].type == 'v') {
     1242  if (V1[0].type == ST_VECTOR_TMP) {
    10371243    free (V1[0].vector[0].elements.Ptr);
    10381244    free (V1[0].vector);
     
    10531259  Ny = V1[0].buffer[0].matrix.Naxis[1];
    10541260
    1055   if (V1[0].type == 'm') {
     1261  if (V1[0].type == ST_MATRIX_TMP) {
    10561262    OUT[0].buffer = V1[0].buffer;
    1057     V1[0].type = 'M'; /* prevent it from being freed below */
     1263    V1[0].type = ST_MATRIX; /* prevent it from being freed below */
    10581264  } else {
    10591265    OUT[0].buffer = InitBuffer ();
    10601266    CopyBuffer (OUT[0].buffer, V1[0].buffer);
    10611267  }
    1062   OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
     1268  OUT[0].type = ST_MATRIX_TMP;      /*** <<--- says this is a temporary matrix ***/
    10631269  M1  = (float *) V1[0].buffer[0].matrix.buffer;
    10641270  out = (float *)OUT[0].buffer[0].matrix.buffer;
     
    11161322  }
    11171323 
    1118   if (V1[0].type == 'm') {
     1324  if (V1[0].type == ST_MATRIX_TMP) {
    11191325    free (V1[0].buffer[0].header.buffer);
    11201326    free (V1[0].buffer[0].matrix.buffer);
  • trunk/Ohana/src/opihi/pantasks/CheckController.c

    r23530 r36375  
    2929  if (p != NULL) goto escape;
    3030
     31  /** skip past any leading garbage? ***/
     32
     33  /** find "Njobs: **/
     34  p = memstr (buffer.buffer, "BEGIN BLOCK Njobs:", MIN(buffer.Nbuffer, 256));
     35  p += strlen("BEGIN BLOCK Njobs:");
     36
    3137  /** parse job list **/
    32   status = sscanf (buffer.buffer, "%*s %d", &Njobs);
     38  status = sscanf (p, "%d", &Njobs);
    3339  if (status != 1) goto escape;
    3440  if (VerboseMode()) gprint (GP_ERR, "parse %d jobs on stack %f\n", Njobs, TimerElapsed(&start, TRUE));
    3541
    36   p = buffer.buffer;
     42  /* output looks like:
     43     BEGIN BLOCK Njobs: NN\n
     44     ID name machine\n
     45     ID name machine\n
     46  */
     47
     48  // p is currently pointing at "BEGIN BLOCK Njobs"
     49
    3750  for (i = 0; i < Njobs; i++) {
    3851    q = strchr (p, '\n');
     
    6780  if (p != NULL) goto escape;
    6881
     82  /** skip past any leading garbage? ***/
     83
     84  /** find "Njobs: **/
     85  p = memstr (buffer.buffer, "BEGIN BLOCK Njobs:", MIN(buffer.Nbuffer, 256));
     86  p += strlen("BEGIN BLOCK Njobs:");
     87
    6988  /** parse job list **/
    70   status = sscanf (buffer.buffer, "%*s %d", &Njobs);
     89  status = sscanf (p, "%d", &Njobs);
    7190  if (status != 1) goto escape;
    7291  if (VerboseMode()) gprint (GP_ERR, "check crash stack %f\n", TimerElapsed(&start, TRUE));
    7392
    74   p = buffer.buffer;
     93  /* output looks like:
     94     BEGIN BLOCK Njobs: NN\n
     95     ID name machine\n
     96     ID name machine\n
     97  */
     98
     99  // p is currently pointing at "BEGIN BLOCK Njobs"
     100
    75101  for (i = 0; i < Njobs; i++) {
    76102    q = strchr (p, '\n');
  • trunk/Ohana/src/opihi/pcontrol/JobOps.c

    r32632 r36375  
    5959  pcontrol_exit (53);
    6060  return (NULL);
     61}
     62
     63int GetJobStackIDbyName (char *name) {
     64  if (!strcasecmp (name, "ALLJOBS"))  return PCONTROL_JOB_ALLJOBS;
     65  if (!strcasecmp (name, "PENDING"))  return PCONTROL_JOB_PENDING;
     66  if (!strcasecmp (name, "BUSY"))     return PCONTROL_JOB_BUSY   ;
     67  if (!strcasecmp (name, "RESP"))     return PCONTROL_JOB_RESP   ;
     68  if (!strcasecmp (name, "DONE"))     return PCONTROL_JOB_DONE   ;
     69  if (!strcasecmp (name, "KILL"))     return PCONTROL_JOB_KILL   ;
     70  if (!strcasecmp (name, "EXIT"))     return PCONTROL_JOB_EXIT   ;
     71  if (!strcasecmp (name, "CRASH"))    return PCONTROL_JOB_CRASH  ;
     72  return (PCONTROL_JOB_NONE);
    6173}
    6274
  • trunk/Ohana/src/opihi/pcontrol/jobstack.c

    r12470 r36375  
    2222  /* print list */
    2323  LockStack (stack);
    24   gprint (GP_LOG, "Njobs: %d\n", stack[0].Nobject);
     24  gprint (GP_LOG, "BEGIN BLOCK Njobs: %d\n", stack[0].Nobject);
    2525  for (i = 0; i < stack[0].Nobject; i++) {
    2626    job = stack[0].object[i];
  • trunk/Ohana/src/opihi/pcontrol/status.c

    r32632 r36375  
    11# include "pcontrol.h"
    22
    3 int PrintJobStack (int Nstack);
     3int PrintJobStack (int Nstack, char *command, char *hostname, int state, float age);
    44int PrintHostStack (int Nstack);
    55
    66int status (int argc, char **argv) {
    77
    8   PrintJobStack (PCONTROL_JOB_ALLJOBS);
    9   PrintHostStack (PCONTROL_HOST_ALLHOSTS);
     8  int N;
     9
     10  if (get_argument (argc, argv, "-h")) goto usage;
     11  if (get_argument (argc, argv, "-help")) goto usage;
     12  if (get_argument (argc, argv, "--help")) goto usage;
     13
     14  /* I would like to add the following options:
     15   * strsub on argv[0]
     16   * strsub on hostname, realhost
     17   * list hostname and realhost
     18   * filter by state
     19   * filter by dtime
     20  */
     21
     22  // -cmd (cmd)
     23  // -host (hostname)
     24  // -state (busy, pending, done, kill, exit, crash, resp, hung
     25  // -age (seconds?) (minutes?)
     26  // -nohost
     27
     28  char *COMMAND = NULL;
     29  if ((N = get_argument (argc, argv, "-cmd"))) {
     30    remove_argument (N, &argc, argv);
     31    COMMAND = strcreate (argv[N]);
     32    remove_argument (N, &argc, argv);
     33  }
     34
     35  char *HOSTNAME = NULL;
     36  if ((N = get_argument (argc, argv, "-host"))) {
     37    remove_argument (N, &argc, argv);
     38    HOSTNAME = strcreate (argv[N]);
     39    remove_argument (N, &argc, argv);
     40  }
     41
     42  int STATE = PCONTROL_JOB_ALLJOBS;
     43  if ((N = get_argument (argc, argv, "-state"))) {
     44    remove_argument (N, &argc, argv);
     45    STATE = GetJobStackIDbyName (argv[N]);
     46    remove_argument (N, &argc, argv);
     47    if (STATE == PCONTROL_JOB_NONE) goto usage;
     48  }
     49
     50  float AGE = 0.0;
     51  if ((N = get_argument (argc, argv, "-age"))) {
     52    remove_argument (N, &argc, argv);
     53    AGE = atof (argv[N]);
     54    remove_argument (N, &argc, argv);
     55  }
     56
     57  int SHOWHOST = TRUE;
     58  if ((N = get_argument (argc, argv, "-nohost"))) {
     59    remove_argument (N, &argc, argv);
     60    SHOWHOST = FALSE;
     61  }
     62  if ((N = get_argument (argc, argv, "+jobs"))) {
     63    remove_argument (N, &argc, argv);
     64    SHOWHOST = FALSE;
     65  }
     66
     67  int SHOWJOBS = TRUE;
     68  if ((N = get_argument (argc, argv, "-nojobs"))) {
     69    remove_argument (N, &argc, argv);
     70    SHOWJOBS = FALSE;
     71  }
     72  if ((N = get_argument (argc, argv, "+host"))) {
     73    remove_argument (N, &argc, argv);
     74    SHOWJOBS = FALSE;
     75  }
     76
     77  if (SHOWJOBS) {
     78    PrintJobStack (PCONTROL_JOB_ALLJOBS, COMMAND, HOSTNAME, STATE, AGE);
     79  }
     80  if (SHOWHOST) {
     81    PrintHostStack (PCONTROL_HOST_ALLHOSTS);
     82  }
    1083
    1184  return (TRUE);
     85
     86usage:
     87  gprint (GP_ERR, "USAGE: status [-cmd command] [-host hostname] [-state state] [-age seconds] [+jobs,-nohost] [+host,-nojobs]\n");
     88  return FALSE;
    1289}
    1390
    14 int PrintJobStack (int Nstack) {
     91int PrintJobStack (int Nstack, char *command, char *hostname, int state, float age) {
    1592
    1693  int i, j, Nobject;
     
    30107    job = stack[0].object[i];
    31108    ASSERT (job != NULL, "programming error");
    32     if (job[0].realhost == NULL) {
    33         gprint (GP_LOG, "%3d %9s ", i, job[0].hostname);
    34     } else {
    35         gprint (GP_LOG, "%3d %9s ", i, job[0].realhost);
    36     }
    37     gprint (GP_LOG, "%7s  ", GetJobStackName (job[0].state));
     109
     110    char *thishost = (job[0].realhost == NULL) ? job[0].hostname : job[0].realhost;
    38111
    39112    switch (job[0].state) {
     
    45118        gettimeofday (&now, (void *) NULL);
    46119        dtime = DTIME (now, job[0].start);
    47         gprint (GP_LOG, "%8.2f ", dtime);
    48120        break;
    49121
     
    55127      default:
    56128        dtime = DTIME (job[0].stop, job[0].start);
    57         gprint (GP_LOG, "%8.2f ", dtime);
    58129        break;
    59130    }
     131
     132    // check on the filters
     133    if (command) {
     134      if (!strstr (job[0].argv[0], command)) continue;
     135    }
     136    if (hostname) {
     137      if (!strstr (thishost, hostname)) continue;
     138    }
     139    if (age > 0.0) {
     140      if (dtime < age) continue;
     141    }
     142    if (state != PCONTROL_JOB_ALLJOBS) {
     143      // allow PCONTROL_JOB_RESP == BUSY
     144      int validState = FALSE;
     145      validState |= (state == PCONTROL_JOB_RESP) && (job[0].state == PCONTROL_JOB_BUSY);
     146      validState |= (state == PCONTROL_JOB_BUSY) && (job[0].state == PCONTROL_JOB_RESP);
     147      validState |= (state == job[0].state);
     148      if (!validState) continue;
     149    }
     150
     151    gprint (GP_LOG, "%3d %9s ", i, thishost);
     152    gprint (GP_LOG, "%7s  ", GetJobStackName (job[0].state));
     153    gprint (GP_LOG, "%8.2f ", dtime);
    60154
    61155    PrintID (GP_LOG, job[0].JobID);
  • trunk/Ohana/src/relastro/src

  • trunk/ippToPsps

  • trunk/ippconfig

  • trunk/ippconfig/gpc1

  • trunk/ippconfig/gpc1/camera.config

    r31717 r36375  
    139139  CMF.XRAD STR {CHIP.NAME}.xrad # use .PSF and .EXT?
    140140  CMF.XFIT STR {CHIP.NAME}.xfit # use .PSF and .EXT?
     141  CMF.XGAL STR {CHIP.NAME}.xgal # use .PSF and .EXT?
    141142  CMF.DETEFF STR {CHIP.NAME}.deteff
    142143
  • trunk/ippconfig/recipes/filerules-mef.mdc

    r35865 r36375  
    8686PSPHOT.PSF.LOAD         INPUT    @FILES        CHIP       PSF       
    8787PSPHOT.INPUT.CMF        INPUT    @FILES        CHIP       CMF       
     88PSPHOT.INPUT.CFF        INPUT    @FILES        CHIP       CFF
    8889PSPHOT.INPUT.TEXT       INPUT    @FILES        CHIP       SRCTEXT       
    8990PSPHOT.EXPNUM           INPUT    @FILES        CHIP       MASK       
     
    247248PSPHOT.OUT.CMF.SPL      OUTPUT {OUTPUT}.{CHIP.NAME}.cmf          CMF       NONE       CHIP       TRUE      SPLIT
    248249PSPHOT.OUT.CMF.MEF      OUTPUT {OUTPUT}.cmf                      CMF       NONE       CHIP       TRUE      MEF
     250PSPHOT.OUTPUT.CFF       OUTPUT {OUTPUT}.cff                      CFF       NONE       CHIP       TRUE      MEF
    249251PSPHOT.PSF.RAW.SAVE     OUTPUT {OUTPUT}.psf                      PSF       NONE       CHIP       TRUE      MEF
    250252PSPHOT.PSF.SKY.SAVE     OUTPUT {OUTPUT}.psf                      PSF       NONE       CHIP       TRUE      MEF
  • trunk/ippconfig/recipes/filerules-simple.mdc

    r35865 r36375  
    5757PSPHOT.PSF.LOAD           INPUT    @FILES        CHIP       PSF       
    5858PSPHOT.INPUT.CMF          INPUT    @FILES        CHIP       CMF       
     59PSPHOT.INPUT.CFF          INPUT    @FILES        CHIP       CFF
    5960PSPHOT.INPUT.TEXT         INPUT    @FILES        CHIP       SRCTEXT       
    6061PSPHOT.EXPNUM             INPUT    @FILES        CHIP       MASK
     
    209210PSPHOT.OUTPUT.CMF            OUTPUT {OUTPUT}.cmf                  CMF             NONE       CHIP       TRUE      NONE
    210211PSPHOT.OUT.CMF.MEF           OUTPUT {OUTPUT}.cmf                  CMF             NONE       CHIP       TRUE      NONE
     212PSPHOT.OUTPUT.CFF            OUTPUT {OUTPUT}.cff                  CFF             NONE       CHIP       TRUE      NONE
    211213PSPHOT.PSF.RAW.SAVE          OUTPUT {OUTPUT}.psf                  PSF             NONE       FPA        TRUE      NONE
    212214PSPHOT.PSF.SKY.SAVE          OUTPUT {OUTPUT}.psf                  PSF             NONE       FPA        TRUE      NONE
  • trunk/ippconfig/recipes/filerules-split.mdc

    r36360 r36375  
    7777PSPHOT.PSF.LOAD           INPUT    @FILES        CHIP       PSF       
    7878PSPHOT.INPUT.CMF          INPUT    @FILES        CHIP       CMF       
     79PSPHOT.INPUT.CFF          INPUT    @FILES        CHIP       CFF
    7980PSPHOT.INPUT.TEXT         INPUT    @FILES        CHIP       SRCTEXT       
    8081PSPHOT.EXPNUM             INPUT    @FILES        CHIP       EXPNUM
     
    233234PSPHOT.OUT.CMF.SPL           OUTPUT {OUTPUT}.{CHIP.NAME}.cmf          CMF             NONE       CHIP       TRUE      NONE
    234235PSPHOT.OUT.CMF.MEF           OUTPUT {OUTPUT}.cmf                      CMF             NONE       FPA        TRUE      MEF
     236PSPHOT.OUTPUT.CFF            OUTPUT {OUTPUT}.cff                      CFF             NONE       CHIP       TRUE      NONE
    235237PSPHOT.PSF.RAW.SAVE          OUTPUT {OUTPUT}.{CHIP.NAME}.psf          PSF             NONE       CHIP       TRUE      MEF
    236238PSPHOT.PSF.SKY.SAVE          OUTPUT {OUTPUT}.psf                      PSF             NONE       FPA        TRUE      MEF
  • trunk/ippconfig/recipes/ppSim.config

    r32355 r36375  
    6161PSF.THETA       F32     0.0
    6262PSF.CONVOLVE    BOOL    FALSE           # generate fake stars with PSF (F), or smooth with PSF (T)?
     63CONVOLVE.NSIGMA F32     5.0             # smooth image out to NSIGMA * sigma
    6364
    6465STARS.GRID      BOOL    FALSE           # Add grid of fake stars with constant flux
  • trunk/ippconfig/recipes/ppSub.config

  • trunk/ippconfig/recipes/psphot.config

    r36225 r36375  
    1 
    21# these options turn on different inputs and/or outputs
    32SAVE.OUTPUT                         BOOL  TRUE
     
    181180EXT_FIT_MIN_TOL                     F32   0.01            # Fit tolerance for EXT
    182181EXT_FIT_MAX_TOL                     F32   2.00            # Fit tolerance for EXT
     182EXT_FIT_NSIGMA_CONV                 F32   9.00            # Number of sigma for PSF convolved fits
    183183
    184184# the following is used to require a minimum quality of fit before
     
    189189
    190190# extended source aperture-like measurements
    191 EXTENDED_SOURCE_ANALYSIS            BOOL  FALSE  # perform any of the aperture-like measurements?
     191EXTENDED_SOURCE_PETROSIAN           BOOL  FALSE
     192EXTENDED_SOURCE_ANNULI              BOOL  FALSE
     193EXTENDED_SOURCE_RAW_RADIUS          BOOL  FALSE  # use circular (T) or elliptical (F) contours for petrosians?
    192194EXTENDED_SOURCE_SN_LIM              F32   20.0
    193 EXTENDED_SOURCE_RAW_RADIUS          BOOL  FALSE
    194 EXTENDED_SOURCE_PETROSIAN           BOOL  FALSE
    195 EXTENDED_SOURCE_ISOPHOTAL           BOOL  FALSE
    196 EXTENDED_SOURCE_ANNULI              BOOL  FALSE
    197 EXTENDED_SOURCE_KRON                BOOL  FALSE
    198 PETROSIAN_FOR_STARS                 BOOL  FALSE
     195
     196EXT.NSIGMA.LIMIT.USE                BOOL  TRUE
     197
     198EXT.FIT.MIN.GAL.LIMIT               F32   10.0
     199EXT.FIT.MIN.GAL.LIMIT.USE           BOOL  FALSE
    199200
    200201KRON_ITERATIONS                     S32   2
     
    208209EXTENDED_SOURCE_FITS                BOOL  FALSE  # perform the detailed extended sourc fits?
    209210EXTENDED_SOURCE_FITS_INTERACTIVE    BOOL  FALSE  # perform the detailed extended sourc fits?
     211EXTENDED_SOURCE_FITS_POISSON        BOOL  FALSE   # use poisson errors for extended source models
    210212
    211213EXTENDED_SOURCE_MODELS_SELECTION    STR   ALL
     
    258260# Extended source fit parameters
    259261EXTENDED_TEST                       METADATA
    260   EXTENDED_SOURCE_ANALYSIS            BOOL  TRUE  # perform any of the aperture-like measurements?
    261262  EXTENDED_SOURCE_SN_LIM              F32   20.0
    262263  EXTENDED_SOURCE_PETROSIAN           BOOL  TRUE
    263   EXTENDED_SOURCE_ISOPHOTAL           BOOL  TRUE
    264   EXTENDED_SOURCE_ANNULI              BOOL  TRUE
    265   EXTENDED_SOURCE_KRON                BOOL  FALSE
    266264END
    267265
     
    293291INTERPOLATE_AP                      BOOL  TRUE
    294292
    295 POISSON.ERRORS.PHOT.LMM             BOOL  TRUE   
     293POISSON.ERRORS.PHOT.LMM             BOOL  TRUE
    296294POISSON.ERRORS.PHOT.LIN             BOOL  FALSE
    297295POISSON.ERRORS.PARAMS               BOOL  TRUE
     
    408406END
    409407
     408EXT.ANALYSIS.MAG.LIMITS METADATA
     409    TYPE  DATA FILTER.ID MAG.LIMIT
     410    gband DATA g         NAN           
     411    rband DATA r         NAN             
     412    iband DATA i         NAN             
     413    zband DATA z         NAN             
     414    yband DATA y         NAN             
     415    wband DATA w         NAN             
     416    other DATA any       NAN             
     417END
     418
    410419# if true keep all matched sources, even if we get a non-finite aperture flux measurement
    411420PSPHOT.STACK.KEEP.BAD.MATCHES  BOOL     F
     
    414423RADIAL_APERTURES_SN_LIM             F32   0.0  # S/N limit for radial aperture calculation
    415424
     425GALAXY_SHAPES                       BOOL  F
     426GALAXY_SHAPES_FR_MAJOR_MIN          F32   0.5
     427GALAXY_SHAPES_FR_MAJOR_MAX          F32   2.0
     428GALAXY_SHAPES_FR_MAJOR_DEL          F32   0.1
     429GALAXY_SHAPES_FR_MINOR_MIN          F32   0.5
     430GALAXY_SHAPES_FR_MINOR_MAX          F32   2.0
     431GALAXY_SHAPES_FR_MINOR_DEL          F32   0.1
     432
     433
    416434# Extended source fit parameters
    417435STACKPHOT                             METADATA
    418436  EXTENDED_SOURCE_FITS                BOOL  TRUE  # perform any of the aperture-like measurements?
    419   EXTENDED_SOURCE_ANALYSIS            BOOL  TRUE  # perform any of the aperture-like measurements?
    420437  EXTENDED_SOURCE_SN_LIM              F32   10.0
    421438  EXTENDED_SOURCE_PETROSIAN           BOOL  TRUE
    422439  EXTENDED_SOURCE_ANNULI              BOOL  TRUE
     440  EXT.NSIGMA.LIMIT.USE                BOOL  FALSE
     441
    423442  PSPHOT.STACK.MATCH.PSF.SOURCE       STR   AUTO # which inputs to convolve? (RAW, CNV, AUTO)
    424443  PSPHOT.STACK.TARGET.PSF.AUTO        BOOL  F    # automatically determine target PSF size?
     
    430449  RADIAL_APERTURES                    BOOL  T    # calculate flux in circular radial apertures?
    431450  RADIAL_APERTURES_SN_LIM             F32   0.0  # S/N limit for radial aperture calculation
    432   OUTPUT.FORMAT                       STR   PS1_SV1
    433   PETROSIAN_FOR_STARS                 BOOL  FALSE
     451  OUTPUT.FORMAT                       STR   PS1_SV2
    434452
    435453  # subtract radial profiles for extremely bright stars?
     
    441459  LMM_FIT_CHISQ_CONVERGENCE           BOOL  FALSE           # use the (old) chisq convergence or the new parameter one
    442460  LMM_FIT_GAIN_FACTOR_MODE            S32   2               # there are 3 options to determine the gain factor (0,1,2)
     461  EXT_FIT_MIN_TOL                     F32   0.1             # Fit tolerance for EXT
    443462
    444463  EXT_FIT_MAX_RADIUS                  F32   50.0
     
    446465  EXT_MODEL                           STR   PS_MODEL_QGAUSS
    447466  PEAKS_NMAX_TOTAL                    S32   0 # set this to limit the allowed number of peaks - Yields fault instead of avoid memory explosion
     467
     468  SAVE.RESID                          BOOL  TRUE
    448469END
    449470
     
    451472STACKPHOT_TEST                        METADATA
    452473  EXTENDED_SOURCE_FITS                BOOL  F  # perform any of the aperture-like measurements?
    453   EXTENDED_SOURCE_ANALYSIS            BOOL  F  # perform any of the aperture-like measurements?
    454474  EXTENDED_SOURCE_SN_LIM              F32   10.0
    455475  EXTENDED_SOURCE_PETROSIAN           BOOL  F
    456   EXTENDED_SOURCE_ANNULI              BOOL  F
     476
    457477  PSPHOT.STACK.MATCH.PSF.SOURCE       STR   AUTO # which inputs to convolve? (RAW, CNV, AUTO)
    458478  PSPHOT.STACK.TARGET.PSF.AUTO        BOOL  F    # automatically determine target PSF size?
     
    471491STACKPHOT_TEST_V1                     METADATA
    472492  EXTENDED_SOURCE_FITS                BOOL  F  # perform any of the aperture-like measurements?
    473   EXTENDED_SOURCE_ANALYSIS            BOOL  F  # perform any of the aperture-like measurements?
    474493  EXTENDED_SOURCE_SN_LIM              F32   20.0
    475494  EXTENDED_SOURCE_PETROSIAN           BOOL  TRUE
    476   EXTENDED_SOURCE_ANNULI              BOOL  TRUE
     495
    477496  PSPHOT.STACK.MATCH.PSF.SOURCE       STR   AUTO # which inputs to convolve? (RAW, CNV, AUTO)
    478497  PSPHOT.STACK.TARGET.PSF.AUTO        BOOL  F    # automatically determine target PSF size?
     
    496515SINGLE_TEST_V1                     METADATA
    497516  EXTENDED_SOURCE_FITS                BOOL  F  # perform any of the aperture-like measurements?
    498   EXTENDED_SOURCE_ANALYSIS            BOOL  F  # perform any of the aperture-like measurements?
    499517  EXTENDED_SOURCE_SN_LIM              F32   20.0
    500518  EXTENDED_SOURCE_PETROSIAN           BOOL  TRUE
    501   EXTENDED_SOURCE_ANNULI              BOOL  TRUE
     519
    502520  PSPHOT.STACK.MATCH.PSF.SOURCE       STR   AUTO # which inputs to convolve? (RAW, CNV, AUTO)
    503521  PSPHOT.STACK.TARGET.PSF.AUTO        BOOL  F    # automatically determine target PSF size?
     
    506524  RADIAL_APERTURES                    BOOL  F    # calculate flux in circular radial apertures?
    507525  RADIAL_APERTURES_SN_LIM             F32   0.0  # S/N limit for radial aperture calculation
    508 #  OUTPUT.FORMAT                       STR   PS1_SV1
    509526  OUTPUT.FORMAT                       STR   PS1_V3
    510527
    511   # CONSTANT_PHOTOMETRIC_WEIGHTS        BOOL  TRUE
    512   # POISSON.ERRORS.PHOT.LMM             BOOL  FALSE
    513528  CONSTANT_PHOTOMETRIC_WEIGHTS        BOOL  FALSE
    514529  POISSON.ERRORS.PHOT.LMM             BOOL  TRUE
     
    625640  # Extended source fit parameters
    626641  # these models are used for high-quality shape analysis after all sources have been removed
     642  SAVE.RESID BOOL T
     643
    627644  EXTENDED_SOURCE_FITS                BOOL  TRUE  # perform the detailed extended sourc fits?
    628   EXT_MODEL                           STR   PS_MODEL_GAUSS
     645  EXT_MODEL                           STR   PS_MODEL_QGAUSS
     646  PSF_MODEL                           STR   PS_MODEL_PS1_V1
     647
     648  LMM_FIT_CHISQ_CONVERGENCE           BOOL  FALSE           # use the (old) chisq convergence or the new parameter one
     649  LMM_FIT_GAIN_FACTOR_MODE            S32   2               # there are 3 options to determine the gain factor (0,1,2)
     650  EXT_FIT_MIN_TOL                     F32   0.1             # Fit tolerance for EXT
     651
     652  # XXX these are only needed if we want to get perfect fits of the synthetic data
     653  PSF_FIT_RADIUS_SCALE         F32   3.75
     654  EXT_FIT_NSIGMA_CONV          F32   11
     655  PSF.RESIDUALS BOOL F
    629656
    630657  # if this is defined, it gives a list of the model names to fit below (ALL or NONE are also valid)
     
    651678  END
    652679END
     680
     681FULLFORCE_WARP METADATA
     682    GALAXY_SHAPES           BOOL    TRUE
     683    RADIAL_APERTURES        BOOL    TRUE
     684    EXTENDED_SOURCE_FITS    BOOL    TRUE    # this casues the xfit extension to be written out
     685    EXTENDED_SOURCE_PETROSIAN BOOL    TRUE  # I want petrosian mags
     686    SAVE.PSF                BOOL    FALSE
     687    SAVE.BACKMDL            BOOL    FALSE
     688    # SAVE.RESID            BOOL    FALSE
     689    # OUTPUT.FORMAT         STR     PS1_V3
     690END
  • trunk/ippconfig/recipes/reductionClasses.mdc

    r36169 r36375  
    172172        PSVIDEOPHOT             STR     PSVIDEOPHOT
    173173        STATICSKY_CALIBRATION   STR     STATICSKY_CAL
     174        FULLFORCE_PSPHOT  STR   FULLFORCE_WARP
    174175END
    175176
     
    249250        BACKGROUND_PPBACKGROUND STR     BACKGROUND
    250251        BACKGROUND_PSWARP       STR     BACKGROUND
     252        FULLFORCE_PSPHOT  STR   FULLFORCE_WARP
    251253END
    252254
  • trunk/ippconfig/simple/camera.config

    r33836 r36375  
    6161  CMF.XFIT STR xfit
    6262  CMF.DETEFF STR deteff
     63  CMF.XGAL STR xgal
    6364
    6465  PSF.HEAD  STR hdr
  • trunk/ippconfig/simtest/format.config

    r29554 r36375  
    6060        FPA.LATITUDE    F64     20.7070999146 # North Latitude in Degrees
    6161        FPA.ELEVATION   F32     3048.0 # altitude in meters
    62         CELL.SATURATION F32     65535
     62        CELL.SATURATION F32     1000000
    6363        CELL.BAD        F32     0
    6464        CELL.READDIR    S32     1
  • trunk/ppSim/src/ppSimInsertStars.c

    r35770 r36375  
    7878
    7979    FILE *outfile = fopen (outname, "w");
     80    psAssert (outfile, "cannot write output");
    8081
    8182    float radius = -1.0;
  • trunk/ppSim/src/ppSimSmoothReadout.c

    r29002 r36375  
    44{
    55    bool status;
     6    psTimerStart ("ppSmooth");
    67
    7     // XXX use these defaults?
    8     // float minGauss = 0.1;
    9     float nSigma = 4.0;
     8    float nSigma = psMetadataLookupF32(&status, recipe, "CONVOLVE.NSIGMA"); // SIGMA convolutions (pixels)
     9    if (!status) nSigma = 5.0;
     10
    1011    float sigma = psMetadataLookupF32(&status, recipe, "SEEING"); // Seeing SIGMA (pixels)
    1112
    12     // bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading in psImageConvolve
     13    char *modelName = psMetadataLookupStr(&status, recipe, "PSF.MODEL"); // Seeing SIGMA (pixels)
     14    if (!strcmp (modelName, "PS_MODEL_GAUSS")) {
     15      // bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading in psImageConvolve
     16      // smooth the image in place, applying the mask as we go
     17      psImageSmooth(input->image, sigma, nSigma);
     18      psLogMsg("ppSmooth", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark("ppSmooth"));
     19      return true;
     20    }
    1321
    14     psTimerStart ("ppSmooth");
     22    if (!strcmp (modelName, "PS_MODEL_PS1_V1")) {
     23      // bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading in psImageConvolve
     24      // smooth the image in place, applying the mask as we go
     25      psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheAlloc(nSigma);
     26      psImageSmooth2dCacheKernel_PS1_V1 (smdata, sigma, 1.0);
    1527
    16     // smooth the image in place, applying the mask as we go
    17     psImageSmooth(input->image, sigma, nSigma);
    18     psLogMsg("ppSmooth", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark("ppSmooth"));
     28      psImageSmooth2dCache_F32 (input->image, smdata);
     29
     30      psFree (smdata);
     31      psLogMsg("ppSmooth", PS_LOG_MINUTIA, "smooth image: %f sec\n", psTimerMark("ppSmooth"));
     32      return true;
     33    }
    1934
    2035    // psImageConvolveSetThreads(oldThreads);
    21     return true;
     36    psLogMsg("ppSmooth", PS_LOG_MINUTIA, "failed to smooth image: %f sec\n", psTimerMark("ppSmooth"));
     37    return false;
    2238}
    2339
  • trunk/psLib/src/imageops/Makefile.am

    r21207 r36375  
    77        psImageBackground.c \
    88        psImageConvolve.c \
     9        psImageConvolve2dCache.c \
    910        psImageCovariance.c \
    1011        psImageGeomManip.c \
  • trunk/psLib/src/imageops/psImageConvolve.c

    r35767 r36375  
    3636#define MIN_GAUSS_FRAC 0.25             // Minimum Gaussian fraction to accept when smoothing
    3737
    38 
    39 
    4038static bool threaded = false;           // Run image convolution threaded?
    4139static pthread_mutex_t threadMutex = PTHREAD_MUTEX_INITIALIZER;
    42 
    4340
    4441static void kernelFree(psKernel *kernel)
     
    780777}
    781778
    782 void psImageSmooth_PreAlloc_DataFree (psImageSmooth_PreAlloc_Data *smdata) {
     779void psImageSmoothCacheDataFree (psImageSmoothCacheData *smdata) {
    783780    psFree (smdata->resultX);
    784781    psFree (smdata->resultY);
     
    786783}
    787784
    788 psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma) {
    789 
    790     psImageSmooth_PreAlloc_Data *smdata = psAlloc(sizeof(psImageSmooth_PreAlloc_Data));
    791     psMemSetDeallocator(smdata, (psFreeFunc) psImageSmooth_PreAlloc_DataFree);
     785// allocate the psImageSmoothCache data structure, but do not define the kernel
     786psImageSmoothCacheData *psImageSmoothCacheAlloc (psImage *image, double sigma, double Nsigma) {
     787
     788    psImageSmoothCacheData *smdata = psAlloc(sizeof(psImageSmoothCacheData));
     789    psMemSetDeallocator(smdata, (psFreeFunc) psImageSmoothCacheDataFree);
     790
     791    smdata->kernel = NULL;
    792792
    793793    if (!image) {
     
    796796        smdata->Nx = 0;
    797797        smdata->Ny = 0;
    798         smdata->kernel = NULL;
    799798        smdata->resultX = NULL;
    800799        smdata->resultY = NULL;
     
    807806    smdata->Ny = image->numRows;            // Number of rows
    808807
    809     IMAGE_SMOOTH_GAUSS(smdata->kernel, smdata->Nrange, sigma, F32);
     808    // XXX drop this : we now require a call to a kernel-creation function (like psImageSmoothCacheKernel_Gauss)
     809    // IMAGE_SMOOTH_GAUSS(smdata->kernel, smdata->Nrange, sigma, F32);
    810810       
    811811    // use a temp running buffer for X and Y directions.
     
    819819}
    820820
     821// generate a Gaussian smoothing kernel for supplied sigma.  sigma here does not need to match
     822// that used to allocate the structure, but it is recommended
     823bool psImageSmoothCacheKernel_Gauss (psImageSmoothCacheData *smdata, float sigma) {
     824    // check for NULL structure elements?
     825    psFree (smdata->kernel);
     826    IMAGE_SMOOTH_GAUSS(smdata->kernel, smdata->Nrange, sigma, F32);
     827    return true;
     828}
     829
    821830// we can use the same DATA structure on multiple images of the same size
    822 bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata)
     831bool psImageSmoothCache_F32(psImage *image, psImageSmoothCacheData *smdata)
    823832{
    824833    PS_ASSERT_IMAGE_NON_NULL(image, false);
     834    PS_ASSERT_VECTOR_NON_NULL(smdata->kernel, false);
    825835    // assert on data type
    826836
     
    21562166    return threaded;
    21572167}
    2158 
  • trunk/psLib/src/imageops/psImageConvolve.h

    r35767 r36375  
    2626#define PS_TYPE_KERNEL_NAME "psF32"    ///< the data type for kernel as a string */
    2727
    28 /// a structure to contain data related to image smoothing with a 1D gauss kernel
     28/// a structure to contain data related to image smoothing with a pre-cached 1D gauss kernel
    2929typedef struct {
    3030    int Nx;
     
    3434    psF32 *resultY;
    3535    psVector *kernel;
    36 } psImageSmooth_PreAlloc_Data;
     36} psImageSmoothCacheData;
     37
     38/// a structure to contain data related to image smoothing with a pre-cached 1D gauss kernel
     39typedef struct {
     40    float Nsigma;
     41    int Ns;                             // number of pixel radii
     42    float *radflux;                     // conv kernel in special positions
     43} psImageSmooth2dCacheData;
    3744
    3845/// A convolution kernel
     
    306313);
    307314
    308 psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma);
    309 bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata);
     315psImageSmoothCacheData *psImageSmoothCacheAlloc (psImage *image, double sigma, double Nsigma);
     316bool psImageSmoothCache_F32(psImage *image, psImageSmoothCacheData *smdata);
     317bool psImageSmoothCacheKernel_Gauss (psImageSmoothCacheData *smdata, float sigma);
    310318
    311319/// Control threading for image convolution functions
     
    318326bool psImageConvolveGetThreads(void);
    319327
     328psImageSmooth2dCacheData *psImageSmooth2dCacheAlloc (float Nsigma);
     329bool psImageSmooth2dCacheKernel_PS1_V1 (psImageSmooth2dCacheData *smdata, float sigma, float kappa);
     330bool psImageSmooth2dCacheKernel_Gauss (psImageSmooth2dCacheData *smdata, float sigma);
     331bool psImageSmooth2dCache_F32(psImage *image, psImageSmooth2dCacheData *smdata);
     332
    320333/// @}
    321334#endif // #ifndef PS_IMAGE_CONVOLVE_H
  • trunk/psLib/src/math/psEllipse.c

    r35555 r36375  
    1212// f = exp(-z) where z describes the elliptical contour at any flux level:
    1313
     14// NOTE: major, minor are the 1-sigma lengths in the major,minor directions assuming the
     15// moments represent a Gaussian profile
     16
    1417// sigma shape: z = 0.5((x/sx)^2 + (y/sy)^2 + sxy*x*y)
    1518// sigma axes : z = 0.5((x/sa)^2 + (y/sb)^2), x,y rotated by theta
     
    1720// polarization : e0, e1, e2
    1821
    19 // ellipse rotation (major, minor, theta) -> (x2, y2, xy)
     22// ellipse rotation (major, minor, theta) -> (Mxx, Mxy, Myy)
     23psEllipseMoments psEllipseAxesToMoments(psEllipseAxes axes)
     24{
     25    psEllipseMoments moments;
     26
     27    double f1 = PS_SQR(axes.major) + PS_SQR(axes.minor);
     28    double f2 = PS_SQR(axes.major) - PS_SQR(axes.minor);
     29
     30    moments.x2 = +0.5*f1 + 0.5*f2*cos(2*axes.theta);
     31    moments.y2 = +0.5*f1 - 0.5*f2*cos(2*axes.theta);
     32    moments.xy = +0.5*f2*sin(2*axes.theta);
     33
     34    assert (isfinite(moments.x2));
     35    assert (isfinite(moments.y2));
     36    assert (isfinite(moments.xy));
     37
     38    return moments;
     39}
     40
     41// ellipse rotation (Mxx, Mxy, Myy) -> (major, minor, theta).
     42psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments, double maxAR)
     43{
     44    psEllipseAxes axes;
     45    psEllipseAxes badValue = {NAN, NAN, NAN};
     46
     47    if (!isfinite(moments.x2)) return badValue;
     48    if (!isfinite(moments.y2)) return badValue;
     49    if (!isfinite(moments.xy)) return badValue;
     50
     51    if (moments.x2 < 0) return badValue;
     52    if (moments.y2 < 0) return badValue;
     53
     54    double g1 = moments.x2 + moments.y2;
     55    double g2 = moments.x2 - moments.y2;
     56    double g3 = sqrt(PS_SQR(g2) + 4*PS_SQR(moments.xy));
     57
     58    axes.major = sqrt (0.5*(g1 + g3));
     59    axes.theta = +0.5 * atan2 (+2.0*moments.xy, g2); // theta in radians
     60
     61    // long, thin objects are likely to have a poorly measured minor axis
     62    // the angle and major axis are likely to be ok.
     63    // restrict the axis ratio
     64    double rAR2 = (g1 - g3) / (g1 + g3);
     65    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     66        axes.minor = axes.major / maxAR;
     67    } else {
     68        axes.minor = sqrt (0.5*(g1 - g3));
     69    }
     70
     71    assert (isfinite(axes.major));
     72    assert (isfinite(axes.minor));
     73    assert (isfinite(axes.theta));
     74
     75    return axes;
     76}
     77
     78// ellipse rotation (major, minor, theta) -> (sx, sy, sxy)
     79// theta is postive rotation of major axis away from x-axis
     80psEllipseShape psEllipseAxesToShape(psEllipseAxes axes)
     81{
     82    psEllipseShape shape;
     83    psEllipseShape badValue = {NAN, NAN, NAN};
     84
     85    if (!isfinite(axes.minor)) return badValue;
     86    if (!isfinite(axes.major)) return badValue;
     87    if (!isfinite(axes.theta)) return badValue;
     88
     89    if (axes.minor <= 0) return badValue;
     90    if (axes.major <= 0) return badValue;
     91
     92    double f1 = 1.0 / PS_SQR(axes.minor) + 1.0 / PS_SQR(axes.major);
     93    double f2 = 1.0 / PS_SQR(axes.minor) - 1.0 / PS_SQR(axes.major);
     94
     95    double sxr = 0.5*f1 - 0.5*f2*cos(2*axes.theta);
     96    double syr = 0.5*f1 + 0.5*f2*cos(2*axes.theta);
     97
     98    // sxr, syr cannot be < 0 (f1 >= f2)
     99
     100    shape.sx  = +1.0 / sqrt(sxr);
     101    shape.sy  = +1.0 / sqrt(syr);
     102    shape.sxy = -0.5*f2*sin(2*axes.theta);
     103
     104    assert (isfinite(shape.sx));
     105    assert (isfinite(shape.sy));
     106    assert (isfinite(shape.sxy));
     107
     108    return shape;
     109}
     110
     111// ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
     112psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape, double maxAR)
     113{
     114    psEllipseAxes axes;
     115
     116    double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
     117    double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
     118    double f3 = sqrt(PS_SQR(f2) + 4*PS_SQR(shape.sxy));
     119
     120    axes.minor = sqrt (2.0 / (f1 + f3));
     121    axes.theta = -0.5 * atan2 (+2.0*shape.sxy, f2);
     122
     123    // long, thin objects are likely to have a poorly measured major axis
     124    // the angle and minor axis are likely to be ok.
     125    // restrict the axis ratio
     126    double rAR2 = (f1 - f3) / (f1 + f3);
     127    if (rAR2 < 1.0/PS_SQR(maxAR)) {
     128        axes.major = axes.minor * maxAR;
     129    } else {
     130        axes.major = sqrt (2.0 / (f1 - f3));
     131    }
     132
     133    assert (isfinite(axes.theta));
     134    assert (isfinite(axes.major));
     135    assert (isfinite(axes.minor));
     136
     137    return axes;
     138}
     139
     140// ellipse rotation (major, minor, theta) -> (e0, e1, e2)
    20141psEllipsePol psEllipseAxesToPol(psEllipseAxes axes)
    21142{
     
    35156}
    36157
    37 // ellipse rotation (major, minor, theta) -> (x2, y2, xy)
    38 psEllipsePol psEllipseShapeToPol(psEllipseShape shape)
    39 {
    40     psEllipsePol pol;
    41 
    42     double r = 1.0 / (1.0 - PS_SQR(shape.sx)*PS_SQR(shape.sy)*PS_SQR(shape.sxy));
    43 
    44     pol.e0 = r*(PS_SQR(shape.sx) + PS_SQR(shape.sy));
    45     pol.e1 = r*(PS_SQR(shape.sx) - PS_SQR(shape.sy));
    46     // XXX I do not understand this negative sign
    47     pol.e2 = -r*(2.0*PS_SQR(shape.sx)*PS_SQR(shape.sy)*shape.sxy);
    48 
    49     assert (isfinite(pol.e0));
    50     assert (isfinite(pol.e1));
    51     assert (isfinite(pol.e2));
    52 
    53     return pol;
    54 }
    55 
    56 // ellipse rotation (major, minor, theta) -> (x2, y2, xy)
    57 // XXXX handle case where e0 < LIMIT
     158// ellipse rotation (e0, e1, e2) -> (major, minor, theta)
    58159psEllipseAxes psEllipsePolToAxes(const psEllipsePol pol,
    59160                                 const float minMinorAxis)
     
    96197}
    97198
    98 // ellipse rotation (major, minor, theta) -> (x2, y2, xy)
    99 psEllipseMoments psEllipseAxesToMoments(psEllipseAxes axes)
    100 {
    101     psEllipseMoments moments;
    102 
    103     double f1 = PS_SQR(axes.major) + PS_SQR(axes.minor);
    104     double f2 = PS_SQR(axes.major) - PS_SQR(axes.minor);
    105 
    106     moments.x2 = +0.5*f1 + 0.5*f2*cos(2*axes.theta);
    107     moments.y2 = +0.5*f1 - 0.5*f2*cos(2*axes.theta);
    108     moments.xy = +0.5*f2*sin(2*axes.theta);
    109 
    110     assert (isfinite(moments.x2));
    111     assert (isfinite(moments.y2));
    112     assert (isfinite(moments.xy));
    113 
    114     return moments;
    115 }
    116 
    117 // ellipse rotation (x2, y2, xy) -> (major, minor, theta).  NOTE: major, minor are the
    118 // 1-sigma lengths in the major,minor directions assuming the moments represent a Gaussian
    119 // profile
    120 psEllipseAxes psEllipseMomentsToAxes(psEllipseMoments moments, double maxAR)
    121 {
    122     psEllipseAxes axes;
    123     psEllipseAxes badValue = {NAN, NAN, NAN};
    124 
    125     if (!isfinite(moments.x2)) return badValue;
    126     if (!isfinite(moments.y2)) return badValue;
    127     if (!isfinite(moments.xy)) return badValue;
    128 
    129     if (moments.x2 < 0) return badValue;
    130     if (moments.y2 < 0) return badValue;
    131 
    132     double g1 = moments.x2 + moments.y2;
    133     double g2 = moments.x2 - moments.y2;
    134     double g3 = sqrt(PS_SQR(g2) + 4*PS_SQR(moments.xy));
    135 
    136     axes.major = sqrt (0.5*(g1 + g3));
    137     axes.theta = +0.5 * atan2 (+2.0*moments.xy, g2); // theta in radians
    138 
    139     // long, thin objects are likely to have a poorly measured minor axis
    140     // the angle and major axis are likely to be ok.
    141     // restrict the axis ratio
    142     double rAR2 = (g1 - g3) / (g1 + g3);
    143     if (rAR2 < 1.0/PS_SQR(maxAR)) {
    144         axes.minor = axes.major / maxAR;
    145     } else {
    146         axes.minor = sqrt (0.5*(g1 - g3));
    147     }
    148 
    149     assert (isfinite(axes.major));
    150     assert (isfinite(axes.minor));
    151     assert (isfinite(axes.theta));
    152 
    153     return axes;
    154 }
    155 
    156 // ellipse rotation (major, minor, theta) -> (sx, sy, sxy)
    157 // theta is postive rotation of major axis away from x-axis
    158 psEllipseShape psEllipseAxesToShape(psEllipseAxes axes)
     199// ellipse rotation (sx, sy, sxy) -> (e0, e1, e2)
     200psEllipsePol psEllipseShapeToPol(psEllipseShape shape)
     201{
     202    psEllipsePol pol;
     203
     204    double r = 1.0 / (1.0 - PS_SQR(shape.sx)*PS_SQR(shape.sy)*PS_SQR(shape.sxy));
     205
     206    pol.e0 = r*(PS_SQR(shape.sx) + PS_SQR(shape.sy));
     207    pol.e1 = r*(PS_SQR(shape.sx) - PS_SQR(shape.sy));
     208    // XXX I do not understand this negative sign
     209    pol.e2 = -r*(2.0*PS_SQR(shape.sx)*PS_SQR(shape.sy)*shape.sxy);
     210
     211    assert (isfinite(pol.e0));
     212    assert (isfinite(pol.e1));
     213    assert (isfinite(pol.e2));
     214
     215    return pol;
     216}
     217
     218// ellipse rotation (e0, e1, e2) -> (sx, sy, sxy)
     219psEllipseShape psEllipsePolToShape(psEllipsePol pol)
    159220{
    160221    psEllipseShape shape;
    161     psEllipseShape badValue = {NAN, NAN, NAN};
    162 
    163     if (!isfinite(axes.minor)) return badValue;
    164     if (!isfinite(axes.major)) return badValue;
    165     if (!isfinite(axes.theta)) return badValue;
    166 
    167     if (axes.minor <= 0) return badValue;
    168     if (axes.major <= 0) return badValue;
    169 
    170     double f1 = 1.0 / PS_SQR(axes.minor) + 1.0 / PS_SQR(axes.major);
    171     double f2 = 1.0 / PS_SQR(axes.minor) - 1.0 / PS_SQR(axes.major);
    172 
    173     double sxr = 0.5*f1 - 0.5*f2*cos(2*axes.theta);
    174     double syr = 0.5*f1 + 0.5*f2*cos(2*axes.theta);
    175 
    176     // sxr, syr cannot be < 0 (f1 >= f2)
    177 
    178     shape.sx  = +1.0 / sqrt(sxr);
    179     shape.sy  = +1.0 / sqrt(syr);
    180     shape.sxy = -0.5*f2*sin(2*axes.theta);
     222
     223    double q = sqrt (PS_SQR(pol.e1) + PS_SQR(pol.e2));
     224    double p = PS_SQR(pol.e0) + PS_SQR(q) - 2.0*q*pol.e0;
     225
     226    // double f1 = 4*pol.e0 / p;
     227    // double f2 = 4*q      / p;
     228   
     229    double sxr = 2.0*(pol.e0 - pol.e1) / p;
     230    double syr = 2.0*(pol.e0 + pol.e1) / p;
     231
     232    shape.sx = sqrt(1.0 / sxr);
     233    shape.sy = sqrt(1.0 / syr);
     234
     235    shape.sxy = -2.0 * pol.e2 / p;
    181236
    182237    assert (isfinite(shape.sx));
     
    187242}
    188243
    189 // ellipse derotation (sx, sy, sxy) -> (major, minor, theta)
    190 psEllipseAxes psEllipseShapeToAxes(psEllipseShape shape, double maxAR)
    191 {
    192     psEllipseAxes axes;
    193 
    194     double f1 = 1.0 / PS_SQR(shape.sy) + 1.0 / PS_SQR(shape.sx);
    195     double f2 = 1.0 / PS_SQR(shape.sy) - 1.0 / PS_SQR(shape.sx);
    196     double f3 = sqrt(PS_SQR(f2) + 4*PS_SQR(shape.sxy));
    197 
    198     axes.minor = sqrt (2.0 / (f1 + f3));
    199     axes.theta = -0.5 * atan2 (+2.0*shape.sxy, f2);
    200 
    201     // long, thin objects are likely to have a poorly measured major axis
    202     // the angle and minor axis are likely to be ok.
    203     // restrict the axis ratio
    204     double rAR2 = (f1 - f3) / (f1 + f3);
    205     if (rAR2 < 1.0/PS_SQR(maxAR)) {
    206         axes.major = axes.minor * maxAR;
    207     } else {
    208         axes.major = sqrt (2.0 / (f1 - f3));
    209     }
    210 
    211     assert (isfinite(axes.theta));
    212     assert (isfinite(axes.major));
    213     assert (isfinite(axes.minor));
    214 
    215     return axes;
    216 }
    217 
    218244// XXX keep this construction?
    219245// force the axis ratio to be less than 10
  • trunk/psLib/src/math/psEllipse.h

    r19996 r36375  
    3838} psEllipseShape;
    3939
    40 /// Ellipse defined in terms of polarisations
     40/// Ellipse defined in terms of polarizations
    4141typedef struct {
    4242    double e0;                          ///< Scale (Mxx + Myy)
     
    6565                                   );
    6666
    67 /// Convert axes to polarisation representation
     67/// Convert axes to polarization representation
    6868psEllipsePol psEllipseAxesToPol(psEllipseAxes axes ///< Axes of ellipse
    6969                                );
    7070
    71 /// Convert shape to polarisation representation
     71/// Convert polarization to axes representation
     72psEllipseAxes psEllipsePolToAxes(const psEllipsePol pol, ///< Polarization of ellipse
     73                                 const float minMinorAxis ///< Minimum allowed minor axis
     74    );
     75
     76/// Convert shape to polarization representation
    7277psEllipsePol psEllipseShapeToPol(psEllipseShape shape ///< Shape of ellipse
    7378                                 );
    7479
    75 /// Convert polarisation to axes representation
    76 ///
    77 /// XXX This API goes against the PS convention of outputs being first.
    78 psEllipseAxes psEllipsePolToAxes(const psEllipsePol pol, ///< Polarisation of ellipse
    79                                  const float minMinorAxis ///< Minimum allowed minor axis
    80     );
     80/// Convert shape to polarization representation
     81psEllipseShape psEllipsePolToShape(psEllipsePol pol ///< Shape of ellipse
     82                                 );
    8183
    8284/// @}
  • trunk/psLib/src/math/psMixtureModels.c

  • trunk/psLib/test/imageops

    • Property svn:ignore
      •  

        old new  
        2525tap_psImageConvolve
        2626tap_psImageConvolve2
         27tap_psImageConvolve2dCache
        2728convolutionBench
        2829tap_psImageInterpolate2
  • trunk/psLib/test/imageops/Makefile.am

    r35767 r36375  
    2222        tap_psImageConvolve \
    2323        tap_psImageConvolve2 \
     24        tap_psImageConvolve2dCache \
    2425        tap_psImagePixelExtract \
    2526        tap_psImageInterpolate2 \
  • trunk/psModules

  • trunk/psModules/src/camera/pmFPAfile.c

    r33913 r36375  
    491491    if (!strcasecmp(type, "CMF"))     {
    492492        return PM_FPA_FILE_CMF;
     493    }
     494    if (!strcasecmp(type, "CFF"))     {
     495        return PM_FPA_FILE_CFF;
    493496    }
    494497    if (!strcasecmp(type, "WCS"))     {
  • trunk/psModules/src/camera/pmFPAfile.h

    r33913 r36375  
    3434    PM_FPA_FILE_CMP,
    3535    PM_FPA_FILE_CMF,
     36    PM_FPA_FILE_CFF,
    3637    PM_FPA_FILE_WCS,
    3738    PM_FPA_FILE_RAW,
  • trunk/psModules/src/camera/pmFPAfileDefine.c

    r35561 r36375  
    103103
    104104    type = psMetadataLookupStr(&status, data, "FILE.TYPE");
     105    if (!type) {
     106        psError(PM_ERR_CONFIG, true, "FILE.TYPE is not defined for %s\n", name);
     107        psFree(file);
     108        return NULL;
     109    }
     110
    105111    file->type = pmFPAfileTypeFromString(type);
    106112    if (file->type == PM_FPA_FILE_NONE) {
    107         psError(PM_ERR_CONFIG, true, "FILE.TYPE is not defined for %s\n", name);
     113        psError(PM_ERR_CONFIG, true, "FILE.TYPE %s is not registered in pmFPAfile.c:pmFPAfileTypeFromString\n", type);
    108114        psFree(file);
    109115        return NULL;
  • trunk/psModules/src/camera/pmFPAfileIO.c

    r35561 r36375  
    222222      case PM_FPA_FILE_CMP:
    223223      case PM_FPA_FILE_CMF:
     224      case PM_FPA_FILE_CFF:
    224225      case PM_FPA_FILE_WCS:
    225226      case PM_FPA_FILE_SRCTEXT:
     
    317318      case PM_FPA_FILE_CMP:
    318319      case PM_FPA_FILE_CMF:
     320      case PM_FPA_FILE_CFF:
    319321      case PM_FPA_FILE_WCS:
    320322      case PM_FPA_FILE_PSF:
     
    483485      case PM_FPA_FILE_CMP:
    484486      case PM_FPA_FILE_CMF:
     487      case PM_FPA_FILE_CFF:
    485488        status = pmFPAviewWriteObjects (view, file, config);
    486489        break;
     
    567570      case PM_FPA_FILE_PATTERN:
    568571      case PM_FPA_FILE_CMF:
     572      case PM_FPA_FILE_CFF:
    569573      case PM_FPA_FILE_WCS:
    570574      case PM_FPA_FILE_PSF:
     
    643647      case PM_FPA_FILE_CMP:
    644648      case PM_FPA_FILE_CMF:
     649      case PM_FPA_FILE_CFF:
    645650      case PM_FPA_FILE_WCS:
    646651      case PM_FPA_FILE_PSF:
     
    804809      case PM_FPA_FILE_PATTERN:
    805810      case PM_FPA_FILE_CMF:
     811      case PM_FPA_FILE_CFF:
    806812      case PM_FPA_FILE_WCS:
    807813      case PM_FPA_FILE_PSF:
     
    10161022      case PM_FPA_FILE_CMP:
    10171023      case PM_FPA_FILE_WCS:
     1024      case PM_FPA_FILE_CFF:
    10181025      case PM_FPA_FILE_JPEG:
    10191026      case PM_FPA_FILE_KAPA:
  • trunk/psModules/src/config/pmConfig.c

    r34234 r36375  
    18601860    }
    18611861
    1862     return psMetadataLookupMetadata(NULL, filerules, realname);
     1862    return psMetadataLookupMetadata(&mdok, filerules, realname);
    18631863}
    18641864
  • trunk/psModules/src/objects/Makefile.am

    r36085 r36375  
    4040        pmSourceIO_SX.c \
    4141        pmSourceIO_CMP.c \
     42        pmSourceIO_CFF.c \
    4243        pmSourceIO_SMPDATA.c \
    4344        pmSourceIO_PS1_DEV_0.c \
  • trunk/psModules/src/objects/models/pmModel_DEV.c

    r36106 r36375  
    269269
    270270    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
    271     float scale = moments->Mrf / axes.major;
     271    // the factor of 2.3 comes from Table 1 of Graham and Driver (2005)
     272    float scale = moments->Mrf / axes.major / 2.3;
    272273    axes.major *= scale;
    273274    axes.minor *= scale;
  • trunk/psModules/src/objects/models/pmModel_EXP.c

    r36106 r36375  
    6363// 0.5 PIX: the parameters are defined in terms of pixel coords, so the incoming pixcoords
    6464// values need to be pixel coords
     65//
     66
     67// Notes on changing kappa value from 1.70056 to 1.678
     68// I'm using a functional form f(x,y) = Io exp(-kappa (r / r_e)). 
     69// The article by Graham & Driver (2005) uses a form Ie exp(-bn [(r / r_e) -1])
     70// which is equal to Ie exp(-bn (r / r_e)) exp(bn). 
     71// Thus, my Io = Ie exp(bn) and my kappa is their bn.
     72// My value of kappa is 1.700, their value for bn is 1.678., so I am off by a small amount there (1.5%). 
     73
     74
     75#define KAPPA_EXP 1.678
     76#define OLD_KAPP_EXP 1.70056
     77
    6578
    6679// Lax parameter limits
     
    109122    // for EXP, we can hard-wire kappa(1):
    110123    // float index = 1.0;
    111     float kappa = 1.70056;
     124    float kappa = KAPPA_EXP;
    112125
    113126    // sqrt(z) is r
     
    318331
    319332    // static value for EXP:
    320     float kappa = 1.70056;
     333    float kappa = KAPPA_EXP;
    321334
    322335    // f = Io exp(-kappa*sqrt(z)) -> sqrt(z) = ln(Io/f) / kappa
  • trunk/psModules/src/objects/models/pmModel_SERSIC.c

    r36085 r36375  
    7575
    7676// Lax parameter limits
    77 static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.1 };
     77static float paramsMinLax[] = { -1.0e3, 1.0e-2, -100, -100, 0.001, 0.001, -1.0, 0.0625 };
    7878static float paramsMaxLax[] = { 1.0e5, 1.0e9, 1.0e5, 1.0e5, 100, 100, 1.0, 1.0 };
    7979
  • trunk/psModules/src/objects/pmModel.c

    r34498 r36375  
    217217    // the options allow us to modify various aspects of the model
    218218    if (mode & PM_MODEL_OP_NORM) {
     219        // if we are including the sky, renormalizing should force use to normalized down the sky flux
     220        params->data.F32[PM_PAR_SKY] /= params->data.F32[PM_PAR_I0];
    219221        params->data.F32[PM_PAR_I0] = 1.0;
    220222    }
    221223    if (!(mode & PM_MODEL_OP_SKY)) {
    222224        params->data.F32[PM_PAR_SKY] = 0.0;
    223     }
     225    } 
    224226    if (mode & PM_MODEL_OP_CENTER) {
    225227        params->data.F32[PM_PAR_XPOS] = image->col0 + 0.5*image->numCols;
  • trunk/psModules/src/objects/pmModelFuncs.h

    r35560 r36375  
    3636
    3737typedef enum {
    38     PM_MODEL_STATUS_NONE         = 0x00, ///< model fit not yet attempted, no other info
    39     PM_MODEL_STATUS_FITTED       = 0x01, ///< model fit completed
    40     PM_MODEL_STATUS_NONCONVERGE  = 0x02, ///< model fit did not converge
    41     PM_MODEL_STATUS_OFFIMAGE     = 0x04, ///< model fit drove out of range
    42     PM_MODEL_STATUS_BADARGS      = 0x08, ///< model fit called with invalid args
    43     PM_MODEL_STATUS_LIMITS       = 0x10, ///< model parameters hit limits
    44     PM_MODEL_STATUS_WEAK_FIT     = 0x20, ///< model fit met loose tolerance, but not tight tolerance
     38    PM_MODEL_STATUS_NONE           = 0x000, ///< model fit not yet attempted, no other info
     39    PM_MODEL_STATUS_FITTED         = 0x001, ///< model fit completed
     40    PM_MODEL_STATUS_NONCONVERGE    = 0x002, ///< model fit did not converge
     41    PM_MODEL_STATUS_OFFIMAGE       = 0x004, ///< model fit drove out of range
     42    PM_MODEL_STATUS_BADARGS        = 0x008, ///< model fit called with invalid args
     43    PM_MODEL_STATUS_LIMITS         = 0x010, ///< model parameters hit limits
     44    PM_MODEL_STATUS_WEAK_FIT       = 0x020, ///< model fit met loose tolerance, but not tight tolerance
     45    PM_MODEL_STATUS_NAN_CHISQ      = 0x040, ///< model fit failed with a NAN chisq
     46    PM_MODEL_SERSIC_PCM_FAIL_GUESS = 0x080, ///< sersic model fit failed on the initial moments-based guess
     47    PM_MODEL_SERSIC_PCM_FAIL_GRID  = 0x100, ///< sersic model fit failed on the grid search
     48    PM_MODEL_PCM_FAIL_GUESS        = 0x200, ///< non-sersic model fit failed on the initial moments-based guess
     49    PM_MODEL_BEST_FIT              = 0x400, ///< this model was the best fit and was subtracted
    4550} pmModelStatus;
    4651
  • trunk/psModules/src/objects/pmModelUtils.c

    r36287 r36375  
    129129bool pmModelAxesToParams (float *Sxx, float *Sxy, float *Syy, psEllipseAxes axes, bool useReff)  {
    130130
     131    // restrict axex to 0.5 here not below
     132    if (axes.minor < 0.2) axes.minor = 0.2;
     133    if (axes.major < 0.2) axes.major = 0.2;
     134
    131135    psEllipseShape shape = psEllipseAxesToShape (axes);
    132136
     
    137141    // set the shape parameters
    138142    if (useReff) {
    139         *Sxx  = PS_MAX(0.5, shape.sx);
    140         *Syy  = PS_MAX(0.5, shape.sy);
     143        // *Sxx  = PS_MAX(0.5, shape.sx);
     144        // *Syy  = PS_MAX(0.5, shape.sy);
     145        *Sxx  = shape.sx;
     146        *Syy  = shape.sy;
    141147        *Sxy  = shape.sxy * 2.0;
    142148    } else {
    143         *Sxx  = PS_MAX(0.5, M_SQRT2*shape.sx);
    144         *Syy  = PS_MAX(0.5, M_SQRT2*shape.sy);
     149        // *Sxx  = PS_MAX(0.5, M_SQRT2*shape.sx);
     150        // *Syy  = PS_MAX(0.5, M_SQRT2*shape.sy);
     151        *Sxx  = M_SQRT2*shape.sx;
     152        *Syy  = M_SQRT2*shape.sy;
    145153        *Sxy  = shape.sxy;
    146154    }
     
    193201    if (!isfinite(axes.minor)) return false;
    194202    if (!isfinite(axes.theta)) return false;
     203    if (axes.major == 0) return false;
    195204
    196205    // Mxx, Mxy, Myy define the elliptical shape, but Mrf defines the width
  • trunk/psModules/src/objects/pmModel_CentralPixel.c

    r36085 r36375  
    695695    int   npix = 0;
    696696
    697     float kappa = -0.275552 + 1.972625*Sindex + 0.003487 * PS_SQR(Sindex);
     697    // -0.275552 + 1.972625*Sindex + 0.003487 * PS_SQR(Sindex);
     698    float kappa = pmSersicKappa (Sindex);
    698699    float rindex = 0.5 / Sindex;
    699700
     
    703704
    704705    float delta = 1.0 / (float) Nsub;
    705     float off = -Nsub2 * delta;
    706     for (float ix = off; ix < 0.5; ix += delta) {
    707         for (float iy = off; iy < 0.5; iy += delta) {
    708 
    709             float dX = dx + ix;
    710             float dY = dy + iy;
     706    // float off = -Nsub2 * delta;
     707
     708    int Sx = (int) floor(dx / delta);
     709    int Sy = (int) floor(dy / delta);
     710
     711    for (int ix = -Nsub2; ix <= Nsub2; ix++) {
     712      float dX = delta * (Sx + ix);
     713      for (int iy = -Nsub2; iy <= Nsub2; iy++) {
     714        float dY = delta * (Sy + iy);
    711715            float z = PS_SQR(dX / Rxx) + PS_SQR(dY / Ryy) + dX * dY * Rxy;
    712716
    713717            float q = pow (z, rindex);
    714718            float f = exp(-kappa*q);
     719
     720            // if ((ix == 0) && (iy == 0)) {
     721            //   // fprintf (stderr, "this: %f  %f  %f  --  full : %f %f\n", z, q, f, flux, (float) npix);
     722            // }
    715723
    716724            flux += f;
  • trunk/psModules/src/objects/pmPCM_MinimizeChisq.c

    r36085 r36375  
    135135        }
    136136
     137        if (min->isInteractive) {
     138            fprintf (stderr, "%d : ", min->iter);
     139            for (int ti = 0; ti < params->n; ti++) {
     140                fprintf (stderr, "%f  ", params->data.F32[ti]);
     141            }
     142            fprintf (stderr, " : %f\n", min->value);
     143        }
     144
    137145        char key[10]; // used for interactive responses
    138146        bool testValue = false;
     
    140148        // set a new guess for Alpha, Beta, Params
    141149        if (!psMinLM_GuessABP(Alpha, Beta, Params, alpha, beta, params, paramMask, checkLimits, lambda, &dLinear)) {
    142             if (min->isInteractive) {
     150            if (false && min->isInteractive) {
    143151                fprintf (stdout, "guess failed (singular matrix or NaN values), continue? [Y,n] ");
    144152                if (!fgets(key, 8, stdin)) {
     
    167175        }
    168176
    169         if (min->isInteractive) {
     177        if (false && min->isInteractive) {
    170178            p_psVectorPrint(psTraceGetDestination(), Params, "current parameters: ");
    171179            fprintf (stdout, "last chisq : %f\n", min->value);
     
    473481# else
    474482    if (pcm->use1Dgauss) {
    475         // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    476         // * the model flux is not masked
    477         // * threading takes place above this level
    478         pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
    479         psImageSmooth_PreAlloc_F32 (pcm->modelConvFlux, pcm->smdata);
    480         // psImageSmooth (pcm->modelConvFlux, pcm->sigma, pcm->nsigma);
     483
     484        if (USE_1D_CACHE) {
     485            // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     486            // * the model flux is not masked
     487            // * threading takes place above this level
     488            pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     489            psImageSmoothCache_F32 (pcm->modelConvFlux, pcm->smdata);
     490        } else {
     491            pcm->modelConvFlux = psImageCopy (pcm->modelConvFlux, pcm->modelFlux, pcm->modelFlux->type.type);
     492            psImageSmooth2dCache_F32 (pcm->modelConvFlux, pcm->smdata2d);
     493        }
    481494    } else {
    482495        psImageConvolveKernel (pcm->modelConvFlux, pcm->modelFlux, NULL, 0, pcm->psfFFT);
     
    493506# else
    494507        if (pcm->use1Dgauss) {
    495             // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    496             // * the model flux is not masked
    497             // * threading takes place above this level
    498             dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
    499             psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
    500             // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     508            if (USE_1D_CACHE) {
     509                // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     510                // * the model flux is not masked
     511                // * threading takes place above this level
     512                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     513                psImageSmoothCache_F32 (dmodelConv, pcm->smdata);
     514            } else {
     515                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     516                psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d);
     517            }
    501518        } else {
    502519            psImageConvolveKernel (dmodelConv, dmodel, NULL, 0, pcm->psfFFT);
     
    514531
    515532        if (pcm->use1Dgauss) {
    516             // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    517             // * the model flux is not masked
    518             // * threading takes place above this level
    519             dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
    520             psImageSmooth_PreAlloc_F32 (dmodelConv, pcm->smdata);
    521             // psImageSmooth (dmodelConv, pcm->sigma, pcm->nsigma);
     533            if (USE_1D_CACHE) {
     534                // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
     535                // * the model flux is not masked
     536                // * threading takes place above this level
     537                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     538                psImageSmoothCache_F32 (dmodelConv, pcm->smdata);
     539            } else {
     540                dmodelConv = psImageCopy (dmodelConv, dmodel, dmodel->type.type);
     541                psImageSmooth2dCache_F32 (dmodelConv, pcm->smdata2d);
     542            }
    522543        } else {
    523544            psImageConvolveFFT (dmodelConv, dmodel, NULL, 0, pcm->psf);
     
    541562    static int Npass = 0;
    542563    char name[128];
    543     snprintf (name, 128, "psf.%03d.fits", Npass); psphotSaveImage (NULL, pcm->psf->image, name);
     564    if (!pcm->use1Dgauss) {
     565      snprintf (name, 128, "psf.%03d.fits", Npass); psphotSaveImage (NULL, pcm->psf->image, name);
     566    }
    544567    snprintf (name, 128, "mod.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelFlux, name);
    545568    snprintf (name, 128, "cnv.%03d.fits", Npass); psphotSaveImage (NULL, pcm->modelConvFlux, name);
     
    579602
    580603            float ymodel  = pcm->modelConvFlux->data.F32[i][j];
    581             float yweight = 1.0 / source->variance->data.F32[i][j];
     604
     605            // XXXX note this point here:::
     606            float yweight = pcm->poissonErrors ? 1.0 / source->variance->data.F32[i][j] : 1.0;
    582607            float delta = ymodel - source->pixels->data.F32[i][j];
    583608
  • trunk/psModules/src/objects/pmPCMdata.c

    r36089 r36375  
    4343
    4444# define USE_DELTA_PSF 0
    45 # define USE_1D_GAUSS 1
    4645
    4746static void pmPCMdataFree (pmPCMdata *pcm) {
     
    5857    psFree (pcm->psfFFT);
    5958    psFree (pcm->constraint);
     59
    6060    psFree (pcm->smdata); // pre-allocated data for psImageSmooth_PreAlloc
     61    psFree (pcm->smdata2d); // pre-allocated data for psImageSmooth_PreAlloc
    6162    return;
    6263}
     
    8889    }
    8990
     91    pcm->smdata = NULL;
     92    pcm->smdata2d = NULL;
     93
    9094    pcm->modelConv = NULL;
    9195    pcm->psf = NULL;
     
    9498    pcm->nDOF = 0;
    9599
     100    pcm->poissonErrors = true;
     101
    96102    // full convolution with the PSF is expensive.  if we have to save time, we can do a 1D
    97103    // convolution with a Gaussian approximation to the kernel
    98104    pcm->use1Dgauss = false;
    99     pcm->nsigma = 3.0;
     105    pcm->nsigma = NAN; // this is set to something defined by the user
    100106    pcm->sigma = 1.0; // this should be set to something sensible when the psf is known
    101107
     
    248254}
    249255
     256static int modelType_GAUSS = -1;
     257static int modelType_PS1_V1 = -1;
     258
     259// generate a Gaussian smoothing kernel for supplied sigma.  sigma here does not need to match
     260// that used to allocate the structure, but it is recommended
     261bool psImageSmoothCacheKernel_PS1_V1 (psImageSmoothCacheData *smdata, float sigma, float kappa) {
     262    // check for NULL structure elements?
     263
     264    int size = smdata->Nrange;
     265
     266    psFree (smdata->kernel);
     267    smdata->kernel = psVectorAlloc(2 * smdata->Nrange + 1, PS_TYPE_F32);
     268
     269    double sum = 0.0;                   // Sum of Gaussian, for normalization
     270    double factor = 1.0 / (sigma * M_SQRT2);    // Multiplier for i -> z
     271
     272    // PS1_V1 is a power-law with fitted linear term:
     273    // 1 / (1 + kappa z + z^1.666)  where z = (r/sigma)^2
     274
     275    // generate the kernel (not normalized)
     276    for (int i = -size, j = 0; i <= size; i++, j++) {
     277        float z = PS_SQR(i * factor);
     278        sum += smdata->kernel->data.F32[j] = 1.0 / (1 + kappa * z + pow(z,1.666));
     279    }
     280
     281    // renormalize kernel to integral of 1.0
     282    for (int i = 0; i < 2 * size + 1; i++) {
     283        smdata->kernel->data.F32[i] /= sum;
     284    }
     285
     286    return true;
     287}
     288
     289psImageSmoothCacheData *psImageSmoothCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) {
     290
     291    psAssert (modelPSF, "psf model must be defined");
     292   
     293    psEllipseAxes axes;
     294    bool useReff = pmModelUseReff (modelPSF->type);
     295    psF32 *PAR = modelPSF->params->data.F32;
     296    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
     297   
     298    *sigma = NAN;
     299    *kappa = NAN;
     300
     301    // XXX need to do this more carefully
     302    if (modelPSF->type == modelType_GAUSS) {
     303        float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
     304        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     305        *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     306    }
     307    if (modelPSF->type == modelType_PS1_V1) {
     308        *sigma = 0.5 * (axes.major + axes.minor);
     309        *kappa = PAR[PM_PAR_7];
     310    }
     311    psAssert (isfinite(*sigma), "invalid model type");
     312
     313    // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector
     314    psImageSmoothCacheData *smdata = psImageSmoothCacheAlloc (flux, *sigma, nsigma);
     315
     316    if (modelPSF->type == modelType_GAUSS) {
     317        psImageSmoothCacheKernel_Gauss (smdata, *sigma);
     318    }
     319    if (modelPSF->type == modelType_PS1_V1) {
     320        psImageSmoothCacheKernel_PS1_V1 (smdata, *sigma, *kappa);
     321    }
     322
     323    return smdata;
     324}
     325
     326psImageSmooth2dCacheData *psImageSmooth2dCacheSetKernel (float *sigma, float *kappa, float nsigma, psImage *flux, pmModel *modelPSF) {
     327
     328    psAssert (modelPSF, "psf model must be defined");
     329   
     330    psEllipseAxes axes;
     331    bool useReff = pmModelUseReff (modelPSF->type);
     332    psF32 *PAR = modelPSF->params->data.F32;
     333    pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
     334   
     335    *sigma = NAN;
     336    *kappa = NAN;
     337
     338    // XXX need to do this more carefully
     339    if (modelPSF->type == modelType_GAUSS) {
     340        float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
     341        float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
     342        *sigma = 0.50 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
     343    }
     344    if (modelPSF->type == modelType_PS1_V1) {
     345        *sigma = 0.5 * (axes.major + axes.minor);
     346        *kappa = PAR[PM_PAR_7];
     347    }
     348    psAssert (isfinite(*sigma), "invalid model type");
     349
     350    // psImageSmoothCacheAlloc generates a structure but does not assign the smoothing vector
     351    psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheAlloc (nsigma);
     352
     353    if (modelPSF->type == modelType_GAUSS) {
     354        psImageSmooth2dCacheKernel_Gauss (smdata, *sigma);
     355    }
     356    if (modelPSF->type == modelType_PS1_V1) {
     357        psImageSmooth2dCacheKernel_PS1_V1 (smdata, *sigma, *kappa);
     358    }
     359
     360    return smdata;
     361}
     362
    250363pmPCMdata *pmPCMinit(pmSource *source, pmSourceFitOptions *fitOptions, pmModel *model, psImageMaskType maskVal, float psfSize) {
    251364
    252     // make sure we save a cached copy of the psf flux
    253     pmSourceCachePSF (source, maskVal);
    254 
    255     // convert the cached cached psf model for this source to a psKernel
    256     psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
    257     if (!psf) {
    258         // NOTE: this only happens if the source is too close to an edge
    259         model->flags |= PM_MODEL_STATUS_BADARGS;
    260         return NULL;
    261     }
    262 
    263 # if (USE_DELTA_PSF)
    264     psImageInit (psf->image, 0.0);
    265     psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0;
    266 # endif
     365    modelType_GAUSS = pmModelClassGetType ("PS_MODEL_GAUSS");
     366    modelType_PS1_V1 = pmModelClassGetType ("PS_MODEL_PS1_V1");
    267367
    268368    // count the number of unmasked pixels:
     
    298398    if (nPix <  nParams + 1) {
    299399        psTrace ("psModules.objects", 4, "insufficient valid pixels\n");
    300         psFree (psf);
    301400        psFree (constraint);
    302401        model->flags |= PM_MODEL_STATUS_BADARGS;
     
    306405    // generate PCM data storage structure
    307406    pmPCMdata *pcm = pmPCMdataAlloc (params, constraint->paramMask, source);
    308 
    309     pcm->psf = psf;
    310407    pcm->modelConv = psMemIncrRefCounter(model);
    311408    pcm->constraint = constraint;
     409
     410    pcm->poissonErrors = fitOptions->poissonErrors;
     411    pcm->nsigma = fitOptions->nsigma;
    312412
    313413    pcm->nPix = nPix;
     
    316416
    317417# if (USE_1D_GAUSS)
    318     pmModel *modelPSF = source->modelPSF;
    319     psAssert (modelPSF, "psf model must be defined");
    320    
    321     psEllipseAxes axes;
    322     bool useReff = pmModelUseReff (modelPSF->type);
    323     psF32 *PAR = modelPSF->params->data.F32;
    324     pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
    325    
    326     float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
    327     float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    328418
    329419    pcm->use1Dgauss = true;
    330     pcm->sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
    331     pcm->nsigma = 2.0;
    332 
    333     pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     420    if (USE_1D_CACHE) {
     421        pcm->smdata = psImageSmoothCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF);
     422    } else {
     423        pcm->smdata2d = psImageSmooth2dCacheSetKernel (&pcm->sigma, &pcm->kappa, pcm->nsigma, source->pixels, source->modelPSF);
     424    }
     425
    334426# else
     427    // make sure we save a cached copy of the psf flux
     428    pmSourceCachePSF (source, maskVal);
     429
     430    // convert the cached cached psf model for this source to a psKernel
     431    psKernel *psf = pmPCMkernelFromPSF (source, psfSize);
     432    if (!psf) {
     433        // NOTE: this only happens if the source is too close to an edge
     434        model->flags |= PM_MODEL_STATUS_BADARGS;
     435        return NULL;
     436    }
     437
     438# if (USE_DELTA_PSF)
     439    psImageInit (psf->image, 0.0);
     440    psf->image->data.F32[(int)(0.5*psf->image->numRows)][(int)(0.5*psf->image->numCols)] = 1.0;
     441# endif
     442    pcm->psf = psf;
    335443    pcm->smdata = NULL;
    336444# endif
     
    395503            pcm->dmodelsConvFlux->data[n] = psImageCopy (pcm->dmodelsConvFlux->data[n], source->pixels, PS_TYPE_F32);
    396504        }
    397         psFree(pcm->smdata);
    398         pcm->smdata = psImageSmooth_PreAlloc_DataAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     505
     506        // If we have changed the window, we need to redefine the smoothing target vectors (but pcm->sigma,kappa,nsigma remain)
     507        if (USE_1D_CACHE) {
     508            psFree(pcm->smdata);
     509            pcm->smdata = psImageSmoothCacheAlloc (source->pixels, pcm->sigma, pcm->nsigma);
     510
     511            pmModel *modelPSF = source->modelPSF;
     512            if (modelPSF->type == modelType_GAUSS) {
     513                psImageSmoothCacheKernel_Gauss (pcm->smdata, pcm->sigma);
     514            }
     515            if (modelPSF->type == modelType_PS1_V1) {
     516                psImageSmoothCacheKernel_PS1_V1 (pcm->smdata, pcm->sigma, pcm->kappa);
     517            }
     518        } else {
     519            psFree(pcm->smdata2d);
     520            pcm->smdata2d = psImageSmooth2dCacheAlloc (pcm->nsigma);
     521
     522            pmModel *modelPSF = source->modelPSF;
     523            if (modelPSF->type == modelType_GAUSS) {
     524                // psImageSmooth2dCacheKernel_Gauss (pcm->smdata2d, pcm->sigma);
     525            }
     526            if (modelPSF->type == modelType_PS1_V1) {
     527                psImageSmooth2dCacheKernel_PS1_V1 (pcm->smdata2d, pcm->sigma, pcm->kappa);
     528            }
     529        }
    399530    }
    400531
     
    403534
    404535// construct a realization of the source model
    405 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize) {
     536bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma) {
    406537
    407538    PS_ASSERT_PTR_NON_NULL(source, false);
     
    420551    // convolve the model image with the PSF
    421552    if (USE_1D_GAUSS) {
    422         // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    423         // * the model flux is not masked
    424         // * threading takes place above this level
    425553       
    426         // define the Gauss parameters from the psf
    427         pmModel *modelPSF = source->modelPSF;
    428         psAssert (modelPSF, "psf model must be defined");
    429    
    430         psEllipseAxes axes;
    431         bool useReff = pmModelUseReff (modelPSF->type);
    432         psF32 *PAR = modelPSF->params->data.F32;
    433         pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
    434    
    435         float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
    436         float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    437 
    438         float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
    439         float nsigma = 2.0;
    440 
    441         psImageSmooth (source->modelFlux, sigma, nsigma);
     554        float sigma = NAN;
     555        float kappa = NAN;
     556
     557        if (USE_1D_CACHE) {
     558            psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF);
     559            psImageSmoothCache_F32 (source->modelFlux, smdata);
     560            psFree (smdata);
     561        } else {
     562            psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, nsigma, source->modelFlux, source->modelPSF);
     563            psImageSmooth2dCache_F32 (source->modelFlux, smdata);
     564            psFree (smdata);
     565        }
     566        // old call: psImageSmooth (source->modelFlux, sigma, nsigma);
    442567    } else {
    443568        // make sure we save a cached copy of the psf flux
     
    459584
    460585// construct a realization of the source model
    461 bool pmPCMMakeModel (pmSource *source, pmModel *model, psImageMaskType maskVal, int psfSize) {
     586bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize) {
    462587
    463588    PS_ASSERT_PTR_NON_NULL(source, false);
     
    468593
    469594    // modelFlux always has unity normalization (I0 = 1.0)
    470     pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
     595    // pmModelAdd (source->modelFlux, source->maskObj, model, PM_MODEL_OP_FULL | PM_MODEL_OP_NORM, maskVal);
     596    pmModelAdd (source->modelFlux, NULL, model, PM_MODEL_OP_FULL | PM_MODEL_OP_SKY | PM_MODEL_OP_NORM, maskVal);
    471597
    472598    // convolve the model image with the PSF
    473599    if (USE_1D_GAUSS) {
    474         // do not use the threaded, mask-aware version of this code (psImageSmoothMaskPixelsThread):
    475         // * the model flux is not masked
    476         // * threading takes place above this level
    477        
    478         // define the Gauss parameters from the psf
    479         pmModel *modelPSF = source->modelPSF;
    480         psAssert (modelPSF, "psf model must be defined");
    481    
    482         psEllipseAxes axes;
    483         bool useReff = pmModelUseReff (modelPSF->type);
    484         psF32 *PAR = modelPSF->params->data.F32;
    485         pmModelParamsToAxes (&axes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], useReff);
    486    
    487         float FWHM_MAJOR = 2*modelPSF->modelRadius (modelPSF->params, 0.5*PAR[PM_PAR_I0]);
    488         float FWHM_MINOR = FWHM_MAJOR * (axes.minor / axes.major);
    489 
    490         float sigma = 0.5 * (FWHM_MAJOR + FWHM_MINOR) / 2.35;
    491         float nsigma = 2.0;
    492 
    493         psImageSmooth (source->modelFlux, sigma, nsigma);
     600
     601        float sigma = NAN;
     602        float kappa = NAN;
     603
     604        if (USE_1D_CACHE) {
     605            psImageSmoothCacheData *smdata = psImageSmoothCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF);
     606            psImageSmoothCache_F32 (source->modelFlux, smdata);
     607            psFree (smdata);
     608        } else {
     609            psImageSmooth2dCacheData *smdata = psImageSmooth2dCacheSetKernel (&sigma, &kappa, Nsigma, source->modelFlux, source->modelPSF);
     610            psImageSmooth2dCache_F32 (source->modelFlux, smdata);
     611            psFree (smdata);
     612        }
     613        // old call: psImageSmooth (source->modelFlux, sigma, nsigma);
    494614    } else {
    495615        // make sure we save a cached copy of the psf flux
     
    509629    return true;
    510630}
    511 
  • trunk/psModules/src/objects/pmPCMdata.h

    r36085 r36375  
    1414/// @addtogroup Objects Object Detection / Analysis Functions
    1515/// @{
     16
     17// XXX this is basically for testing -- when I am happy with the convolution process, I'll strip this out
     18# define USE_1D_CACHE 0
     19# define USE_1D_GAUSS 1
    1620
    1721/** pmPCMdata : PSF Convolved Model data storage structure
     
    3640    int nDOF;
    3741
     42    bool poissonErrors;
     43
    3844    bool use1Dgauss;
     45    float kappa;
    3946    float sigma;
    4047    float nsigma;
    4148
    42     psImageSmooth_PreAlloc_Data *smdata;
     49    // psArray *smdata;
     50    psImageSmoothCacheData *smdata;
     51    psImageSmooth2dCacheData *smdata2d;
    4352} pmPCMdata;
    4453
     
    96105bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize);
    97106
    98 bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize);
     107bool pmPCMCacheModel (pmSource *source, psImageMaskType maskVal, int psfSize, float nsigma);
    99108
    100 bool pmPCMMakeModel (pmSource *source, pmModel *model, psImageMaskType maskVal, int psfSize);
     109bool pmPCMMakeModel (pmSource *source, pmModel *model, float Nsigma, psImageMaskType maskVal, int psfSize);
    101110
    102111/// @}
  • trunk/psModules/src/objects/pmSource.c

    r35768 r36375  
    6666    psFree(tmp->extpars);
    6767    psFree(tmp->diffStats);
     68    psFree(tmp->galaxyFits);
    6869    psFree(tmp->radialAper);
    6970    psTrace("psModules.objects", 10, "---- end ----\n");
     
    164165    source->extpars = NULL;
    165166    source->diffStats = NULL;
     167    source->galaxyFits = NULL;
    166168    source->radialAper = NULL;
    167169    source->parent = NULL;
     
    690692            // why do we recalculate moments here?
    691693            // we already attempt to do this in psphotSourceStats
    692             // pmSourceMoments (source, INNER_RADIUS);
    693694            Nsatstar ++;
    694695            continue;
     
    804805    return true;
    805806}
    806 
    807 /******************************************************************************
    808 pmSourceMoments(source, radius): this function takes a subImage defined in the
    809 pmSource data structure, along with the peak location, and determines the
    810 various moments associated with that peak.
    811 
    812 Requires the following to have been created:
    813     pmSource
    814     pmSource->peak
    815     pmSource->pixels
    816     pmSource->variance
    817     pmSource->mask
    818 
    819 XXX: The peak calculations are done in image coords, not subImage coords.
    820 
    821 XXX EAM : this version clips input pixels on S/N
    822 XXX EAM : this version returns false for several reasons
    823 *****************************************************************************/
    824 # define VALID_RADIUS(X,Y,RAD2) (((RAD2) >= (PS_SQR(X) + PS_SQR(Y))) ? 1 : 0)
    825 
    826 /*** this been moved to pmSourceMoments.c ***/
    827 # if (0)
    828 bool pmSourceMoments(pmSource *source,
    829                      psF32 radius)
    830 {
    831     psTrace("psModules.objects", 10, "---- begin ----\n");
    832     PS_ASSERT_PTR_NON_NULL(source, false);
    833     PS_ASSERT_PTR_NON_NULL(source->peak, false);
    834     PS_ASSERT_PTR_NON_NULL(source->pixels, false);
    835     PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
    836 
    837     //
    838     // XXX: Verify the setting for sky if source->moments == NULL.
    839     //
    840     psF32 sky = 0.0;
    841     if (source->moments == NULL) {
    842         source->moments = pmMomentsAlloc();
    843     } else {
    844         sky = source->moments->Sky;
    845     }
    846 
    847     //
    848     // Sum = SUM (z - sky)
    849     // X1  = SUM (x - xc)*(z - sky)
    850     // X2  = SUM (x - xc)^2 * (z - sky)
    851     // XY  = SUM (x - xc)*(y - yc)*(z - sky)
    852     //
    853     psF32 peakPixel = -PS_MAX_F32;
    854     psS32 numPixels = 0;
    855     psF32 Sum = 0.0;
    856     psF32 Var = 0.0;
    857     psF32 X1 = 0.0;
    858     psF32 Y1 = 0.0;
    859     psF32 X2 = 0.0;
    860     psF32 Y2 = 0.0;
    861     psF32 XY = 0.0;
    862     psF32 x  = 0;
    863     psF32 y  = 0;
    864     psF32 R2 = PS_SQR(radius);
    865 
    866     psF32 xPeak = source->peak->x;
    867     psF32 yPeak = source->peak->y;
    868     psF32 xOff = source->pixels->col0 - source->peak->x;
    869     psF32 yOff = source->pixels->row0 - source->peak->y;
    870 
    871     // XXX why do I get different results for these two methods of finding Sx?
    872     // XXX Sx, Sy would be better measured if we clip pixels close to sky
    873     // XXX Sx, Sy can still be imaginary, so we probably need to keep Sx^2?
    874     // We loop through all pixels in this subimage (source->pixels), and for each
    875     // pixel that is not masked, AND within the radius of the peak pixel, we
    876     // proceed with the moments calculation.  need to do two loops for a
    877     // numerically stable result.  first loop: get the sums.
    878     // XXX EAM : mask == 0 is valid
    879 
    880     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    881 
    882         psF32 *vPix = source->pixels->data.F32[row];
    883         psF32 *vWgt = source->variance->data.F32[row];
    884         psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    885 
    886         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
    887             if (vMsk) {
    888                 if (*vMsk) {
    889                     vMsk++;
    890                     psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to mask: %d\n",
    891                             col, row, (int)*vMsk);
    892                     continue;
    893                 }
    894                 vMsk++;
    895             }
    896             if (isnan(*vPix)) continue;
    897 
    898             psF32 xDiff = col + xOff;
    899             psF32 yDiff = row + yOff;
    900 
    901             // radius is just a function of (xDiff, yDiff)
    902             if (!VALID_RADIUS(xDiff, yDiff, R2)) {
    903 #if 1
    904                 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to position: %f %f\n",
    905                         col, row, xDiff, yDiff);
    906 #endif
    907                 continue;
    908             }
    909 
    910             psF32 pDiff = *vPix - sky;
    911             psF32 wDiff = *vWgt;
    912 
    913             // XXX EAM : check for valid S/N in pixel
    914             // XXX EAM : should this limit be user-defined?
    915 #if 1
    916             if (PS_SQR(pDiff) < wDiff) {
    917                 psTrace("psModules.objects", 10, "Ignoring pixel %d,%d due to insignificance: %f, %f\n",
    918                         col, row, pDiff, wDiff);
    919                 continue;
    920             }
    921 #endif
    922 
    923             Var += wDiff;
    924             Sum += pDiff;
    925 
    926             psF32 xWght = xDiff * pDiff;
    927             psF32 yWght = yDiff * pDiff;
    928 
    929             X1  += xWght;
    930             Y1  += yWght;
    931 
    932             XY  += xDiff * yWght;
    933             X2  += xDiff * xWght;
    934             Y2  += yDiff * yWght;
    935 
    936             peakPixel = PS_MAX (*vPix, peakPixel);
    937             numPixels++;
    938         }
    939     }
    940 
    941     // if we have less than (1/4) of the possible pixels, force a retry
    942     // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    943     if ((numPixels < 0.75*R2) || (Sum <= 0)) {
    944         psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n",
    945                  numPixels, (int)(0.75*R2), Sum);
    946         psTrace("psModules.objects", 10, "---- end (false) ----\n");
    947         return (false);
    948     }
    949 
    950     psTrace ("psModules.objects", 4, "sky: %f  Sum: %f  X1: %f  Y1: %f  X2: %f  Y2: %f  XY: %f  Npix: %d\n",
    951              sky, Sum, X1, Y1, X2, Y2, XY, numPixels);
    952 
    953     //
    954     // first moment X  = X1/Sum + xc
    955     // second moment X = sqrt (X2/Sum - (X1/Sum)^2)
    956     // Sxy             = XY / Sum
    957     //
    958     x = X1/Sum;
    959     y = Y1/Sum;
    960     if ((fabs(x) > radius) || (fabs(y) > radius)) {
    961         psTrace ("psModules.objects", 3, "large centroid swing; invalid peak %d, %d\n",
    962                  source->peak->x, source->peak->y);
    963         psTrace("psModules.objects", 10, "---- end(false)  ----\n");
    964         return (false);
    965     }
    966 
    967     source->moments->Mx = x + xPeak;
    968     source->moments->My = y + yPeak;
    969 
    970     // XXX EAM : Sxy needs to have x*y subtracted
    971     source->moments->Mxy = XY/Sum - x*y;
    972     source->moments->Sum = Sum;
    973     source->moments->SN  = Sum / sqrt(Var);
    974     source->moments->Peak = peakPixel;
    975     source->moments->nPixels = numPixels;
    976 
    977     // XXX EAM : these values can be negative, so we need to limit the range
    978     // XXX EAM : make the use of this consistent: should this be the second moment or sqrt?
    979     // source->moments->Mxx = sqrt(PS_MAX(X2/Sum - PS_SQR(x), 0));
    980     // source->moments->Myy = sqrt(PS_MAX(Y2/Sum - PS_SQR(y), 0));
    981     source->moments->Mxx = PS_MAX(X2/Sum - PS_SQR(x), 0);
    982     source->moments->Myy = PS_MAX(Y2/Sum - PS_SQR(y), 0);
    983 
    984     psTrace ("psModules.objects", 4,
    985              "sky: %f  Sum: %f  Mx: %f  My: %f  Mxx: %f  Myy: %f  Mxy: %f\n",
    986              sky, Sum, source->moments->Mx, source->moments->My,
    987              source->moments->Mxx, source->moments->Myy, source->moments->Mxy);
    988 
    989     psTrace("psModules.objects", 10, "---- end ----\n");
    990     return(true);
    991 }
    992 # endif
    993807
    994808// construct a realization of the source model
  • trunk/psModules/src/objects/pmSource.h

    r34403 r36375  
    4040    PM_SOURCE_TMPF_PETRO_KEEP        = 0x0100,
    4141    PM_SOURCE_TMPF_PETRO_SKIP        = 0x0200,
     42    PM_SOURCE_TMPF_EXT_FIT           = 0x0400,  // not just galaxies (trails as well)
     43    PM_SOURCE_TMPF_PETRO             = 0x0800,
    4244} pmSourceTmpF;
    4345
     
    117119    pmSourceExtendedPars *extpars;      ///< extended source parameters
    118120    pmSourceDiffStats *diffStats;       ///< extra parameters for difference detections
     121    pmSourceGalaxyFits *galaxyFits;     ///< fits to galaxy models (psphotFullForce only)
    119122    psArray *radialAper;                ///< radial flux in circular apertures
    120123    pmSource *parent;                   ///< reference to the master source from which this is derived
  • trunk/psModules/src/objects/pmSourceExtendedPars.c

    r34403 r36375  
    286286    return pars;
    287287}
     288
     289// *** pmSourceExtFitPars describes extra metadata related to an extended fit
     290static void pmSourceGalaxyFitsFree (pmSourceGalaxyFits *tmp) {
     291 
     292    psFree (tmp->Flux);
     293    psFree (tmp->dFlux);
     294    psFree (tmp->chisq);
     295
     296    return;
     297}
     298
     299pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void) {
     300
     301    pmSourceGalaxyFits *tmp = (pmSourceGalaxyFits *) psAlloc(sizeof(pmSourceGalaxyFits));
     302    psMemSetDeallocator(tmp, (psFreeFunc) pmSourceGalaxyFitsFree);
     303
     304    tmp->Flux  = psVectorAllocEmpty (25, PS_TYPE_F32);
     305    tmp->dFlux = psVectorAllocEmpty (25, PS_TYPE_F32);
     306    tmp->chisq = psVectorAllocEmpty (25, PS_TYPE_F32);
     307    tmp->nPix = 0;
     308
     309    return tmp;
     310}
  • trunk/psModules/src/objects/pmSourceExtendedPars.h

    r32347 r36375  
    8282} pmSourceExtFitPars;
    8383
     84typedef struct {
     85  psVector *Flux;
     86  psVector *dFlux;
     87  psVector *chisq;
     88  int nPix;
     89} pmSourceGalaxyFits;
     90
    8491pmSourceRadialFlux *pmSourceRadialFluxAlloc();
    8592bool psMemCheckSourceRadialFlux(psPtr ptr);
     
    109116pmSourceExtFitPars *pmSourceExtFitParsAlloc (void);
    110117
     118pmSourceGalaxyFits *pmSourceGalaxyFitsAlloc (void);
     119
     120
    111121/// @}
    112122# endif /* PM_SOURCE_H */
  • trunk/psModules/src/objects/pmSourceFitModel.c

    r36085 r36375  
    5959    opt->maxTol = 1.00;
    6060    opt->weight = 1.00;
     61    opt->nsigma = 5.00;
    6162    opt->maxChisqDOF = NAN;
    6263    opt->poissonErrors = true;
     
    281282    // set the model success or failure status
    282283    model->flags |= PM_MODEL_STATUS_FITTED;
    283     if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     284    if (!fitStatus) {
     285        if (isnan(myMin->value)) {
     286          model->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     287        } else {
     288          model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     289        }
     290    }
    284291
    285292    if (myMin->chisqConvergence) {
  • trunk/psModules/src/objects/pmSourceFitModel.h

    r36085 r36375  
    3434    float weight;                       ///< use this weight for constant-weight fits
    3535    float covarFactor;                  ///< covariance factor for calculating the chisq
     36    float nsigma;                       ///< how far out to convolve
    3637    bool poissonErrors;                 ///< use poisson errors for fits?
    3738    bool saveCovariance;
  • trunk/psModules/src/objects/pmSourceFitPCM.c

    r36085 r36375  
    5151# define TIMING 0
    5252
     53bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal);
     54
    5355bool pmSourceFitPCM (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, int psfSize) {
    5456   
     
    113115    } else {
    114116        // xxx this is wrong because it does not convolve with the psf
    115         pmSourceChisqUnsubtracted (source, pcm->modelConv, maskVal);
     117        pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     118        pmSourceChisqModelFlux (source, pcm->modelConv, maskVal);
    116119    }
    117120    if (TIMING) { t4 = psTimerMark ("pmSourceFitPCM"); }
     
    119122    // set the model success or failure status
    120123    pcm->modelConv->flags |= PM_MODEL_STATUS_FITTED;
    121     if (!fitStatus) pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
     124
     125    if (!fitStatus) {
     126        if (isnan(myMin->value)) {
     127            pcm->modelConv->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     128        } else {
     129            pcm->modelConv->flags |= PM_MODEL_STATUS_NONCONVERGE;
     130        }
     131    }
    122132
    123133    if (myMin->chisqConvergence) {
  • trunk/psModules/src/objects/pmSourceFitSet.c

    r36085 r36375  
    352352        // set the model success or failure status
    353353        model->flags |= PM_MODEL_STATUS_FITTED;
    354         if (!fitStatus) model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     354        if (!fitStatus) {
     355          if (isnan(myMin->value)) {
     356            model->flags |= PM_MODEL_STATUS_NAN_CHISQ;
     357          } else {
     358            model->flags |= PM_MODEL_STATUS_NONCONVERGE;
     359          }
     360        }
    355361
    356362        // models can go insane: reject these
  • trunk/psModules/src/objects/pmSourceIO.c

    r35610 r36375  
    6969                        psString *xfitname,    // Extension name for extended fitted measurements
    7070                        psString *xradname,    // Extension name for radial apertures
     71                        psString *xgalname,    // Extension name for galaxy shapes
    7172                        const pmFPAfile *file, // File of interest
    7273                        const pmFPAview *view  // View to level of interest
     
    140141        }
    141142        *xradname = pmFPAfileNameFromRule (rule, file, view);
     143    }
     144
     145    // EXTNAME for radial apertures
     146    if (xgalname) {
     147        const char *rule = psMetadataLookupStr(&status, menu, "CMF.XGAL");
     148        if (!rule) {
     149            psError(PS_ERR_UNKNOWN, true, "missing entry for CMF.XGAL in EXTNAME.RULES in camera.config");
     150            return false;
     151        }
     152        *xgalname = pmFPAfileNameFromRule (rule, file, view);
    142153    }
    143154
     
    362373            status &= pmSourcesWrite_##TYPE##_XRAD (file->fits, readout, sources, file->header, xradname, recipe); \
    363374        }                                                               \
     375        if (xgalname) {                                                 \
     376            status &= pmSourcesWrite_##TYPE##_XGAL (file->fits, sources, xgalname, recipe); \
     377        }                                                               \
    364378    }
    365379
     
    464478        }
    465479
    466         // if this is not TRUE, the output files only contain the psf measurements.
    467         bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
     480        // if none of these are TRUE, the output files only contain the psf measurements.
     481        bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     482        bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     483        bool XSRC_OUTPUT = doPetrosian || doAnnuli;
    468484        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
    469485        bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES");
     486        bool XGAL_OUTPUT = psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES");
    470487
    471488        // define the EXTNAME values for the different data segments:
     
    476493        psString xfitname = NULL;
    477494        psString xradname = NULL;
     495        psString xgalname = NULL;
    478496        if (!pmSourceIOextnames(&headname, &dataname, &deteffname,
    479497                                XSRC_OUTPUT ? &xsrcname : NULL,
    480498                                XFIT_OUTPUT ? &xfitname : NULL,
    481499                                XRAD_OUTPUT ? &xradname : NULL,
     500                                XGAL_OUTPUT ? &xgalname : NULL,
    482501                                file, view)) {
    483502            return false;
     
    563582                psMetadataAddStr (outhead, PS_LIST_TAIL, "XRADNAME", PS_META_REPLACE, "name of XRAD table extension", xradname);
    564583            }
     584            if (xgalname) {
     585                psMetadataAddStr (outhead, PS_LIST_TAIL, "XGALNAME", PS_META_REPLACE, "name of XGAL table extension", xgalname);
     586            }
    565587
    566588            // these are case-sensitive since the EXTYPE is case-sensitive
     
    609631        psFree (xfitname);
    610632        psFree (xradname);
     633        psFree (xgalname);
    611634        psFree (deteffname);
    612635
     
    620643        psFree (xfitname);
    621644        psFree (xradname);
     645        psFree (xgalname);
    622646        psFree (deteffname);
    623647        return false;
    624648
     649      case PM_FPA_FILE_CFF: {
     650        // determine the output table format
     651        psMetadata *recipe = psMetadataLookupMetadata(&status, config->recipes, "PSPHOT");
     652        if (!status) {
     653            psError(PS_ERR_UNKNOWN, true, "missing recipe PSPHOT in config data");
     654            return false;
     655        }
     656
     657        hdu = pmFPAviewThisHDU (view, fpa);
     658        pmConfigConformHeader(hdu->header, file->format);
     659        psFitsWriteBlank (file->fits, hdu->header, NULL);
     660        file->header = hdu->header;
     661        file->wrote_phu = true;
     662        if (!pmSourcesWrite_CFF(readout, file->fits, sources, hdu->header, recipe)) {
     663            psError(PS_ERR_UNKNOWN, false, "failed to write CFF");
     664            return false;
     665        }
     666        break;
     667      }
     668       
    625669      default:
    626670        fprintf (stderr, "warning: type mismatch\n");
     
    914958    psArray *sources = NULL;
    915959    pmHDU *hdu;
     960
     961    // define the EXTNAME values for the different data segments:
     962    psString headname = NULL;
     963    psString dataname = NULL;
     964    psString deteffname = NULL;
     965    psString xsrcname = NULL;
     966    psString xfitname = NULL;
     967    psString xradname = NULL;
     968    psString xgalname = NULL;
     969
     970    psMetadata *tableHeader = NULL;
     971    char *xtension = NULL;
    916972
    917973    switch (file->type) {
     
    9631019        hdu = pmFPAviewThisHDU (view, file->fpa);
    9641020
    965         // define the EXTNAME values for the different data segments:
    966         psString headname = NULL;
    967         psString dataname = NULL;
    968         psString deteffname = NULL;
    969         psString xsrcname = NULL;
    970         psString xfitname = NULL;
    971         psString xradname = NULL;
    972 
    9731021        // determine the output table format. Assume if we need to output extendend source
    9741022        // parameters that they may exist in the input.
     
    9811029        }
    9821030
    983         // if this is not TRUE, the output files only contain the psf measurements.
    984         bool XSRC_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_ANALYSIS");
     1031        // if none of these are TRUE, we only read the psf measurements
     1032        // XXX: shouldn't we look for these extensions and read the regardless of the recipe values?
     1033        bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     1034        bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     1035        bool XSRC_OUTPUT = doPetrosian || doAnnuli;
    9851036        bool XFIT_OUTPUT = psMetadataLookupBool(&status, recipe, "EXTENDED_SOURCE_FITS");
    9861037        bool XRAD_OUTPUT = psMetadataLookupBool(&status, recipe, "RADIAL_APERTURES");
     1038        bool XGAL_OUTPUT = false; // psMetadataLookupBool(&status, recipe, "GALAXY_SHAPES");
    9871039
    9881040        if (!pmSourceIOextnames(&headname, &dataname, &deteffname,
     
    9901042                XFIT_OUTPUT ? &xfitname : NULL,
    9911043                XRAD_OUTPUT ? &xradname : NULL,
     1044                XGAL_OUTPUT ? &xgalname : NULL,
    9921045                file, view)) {
    9931046            return false;
     
    10331086        }
    10341087
    1035         psMetadata *tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1088        tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
    10361089        if (!tableHeader) psAbort("cannot read table header");
    10371090
    1038         char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1091        xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
    10391092        if (!xtension) psAbort("cannot read table type");
    10401093        if (strcmp (xtension, "BINTABLE")) {
     
    11321185        break;
    11331186
     1187      case PM_FPA_FILE_CFF:
     1188        // read in header, if not yet loaded
     1189        hdu = pmFPAviewThisHDU (view, file->fpa);
     1190
     1191        // look these up in the camera config?
     1192        // headrule = {CHIP.NAME}.hdr
     1193        // datarule = {CHIP.NAME}.cff
     1194
     1195        // define the EXTNAME values for the different data segments:
     1196        headname = pmFPAfileNameFromRule("{CHIP.NAME}.hdr", file, view);
     1197        dataname = pmFPAfileNameFromRule("{CHIP.NAME}.cff", file, view);
     1198
     1199        // advance to the IMAGE HEADER extension
     1200        if (hdu->header == NULL) {
     1201            // if the IMAGE header does not exist, we have no data for this view
     1202            if (!psFitsMoveExtNameClean (file->fits, headname)) {
     1203                readout->data_exists = false;
     1204                psFree (headname);
     1205                psFree (dataname);
     1206                return true;
     1207            }
     1208            hdu->header = psFitsReadHeader (NULL, file->fits);
     1209        }
     1210
     1211        // advance to the table data extension
     1212        // since we have read the IMAGE header, the TABLE header should exist
     1213        if (!psFitsMoveExtName (file->fits, dataname)) {
     1214            psAbort("cannot find data extension %s in %s", dataname, file->filename);
     1215        }
     1216
     1217        tableHeader = psFitsReadHeader(NULL, file->fits); // The FITS header
     1218        if (!tableHeader) psAbort("cannot read table header");
     1219
     1220        // verify this is a binary table
     1221        char *xtension = psMetadataLookupStr (NULL, tableHeader, "XTENSION");
     1222        if (!xtension) psAbort("cannot read table type");
     1223        if (strcmp (xtension, "BINTABLE")) {
     1224            psWarning ("no binary table in extension %s, skipping\n", dataname);
     1225            psFree(tableHeader);
     1226            return false;
     1227        }
     1228
     1229        sources = pmSourcesRead_CFF(file->fits, hdu->header);
     1230
     1231        psTrace("psModules.objects", 6, "read CMF table from %s : %s : %s", file->filename, headname, dataname);
     1232        psFree (headname);
     1233        psFree (dataname);
     1234        psFree (tableHeader);
     1235        break;
     1236
    11341237      default:
    11351238        fprintf (stderr, "warning: type mismatch\n");
  • trunk/psModules/src/objects/pmSourceIO.h

    r35610 r36375  
    2121  bool pmSourcesWrite_##TYPE##_XFIT(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname); \
    2222  bool pmSourcesWrite_##TYPE##_XRAD(psFits *fits, pmReadout *readout, psArray *sources, psMetadata *imageHeader, char *extname, psMetadata *recipe); \
     23  bool pmSourcesWrite_##TYPE##_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe); \
    2324  psArray *pmSourcesRead_##TYPE (psFits *fits, psMetadata *header); \
    2425  bool pmSourcesRead_##TYPE##_XSRC (psFits *fits, pmReadout *readout, psMetadata *header, psMetadata *tableHeader, psArray *sources, long *index); \
     
    5253
    5354psArray *pmSourcesReadCMP (char *filename, psMetadata *header);
     55psArray *pmSourcesRead_CFF (psFits *fits, psMetadata *header);
     56bool pmSourcesWrite_CFF (pmReadout *readout, psFits *fits, psArray *sources, psMetadata *header, psMetadata *recipe);
    5457
    5558bool pmSourcesWritePSFs (psArray *sources, char *filename);
  • trunk/psModules/src/objects/pmSourceIO_CMF.c.in

    r35768 r36375  
    789789    char name[64];
    790790
     791    pmModelType modelTypeTrail = pmModelClassGetType("PS_MODEL_TRAIL");
     792
    791793    // create a header to hold the output data
    792794    psMetadata *outhead = psMetadataAlloc ();
     
    798800    sources = psArraySort (sources, pmSourceSortByFlux);
    799801
    800     @>PS1_DV2@ float magOffset;
    801     @>PS1_DV2@ float zeroptErr;
    802     @>PS1_DV2@ float fwhmMajor;
    803     @>PS1_DV2@ float fwhmMinor;
    804     @>PS1_DV2@ pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
     802    float magOffset;
     803    float zeroptErr;
     804    float fwhmMajor;
     805    float fwhmMinor;
     806    pmSourceOutputsCommonValues (&magOffset, &zeroptErr, &fwhmMajor, &fwhmMinor, readout, imageHeader);
    805807
    806808    // we are writing one row per model; we need to write out same number of columns for each row: find the max Nparams
     
    823825    @>PS1_DV2@ pmChip *chip = readout->parent->parent;
    824826
     827    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     828    badModel |= PM_MODEL_STATUS_BADARGS;
     829    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     830    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     831    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     832    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     833    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     834
    825835    table = psArrayAllocEmpty (sources->n);
    826836
     
    847857
    848858            // skip models which were not actually fitted
    849             if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     859            // XXX
     860            if (model->flags & badModel) continue;
    850861
    851862            PAR = model->params->data.F32;
     
    853864            xPos = PAR[PM_PAR_XPOS];
    854865            yPos = PAR[PM_PAR_YPOS];
    855             xErr = dPAR[PM_PAR_XPOS];
    856             yErr = dPAR[PM_PAR_YPOS];
     866
     867            // for the extended source models, we do not always fit the centroid in the non-linear fitting process
     868            // current situation (hard-wired into psphotSourceFits.c:psphotFitPCM,
     869            // SERSIC, DEV, EXP : X,Y not fitted (PCM and not PCM)
     870            // TRAIL : X,Y are fitted
     871            //
     872           
     873            // XXX this should be based on what happened, not on the model type
     874            if (model->type == modelTypeTrail) {
     875                xErr = dPAR[PM_PAR_XPOS];
     876                yErr = dPAR[PM_PAR_YPOS];
     877            } else {
     878                // this is definitely an underestimate since it does not
     879                // account for the extent of the source
     880                xErr = fwhmMajor * model->magErr / 2.35;
     881                yErr = fwhmMinor * model->magErr / 2.35;
     882            }
    857883
    858884            @>PS1_DV2@ psSphere ptSky = {0.0, 0.0, 0.0, 0.0};
     
    870896            row = psMetadataAlloc ();
    871897
    872             // XXX we are not writing out the mode (flags) or the type (psf, ext, etc)
    873898            // the psMetadataAdd entry and the double quotes are used by grep to select the output fields for automatic documentation
    874899            // This set of psMetadataAdd Entries marks the "----" "Start of the XFIT segment"
     
    888913            @>PS1_DV2@ float calMag = isfinite(magOffset) ? model->mag + magOffset : NAN;
    889914            @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CAL_MAG", PS_DATA_F32, "EXT Magnitude using supplied calibration",   calMag);
    890             @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ",   PS_DATA_F32, "EXT Magnitude using supplied calibration",   model->chisq);
    891             @>PS1_DV2@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF",    PS_DATA_S32, "EXT Magnitude using supplied calibration",   model->nDOF);
     915            @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_CHISQ",   PS_DATA_F32, "EXT Model Chisq",   model->chisq);
     916            @>PS1_DV2,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_NDOF",    PS_DATA_S32, "EXT Model num degrees of freedom",   model->nDOF);
     917            @>PS1_SV1,PS1_SV?@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_MODEL_TYPE",    PS_DATA_S32, "type for chosen EXT_MODEL",   source->modelEXT ? source->modelEXT->type : -1);
     918
     919            // EAM : adding for PV2 outputs:
     920            @>PS1_SV1@ psMetadataAdd (row, PS_LIST_TAIL, "EXT_FLAGS", PS_DATA_S16, "model fit flags (pmModelStatus)", source->modelEXT ? source->modelEXT->flags : 0);
    892921
    893922            @>PS1_DV2@ psMetadataAddF32 (row, PS_LIST_TAIL, "POSANGLE",   0, "position angle at source (degrees)",         posAngle);
     
    946975
    947976                snprintf (name, 64, "EXT_PAR_%02d", k);
    948 
     977               
    949978                if (k < model->params->n) {
    950979                    psMetadataAddF32 (row, PS_LIST_TAIL, name, 0, "", model->params->data.F32[k]);
     
    956985            // optionally, write out the covariance matrix values
    957986            // XXX do I need to pad this to match the biggest covar matrix?
    958             if (model->covar) {
     987            if (false && model->covar) {
    959988                for (int iy = 0; iy < model->covar->numCols; iy++) {
    960989                    for (int ix = iy; ix < model->covar->numCols; ix++) {
     
    10581087        model->magErr = psMetadataLookupF32(&status, row, "EXT_INST_MAG_SIG");
    10591088
     1089        model->chisq = psMetadataLookupF32(&status, row, "EXT_CHISQ");
     1090        model->nDOF = psMetadataLookupF32(&status, row, "EXT_NDOF");
     1091
     1092        // EXT_MODEL_TYPE gives the model chosen by psphot as the best.
     1093        // Putting this into the XFIT table makes 3 copies of it (one for each model)
     1094        // but since we have many fewer XFIT rows than psf rows that is cheaper than putting it
     1095        // in the psf table.
     1096        psS32 extModelType = psMetadataLookupS32(&status, row, "EXT_MODEL_TYPE");
     1097        if (!status) {
     1098            // older cmfs don't have this column
     1099            extModelType = -1;
     1100        }
     1101
    10601102        psEllipseAxes axes;
    10611103        axes.major = psMetadataLookupF32(&status, row, "EXT_WIDTH_MAJ");
     
    10721114        if (model->params->n > 7) {
    10731115            PAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07");
    1074         }
    1075         // read the covariance matrix
    1076         int nparams = model->params->n;
    1077         psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32);
    1078         for (int y = 0; y < nparams; y++) {
    1079             for (int x = 0; x < nparams; x++) {
    1080                 char name[64];
    1081                 snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x);
    1082                 covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name);
     1116            // XXX add an error:
     1117            // dPAR[7] = psMetadataLookupF32(&status, row, "EXT_PAR_07_");
     1118        }
     1119
     1120        // XXX : make this depend on what is in the cmf
     1121        if (0) {
     1122            // read the covariance matrix
     1123            int nparams = model->params->n;
     1124            psImage *covar = psImageAlloc(nparams, nparams, PS_TYPE_F32);
     1125            for (int y = 0; y < nparams; y++) {
     1126                for (int x = 0; x < nparams; x++) {
     1127                    char name[64];
     1128                    snprintf(name, 64, "EXT_COVAR_%02d_%02d", y, x);
     1129                    covar->data.F32[y][x] = psMetadataLookupF32(&status, row, name);
     1130                }
     1131            }
     1132            model->covar = covar;
     1133        }
     1134
     1135        if (modelType == extModelType) {
     1136            // The software that created this source picked this model as the best of the fits.
     1137            // Set the extModel to point to it.
     1138            // This is important for programs like psastro (skycal) so that its output cmfs
     1139            // will have valid EXT_MODEL_TYPE
     1140            psFree(source->modelEXT);
     1141            source->modelEXT = psMemIncrRefCounter(model);
     1142            source->type = PM_SOURCE_TYPE_EXTENDED;
     1143            if (0) {
     1144                // since FLAGS were read we don't need to do this
     1145                source->mode |= PM_SOURCE_MODE_EXTMODEL;
     1146                source->mode |= PM_SOURCE_MODE_NONLINEAR_FIT;
    10831147            }
    10841148        }
    1085         model->covar = covar;
    10861149
    10871150        psArrayAdd(source->modelFits, 1, model);
    10881151        psFree(model);
    1089 
    10901152        psFree(row);
    10911153    }
     
    12091271
    12101272        write_annuli:
    1211             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX",       PS_DATA_VECTOR, "flux within annuli",       radFlux);
    1212             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_ERR",   PS_DATA_VECTOR, "flux error in annuli",     radFluxErr);
    1213             psMetadataAdd (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_DATA_VECTOR, "flux standard deviation",  radFluxStdev);
    1214             psMetadataAdd (row, PS_LIST_TAIL, "APER_FILL",       PS_DATA_VECTOR, "fill factor of annuli",    radFill);
     1273            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX",       PS_META_REPLACE, "flux within annuli",       radFlux);
     1274            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_ERR",   PS_META_REPLACE, "flux error in annuli",     radFluxErr);
     1275            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FLUX_STDEV", PS_META_REPLACE, "flux standard deviation",  radFluxStdev);
     1276            psMetadataAddVector (row, PS_LIST_TAIL, "APER_FILL",       PS_META_REPLACE, "fill factor of annuli",    radFill);
    12151277            psFree (radFlux);
    12161278            psFree (radFluxErr);
     
    13431405    return true;
    13441406}
     1407
     1408// XXX where should I record the number of columns??
     1409bool pmSourcesWrite_CMF_@CMFMODE@_XGAL (psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     1410{
     1411    bool status = false;
     1412
     1413    // perform full non-linear fits / extended source analysis?
     1414    if (!psMetadataLookupBool (&status, recipe, "GALAXY_SHAPES")) {
     1415        psLogMsg ("psphot", PS_LOG_INFO, "galaxy shapes were not measured, skipping\n");
     1416        return true;
     1417    }
     1418
     1419    // create a header to hold the output data
     1420    psMetadata *outhead = psMetadataAlloc ();
     1421
     1422    // write the links to the image header
     1423    psMetadataAddStr (outhead, PS_LIST_TAIL, "EXTNAME", PS_META_REPLACE, "galaxy table extension", extname);
     1424
     1425    // let's write these out in S/N order
     1426    sources = psArraySort (sources, pmSourceSortByFlux);
     1427
     1428    psArray *table = psArrayAllocEmpty (sources->n);
     1429
     1430    for (int i = 0; i < sources->n; i++) {
     1431
     1432        pmSource *thisSource = sources->data[i];
     1433
     1434        // this is the "real" version of this source
     1435        pmSource *source = thisSource->parent ? thisSource->parent : thisSource;
     1436
     1437        // if we did not fit the galaxy model, modelFits will be NULL
     1438        if (source->modelFits == NULL) continue;
     1439
     1440        // if we did not fit the galaxy model, galaxyFits will also be NULL
     1441        if (source->galaxyFits == NULL) continue;
     1442
     1443        pmModel *model = source->modelFits->data[0];
     1444        if (!model) return false;
     1445
     1446        // X,Y coordinates are stored with the model parameters
     1447        psF32 *PAR = model->params->data.F32;
     1448
     1449        psMetadata *row = psMetadataAlloc ();
     1450
     1451        // we write out the x,y positions so people can link to the psf either way (position or ID)
     1452        psMetadataAddU32 (row, PS_LIST_TAIL, "IPP_IDET",         0, "IPP detection identifier index", source->seq);
     1453        psMetadataAddF32 (row, PS_LIST_TAIL, "X_FIT",            0, "model x coordinate",             PAR[PM_PAR_XPOS]);
     1454        psMetadataAddF32 (row, PS_LIST_TAIL, "Y_FIT",            0, "model y coordinate",             PAR[PM_PAR_YPOS]);
     1455        psMetadataAddF32 (row, PS_LIST_TAIL, "NPIX",             0, "number of pixels for fits",      source->galaxyFits->nPix);
     1456
     1457        psVector *Flux = source->galaxyFits->Flux;
     1458        psVector *dFlux = source->galaxyFits->dFlux;
     1459        psVector *chisq = source->galaxyFits->chisq;
     1460
     1461        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX",     PS_META_REPLACE, "normalization for galaxy flux", Flux);
     1462        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_FLUX_ERR", PS_META_REPLACE, "error on normalization", dFlux);
     1463        psMetadataAddVector (row, PS_LIST_TAIL, "GAL_CHISQ",    PS_META_REPLACE, "galaxy fit chisq", chisq);
     1464
     1465        psArrayAdd (table, 100, row);
     1466        psFree (row);
     1467    }
     1468
     1469    if (table->n == 0) {
     1470        if (!psFitsWriteBlank (fits, outhead, extname)) {
     1471            psError(psErrorCodeLast(), false, "Unable to write empty sources file.");
     1472            psFree(outhead);
     1473            psFree(table);
     1474            return false;
     1475        }
     1476        psFree (outhead);
     1477        psFree (table);
     1478        return true;
     1479    }
     1480
     1481    psTrace ("pmFPAfile", 5, "writing galaxy data %s\n", extname);
     1482    if (!psFitsWriteTable (fits, outhead, table, extname)) {
     1483        psError(psErrorCodeLast(), false, "writing galaxy data %s\n", extname);
     1484        psFree (outhead);
     1485        psFree(table);
     1486        return false;
     1487    }
     1488    psFree (outhead);
     1489    psFree (table);
     1490    return true;
     1491}
     1492
  • trunk/psModules/src/objects/pmSourceIO_PS1_CAL_0.c

    r35768 r36375  
    713713    return true;
    714714}
     715
     716bool pmSourcesWrite_PS1_CAL_0_XGAL (psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     717{
     718    return true;
     719}
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_0.c

    r35768 r36375  
    255255    return true;
    256256}
     257
     258bool pmSourcesWrite_PS1_DEV_0_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     259{
     260    return true;
     261}
  • trunk/psModules/src/objects/pmSourceIO_PS1_DEV_1.c

    r35768 r36375  
    595595    return true;
    596596}
     597
     598bool pmSourcesWrite_PS1_DEV_1_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     599{
     600    return true;
     601}
  • trunk/psModules/src/objects/pmSourceIO_SMPDATA.c

    r35768 r36375  
    225225    return true;
    226226}
     227
     228bool pmSourcesWrite_SMPDATA_XGAL(psFits *fits, psArray *sources, char *extname, psMetadata *recipe)
     229{
     230    return true;
     231}
  • trunk/psModules/src/objects/pmSourceMasks.h

    r34403 r36375  
    5656    PM_SOURCE_MODE2_DIFF_SELF_MATCH       = 0x00000800, ///< positive detection match is probably this source
    5757    PM_SOURCE_MODE2_SATSTAR_PROFILE       = 0x00001000, ///< saturated source is modeled with a radial profile
     58
     59    PM_SOURCE_MODE2_ECONTOUR_FEW_PTS      = 0x00002000, ///< too few points to measure the elliptical contour
     60    PM_SOURCE_MODE2_RADBIN_NAN_CENTER     = 0x00004000, ///< radial bins failed with too many NaN center bin
     61    PM_SOURCE_MODE2_PETRO_NAN_CENTER      = 0x00008000, ///< petrosian radial bins failed with too many NaN center bin
     62    PM_SOURCE_MODE2_PETRO_NO_PROFILE      = 0x00010000, ///< petrosian not build because radial bins missing
     63
     64    PM_SOURCE_MODE2_PETRO_INSIG_RATIO     = 0x00020000, ///< insignificant measurement of petrosian ratio
     65    PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN   = 0x00040000, ///< petrosian ratio in the 0th bin (likely bad)
     66   
     67    PM_SOURCE_MODE2_EXT_FITS_RUN          = 0x00080000, ///< we attempted to run extended fits on this source
     68    PM_SOURCE_MODE2_EXT_FITS_FAIL         = 0x00100000, ///< at least one of the model fits failed
     69    PM_SOURCE_MODE2_EXT_FITS_RETRY        = 0x00200000, ///< one of the model fits was re-tried with new window
     70    PM_SOURCE_MODE2_EXT_FITS_NONE         = 0x00400000, ///< ALL of the model fits failed
     71   
     72   
    5873} pmSourceMode2;
    5974
  • trunk/psModules/src/objects/pmSourceMoments.c

    r35560 r36375  
    6565void pmSourceMomentsSetVerbose(bool state){ beVerbose = state; }
    6666
     67bool pmSourceMomentsHighOrder    (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal);
     68bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal);
     69bool pmSourceMomentsKronFluxes   (pmSource *source, float sigma,  float minSN, psImageMaskType maskVal);
     70
    6771// if mode & EXTERNAL or mode2 & MATCHED, do not re-calculate the centroid (use peak as centroid)
    68 
    6972bool pmSourceMoments(pmSource *source, float radius, float sigma, float minSN, float minKronRadius, psImageMaskType maskVal)
    7073{
     
    7477    PS_ASSERT_FLOAT_LARGER_THAN(radius, 0.0, false);
    7578
    76     // this function assumes the sky has been well-subtracted for the image
    77     float sky = 0.0;
    78 
    7979    if (source->moments == NULL) {
    8080      source->moments = pmMomentsAlloc();
    8181    }
    82 
    83     float Sum = 0.0;
    84     float Var = 0.0;
    85     float SumCore = 0.0;
    86     float VarCore = 0.0;
    87     float R2 = PS_SQR(radius);
    88     float minSN2 = PS_SQR(minSN);
    89     float rsigma2 = 0.5 / PS_SQR(sigma);
    9082
    9183    // a note about coordinates: coordinates of objects throughout psphot refer to the primary
     
    110102    // of any object drops pretty quickly outside 1-2 sigmas.  (The exception is bright
    111103    // saturated stars, for which we need to use a very large radius here)
     104    // NOTE: if (mode & EXTERNAL) or (mode2 & MATCHED), do not re-calculate the centroid (use peak as centroid)
     105    // (we still call this function because it sets moments->Sum,SN,Peak,nPixels
    112106    if (!pmSourceMomentsGetCentroid (source, 1.5*sigma, 0.0, minSN, maskVal, source->peak->xf, source->peak->yf)) {
    113107        return false;
    114108    }
    115109
     110    pmSourceMomentsHighOrder (source, radius, sigma, minSN, maskVal);
     111
     112    // now calculate the 1st radial moment (for kron flux) using symmetrical averaging
     113    pmSourceMomentsRadialMoment (source, radius, minKronRadius, maskVal);
     114
     115    // now calculate the kron flux values using the 1st radial moment
     116    pmSourceMomentsKronFluxes (source, sigma, minSN, maskVal);
     117
     118    psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
     119             source->moments->Mrf,   source->moments->KronFlux,
     120             source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
     121             source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
     122             source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
     123
     124    psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  Npix: %d\n",
     125             source->peak->xf, source->peak->yf,
     126             source->peak->rawFlux, sqrt(source->peak->detValue),
     127             source->moments->Mx, source->moments->My,
     128             source->moments->Sum,
     129             source->moments->Mxx, source->moments->Mxy, source->moments->Myy,
     130             source->moments->nPixels);
     131
     132    return(true);
     133}
     134
     135bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
     136
     137    // First Pass: calculate the first moments (these are subtracted from the coordinates below)
     138    // Sum = SUM (z - sky)
     139    // X1  = SUM (x - xc)*(z - sky)
     140    // .. etc
     141
     142    float sky = 0.0;
     143
     144    float peakPixel = -PS_MAX_F32;
     145    psS32 numPixels = 0;
     146    float Sum = 0.0;
     147    float Var = 0.0;
     148    float X1 = 0.0;
     149    float Y1 = 0.0;
     150    float R2 = PS_SQR(radius);
     151    float minSN2 = PS_SQR(minSN);
     152    float rsigma2 = 0.5 / PS_SQR(sigma);
     153
     154    float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
     155    float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
     156
     157    // we are guaranteed to have a valid pixel and variance at this location (right? right?)
     158    // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
     159    // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     160    // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
     161    // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
     162
     163    // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
     164    // not depend on the fractional pixel location of the source.  However, the aperture
     165    // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
     166    // position of the expected centroid
     167
     168    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     169
     170        float yDiff = row + 0.5 - yPeak;
     171        if (fabs(yDiff) > radius) continue;
     172
     173        float *vPix = source->pixels->data.F32[row];
     174        float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row];
     175
     176        psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
     177        // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
     178
     179        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     180            if (vMsk) {
     181                if (*vMsk & maskVal) {
     182                    vMsk++;
     183                    continue;
     184                }
     185                vMsk++;
     186            }
     187            if (isnan(*vPix)) continue;
     188
     189            float xDiff = col + 0.5 - xPeak;
     190            if (fabs(xDiff) > radius) continue;
     191
     192            // radius is just a function of (xDiff, yDiff)
     193            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
     194            if (r2 > R2) continue;
     195
     196            float pDiff = *vPix - sky;
     197            float wDiff = *vWgt;
     198
     199            // skip pixels below specified significance level.  for a PSFs, this
     200            // over-weights the wings of bright stars compared to those of faint stars.
     201            // for the estimator used for extended source analysis (where the window
     202            // function is allowed to be arbitrarily large), we need to clip to avoid
     203            // negative second moments.
     204            if (PS_SQR(pDiff) < minSN2*wDiff) continue; //
     205            if ((minSN > 0.0) && (pDiff < 0)) continue; //
     206
     207            // Apply a Gaussian window function.  Be careful with the window function.  S/N
     208            // weighting over weights the sky for faint sources
     209            if (sigma > 0.0) {
     210                float z  = r2*rsigma2;
     211                assert (z >= 0.0);
     212                float weight  = exp(-z);
     213
     214                wDiff *= weight;
     215                pDiff *= weight;
     216            }
     217
     218            Var += wDiff;
     219            Sum += pDiff;
     220
     221            float xWght = xDiff * pDiff;
     222            float yWght = yDiff * pDiff;
     223
     224            X1  += xWght;
     225            Y1  += yWght;
     226
     227            peakPixel = PS_MAX (*vPix, peakPixel);
     228            numPixels++;
     229        }
     230    }
     231
     232    // if we have less than (1/4) of the possible pixels (in circle or box), force a retry
     233    int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0);
     234
     235    // XXX EAM - the limit is a bit arbitrary.  make it user defined?
     236    if ((numPixels < minPixels) || (Sum <= 0)) {
     237        psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);
     238        return (false);
     239    }
     240
     241    // calculate the first moment.
     242    float Mx = X1/Sum;
     243    float My = Y1/Sum;
     244    if ((fabs(Mx) > radius) || (fabs(My) > radius)) {
     245        psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);
     246        return (false);
     247    }
     248    if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) {
     249        psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y);
     250    }
     251
     252    psTrace ("psModules.objects", 5, "id: %d, sky: %f  Mx: %f  My: %f  Sum: %f  X1: %f  Y1: %f  Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);
     253
     254    // add back offset of peak in primary image
     255    // also offset from pixel index to pixel coordinate
     256    // (the calculation above uses pixel index instead of coordinate)
     257    // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords
     258
     259    // we only update the centroid if the position is not supplied from elsewhere
     260    bool skipCentroid = false;
     261    skipCentroid |= (source->mode  & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions
     262    skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions
     263
     264    if (skipCentroid) {
     265        source->moments->Mx = source->peak->xf;
     266        source->moments->My = source->peak->yf;
     267    } else {
     268        source->moments->Mx = Mx + xGuess;
     269        source->moments->My = My + yGuess;
     270    }
     271
     272    source->moments->Sum = Sum;
     273    source->moments->SN  = Sum / sqrt(Var);
     274    source->moments->Peak = peakPixel;
     275    source->moments->nPixels = numPixels;
     276
     277    return true;
     278}
     279
     280float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) {
     281
     282    psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32);
     283
     284    for (int i = 0; i < sources->n; i++) {
     285        pmSource *src = sources->data[i]; // Source of interest
     286        if (!src || !src->moments) {
     287            continue;
     288        }
     289
     290        if (src->mode & PM_SOURCE_MODE_BLEND) {
     291            continue;
     292        }
     293
     294        if (!src->moments->nPixels) continue;
     295
     296        if (src->moments->SN < PSF_SN_LIM) continue;
     297
     298        // XXX put in Mxx,Myy cut based on clump location
     299
     300        psVectorAppend(radii, src->moments->Mrf);
     301    }
     302
     303    // find the peak in this image
     304    psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
     305
     306    if (!psVectorStats (stats, radii, NULL, NULL, 0)) {
     307        psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
     308        psFree(stats);
     309        return NAN;
     310    }
     311
     312    float minRadius = stats->sampleMedian;
     313
     314    psFree(radii);
     315    psFree(stats);
     316    return minRadius;
     317}
     318
     319bool pmSourceMomentsHighOrder (pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal) {
     320
     321    // this function assumes the sky has been well-subtracted for the image
     322    float Sum = 0.0;
     323    float R2 = PS_SQR(radius);
     324    float minSN2 = PS_SQR(minSN);
     325    float rsigma2 = 0.5 / PS_SQR(sigma);
     326
    116327    // Now calculate higher-order moments, using the above-calculated first moments to adjust coordinates
    117     // Xn  = SUM (x - xc)^n * (z - sky)
     328    // Xn  = SUM (x - xc)^n * (z - sky) -- note that sky is 0.0 by definition here
    118329    float XX = 0.0;
    119330    float XY = 0.0;
     
    129340    float YYYY = 0.0;
    130341
    131     Sum = 0.0;  // the second pass may include slightly different pixels, re-determine Sum
    132 
    133     // float dX = source->moments->Mx - source->peak->xf;
    134     // float dY = source->moments->My - source->peak->yf;
    135     // float dR = hypot(dX, dY);
    136     // float Xo = (dR < 2.0) ? source->moments->Mx : source->peak->xf;
    137     // float Yo = (dR < 2.0) ? source->moments->My : source->peak->yf;
    138342    float Xo = source->moments->Mx;
    139343    float Yo = source->moments->My;
     
    154358
    155359        psImageMaskType  *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    156         // psImageMaskType  *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    157360
    158361        for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
     
    173376            if (r2 > R2) continue;
    174377
    175             float fDiff = *vPix - sky;
     378            float fDiff = *vPix;
    176379            float pDiff = fDiff;
    177380            float wDiff = *vWgt;
     
    181384            // stars.
    182385            if (PS_SQR(pDiff) < minSN2*wDiff) continue;
    183             if ((minSN > 0.0) && (pDiff < 0)) continue; //
     386            if ((minSN > 0.0) && (pDiff < 0)) continue;
    184387
    185388            // Apply a Gaussian window function.  Be careful with the window function.  S/N
    186             // weighting over weights the sky for faint sources
     389            // weighting over-weights the sky for faint sources
    187390            if (sigma > 0.0) {
    188391                float z = r2 * rsigma2;
     
    230433            XYYY  += xyyy;
    231434            YYYY  += yyyy;
    232 
    233             // Kron Flux uses the 1st radial moment (NOT Gaussian windowed?)
    234             // XXX float r = sqrt(r2);
    235             // XXX float rf = r * fDiff;
    236             // XXX float rh = sqrt(r) * fDiff;
    237             // XXX float rs = fDiff;
    238             // XXX
    239             // XXX float rfw = r * pDiff;
    240             // XXX float rhw = sqrt(r) * pDiff;
    241             // XXX
    242             // XXX RF  += rf;
    243             // XXX RH  += rh;
    244             // XXX RS  += rs;
    245             // XXX
    246             // XXX RFW  += rfw;
    247             // XXX RHW  += rhw;
    248435        }
    249436    }
     
    263450    source->moments->Myyyy = YYYY/Sum;
    264451
    265     // *** now calculate the 1st radial moment (for kron flux) -- symmetrical averaging
     452    return true;
     453}
     454
     455bool pmSourceMomentsRadialMoment (pmSource *source, float radius, float minKronRadius, psImageMaskType maskVal) {
     456
    266457
    267458    float **vPix = source->pixels->data.F32;
    268     float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32;
    269459    psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
    270460
     
    272462    float RH = 0.0;
    273463    float RS = 0.0;
     464
     465    // centroid around which to calculate the moments
     466    float Xo = source->moments->Mx;
     467    float Yo = source->moments->My;
     468
     469    // center of mass in subimage.  Note: the calculation below uses pixel index, so we correct
     470    // xCM, yCM from pixel coords to pixel index here.
     471    float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage
     472    float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage
     473
     474    float R2 = PS_SQR(radius);
    274475
    275476    for (psS32 row = 0; row < source->pixels->numRows ; row++) {
     
    304505            if (r2 > R2) continue;
    305506
    306             float fDiff1 = vPix[row][col] - sky;
    307             float fDiff2 = vPix[yFlip][xFlip] - sky;
     507            float fDiff1 = vPix[row][col];
     508            float fDiff2 = vPix[yFlip][xFlip];
    308509            float pDiff = (fDiff1 > 0.0) ? sqrt(fabs(fDiff1*fDiff2)) : -sqrt(fabs(fDiff1*fDiff2));
    309510
     
    329530        kronRefRadius = MIN(radius, kronRefRadius);
    330531    }
    331     source->moments->Mrf = kronRefRadius;
    332 
    333     // *** now calculate the kron flux values using the 1st radial moment
    334 
    335     float radKinner = 1.0*kronRefRadius;
    336     float radKron   = 2.5*kronRefRadius;
    337     float radKouter = 4.0*kronRefRadius;
     532
     533    // if source is externally supplied and it already has a finite Mrf do not change it
     534    if (! ((source->mode & PM_SOURCE_MODE_EXTERNAL) && isfinite(source->moments->Mrf))) {
     535        source->moments->Mrf = kronRefRadius;
     536    }
     537
     538    return true;
     539}
     540
     541bool pmSourceMomentsKronFluxes (pmSource *source, float sigma, float minSN, psImageMaskType maskVal) {
     542
     543    float **vPix = source->pixels->data.F32;
     544    float **vWgt = source->variance ? source->variance->data.F32 : source->pixels->data.F32;
     545    psImageMaskType **vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
     546
     547    float radKinner = 1.0*source->moments->Mrf;
     548    float radKron   = 2.5*source->moments->Mrf;
     549    float radKouter = 4.0*source->moments->Mrf;
    338550
    339551    int nKronPix = 0;
     
    341553    int nInner = 0;
    342554    int nOuter = 0;
    343     Sum = Var = 0.0;
     555   
     556    float Sum = 0.0;
     557    float Var = 0.0;
     558    float SumCore = 0.0;
     559    float VarCore = 0.0;
    344560    float SumInner = 0.0;
    345561    float SumOuter = 0.0;
     562
     563    // centroid around which to calculate the moments
     564    float Xo = source->moments->Mx;
     565    float Yo = source->moments->My;
     566
     567    // center of mass in subimage.  Note: the calculation below uses pixel index, so we correct
     568    // xCM, yCM from pixel coords to pixel index here.
     569    float xCM = Xo - 0.5 - source->pixels->col0; // coord of peak in subimage
     570    float yCM = Yo - 0.5 - source->pixels->row0; // coord of peak in subimage
     571
     572    float minSN2 = PS_SQR(minSN);
    346573
    347574    // calculate the Kron flux, and related fluxes (NO symmetrical averaging)
     
    362589            float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
    363590
    364             float fDiff1 = vPix[row][col] - sky;
     591            float fDiff1 = vPix[row][col];
    365592            float pDiff = fDiff1;
    366593            float wDiff = vWgt[row][col];
     
    376603                Var += wDiff;
    377604                nKronPix ++;
    378                 // if (beVerbose) fprintf (stderr, "mome: %d %d  %f  %f  %f\n", col, row, sky, *vPix, Sum);
    379605            }
    380606
     
    397623    }
    398624    // *** should I rescale these fluxes by pi R^2 / nNpix?
    399     // XXX source->moments->KronCore    = SumCore       * M_PI * PS_SQR(sigma) / nCorePix;
    400     // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI * PS_SQR(sigma) / nCorePix;
    401     // XXX source->moments->KronFlux    = Sum       * M_PI * PS_SQR(radKron) / nKronPix;
    402     // XXX source->moments->KronFluxErr = sqrt(Var) * M_PI * PS_SQR(radKron) / nKronPix;
    403     // XXX source->moments->KronFinner = SumInner * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
    404     // XXX source->moments->KronFouter = SumOuter * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
     625    // XXX source->moments->KronCore    = SumCore       * M_PI *  PS_SQR(sigma) / nCorePix;
     626    // XXX source->moments->KronCoreErr = sqrt(VarCore) * M_PI *  PS_SQR(sigma) / nCorePix;
     627    // XXX source->moments->KronFlux    = Sum           * M_PI * PS_SQR(radKron) / nKronPix;
     628    // XXX source->moments->KronFluxErr = sqrt(Var)     * M_PI * PS_SQR(radKron) / nKronPix;
     629    // XXX source->moments->KronFinner  = SumInner      * M_PI * (PS_SQR(radKron)   - PS_SQR(radKinner)) / nInner;
     630    // XXX source->moments->KronFouter  = SumOuter      * M_PI * (PS_SQR(radKouter) -   PS_SQR(radKron)) / nOuter;
    405631
    406632    source->moments->KronCore    = SumCore;
     
    408634    source->moments->KronFlux    = Sum;
    409635    source->moments->KronFluxErr = sqrt(Var);
    410     source->moments->KronFinner = SumInner;
    411     source->moments->KronFouter = SumOuter;
     636    source->moments->KronFinner  = SumInner;
     637    source->moments->KronFouter  = SumOuter;
    412638
    413639    // XXX not sure I should save this here...
     
    416642    source->moments->KronRadiusPSF  = source->moments->Mrf;
    417643
    418     psTrace ("psModules.objects", 4, "Mrf: %f  KronFlux: %f  Mxx: %f  Mxy: %f  Myy: %f  Mxxx: %f  Mxxy: %f  Mxyy: %f  Myyy: %f  Mxxxx: %f  Mxxxy: %f  Mxxyy: %f  Mxyyy: %f  Mxyyy: %f\n",
    419              source->moments->Mrf,   source->moments->KronFlux,
    420              source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy,
    421              source->moments->Mxxx,  source->moments->Mxxy,  source->moments->Mxyy,  source->moments->Myyy,
    422              source->moments->Mxxxx, source->moments->Mxxxy, source->moments->Mxxyy, source->moments->Mxyyy, source->moments->Myyyy);
    423 
    424     psTrace ("psModules.objects", 3, "peak %f %f (%f = %f) Mx: %f  My: %f  Sum: %f  Mxx: %f  Mxy: %f  Myy: %f  sky: %f  Npix: %d\n",
    425              source->peak->xf, source->peak->yf, source->peak->rawFlux, sqrt(source->peak->detValue), source->moments->Mx,   source->moments->My, Sum, source->moments->Mxx,   source->moments->Mxy,   source->moments->Myy, sky, source->moments->nPixels);
    426 
    427     return(true);
    428 }
    429 
    430 bool pmSourceMomentsGetCentroid(pmSource *source, float radius, float sigma, float minSN, psImageMaskType maskVal, float xGuess, float yGuess) {
    431 
    432     // First Pass: calculate the first moments (these are subtracted from the coordinates below)
    433     // Sum = SUM (z - sky)
    434     // X1  = SUM (x - xc)*(z - sky)
    435     // .. etc
    436 
    437     float sky = 0.0;
    438 
    439     float peakPixel = -PS_MAX_F32;
    440     psS32 numPixels = 0;
    441     float Sum = 0.0;
    442     float Var = 0.0;
    443     float X1 = 0.0;
    444     float Y1 = 0.0;
    445     float R2 = PS_SQR(radius);
    446     float minSN2 = PS_SQR(minSN);
    447     float rsigma2 = 0.5 / PS_SQR(sigma);
    448 
    449     float xPeak = xGuess - source->pixels->col0; // coord of peak in subimage
    450     float yPeak = yGuess - source->pixels->row0; // coord of peak in subimage
    451 
    452     // we are guaranteed to have a valid pixel and variance at this location (right? right?)
    453     // float weightNorm = source->pixels->data.F32[yPeak][xPeak] / sqrt (source->variance->data.F32[yPeak][xPeak]);
    454     // psAssert (isfinite(source->pixels->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    455     // psAssert (isfinite(source->variance->data.F32[yPeak][xPeak]), "peak must be on valid pixel");
    456     // psAssert (source->variance->data.F32[yPeak][xPeak] > 0, "peak must be on valid pixel");
    457 
    458     // the moments [Sum(x*f) / Sum(f)] are calculated in pixel index values, and should
    459     // not depend on the fractional pixel location of the source.  However, the aperture
    460     // (radius) and the Gaussian window (sigma) depend subtly on the fractional pixel
    461     // position of the expected centroid
    462 
    463     for (psS32 row = 0; row < source->pixels->numRows ; row++) {
    464 
    465         float yDiff = row + 0.5 - yPeak;
    466         if (fabs(yDiff) > radius) continue;
    467 
    468         float *vPix = source->pixels->data.F32[row];
    469         float *vWgt = source->variance ? source->variance->data.F32[row] : source->pixels->data.F32[row];
    470 
    471         psImageMaskType *vMsk = (source->maskObj == NULL) ? NULL : source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[row];
    472         // psImageMaskType *vMsk = (source->maskView == NULL) ? NULL : source->maskView->data.PS_TYPE_IMAGE_MASK_DATA[row];
    473 
    474         for (psS32 col = 0; col < source->pixels->numCols ; col++, vPix++, vWgt++) {
    475             if (vMsk) {
    476                 if (*vMsk & maskVal) {
    477                     vMsk++;
    478                     continue;
    479                 }
    480                 vMsk++;
    481             }
    482             if (isnan(*vPix)) continue;
    483 
    484             float xDiff = col + 0.5 - xPeak;
    485             if (fabs(xDiff) > radius) continue;
    486 
    487             // radius is just a function of (xDiff, yDiff)
    488             float r2  = PS_SQR(xDiff) + PS_SQR(yDiff);
    489             if (r2 > R2) continue;
    490 
    491             float pDiff = *vPix - sky;
    492             float wDiff = *vWgt;
    493 
    494             // skip pixels below specified significance level.  for a PSFs, this
    495             // over-weights the wings of bright stars compared to those of faint stars.
    496             // for the estimator used for extended source analysis (where the window
    497             // function is allowed to be arbitrarily large), we need to clip to avoid
    498             // negative second moments.
    499             if (PS_SQR(pDiff) < minSN2*wDiff) continue; //
    500             if ((minSN > 0.0) && (pDiff < 0)) continue; //
    501 
    502             // Apply a Gaussian window function.  Be careful with the window function.  S/N
    503             // weighting over weights the sky for faint sources
    504             if (sigma > 0.0) {
    505                 float z  = r2*rsigma2;
    506                 assert (z >= 0.0);
    507                 float weight  = exp(-z);
    508 
    509                 wDiff *= weight;
    510                 pDiff *= weight;
    511             }
    512 
    513             Var += wDiff;
    514             Sum += pDiff;
    515 
    516             float xWght = xDiff * pDiff;
    517             float yWght = yDiff * pDiff;
    518 
    519             X1  += xWght;
    520             Y1  += yWght;
    521 
    522             peakPixel = PS_MAX (*vPix, peakPixel);
    523             numPixels++;
    524         }
    525     }
    526 
    527     // if we have less than (1/4) of the possible pixels (in circle or box), force a retry
    528     int minPixels = PS_MIN(0.75*R2, source->pixels->numCols*source->pixels->numRows/4.0);
    529 
    530     // XXX EAM - the limit is a bit arbitrary.  make it user defined?
    531     if ((numPixels < minPixels) || (Sum <= 0)) {
    532         psTrace ("psModules.objects", 3, "insufficient valid pixels (%d vs %d; %f) for source\n", numPixels, minPixels, Sum);
    533         return (false);
    534     }
    535 
    536     // calculate the first moment.
    537     float Mx = X1/Sum;
    538     float My = Y1/Sum;
    539     if ((fabs(Mx) > radius) || (fabs(My) > radius)) {
    540         psTrace ("psModules.objects", 3, "extreme centroid swing; invalid peak %d, %d\n", source->peak->x, source->peak->y);
    541         return (false);
    542     }
    543     if ((fabs(Mx) > 2.0) || (fabs(My) > 2.0)) {
    544         psTrace ("psModules.objects", 3, " big centroid swing; ok peak? %d, %d\n", source->peak->x, source->peak->y);
    545     }
    546 
    547     psTrace ("psModules.objects", 5, "id: %d, sky: %f  Mx: %f  My: %f  Sum: %f  X1: %f  Y1: %f  Npix: %d\n", source->id, sky, Mx, My, Sum, X1, Y1, numPixels);
    548 
    549     // add back offset of peak in primary image
    550     // also offset from pixel index to pixel coordinate
    551     // (the calculation above uses pixel index instead of coordinate)
    552     // 0.5 PIX: moments are calculated using the pixel index and converted here to pixel coords
    553 
    554     // we only update the centroid if the position is not supplied from elsewhere
    555     bool skipCentroid = false;
    556     skipCentroid |= (source->mode  & PM_SOURCE_MODE_EXTERNAL); // skip externally supplied positions
    557     skipCentroid |= (source->mode2 & PM_SOURCE_MODE2_MATCHED); // skip sources defined by other image positions
    558 
    559     if (skipCentroid) {
    560         source->moments->Mx = source->peak->xf;
    561         source->moments->My = source->peak->yf;
    562     } else {
    563         source->moments->Mx = Mx + xGuess;
    564         source->moments->My = My + yGuess;
    565     }
    566 
    567     source->moments->Sum = Sum;
    568     source->moments->SN  = Sum / sqrt(Var);
    569     source->moments->Peak = peakPixel;
    570     source->moments->nPixels = numPixels;
    571 
    572644    return true;
    573645}
    574 
    575 float pmSourceMinKronRadius(psArray *sources, float PSF_SN_LIM) {
    576 
    577     psVector *radii = psVectorAllocEmpty(100, PS_TYPE_F32);
    578 
    579     for (int i = 0; i < sources->n; i++) {
    580         pmSource *src = sources->data[i]; // Source of interest
    581         if (!src || !src->moments) {
    582             continue;
    583         }
    584 
    585         if (src->mode & PM_SOURCE_MODE_BLEND) {
    586             continue;
    587         }
    588 
    589         if (!src->moments->nPixels) continue;
    590 
    591         if (src->moments->SN < PSF_SN_LIM) continue;
    592 
    593         // XXX put in Mxx,Myy cut based on clump location
    594 
    595         psVectorAppend(radii, src->moments->Mrf);
    596     }
    597 
    598     // find the peak in this image
    599     psStats *stats = psStatsAlloc (PS_STAT_SAMPLE_MEDIAN);
    600 
    601     if (!psVectorStats (stats, radii, NULL, NULL, 0)) {
    602         psError(PS_ERR_UNKNOWN, false, "Unable to get image statistics.\n");
    603         psFree(stats);
    604         return NAN;
    605     }
    606 
    607     float minRadius = stats->sampleMedian;
    608 
    609     psFree(radii);
    610     psFree(stats);
    611     return minRadius;
    612 }
    613 
  • trunk/psModules/src/objects/pmSourcePhotometry.c

    r34498 r36375  
    113113    source->apFluxErr = NAN;
    114114
     115    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     116    badModel |= PM_MODEL_STATUS_BADARGS;
     117    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     118    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     119    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     120    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     121    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     122
    115123    // XXXXXX review:
    116124    // Select the 'best' model -- this is used for PSF_QF,_PERFECT & ???. isPSF is true if this
     
    162170        for (int i = 0; i < source->modelFits->n; i++) {
    163171            pmModel *model = source->modelFits->data[i];
    164             if (model->flags & PM_MODEL_STATUS_BADARGS) continue;
     172            if (model->flags & badModel) continue;
    165173            status = pmSourcePhotometryModel (&model->mag, NULL, model);
    166174            if (model == source->modelEXT) foundEXT = true;
     
    902910}
    903911
     912bool pmSourceChisqModelFlux (pmSource *source, pmModel *model, psImageMaskType maskVal)
     913{
     914    PS_ASSERT_PTR_NON_NULL(source, false);
     915    PS_ASSERT_PTR_NON_NULL(model, false);
     916
     917    float dC = 0.0;
     918    int Npix = 0;
     919
     920    psVector *params = model->params;
     921    psImage  *image = source->pixels;
     922    psImage  *modelFlux = source->modelFlux;
     923    psImage  *mask = source->maskObj;
     924    psImage  *variance = source->variance;
     925
     926    float Io = params->data.F32[PM_PAR_I0];
     927
     928    for (int iy = 0; iy < image->numRows; iy++) {
     929        for (int ix = 0; ix < image->numCols; ix++) {
     930
     931            // skip pixels which are masked
     932            if (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] & maskVal) continue;
     933
     934            if (variance->data.F32[iy][ix] <= 0) continue;
     935
     936            dC += PS_SQR (image->data.F32[iy][ix] - Io*modelFlux->data.F32[iy][ix]) / variance->data.F32[iy][ix];
     937            Npix ++;
     938        }
     939    }
     940    model->nPix = Npix;
     941    model->nDOF = Npix - model->nPar;
     942    model->chisq = dC;
     943    model->chisqNorm = dC / model->nDOF;
     944
     945    return (true);
     946}
     947
    904948double pmSourceModelWeight(const pmSource *Mi, int term, const pmSourceFitVarMode fitVarMode, const float covarFactor, psImageMaskType maskVal)
    905949{
  • trunk/psphot

  • trunk/psphot/src

  • trunk/psphot/src/Makefile.am

    r34317 r36375  
    2525libpsphot_la_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    2626
    27 bin_PROGRAMS = psphot psphotForced psphotMinimal psphotMakePSF psphotStack psphotModelTest
     27bin_PROGRAMS = psphot psphotForced psphotFullForce psphotMinimal psphotMakePSF psphotStack psphotModelTest psmakecff
    2828# bin_PROGRAMS = psphotPetrosianStudy psphotTest psphotMomentsStudy
    2929
     
    3636psphotForced_LDADD = libpsphot.la
    3737
     38psphotFullForce_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     39psphotFullForce_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     40psphotFullForce_LDADD = libpsphot.la
     41
    3842psphotMinimal_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
    3943psphotMinimal_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     
    5155psphotModelTest_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
    5256psphotModelTest_LDADD = libpsphot.la
     57
     58psmakecff_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     59psmakecff_LDFLAGS = $(PSPHOT_LIBS) $(PSMODULE_LIBS) $(PSLIB_LIBS)
     60psmakecff_LDADD = libpsphot.la
     61
    5362
    5463# psphotMomentsStudy_CFLAGS = $(PSPHOT_CFLAGS) $(PSMODULE_CFLAGS) $(PSLIB_CFLAGS)
     
    7786        psphotForced.c             \
    7887        psphotForcedArguments.c    \
     88        psphotParseCamera.c        \
     89        psphotImageLoop.c          \
     90        psphotMosaicChip.c         \
     91        psphotCleanup.c
     92
     93# generalized forced photometry (including Kron, Petro, and Models) of specified positions given a specified psf
     94psphotFullForce_SOURCES = \
     95        psphotFullForce.c             \
     96        psphotFullForceArguments.c    \
    7997        psphotParseCamera.c        \
    8098        psphotImageLoop.c          \
     
    129147        psphotCleanup.c
    130148
     149# a program that takes a cmf file and makes a cff file (input file for psphotFullForce
     150psmakecff_SOURCES = \
     151        psmakecff.c
     152
    131153# psphotTest_SOURCES = \
    132154#         psphotTest.c
     
    155177        psphotReadoutMinimal.c         \
    156178        psphotForcedReadout.c          \
     179        psphotFullForceReadout.c       \
     180        psphotFullForce.SourceStats.c \
    157181        psphotMakePSFReadout.c         \
    158182        psphotModelBackground.c        \
     
    181205        psphotSourceFits.c             \
    182206        psphotRadiusChecks.c           \
     207        psphotChooseAnalysisOptions.c  \
    183208        psphotOutput.c                 \
    184209        psphotFakeSources.c            \
     
    198223        psphotRadialPlot.c             \
    199224        psphotKronIterate.c            \
     225        psphotKronFlux.c            \
     226        psphotPetroFlux.c            \
     227        psphotGalaxyShape.c            \
    200228        psphotRadialProfileWings.c     \
    201229        psphotDeblendSatstars.c        \
  • trunk/psphot/src/psphot.h

    r36117 r36375  
    1818    PSPHOT_SINGLE,
    1919    PSPHOT_FORCED,
     20    PSPHOT_FULL_FORCE,
    2021    PSPHOT_MAKE_PSF,
    2122    PSPHOT_MODEL_TEST,
     
    8182bool            psphotSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool setWindow);
    8283
     84bool            psphotFullForceSourceStats (pmConfig *config, const pmFPAview *view, const char *filerule, bool setWindow);
     85bool            psphotFullForceSourceStatsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool setWindow);
     86
    8387bool            psphotDeblendSatstars (pmConfig *config, const pmFPAview *view, const char *filerule);
    8488bool            psphotDeblendSatstarsReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     
    121125bool            psphotAddOrSubNoiseReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe, bool add);
    122126bool            psphotAddOrSubNoise_Threaded (psThreadJob *job);
     127
     128bool            psphotChooseAnalysisOptions (pmConfig *config, const pmFPAview *view, const char *filerule);
     129bool            psphotChooseAnalysisOptionsReadout(pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe);
     130bool            psphotChooseAnalysisOptionsByObject(pmConfig *config, const pmFPAview *view, const char *filerule, psArray *objects);
    123131
    124132bool            psphotExtendedSourceAnalysis (pmConfig *config, const pmFPAview *view, const char *filerule);
     
    341349bool psphotForcedReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
    342350
     351pmConfig *psphotFullForceArguments(int argc, char **argv);
     352bool psphotFullForceReadout(pmConfig *config, const pmFPAview *view, const char *filerule);
     353
    343354pmConfig *psphotMinimalArguments(int argc, char **argv);
    344355bool psphotReadoutMinimal(pmConfig *config, const pmFPAview *view, const char *filerule);
     
    414425} psphotStackOptions;
    415426
     427typedef struct {
     428    float fRmajorMin;
     429    float fRmajorMax;
     430    float fRmajorDel;
     431    float fRminorMin;
     432    float fRminorMax;
     433    float fRminorDel;
     434} psphotGalaxyShapeOptions;
     435
    416436/*** psphotStackMatchPSF prototypes ***/
    417437bool psphotStackMatchPSFs (pmConfig *config, const pmFPAview *view);
     
    497517bool psphotKronIterate_Threaded (psThreadJob *job);
    498518
     519bool psphotKronFlux (pmConfig *config, const pmFPAview *view, const char *filerule);
     520bool psphotKronFluxReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char *filerule, pmReadout *readout, psArray *sources);
     521bool psphotKronFlux_Threaded (psThreadJob *job);
     522bool psphotKronFluxSource (pmSource *source, psImageMaskType maskVal);
     523
     524bool psphotPetroFlux (pmConfig *config, const pmFPAview *view, const char *filerule);
     525bool psphotPetroFluxReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char * filerule, pmReadout *readout, psArray *sources);
     526bool psphotPetroFlux_Threaded (psThreadJob *job);
     527bool psphotPetroFluxSource (pmSource *source, psImageMaskType maskVal);
     528
     529bool psphotGalaxyShape (pmConfig *config, const pmFPAview *view, const char *filerule);
     530bool psphotGalaxyShapeReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, const char * filerule, pmReadout *readout, psArray *sources, pmPSF *psf);
     531bool psphotGalaxyShape_Threaded (psThreadJob *job);
     532bool psphotGalaxyShapeGrid (pmSource *source, pmSourceFitOptions *fitOptions, psphotGalaxyShapeOptions *opt, psImageMaskType maskVal, int psfSize);
     533bool psphotGalaxyShapeSource (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, int psfSize, bool saveResults);
     534psphotGalaxyShapeOptions *psphotGalaxyShapeOptionsAlloc();
     535
    499536bool psphotRadialProfileWings (pmConfig *config, const pmFPAview *view, const char *filerule);
    500537bool psphotRadialProfileWingsReadout(pmConfig *config, psMetadata *recipe, const pmFPAview *view, pmReadout *readout, psArray *sources);
  • trunk/psphot/src/psphotArguments.c

    r33690 r36375  
    217217    pmConfigFileSetsMD (config->arguments, &argc, argv, "PSPHOT.PSF", "-psf",      "-psflist");
    218218    pmConfigFileSetsMD (config->arguments, &argc, argv, "SRC",        "-src",      "-srclist");
     219    // XXX allow this format? pmConfigFileSetsMD (config->arguments, &argc, argv, "FORCE",      "-force",    "-forcelist");
    219220    pmConfigFileSetsMD (config->arguments, &argc, argv, "EXPNUM",     "-expnum",   "-expnumlist");
    220221
  • trunk/psphot/src/psphotBlendFit.c

    r36096 r36375  
    274274
    275275# if (PS_TRACE_ON)
    276         int TEST_ON = false;
    277276# define TEST_X 653
    278277# define TEST_Y 466
    279         if ((fabs(source->peak->xf - TEST_X) < 5) && (fabs(source->peak->yf - TEST_Y) < 5)) {
     278# define TESTING 1
     279        int TEST_ON = false;
     280        if (TESTING && (fabs(source->peak->xf - TEST_X) < 5) && (fabs(source->peak->yf - TEST_Y) < 5)) {
    280281            fprintf (stderr, "test object\n");
    281282            psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
  • trunk/psphot/src/psphotDefineFiles.c

    r34528 r36375  
    150150    }
    151151
     152    if (psMetadataLookupPtr(NULL, config->arguments, "FORCE")) {
     153        if (!pmFPAfileDefineFromArgs (&status, config, "PSPHOT.INPUT.CFF", "FORCE")) {
     154            psError(PSPHOT_ERR_CONFIG, false, "Failed to find/build PSPHOT.INPUT.CFF");
     155            return status;
     156        }
     157    }
     158
    152159    if (psMetadataLookupPtr(NULL, config->arguments, "SRCTEXT")) {
    153160        // XXX cannot use pmFPAfileDefineFromArgs: this is explicitly a FITS-based I/O function
  • trunk/psphot/src/psphotEllipticalContour.c

    r32348 r36375  
    6464        psFree (y);
    6565        psFree (yErr);
     66        source->mode2 |= PM_SOURCE_MODE2_ECONTOUR_FEW_PTS;
    6667        return false;
    6768    }
  • trunk/psphot/src/psphotExtendedSourceAnalysis.c

    r34404 r36375  
    11# include "psphotInternal.h"
    2 
    3 // measure the elliptical radial profile and use this to measure the petrosian parameters for the sources
     2void psphotRadialProfileShowSkips ();
     3
     4// measure the petrosian parameters for the sources
    45
    56// for now, let's store the detections on the readout->analysis for each readout
     
    1516    psAssert (recipe, "missing recipe?");
    1617
    17     // perform full non-linear fits / extended source analysis?
    18     if (!psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANALYSIS")) {
     18    bool doPetrosian = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
     19    bool doAnnuli    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
     20
     21    // measure petrosians?
     22    if (!doPetrosian && !doAnnuli) {
    1923        psLogMsg ("psphot", PS_LOG_INFO, "skipping extended source measurements\n");
    2024        return true;
     
    3337}
    3438
     39/*** for the moment, this test code : it is not thread safe ***/
     40int    Nall = 0;
     41int  Nskip1 = 0;
     42int  Nskip2 = 0;
     43int  Nskip3 = 0;
     44int  Nskip4 = 0;
     45int  Nskip5 = 0;
     46int  Nskip6 = 0;
     47
     48# define SKIP(VALUE) { VALUE++; continue; }
     49
    3550// aperture-like measurements for extended sources
    3651bool psphotExtendedSourceAnalysisReadout (pmConfig *config, const pmFPAview *view, const char *filerule, int index, psMetadata *recipe) {
     
    110125
    111126// set this to 0 to run without threading
    112 # if (1)           
     127# if (0)           
    113128            if (!psThreadJobAddPending(job)) {
    114129                psError(PS_ERR_UNKNOWN, false, "Unable to guess model.");
     
    164179    psLogMsg ("psphot", PS_LOG_INFO, "  %d annuli\n", Nannuli);
    165180
     181# if (PS_TRACE_ON)
     182    fprintf (stderr, "ext analysis skipped @ 1  : %d\n", Nskip1);
     183    fprintf (stderr, "ext analysis skipped @ 2  : %d\n", Nskip2);
     184    fprintf (stderr, "ext analysis skipped @ 3  : %d\n", Nskip3);
     185    fprintf (stderr, "ext analysis skipped @ 4  : %d\n", Nskip4);
     186    fprintf (stderr, "ext analysis skipped @ 5  : %d\n", Nskip5);
     187    fprintf (stderr, "ext analysis skipped @ 6  : %d\n", Nskip6);
     188#endif
     189
     190    psphotRadialProfileShowSkips ();
     191
    166192    psphotVisualShowResidualImage (readout, false);
    167193
    168     bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
    169     if (doPetrosian) {
    170         psphotVisualShowPetrosians (sources);
    171     }
     194    psphotVisualShowPetrosians (sources);
    172195
    173196    return true;
     
    190213    float skynoise          = PS_SCALAR_VALUE(job->args->data[4],F32);
    191214
    192     // S/N limit to perform full non-linear fits
    193     float SN_LIM = psMetadataLookupF32 (&status, recipe, "EXTENDED_SOURCE_SN_LIM");
    194 
    195     // which extended source analyses should we perform?
    196215    bool doPetrosian    = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_PETROSIAN");
    197     bool doAnnuli       = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_ANNULI");
    198     bool doPetroStars   = psMetadataLookupBool (&status, recipe, "PETROSIAN_FOR_STARS");
    199216
    200217    // user-defined masks to test for good/bad pixels (build from recipe list if not yet set)
     
    207224        pmSource *source = sources->data[i];
    208225
    209         // if we have checked the source validity on the basis of the object set, then
    210         // we either skip these tests below or we skip the source completely
    211         if (source->tmpFlags & PM_SOURCE_TMPF_PETRO_SKIP) continue;
    212         if (source->tmpFlags & PM_SOURCE_TMPF_PETRO_KEEP) goto keepSource;
    213 
    214         // skip PSF-like and non-astronomical objects
    215         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    216         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    217         if (source->mode & PM_SOURCE_MODE_DEFECT) continue;
    218         if (source->mode & PM_SOURCE_MODE_SATSTAR) continue;
    219 
    220         // skip saturated stars modeled with a radial profile
    221         if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue;
    222 
    223         // optionally allow non-extended objects to get petrosians as well
    224         if (!doPetroStars) {
    225             if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue;
    226             if (source->type == PM_SOURCE_TYPE_STAR) continue;
    227         }
    228 
    229         // limit selection to some SN limit
    230         // assert (source->peak); // how can a source not have a peak?
    231         // limit selection to some SN limit
    232         bool skipSource = false;
    233         if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    234             skipSource = (source->moments->KronFlux < SN_LIM * source->moments->KronFluxErr);
    235         } else {
    236             skipSource = (sqrt(source->peak->detValue) < SN_LIM);
    237         }
    238         if (skipSource) continue;
    239 
    240         // limit selection by analysis region (this automatically apply
    241         if (source->peak->x < region->x0) continue;
    242         if (source->peak->y < region->y0) continue;
    243         if (source->peak->x > region->x1) continue;
    244         if (source->peak->y > region->y1) continue;
    245 
    246     keepSource:
     226        Nall ++;
     227
     228        // rules for measuring petrosian parameters for specific objects are set in
     229        // psphotChooseAnalysisOptions.c
     230        if (!(source->tmpFlags & PM_SOURCE_TMPF_PETRO)) SKIP (Nskip1);
     231
     232        // limit selection by analysis region (XXX move this into psphotChooseAnalysisOption?)
     233        if (source->peak->x < region->x0) SKIP (Nskip2);
     234        if (source->peak->y < region->y0) SKIP (Nskip3);
     235        if (source->peak->x > region->x1) SKIP (Nskip4);
     236        if (source->peak->y > region->y1) SKIP (Nskip5);
    247237
    248238        // replace object in image
     
    259249        pmSourceRedefinePixels (source, readout, source->peak->xf, source->peak->yf, 1.5*radius);
    260250
    261         // if we request any of these measurements, we require the radial profile
    262         if (doPetrosian || doAnnuli) {
    263             if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) {
    264                 // all measurements below require the radial profile; skip them all
    265                 // re-subtract the object, leave local sky
    266                 psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    267                 pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    268                 continue;
    269             }
    270             Nannuli ++;
    271             source->mode |= PM_SOURCE_MODE_RADIAL_FLUX;
    272         }
     251        // measure the radial profile
     252        if (!psphotRadialProfile (source, recipe, skynoise, maskVal)) {
     253          // re-subtract the object, leave local sky
     254          psTrace ("psphot", 5, "failed to extract radial profile for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     255          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     256          SKIP (Nskip6);
     257        }
     258
     259        Nannuli ++;
     260        source->mode |= PM_SOURCE_MODE_RADIAL_FLUX;
    273261
    274262        // Petrosian Mags
    275263        if (doPetrosian) {
    276             if (!psphotPetrosian (source, recipe, skynoise, maskVal)) {
    277                 psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    278             } else {
    279                 psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    280                 Npetro ++;
    281                 source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
    282             }
     264          if (!psphotPetrosian (source, recipe, skynoise, maskVal)) {
     265            psTrace ("psphot", 5, "FAILED petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     266          } else {
     267            psTrace ("psphot", 5, "measured petrosian flux & radius for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
     268            Npetro ++;
     269            source->mode |= PM_SOURCE_MODE_EXTENDED_STATS;
     270          }
    283271        }
    284272
  • trunk/psphot/src/psphotExtendedSourceFits.c

    r36108 r36375  
    6565    psphotVisualShowImage(readout);
    6666
    67     // psphotSaveImage (NULL, readout->image, "test.01.fits");
    68 
    6967    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    7068    psAssert (detections, "missing detections?");
     
    111109    if (!status || !isfinite(fitMaxTol) || fitMaxTol <= 0) {
    112110        fitMaxTol = 1.0;
     111    }
     112
     113    float fitNsigmaConv = psMetadataLookupF32 (&status, recipe, "EXT_FIT_NSIGMA_CONV"); // number of sigma for the convolution
     114    if (!status || !isfinite(fitNsigmaConv) || fitNsigmaConv <= 0) {
     115        fitNsigmaConv = 5.0;
    113116    }
    114117
     
    137140    fitOptions->minTol         = fitMinTol;
    138141    fitOptions->maxTol         = fitMaxTol;
     142    fitOptions->nsigma         = fitNsigmaConv;
    139143
    140144    fitOptions->gainFactorMode   = gainFactorMode;
    141145    fitOptions->chisqConvergence = chisqConvergence;
    142146    fitOptions->isInteractive    = isInteractive;
     147
     148    // use poissonian errors or local-sky errors
     149    fitOptions->poissonErrors = psMetadataLookupBool (&status, recipe, "EXTENDED_SOURCE_FITS_POISSON");
     150    if (!status) fitOptions->poissonErrors = true;
    143151
    144152    // maskVal is used to test for rejected pixels, and must include markVal
     
    285293            psArrayAdd(job->args, 1, cells->data[j]); // sources
    286294            psArrayAdd(job->args, 1, models);
     295
    287296            // Allocate a metadata iterator here because psMetadataIteratorAlloc/Free are not thread safe
    288297            psMetadataIterator *iter = psMetadataIteratorAlloc (models, PS_LIST_HEAD, NULL);
     
    386395    psphotSersicModelClassCleanup();
    387396
    388     // psphotSaveImage (NULL, readout->image, "test.02.fits");
    389 
    390397    psphotVisualShowResidualImage (readout, false);
    391398
     
    428435    // psTraceSetLevel ("psLib.math.psMinimizeLMChi2_Alt", 5);
    429436
     437    pmModelStatus badModel = PM_MODEL_STATUS_NONE;
     438    badModel |= PM_MODEL_STATUS_BADARGS;
     439    badModel |= PM_MODEL_STATUS_OFFIMAGE;
     440    badModel |= PM_MODEL_STATUS_NAN_CHISQ;
     441    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
     442    badModel |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
     443    badModel |= PM_MODEL_PCM_FAIL_GUESS;
     444
    430445    // choose the sources of interest
    431446    for (int i = 0; i < sources->n; i++) {
     
    433448        pmSource *source = sources->data[i];
    434449
    435         // skip PSF-like and non-astronomical objects
    436         if (!(source->mode & PM_SOURCE_MODE_EXT_LIMIT)) continue;
    437         if (source->type == PM_SOURCE_TYPE_DEFECT) continue;
    438         if (source->type == PM_SOURCE_TYPE_SATURATED) continue;
    439 
    440         // skip saturated stars modeled with a radial profile
    441         if (source->mode2 & PM_SOURCE_MODE2_SATSTAR_PROFILE) continue;
    442 
    443         // XXX this should use peak?
     450        // rules for measuring petrosian parameters for specific objects are set in
     451        // psphotChooseAnalysisOptions.c
     452        if (!(source->tmpFlags & PM_SOURCE_TMPF_EXT_FIT)) continue;
     453
     454        // limit selection by analysis region (XXX move this into psphotChooseAnalysisOption?)
    444455        if (source->peak->x < region->x0) continue;
    445456        if (source->peak->y < region->y0) continue;
    446457        if (source->peak->x > region->x1) continue;
    447458        if (source->peak->y > region->y1) continue;
    448 
    449 
    450         // XXX for a test, just do the obvious trail
    451         // XXX if (source->peak->xf < 1100) continue;
    452         // XXX if (source->peak->xf > 1400) continue;
    453         // XXX if (source->peak->yf >  245) continue;
    454459
    455460        // replace object in image
     
    462467        psphotSetRadiusMomentsExact(&fitRadius, &windowRadius, readout, source, markVal); // NOTE : 6 allocs
    463468
    464         // XXX WATCH OUT HERE!!
    465         // fitRadius = 30;
    466 
    467469        // UPDATE : we have changed the moments calculation.  There is now an iteration within
    468470        // psphotKronMasked to determine moments appropriate for a larger object.  The values
     
    475477        }
    476478
     479# ifdef TEST_OBJECT
    477480        bool testObject = false;
    478         // testObject |= ((fabs(source->peak->xf -  179) < 5) && (fabs(source->peak->yf - 1138) < 5));
    479         // testObject |= ((fabs(source->peak->xf - 5047) < 5) && (fabs(source->peak->yf -  151) < 5));
    480         // testObject |= ((fabs(source->peak->xf - 3929) < 5) && (fabs(source->peak->yf - 4109) < 5));
    481         // testObject |= ((fabs(source->peak->xf -  915) < 5) && (fabs(source->peak->yf - 5998) < 5));
    482         // testObject |= ((fabs(source->peak->xf - 5406) < 5) && (fabs(source->peak->yf -  326) < 5));
     481        testObject |= ((fabs(source->peak->xf -  179) < 5) && (fabs(source->peak->yf - 1138) < 5));
    483482        if (testObject) {
    484483            fprintf (stderr, "test object @ %f, %f\n", source->peak->xf, source->peak->yf);
     
    486485            psTraceSetLevel ("psphot.psphotExtendedSourceFits_Threaded", 5);
    487486        }
     487# endif
    488488
    489489        // loop here over the models chosen for each source (exclude by S/N)
     
    501501          assert (status);
    502502
    503           // limit selection to some SN limit
    504           bool skipSource = false;
    505           if (source->mode & PM_SOURCE_MODE_EXT_LIMIT) {
    506               skipSource = (source->moments->KronFlux < FIT_SN_LIM * source->moments->KronFluxErr);
    507           } else {
    508               skipSource = (sqrt(source->peak->detValue) < FIT_SN_LIM);
    509           }
    510           if (skipSource) {
     503          // limit selection to some SN limit for specific models (this value only applies if > EXTENDED_SOURCE_SN_LIM)
     504          if (isfinite(FIT_SN_LIM)) {
     505            if (source->moments->KronFlux < FIT_SN_LIM * source->moments->KronFluxErr) {
    511506              Nfaint ++;
    512507              continue;
     508            }
    513509          }
     510
     511          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_RUN;
    514512
    515513          // check on the model type
     
    529527                  psTrace ("psphot", 5, "failed to fit psf-conv model for object at %f, %f", source->moments->Mx, source->moments->My);
    530528                  Nfail ++;
     529                  source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_FAIL;
    531530                  continue;
    532531              }
     
    534533                       source->moments->Mx, source->moments->My, pmModelClassGetName (modelFit->type), modelFit->chisq, modelFit->nPix, modelFit->nIter);
    535534              Nconvolve ++;
    536               if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
     535              if (!(modelFit->flags & badModel)) {
    537536                  NconvolvePass ++;
    538537                  source->mode |= PM_SOURCE_MODE_EXTENDED_FIT;
     
    548547                      Nfail ++;
    549548                      doneFits = true;
     549                      source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_FAIL;
    550550                      continue;
    551551                  }
    552552                  psTrace ("psphot", 4, "fit plain model for %f, %f : %s chisq = %f (npix: %d, niter: %d)\n", source->moments->Mx, source->moments->My, pmModelClassGetName (modelFit->type), modelFit->chisq, modelFit->nPix, modelFit->nIter);
    553553                  Nplain ++;
    554                   if (!(modelFit->flags & (PM_MODEL_STATUS_BADARGS | PM_MODEL_STATUS_NONCONVERGE | PM_MODEL_STATUS_OFFIMAGE))) {
     554                  if (!(modelFit->flags & badModel)) {
    555555                      NplainPass ++;
    556556                      source->mode |= PM_SOURCE_MODE_EXTENDED_FIT;
     
    576576                          fprintf (stderr, "update window : %f %f : %f -> %f\n", source->peak->xf, source->peak->yf, fitRadius, 2*fitRadius);
    577577                          psphotSetWindowTrail (&fitRadius, &windowRadius, readout, source, markVal, fitRadius*2.0);
     578                          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_RETRY;
    578579                      }
    579580                  }
    580581              }
    581582          }
    582           // XXX really need to do this in a cleaner way:
    583           if (!modelFit) continue;
     583          psAssert (modelFit, "modelFit not set?");
    584584
    585585          // test for fit quality / result
     
    590590        }
    591591
     592        // we are allowed to fit both stars and non-stars here -- if we have fitted
     593        // something which we think is a star, we should use that model to subtract the
     594        // object from the image.
     595        if (source->type == PM_SOURCE_TYPE_STAR) {
     596          // ensure the modelPSF is cached
     597          pmSourceCacheModel (source, maskVal);
     598          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
     599          continue;
     600        }
     601
    592602        // evaluate the relative quality of the models, choose one
     603        // the PSF model might be the best fit : allow it to succeed
    593604        float minChisq = NAN;
    594605        int minModel = -1;
     
    596607            pmModel *model = source->modelFits->data[i];
    597608
     609            // skip the really bad fits
    598610            if (!(model->flags & PM_MODEL_STATUS_FITTED)) continue;
    599 
    600             if (model->flags & (PM_MODEL_STATUS_BADARGS)) continue;
     611            if (model->flags & badModel) continue;
     612
    601613            // if (model->flags & (PM_MODEL_STATUS_NONCONVERGE)) continue;
    602             if (model->flags & (PM_MODEL_STATUS_OFFIMAGE)) continue;
    603614
    604615            if ((minModel < 0) || (model->chisq < minChisq)) {
     
    618629          pmSourceCacheModel (source, maskVal);
    619630
     631# if (PS_TRACE_ON)
    620632          pmModel *model = source->modelFits->data[0];
    621633          int flags = 0xffffffff;
     
    623635            flags = model->flags;
    624636          }
    625 
    626637          fprintf (stderr, "failed to fit extended source model to object %d @ %f, %f (%x)\n", source->id, source->moments->Mx, source->moments->My, flags);
     638#endif
    627639          pmSourceSub (source, PM_MODEL_OP_FULL, maskVal);
    628640
     641          source->mode2 |= PM_SOURCE_MODE2_EXT_FITS_NONE;
    629642          continue;
    630643        }
     
    643656        if (source->modelEXT->isPCM) {
    644657            // fprintf (stderr, "subtract PCM extended source model for object %d @ %f, %f\n", source->id, source->moments->Mx, source->moments->My);
    645             pmPCMCacheModel (source, maskVal, psfSize);
     658            pmPCMCacheModel (source, maskVal, psfSize, fitOptions->nsigma);
    646659        } else {
    647660            // fprintf (stderr, "subtract non-PCM extended source model for object %d @ %f, %f\n", source->id, source->moments->Mx, source->moments->My);
    648661            pmSourceCacheModel (source, maskVal);
    649662        }
     663        source->modelEXT->flags |= PM_MODEL_BEST_FIT;
    650664
    651665        // subtract the best fit from the object, leave local sky
     
    655669        psTrace ("psphot", 5, "extended source model for source at %7.1f, %7.1f", source->moments->Mx, source->moments->My);
    656670
     671# ifdef TEST_OBJECT
    657672        if (testObject) {
    658673            psTraceSetLevel ("psModules.objects.pmPCM_MinimizeChisq", 0);
    659674            psTraceSetLevel ("psphot.psphotExtendedSourceFits_Threaded", 0);
    660675        }
     676# endif
    661677    }
    662678
  • trunk/psphot/src/psphotImageLoop.c

    r34258 r36375  
    132132                    }
    133133                    break;
     134                  case PSPHOT_FULL_FORCE:
     135                    if (!psphotFullForceReadout (config, view, "PSPHOT.INPUT")) {
     136                        psError(psErrorCodeLast(), false, "failure in psphotReadout for chip %d, cell %d, readout %d\n", view->chip, view->cell, view->readout);
     137                        psFree (view);
     138                        return false;
     139                    }
     140                    break;
    134141                  case PSPHOT_MAKE_PSF:
    135142                    if (!psphotMakePSFReadout (config, view, "PSPHOT.INPUT")) {
  • trunk/psphot/src/psphotKronIterate.c

    r35769 r36375  
    166166    }
    167167
     168# if (PS_TRACE_ON)
    168169    fprintf (stderr, "--- starting KRON ---\n");
     170#endif
    169171
    170172    // We measure the Kron Radius on a smoothed copy of the readout image
  • trunk/psphot/src/psphotLoadPSF.c

    r29936 r36375  
    11# include "psphotInternal.h"
     2
     3// PSPHOT.PSF.LOAD vs input file -- see note at top
     4bool psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule) {
     5
     6    int num = psphotFileruleCount(config, filerule);
     7
     8    // loop over the available readouts
     9    for (int i = 0; i < num; i++) {
     10
     11        // Generate the mask and weight images, including the user-defined analysis region of interest
     12        if (!psphotLoadPSFReadout (config, view, filerule, "PSPHOT.PSF.LOAD", i)) {
     13            psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
     14            return false;
     15        }
     16    }
     17    return true;
     18}
    219
    320// NOTE : pmPSF_IO.c functions must load the psf model onto the chip->analysis metadata because
     
    5875    return true;
    5976}
    60 
    61 // PSPHOT.PSF.LOAD vs input file -- see note at top
    62 bool psphotLoadPSF (pmConfig *config, const pmFPAview *view, const char *filerule) {
    63 
    64     int num = psphotFileruleCount(config, filerule);
    65 
    66     // loop over the available readouts
    67     for (int i = 0; i < num; i++) {
    68 
    69         // Generate the mask and weight images, including the user-defined analysis region of interest
    70         if (!psphotLoadPSFReadout (config, view, filerule, "PSPHOT.PSF.LOAD", i)) {
    71             psError (PSPHOT_ERR_CONFIG, false, "failed to load PSF model for PSPHOT.PSF.LOAD entry %d", i);
    72             return false;
    73         }
    74     }
    75     return true;
    76 }
  • trunk/psphot/src/psphotMergeSources.c

    r36117 r36375  
    3939    psAssert (newSources, "missing sources?");
    4040
    41     // XXX TEST:
    42     if (detections->allSources) {
    43         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    44     }
    45     if (detections->newSources) {
    46         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    47     }
    48 
    4941    if (!detections->allSources) {
    5042        detections->allSources = psArrayAllocEmpty(newSources->n);
     
    6557// Merge the externally supplied sources with the existing sources.  Mark them as having mode
    6658// PM_SOURCE_MODE_EXTERNAL.
     59
     60// XXX this function needs to be updated slightly for psphotFullForce:
     61// * load the additional parameters to guide the new concepts
    6762
    6863// XXX This function needs to be updated to loop over set of input files.  At the moment, we
     
    7368    bool status;
    7469    pmDetections *extCMF = NULL;
     70    pmDetections *extCFF = NULL;
    7571    psArray *extSourcesTXT = NULL;
    7672    int index = 0;
     
    10298    {
    10399        pmReadout *readoutCMF = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CMF");
    104         if (!readoutCMF) goto loadTXT;
     100        if (!readoutCMF) goto loadCFF;
    105101
    106102        extCMF = psMetadataLookupPtr (NULL, readoutCMF->analysis, "PSPHOT.DETECTIONS");
     
    125121    }
    126122
     123loadCFF:
     124    // load data from input CFF file:
     125    {
     126        pmReadout *readoutCFF = pmFPAfileThisReadout (config->files, view, "PSPHOT.INPUT.CFF");
     127        if (!readoutCFF) goto loadTXT;
     128
     129        extCFF = psMetadataLookupPtr (NULL, readoutCFF->analysis, "PSPHOT.DETECTIONS");
     130        if (extCFF) {
     131            psF32 exptime = psMetadataLookupF32(NULL, readout->parent->concepts, "CELL.EXPOSURE");
     132            for (int i = 0; i < extCFF->allSources->n; i++) {
     133                pmSource *source = extCFF->allSources->data[i];
     134
     135                // setting this bit not only tracks the inputs, it makes pmSourceMoments
     136                // keep the Mx,My values for the centroid. 
     137                source->mode |= PM_SOURCE_MODE_EXTERNAL;
     138
     139                // source->peak->detValue,rawFlux,smoothFlux all set to input flux value which is scaled
     140                // to 1 second exposure time. Scale to this image's exposure.
     141                source->peak->rawFlux    *= exptime;
     142                source->peak->smoothFlux *= exptime;
     143                source->peak->detValue   *= exptime;
     144                // source->peak->xf,yf, moments->Mx,My all set to input position
     145
     146                // drop the loaded source modelPSF
     147                psFree (source->modelPSF);
     148                source->modelPSF = NULL;
     149                source->imageID = index;
     150
     151                psArrayAdd (detections->newSources, 100, source);
     152            }
     153        }
     154    }
     155
    127156loadTXT:
    128157
     
    157186    psFree (detections);
    158187
    159     if (!extCMF && !extSourcesTXT) {
     188    if (!(extCMF || extCFF || extSourcesTXT)) {
    160189        psLogMsg ("psphot", 3, "no external sources for this readout");
    161190        return true;
     
    163192
    164193    int nCMF = extCMF        ? extCMF->allSources->n        : 0;
    165     int nTXT = extSourcesTXT ? extSourcesTXT->n : 0;
    166 
    167     psLogMsg ("psphot", 3, "%d external sources (%d cmf, %d text) merged to yield %ld total sources",
    168               nCMF + nTXT, nCMF, nTXT, sources->n);
     194    int nCFF = extCFF        ? extCFF->allSources->n        : 0;
     195    int nTXT = extSourcesTXT ? extSourcesTXT->n             : 0;
     196
     197    psLogMsg ("psphot", 3, "%d external sources (%d cmf, %d cff, %d text) merged to yield %ld total sources",
     198              nCMF + nCFF + nTXT, nCMF, nCFF, nTXT, sources->n);
    169199    return true;
    170200}
  • trunk/psphot/src/psphotModelTestReadout.c

    r35769 r36375  
    125125
    126126            // get the source moments
    127             status = pmSourceMoments (source, radius, 0.25*radius, 0.0, MIN_KRON_RADIUS, maskVal);
     127          status = pmSourceMoments (source, radius, 0.25*radius, 0.0, MIN_KRON_RADIUS, maskVal);
    128128            if (!status) psAbort("psSourceMoments error");
    129129
  • trunk/psphot/src/psphotPetrosianRadialBins.c

    r36115 r36375  
    186186        psFree(values);
    187187        psFree(stats);
     188        source->mode2 |= PM_SOURCE_MODE2_RADBIN_NAN_CENTER;
    188189        return true;
    189190    }
  • trunk/psphot/src/psphotPetrosianStats.c

    r34086 r36375  
    66// generate the Petrosian radius and flux from the mean surface brightness (r_i)
    77
     8float InterpolateValuesQuadratic (float *Xin, float *Yin, float X);
    89float InterpolateValues     (float X0, float Y0, float X1, float Y1, float X);
    910float InterpolateValuesErrX (float X0, float Y0, float X1, float Y1, float X, float dX0, float dX1);
     
    2021    if (!profile->binSB) {
    2122        psLogMsg ("psphot", PS_LOG_DETAIL, "no petrosian profile, skipping source %f, %f", source->peak->xf, source->peak->yf);
     23        source->mode2 |= PM_SOURCE_MODE2_PETRO_NO_PROFILE;
    2224        return true;
    2325    }
     
    5355    float dFsum2 = 0.0;
    5456
    55     float nSigma = 3.0;
     57    float nSigma = 2.0;
    5658    int lowestSignificantRadius = 0;
    5759    float lowestSignificantRatio = 1.0;
     
    117119                petRadius    = InterpolateValues     (1.0, 0.0, petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
    118120                petRadiusErr = InterpolateValuesErrX (1.0, 0.0, petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, 0.0, petRatioErr->data.F32[nOut]);
    119             } else {
    120                 petRadius    = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
    121                 petRadiusErr = InterpolateValuesErrX (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, petRatioErr->data.F32[nOut-1], petRatioErr->data.F32[nOut]);
     121                source->mode2 |= PM_SOURCE_MODE2_PETRO_RATIO_ZEROBIN;
     122            } else {
     123              // petRadius    = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
     124              if (nOut > 1) {
     125                petRadius    = InterpolateValuesQuadratic (&petRatio->data.F32[nOut-2], &refRadius->data.F32[nOut-2],   PETROSIAN_RATIO);
     126              } else {
     127                petRadius    = InterpolateValuesQuadratic (&petRatio->data.F32[nOut-3], &refRadius->data.F32[nOut-3], PETROSIAN_RATIO);
     128              }
     129# if (PS_TRACE_ON)
     130              float petRadiusLinear = InterpolateValues     (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO);
     131              if (fabs(petRadius - petRadiusLinear) > fabs(refRadius->data.F32[nOut] - refRadius->data.F32[nOut-1])) {
     132                fprintf (stderr, "big difference : %f vs %f\n", petRadius, petRadiusLinear);
     133              }
     134#endif
     135              petRadiusErr = InterpolateValuesErrX (petRatio->data.F32[nOut-1], refRadius->data.F32[nOut-1], petRatio->data.F32[nOut], refRadius->data.F32[nOut], PETROSIAN_RATIO, petRatioErr->data.F32[nOut-1], petRatioErr->data.F32[nOut]);
    122136            }
    123137            above = false;
     
    148162            fprintf (stderr, "nan pet radius\n");
    149163        }
     164        source->mode2 |= PM_SOURCE_MODE2_PETRO_INSIG_RATIO;
    150165    }
    151166
     
    180195    bool found50 = false;
    181196    bool found90 = false;
     197
    182198    // XXX use bisection to do this faster:
    183199    for (int i = 0; !(found50 && found90) && i < refRadius->n; i++) {
     
    235251}
    236252
     253// Lagrange's form of the interpolating polynomial...
     254float InterpolateValuesQuadratic (float *Xin, float *Yin, float X) {
     255
     256  float dx01 = Xin[0] - Xin[1];
     257  float dx02 = Xin[0] - Xin[2];
     258  float dx12 = Xin[1] - Xin[2];
     259
     260  float dx0  = X - Xin[0];
     261  float dx1  = X - Xin[1];
     262  float dx2  = X - Xin[2];
     263
     264  float y0 = Yin[0]*dx1*dx2/(dx01*dx02);
     265  float y1 = Yin[1]*dx0*dx2/(dx01*dx12); // need - sign
     266  float y2 = Yin[2]*dx0*dx1/(dx02*dx12);
     267
     268  float Y = y0 - y1 + y2;
     269  return Y;
     270}
     271
    237272float InterpolateValues (float X0, float Y0, float X1, float Y1, float X) {
    238273    float dydx = (Y1 - Y0) / (X1 - X0);
  • trunk/psphot/src/psphotRadialBins.c

    r34226 r36375  
    4444    psVector *radMin = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.LOWER");
    4545    psVector *radMax = psMetadataLookupPtr (&status, recipe, "RADIAL.ANNULAR.BINS.UPPER");
    46     if (!radMin || !radMin->n) {
    47         psError (PSPHOT_ERR_CONFIG, true, "error in definition of annular bins (radMin missing or empty)");
    48         return false;
    49     }
    50     if (!radMax || !radMax->n) {
    51         psError (PSPHOT_ERR_CONFIG, true, "error in definition of annular bins (radMax missing or empty)");
    52         return false;
    53     }
     46    psAssert (radMin, "RADIAL.ANNULAR.BINS.LOWER is missing from recipe");
     47    psAssert (radMin->n, "RADIAL.ANNULAR.BINS.LOWER is empty in recipe");
     48    psAssert (radMax, "RADIAL.ANNULAR.BINS.UPPER is missing from recipe");
     49    psAssert (radMax->n, "RADIAL.ANNULAR.BINS.UPPER is empty in recipe");
    5450
    5551    psVector *binSB      = psVectorAllocEmpty(radMin->n, PS_TYPE_F32); // surface brightness of radial bin
     
    161157        psFree(values);
    162158        psFree(stats);
     159        source->mode2 |= PM_SOURCE_MODE2_RADBIN_NAN_CENTER;
    163160        return true;
    164161    }
  • trunk/psphot/src/psphotRadialProfile.c

    r32348 r36375  
    11# include "psphotInternal.h"
     2
     3static int Nskip1 = 0;
     4static int Nskip2 = 0;
     5static int Nskip3 = 0;
     6static int Nskip4 = 0;
     7static int Nskip5 = 0;
     8
     9# define SKIP(VALUE) { VALUE++; return false; }
    210
    311bool psphotRadialProfile (pmSource *source, psMetadata *recipe, float skynoise, psImageMaskType maskVal) {
     
    2331    if (!psphotRadialProfilesByAngles (source, Nsec, Rmax)) {
    2432        psError (PS_ERR_UNKNOWN, false, "failed to measure radial profile for petrosian");
    25         return false;
     33        SKIP (Nskip1);
    2634    }
    2735    // allocate: extpars->radFlux->radii,fluxes,theta
     
    3240    if (!psphotRadiiFromProfiles (source, fluxMin, fluxMax)) {
    3341        psError (PS_ERR_UNKNOWN, false, "failed to measure isophotal radii from profiles");
    34         return false;
     42        SKIP (Nskip2);
    3543    }
    3644    // allocate : extpars->radFlux->isophotalRadii (use profile->radii,fluxes)
     
    4048    if (!psphotEllipticalContour (source)) {
    4149        // psLogMsg ("psphot", 3, "failed to measure elliptical contour");
    42         return false;
     50        SKIP (Nskip3);
    4351    }
    4452    // use extpars->radFlux->isophotalRadii,theta (result in extpars->axes)
     
    4856    if (!psphotEllipticalProfile (source, RAW_RADIUS)) {
    4957        psError (PS_ERR_UNKNOWN, false, "failed to generate elliptical profile");
    50         return false;
     58        SKIP (Nskip4);
    5159    }
    5260    // allocate extpars->ellipticalFlux->radiusElliptical,fluxElliptical (use axes to scale raw pixels)
     
    5563    if (!psphotRadialBins (recipe, source, Rmax, skynoise)) {
    5664        psError (PS_ERR_UNKNOWN, false, "failed to generate radial bins");
    57         return false;
     65        SKIP (Nskip5);
    5866    }
    5967    // allocate extpars->radProfile->binSB, binSBstdv, binSum, binFill, radialBins, area (small lengths)
     
    6270    return true;
    6371}
     72
     73void psphotRadialProfileShowSkips () {
     74# if (PS_TRACE_ON)
     75  fprintf (stderr, "radial profile skipped @ 1  : %d\n", Nskip1);
     76  fprintf (stderr, "radial profile skipped @ 2  : %d\n", Nskip2);
     77  fprintf (stderr, "radial profile skipped @ 3  : %d\n", Nskip3);
     78  fprintf (stderr, "radial profile skipped @ 4  : %d\n", Nskip4);
     79  fprintf (stderr, "radial profile skipped @ 5  : %d\n", Nskip5);
     80#endif
     81}
  • trunk/psphot/src/psphotReadout.c

    r34418 r36375  
    316316    psphotSourceSize (config, view, filerule, false); // pass 2 (detections->allSources)
    317317
     318    // XXX currently we are doing both the analysis of the size and the assessment of "fit ext"
     319    // in source size.  this overloads the bit MODE_EXT_LIMIT to mean "fit ext" not just
     320    // "bigger than a PSF"
     321
     322    // decide which source(s) are to be fitted with the extended source analysis code.
     323    psphotChooseAnalysisOptions (config, view, filerule);
     324
    318325    psphotExtendedSourceAnalysis (config, view, filerule); // pass 1 (detections->allSources)
    319326    psphotExtendedSourceFits (config, view, filerule); // pass 1 (detections->allSources)
  • trunk/psphot/src/psphotRoughClass.c

    r32348 r36375  
    8787    if (NX > NY) {
    8888        NXuse = ScaleForClump;
    89         NYuse = (int) (ScaleForClump * (NY / NX) + 0.5);
     89        NYuse = (int) (ScaleForClump * (NX / NY) + 0.5);
    9090    } else {
    9191        NYuse = ScaleForClump;
  • trunk/psphot/src/psphotSetThreads.c

    r35769 r36375  
    4747    psFree(task);
    4848
     49    task = psThreadTaskAlloc("PSPHOT_KRON_FLUX", 4);
     50    task->function = &psphotKronFlux_Threaded;
     51    psThreadTaskAdd(task);
     52    psFree(task);
     53
     54    task = psThreadTaskAlloc("PSPHOT_PETRO_FLUX", 4);
     55    task->function = &psphotPetroFlux_Threaded;
     56    psThreadTaskAdd(task);
     57    psFree(task);
     58
     59    task = psThreadTaskAlloc("PSPHOT_GALAXY_SHAPES", 7);
     60    task->function = &psphotGalaxyShape_Threaded;
     61    psThreadTaskAdd(task);
     62    psFree(task);
     63
    4964    task = psThreadTaskAlloc("PSPHOT_BLEND_FIT", 10);
    5065    task->function = &psphotBlendFit_Threaded;
  • trunk/psphot/src/psphotSourceFits.c

    r36107 r36375  
    1919static int NfitIterPCM = 0;
    2020static int NfitPixPCM = 0;
     21
     22bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize);
     23bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize);
    2124
    2225bool psphotFitInit (int nThreads) {
     
    579582    maskVal |= markVal;
    580583
    581     // allocate the model
     584    // allocate the model (this can only fail on a config error)
    582585    pmModel *model = pmModelAlloc(modelType);
    583     if (!model) {
    584         return NULL;
    585     }
    586 
    587     float t1, t2, t4, t5;
    588     t1 = t2 = t4 = t5 = 0.0;
     586    psAssert (model, "invalid extended model name");
     587
     588    float t1, t2, t3, t4, t5;
     589    t1 = t2 = t3 = t4 = t5 = 0.0;
    589590    if (TIMING) { psTimerStart ("psphotFitPCM"); }
    590591
     
    619620        if (!psphotSersicModelGuessPCM (pcm, source, maskVal, psfSize)) {
    620621            psFree (pcm);
    621             model->flags |= PM_MODEL_STATUS_BADARGS;
     622            model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GUESS;
    622623            return model;
    623624        }
     
    628629        if (!psphotFitSersicShapeAndIndexGridAuto (pcm, readout, source, &options, maskVal, markVal, psfSize)) {
    629630            psFree (pcm);
    630             model->flags |= PM_MODEL_STATUS_BADARGS;
     631            model->flags |= PM_MODEL_SERSIC_PCM_FAIL_GRID;
    631632            psError(PS_ERR_UNKNOWN, true, "Failed to find a index & shape");
    632633            psErrorClear (); // clear the polynomial error
     
    637638        if (!pmSourceModelGuessPCM (pcm, source, maskVal, markVal)) {
    638639            psFree (pcm);
    639             model->flags |= PM_MODEL_STATUS_BADARGS;
     640            model->flags |= PM_MODEL_PCM_FAIL_GUESS;
    640641            return model;
    641642        }
    642643    }
    643644
    644     if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); }
     645    if (TIMING) { t3 = psTimerMark ("psphotFitPCM"); }
    645646
    646647    // psTraceSetLevel("psLib.math.psMinimizeLMChi2", 5);
     
    648649    NfitIterPCM += pcm->modelConv->nIter;
    649650    NfitPixPCM += pcm->modelConv->nDOF;
     651    if (TIMING) { t4 = psTimerMark ("psphotFitPCM"); }
     652
     653    // XXX we might make this more efficient by setting NITER to be fairly small.  if we hit the iteration
     654    // limit, then we could do a small grid search on the size and try again from the best fit
     655
     656    if (options.isInteractive) psphotPCMfitCheckSize (pcm, source, maskVal, psfSize);
     657    // if (pcm->modelConv->nIter == fitOptions->nIter) {
     658    //  psphotPCMfitRetry (pcm, source, &options, maskVal, markVal, psfSize);
     659    // }
    650660    if (TIMING) { t5 = psTimerMark ("psphotFitPCM"); }
    651661
    652662    if (TIMING) {
    653663        int nPixBig = source->pixels->numCols * source->pixels->numRows;
    654         fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t4, t5);
     664        fprintf (stderr, "psphotFitPCM : nIter: %2d, radius: %6.1f, npix: %5d of %5d, t1: %6.4f, t2: %6.4f, t3: %6.4f, t4: %6.4f, t5: %6.4f\n", model->nIter, model->fitRadius, model->nPix, nPixBig, t1, t2, t3, t4, t5);
    655665    }
    656666    if (EXTRA_VERBOSE && !TIMING) {
     
    778788}
    779789
    780 // float indexGuessInv[] = {0.5, 0.33, 0.25, 0.167, 0.125, 0.083};
    781 float indexGuessInv[] = {0.5, 0.4, 0.3, 0.25, 0.20, 0.15, 0.125};
    782 # define N_INDEX_GUESS_INV 7
    783 
    784 // float reffGuess[] = {3.0, 10.0, 20.0, 30.0, 40.0};
    785 float reffGuess[] = {0.5, 0.75, 1.0, 1.4, 2.0};
     790// 0.5 / n for (1.0, 1.25, 1.66, 2.0, 3.33, 4.0)
     791// float indexGuessInv[] = {0.5, 0.4, 0.3, 0.25, 0.20, 0.15, 0.125};
     792
     793// 0.5 / n for (0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0, 6.0)
     794float indexGuessInv[] = {1.00, 0.50, 0.333, 0.25, 0.166, 0.125, 0.10, 0.0833};
     795float indexGuessR1q[] = {1.06, 1.19, 1.335, 1.48, 1.840, 2.290, 2.84, 3.5300};
     796# define N_INDEX_GUESS_INV 8
     797
     798// we are going to guess in fractions about the R1-based guess
     799float reffGuess[] = {0.8, 0.9, 1.0, 1.12, 1.25};
    786800# define N_REFF_GUESS 5
    787801
     
    791805
    792806    // we get a reasonable guess from:
    793     // * Reff = Kron R1
     807    // * Reff = Kron R1 / Q(index) -- Q comes from Graham & Driver
    794808    // * Rmajor / Rminor & Theta from moments
    795809    // * Io from total Kron flux
     
    813827    psEllipseAxes momentAxes = psEllipseMomentsToAxes (moments, 20.0);
    814828
    815     if (0) {
    816         psEllipseAxes guessAxes;
    817         guessAxes.major = source->moments->Mrf;
    818         guessAxes.minor = (momentAxes.minor / momentAxes.minor) * guessAxes.major;
    819         guessAxes.theta = momentAxes.theta;
    820 
    821         if (!isfinite(guessAxes.major)) return false;
    822         if (!isfinite(guessAxes.minor)) return false;
    823         if (!isfinite(guessAxes.theta)) return false;
    824 
    825         // convert the major,minor,theta to shape parameters for an Reff-like model
    826         pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
    827     }
    828 
    829829    // set the model position
    830830    if (!pmModelSetPosition(&PAR[PM_PAR_XPOS], &PAR[PM_PAR_YPOS], source)) {
     
    846846    // loop over index guesses and find the best fit
    847847    for (int j = 0; j < N_REFF_GUESS; j++) {
    848 
    849         psEllipseAxes guessAxes;
    850         guessAxes.major = reffGuess[j] * source->moments->Mrf;
    851         guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major);
    852         guessAxes.theta = momentAxes.theta;
    853 
    854         if (!isfinite(guessAxes.major)) return false;
    855         if (!isfinite(guessAxes.minor)) return false;
    856         if (!isfinite(guessAxes.theta)) return false;
    857 
    858         // convert the major,minor,theta to shape parameters for an Reff-like model
    859         pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
    860 
    861848        for (int i = 0; i < N_INDEX_GUESS_INV; i++) {
    862849            PAR[PM_PAR_7] = indexGuessInv[i];
    863850
     851            psEllipseAxes guessAxes;
     852            guessAxes.major = reffGuess[j] * source->moments->Mrf / indexGuessR1q[i];
     853            guessAxes.minor = guessAxes.major * (momentAxes.minor / momentAxes.major);
     854            guessAxes.theta = momentAxes.theta;
     855
     856            if (!isfinite(guessAxes.major)) return false;
     857            if (!isfinite(guessAxes.minor)) return false;
     858            if (!isfinite(guessAxes.theta)) return false;
     859
     860            // convert the major,minor,theta to shape parameters for an Reff-like model
     861            pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     862
    864863            // generated the modelFlux
    865             pmPCMMakeModel (source, pcm->modelConv, maskVal, psfSize);
     864            // XXX note that this does not add sky to model
     865            pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
    866866       
    867867            float YY = 0.0;
     
    901901                iMin = Io;
    902902                sMin = indexGuessInv[i];
    903                 rMin = reffGuess[j];
     903                rMin = reffGuess[j] / indexGuessR1q[i];
    904904            }
    905             // fprintf (stderr, "%d | %f %f %f %f | %f %f %f %f", i, indexGuessInv[i], reffGuess[j], Io, Chisq, sMin, rMin, iMin, xMin);
    906             // fprintf (stderr, "\n");
     905            if (EXTRA_VERBOSE) {
     906                fprintf (stderr, "%d | %f %f %f %f | %f %f %f %f", i, indexGuessInv[i], reffGuess[j], Io, Chisq, sMin, rMin, iMin, xMin);
     907                fprintf (stderr, "\n");
     908            }
    907909        }
    908910    }
     
    10071009    psVector *Sidx = psVectorAllocEmpty (16, PS_TYPE_F32);
    10081010
    1009     PAR[PM_PAR_7] = indexGuessInv[nStart];
     1011    float Sm = NAN, Sp = NAN, So = NAN;
     1012    if (nStart == 0) {
     1013        Sm = indexGuessInv[nStart];
     1014        So = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]);
     1015        Sp = indexGuessInv[nStart + 1];
     1016    } else if (nStart == N_INDEX_GUESS_INV - 1) {
     1017        Sp = indexGuessInv[nStart];
     1018        So = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]);
     1019        Sm = indexGuessInv[nStart - 1];
     1020    } else {
     1021        Sm = 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]);
     1022        So = indexGuessInv[nStart];
     1023        Sp = 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]);
     1024    }
     1025   
     1026    PAR[PM_PAR_7] = Sm;
    10101027    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
    10111028    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     
    10131030    psVectorAppend (chi2, model->chisqNorm);
    10141031
    1015     PAR[PM_PAR_7] = (nStart < N_INDEX_GUESS_INV - 1) ? 0.5*(indexGuessInv[nStart + 1] + indexGuessInv[nStart]) : 0.1;
     1032    PAR[PM_PAR_7] = So;
    10161033    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
    10171034    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
     
    10191036    psVectorAppend (chi2, model->chisqNorm);
    10201037
    1021     PAR[PM_PAR_7] = (nStart > 0) ? 0.5*(indexGuessInv[nStart - 1] + indexGuessInv[nStart]) : 0.55;
     1038    PAR[PM_PAR_7] = Sp;
    10221039    pmSourceFitPCM (pcm, source, &options, maskVal, markVal, psfSize);
    10231040    if (EXTRA_VERBOSE) fprintf (stderr, "%d >>> %d %f : %f - %f %f - %f %f %f - %f\n", source->id, model->nIter, model->chisqNorm, PAR[7], PAR[2], PAR[3], PAR[4], PAR[5], PAR[6], PAR[1]);
    10241041    psVectorAppend (Sidx, 100*PAR[PM_PAR_7]);
    10251042    psVectorAppend (chi2, model->chisqNorm);
    1026 
    1027     if (chi2->data.F32[1] < chi2->data.F32[2]) {
    1028       if (nStart == N_INDEX_GUESS_INV - 1) {
    1029         PAR[PM_PAR_7] = 0.11;
    1030       } else {
    1031         PAR[PM_PAR_7] = indexGuessInv[nStart + 1];
    1032       }
    1033     } else {
    1034       if (nStart == 0) {
    1035         PAR[PM_PAR_7] = 0.52;
    1036       } else {
    1037         PAR[PM_PAR_7] = indexGuessInv[nStart - 1];
    1038       }
    1039     }
    10401043
    10411044    psPolynomial1D *poly = psPolynomial1DAlloc (PS_POLYNOMIAL_ORD, 2);
     
    10511054    float Smin = -0.5 * poly->coeff[1] / poly->coeff[2] / 100.0;
    10521055
    1053     // constrain Smin to be in a valid range (1.0 - 0.1, corresponding to 0.5 (Gauss) to 5.0 (slightly peakier than Dev)
    1054     Smin = PS_MAX(PS_MIN(Smin, 1.0), 0.1);
     1056    // constrain Smin to be in a valid range: allow the fitted range to go a bit beyond the 3 trial points, but no further
     1057    float Smx = Sm - 0.25*(So - Sm);
     1058    float Spx = Sp + 0.25*(Sp - So);
     1059    Smin = PS_MAX(PS_MIN(Smin, Smx), Spx);
    10551060    PAR[PM_PAR_7] = Smin;
     1061
     1062    // XXX I could set the error on PAR_7 here if I knew how to roughly convert these chisq values to true chisq values
    10561063
    10571064    // return to the original fitting mode (fitOptions)
     
    12461253}
    12471254
    1248  
     1255// # define N_REFF_CHECK 11
     1256// float drefCheck[] = {-0.02, -0.04, -0.06, 0.0, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25};
     1257
     1258// we have an initial fit, check to see if the current size is besst
     1259bool psphotPCMfitCheckSize (pmPCMdata *pcm, pmSource *source, psImageMaskType maskVal, float psfSize) {
     1260
     1261    // PAR is already at my current best guess
     1262    psF32 *PAR = pcm->modelConv->params->data.F32;
     1263
     1264    // store best guess as a shape
     1265    psEllipseAxes centerAxes;
     1266    pmModelParamsToAxes (&centerAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     1267
     1268    float xMin = NAN;
     1269    float iMin = NAN;
     1270    float rMin = NAN;
     1271
     1272    // loop over Reff, keeping the ARatio and Theta constant
     1273    for (int j = -4; j <= 4; j++) {
     1274
     1275        float dref = j * 0.01;
     1276
     1277        psEllipseAxes guessAxes;
     1278        guessAxes.major = centerAxes.major + dref;
     1279        guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1280        guessAxes.theta = centerAxes.theta;
     1281
     1282        if (!isfinite(guessAxes.major)) return false;
     1283        if (!isfinite(guessAxes.minor)) return false;
     1284        if (!isfinite(guessAxes.theta)) return false;
     1285
     1286        // convert the major,minor,theta to shape parameters for an Reff-like model
     1287        pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1288
     1289        // generated the modelFlux
     1290            // XXX note that this does not add sky to model
     1291        pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     1292       
     1293        float YY = 0.0;
     1294        float YM = 0.0;
     1295        float MM = 0.0;
     1296        bool usePoisson = false;
     1297
     1298        for (int iy = 0; iy < source->pixels->numRows; iy++) {
     1299            for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1300                // skip masked points
     1301                if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1302                    continue;
     1303                }
     1304                // skip zero-variance points
     1305                if (source->variance->data.F32[iy][ix] == 0) {
     1306                    continue;
     1307                }
     1308                // skip nan value points
     1309                if (!isfinite(source->pixels->data.F32[iy][ix])) {
     1310                    continue;
     1311                }
     1312
     1313                float fy = source->pixels->data.F32[iy][ix];
     1314                float fm = source->modelFlux->data.F32[iy][ix];
     1315                float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0;
     1316
     1317                YY += PS_SQR(fy) * wt;
     1318                YM += fm * fy * wt;
     1319                MM += PS_SQR(fm) * wt;
     1320            }
     1321        }
     1322
     1323        float Io = YM / MM;
     1324        float Chisq = YY - 2 * Io * YM + Io * Io * MM;
     1325        if (isnan(xMin) || (Chisq < xMin)) {
     1326            xMin = Chisq;
     1327            iMin = Io;
     1328            rMin = dref;
     1329        }
     1330        // fprintf (stderr, "%d | %f %f %f | %f %f %f\n", j, dref, Io, Chisq, rMin, iMin, xMin);
     1331    }
     1332
     1333    psEllipseAxes guessAxes;
     1334    guessAxes.major = centerAxes.major + rMin;
     1335    guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1336    guessAxes.theta = centerAxes.theta;
     1337
     1338    if (!isfinite(guessAxes.major)) return false;
     1339    if (!isfinite(guessAxes.minor)) return false;
     1340    if (!isfinite(guessAxes.theta)) return false;
     1341
     1342    // convert the major,minor,theta to shape parameters for an Reff-like model
     1343    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1344    PAR[PM_PAR_I0] = iMin;
     1345
     1346    return true;
     1347}
     1348
     1349// we have an initial fit, check to see if the current size is besst
     1350bool psphotPCMfitRetry (pmPCMdata *pcm, pmSource *source, pmSourceFitOptions *fitOptions, psImageMaskType maskVal, psImageMaskType markVal, float psfSize) {
     1351
     1352    // PAR is already at my current best guess
     1353    psF32 *PAR = pcm->modelConv->params->data.F32;
     1354
     1355    // store best guess as a shape
     1356    psEllipseAxes centerAxes;
     1357    pmModelParamsToAxes (&centerAxes, PAR[PM_PAR_SXX], PAR[PM_PAR_SXY], PAR[PM_PAR_SYY], true);
     1358
     1359    // retry with axes smaller by 1 pixel
     1360    psEllipseAxes guessAxes;
     1361    guessAxes.major = centerAxes.major - 0.08;
     1362    guessAxes.minor = guessAxes.major * centerAxes.minor / centerAxes.major;
     1363    guessAxes.theta = centerAxes.theta;
     1364
     1365    if (!isfinite(guessAxes.major)) return false;
     1366    if (!isfinite(guessAxes.minor)) return false;
     1367    if (!isfinite(guessAxes.theta)) return false;
     1368
     1369    // convert the major,minor,theta to shape parameters for an Reff-like model
     1370    pmModelAxesToParams (&PAR[PM_PAR_SXX], &PAR[PM_PAR_SXY], &PAR[PM_PAR_SYY], guessAxes, true);
     1371
     1372    // generated the modelFlux
     1373            // XXX note that this does not add sky to model
     1374    pmPCMMakeModel (source, pcm->modelConv, pcm->nsigma, maskVal, psfSize);
     1375       
     1376    float YY = 0.0;
     1377    float YM = 0.0;
     1378    float MM = 0.0;
     1379    bool usePoisson = false;
     1380
     1381    for (int iy = 0; iy < source->pixels->numRows; iy++) {
     1382        for (int ix = 0; ix < source->pixels->numCols; ix++) {
     1383            // skip masked points
     1384            if (source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix]) {
     1385                continue;
     1386            }
     1387            // skip zero-variance points
     1388            if (source->variance->data.F32[iy][ix] == 0) {
     1389                continue;
     1390            }
     1391            // skip nan value points
     1392            if (!isfinite(source->pixels->data.F32[iy][ix])) {
     1393                continue;
     1394            }
     1395
     1396            float fy = source->pixels->data.F32[iy][ix];
     1397            float fm = source->modelFlux->data.F32[iy][ix];
     1398            float wt = (usePoisson) ? 1.0 / source->variance->data.F32[iy][ix] : 1.0;
     1399
     1400            YY += PS_SQR(fy) * wt;
     1401            YM += fm * fy * wt;
     1402            MM += PS_SQR(fm) * wt;
     1403        }
     1404    }
     1405
     1406    float Io = YM / MM;
     1407    PAR[PM_PAR_I0] = Io;
     1408
     1409    pmSourceFitPCM (pcm, source, fitOptions, maskVal, markVal, psfSize);  // NOTE : 1687 allocs in here
     1410
     1411    return true;
     1412}
     1413
     1414
  • trunk/psphot/src/psphotSourceSize.c

    r35180 r36375  
    11# include "psphotInternal.h"
    2 # include <gsl/gsl_sf_gamma.h>
    3 
     2
     3// this structure is only used internally to simplify the function parameters
    44typedef struct {
    55    psImageMaskType maskVal;
     
    1313    bool altDiffExt;
    1414    float altDiffExtThresh;
    15     bool extFitAll;
    16     bool extFitAllReadout;
    17     float extFitAllThresh;
    1815    float soft;
    1916    int grow;
     
    3330bool psphotSourceSelectCR (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options);
    3431bool psphotMaskCosmicRay (pmReadout *readout, pmSource *source, psImageMaskType maskVal, int maxWindowCR);
    35 bool psphotMaskCosmicRayFootprintCheck (psArray *sources);
    3632int  psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh);
    3733float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction);
     
    4137
    4238// we need to call this function after sources have been fitted to the PSF model and
    43 // subtracted.  To determine the CR-nature, this function examines the 9 pixels in the 3x3
    44 // square containing the peak and compares the observed flux to the model.  To determine
    45 // the EXT-nature, this function measures the amount of positive or negative total
    46 // deviation from the psf model at the r = FWHM/2 position
     39// subtracted. 
    4740
    4841// for now, let's store the detections on the readout->analysis for each readout
     
    121114    assert (status);
    122115
    123     // XXX recipe name is not great
     116    // XXX recipe name is not great (NOTE : not used!)
    124117    options.nSigmaMoments = psMetadataLookupF32 (&status, recipe, "PSPHOT.EXT.NSIGMA.MOMENTS");
    125118    assert (status);
    126119
    127     // Optional extended source measurement algorithm to improve diff image trails
     120    // Optional algorithm to define if a source is extended (used by DIFF analysis)
    128121    options.altDiffExt = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE");
    129122    assert (status);
     123
    130124    // Threshold for this alternate method
    131125    options.altDiffExtThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.DIFF.ALTERNATE.THRESH");
    132126    assert (status);
    133     // Option to enable fitting of all objects with extended model.
    134     options.extFitAll = psMetadataLookupBool(&status, recipe, "PSPHOT.EXT.FIT.ALL.SOURCES");
    135     assert (status);
    136     // Fitting everything is fine, but if the source density is high, we probably shouldn't.
    137     options.extFitAllThresh = psMetadataLookupF32(&status, recipe, "PSPHOT.EXT.FIT.ALL.THRESH");
    138     assert (status);
    139    
     127
    140128    // location of a single test source
    141129    options.xtest = psMetadataLookupS32 (&status, recipe, "PSPHOT.CRMASK.XTEST");
     
    422410
    423411    psLogMsg("psModules.objects", PS_LOG_INFO, "Source Size classifications: %4s %4s %4s %4s %4s", "Npsf", "Next", "Nsat", "Ncr", "Nskip");
    424     // Determine if this readout is above the threshold to ext fit all sources
    425     options->extFitAllReadout = false;
    426     if (options->extFitAll) {
    427       float maskFrac = psMetadataLookupF32(&status,readout->analysis,"READOUT.MASK.FRAC");
    428       if (status) {
    429         maskFrac = 0.0;
    430       }
    431       if (sources->n * (1.0 - maskFrac) > options->extFitAllThresh) {
    432         options->extFitAllReadout = false;
    433       }
    434       else {
    435         options->extFitAllReadout = true;
    436       }
    437     }
    438    
     412
    439413    if (!psphotSourceClassRegion (NULL, &psfClump, sources, recipe, psf, options)) {
    440414        psLogMsg ("psphot", 4, "Failed to determine source classification for full image\n");
     
    444418    return true;
    445419   
     420    // NOTE : this section is deactivated (EAM : I think we were getting poor boundary effects?)
    446421    int nRegions = psMetadataLookupS32 (&status, readout->analysis, "PSF.CLUMP.NREGIONS");
    447422    for (int i = 0; i < nRegions; i ++) {
     
    582557        // * SAT stars should not be faint, but defects may?
    583558
    584         // If the recipe requests we do extended source fits to everything, set
    585         // the EXT_LIMIT flag
    586         if (options->extFitAllReadout) {
    587           psTrace("psphotSourceClassRegion.EXTALT",10,"In extFitAll: %d %d\n",options->extFitAll,options->extFitAllReadout);
    588           source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    589         }
    590559        // Defects may not always match CRs from peak curvature analysis
    591560        // Defects may also be marked as SATSTAR -- XXX deactivate this flag?
     
    595564
    596565        // saturated star (too many saturated pixels or peak above saturation limit).  These
    597         // may also be saturated galaxies, or just large saturated regions.
     566        // may also be saturated galaxies, or just large saturated regions.  They are never
     567        // marked as 'extended'
    598568        if (source->mode & PM_SOURCE_MODE_SATSTAR) {
    599569            psTrace("psphotSourceClassRegion.SAT",4,"CLASS: %g %g\t%g %g\t%g %g\t%g %g\t%g SAT\n",
     
    604574        }
    605575
    606         // any sources missing a large fraction should just be treated as PSFs
     576        // any sources missing a large fraction should just be treated as PSFs. They are never
     577        // marked as 'extended'
    607578        if ((source->pixWeightNotBad < 0.9) || (source->pixWeightNotPoor < 0.9)) {
    608579            psTrace("psphotSourceClassRegion.PSF",4,"CLASS: %g %g\t%g %g  %g %g  %g %g\t%g %g\t%g PSF\t%g %g\n",
     
    634605            psTrace("psphotSourceClassRegion.EXT",4,"CLASS: %g %g\t%g %g\t%g %g\t%g %g\t%g EXT\n",
    635606                    source->peak->xf, source->peak->yf, Mminor, kMag, dMag, nSigmaMAG, options->sizeLimitCR, options->magLimitCR, options->nSigmaApResid);
     607            source->type = PM_SOURCE_TYPE_EXTENDED;
    636608            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    637609            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     
    639611            continue;
    640612        }
     613
    641614        // Alternate extended source limit calculation
    642615        if (options->altDiffExt) {
     
    652625                    source->peak->xf, source->peak->yf, Mminor, kMag, dMag, nSigmaMAG, options->sizeLimitCR, options->magLimitCR, options->nSigmaApResid,
    653626                    momentRatioVeres,options->altDiffExtThresh);
     627            source->type = PM_SOURCE_TYPE_EXTENDED;
    654628            source->mode |= PM_SOURCE_MODE_EXT_LIMIT;
    655629            source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
     
    968942}
    969943
    970 bool psphotMaskCosmicRayFootprintCheck (psArray *sources) {
    971 #ifdef CHECK_FOOTPRINTS
    972     // This gets really expensive for complex images
    973     for (int i = 0; i < sources->n; i++) {
    974         pmSource *source = sources->data[i];
    975         pmPeak *peak = source->peak;
    976         pmFootprint *footprint = peak->footprint;
    977         if (!footprint) continue;
    978         for (int j = 0; j < footprint->spans->n; j++) {
    979             pmSpan *sp = footprint->spans->data[j];
    980             psAssert (sp, "missing span");
    981         }
    982     }
    983 #endif
    984     return true;
    985 }
    986 
    987 /**** ------ old versions of cosmic ray masking ----- ****/
    988 
    989 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask);
    990 
    991 // This attempt to mask the cosmic rays used the isophotal boundary
    992 bool psphotMaskCosmicRay_V1 (psImage *mask, pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    993 
    994     // replace the source flux
    995     pmSourceAdd (source, PM_MODEL_OP_FULL, maskVal);
    996 
    997     // flag this as a CR
    998     source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    999     pmPeak *peak = source->peak;
    1000     psAssert (peak, "NULL peak");
    1001 
    1002     // grab the matching footprint
    1003     pmFootprint *footprint = peak->footprint;
    1004     if (!footprint) {
    1005       psTrace("psphot.czw",2,"Using isophot CR mask code.");
    1006 
    1007         // if we have not footprint, use the old code to mask by isophot
    1008         psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1009         return true;
    1010     }
    1011 
    1012     if (!footprint->spans) {
    1013       psTrace("psphot.czw",2,"Using isophot CR mask code.");
    1014 
    1015         // if we have no footprint, use the old code to mask by isophot
    1016         psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1017         return true;
    1018     }
    1019     psphotMaskCosmicRayIsophot (source, maskVal, crMask);
    1020     // mask all of the pixels covered by the spans of the footprint
    1021     for (int j = 1; j < footprint->spans->n; j++) {
    1022         pmSpan *span1 = footprint->spans->data[j];
    1023 
    1024         int iy = span1->y;
    1025         int xs = span1->x0;
    1026         int xe = span1->x1;
    1027 
    1028         for (int ix = xs; ix < xe; ix++) {
    1029             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1030         }
    1031     }
    1032     return true;
    1033 }
    1034 
    1035944# define VERBOSE 0
    1036945int psphotMaskCosmicRayConnected (int xPeak, int yPeak, psImage *mymask, psImage *myvar, psImage *edges, int binning, float sigma_thresh) {
     
    11761085}
    11771086
    1178 bool psphotMaskCosmicRayIsophot (pmSource *source, psImageMaskType maskVal, psImageMaskType crMask) {
    1179 
    1180     source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    1181     pmPeak *peak = source->peak;
    1182     psAssert (peak, "NULL peak");
    1183 
    1184     psImage *mask   = source->maskView;
    1185     psImage *pixels = source->pixels;
    1186     psImage *variance = source->variance;
    1187 
    1188     // XXX This should be a recipe variable
    1189 # define SN_LIMIT 5.0
    1190 
    1191     int xo = peak->x - pixels->col0;
    1192     int yo = peak->y - pixels->row0;
    1193 
    1194     // mark the pixels in this row to the left, then the right
    1195     for (int ix = xo; ix >= 0; ix--) {
    1196         float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);
    1197         if (SN > SN_LIMIT) {
    1198             mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;
    1199         }
    1200     }
    1201     for (int ix = xo + 1; ix < pixels->numCols; ix++) {
    1202         float SN = pixels->data.F32[yo][ix] / sqrt(variance->data.F32[yo][ix]);
    1203         if (SN > SN_LIMIT) {
    1204             mask->data.PS_TYPE_IMAGE_MASK_DATA[yo][ix] |= crMask;
    1205         }
    1206     }
    1207 
    1208     // for each of the neighboring rows, mark the high pixels if they have a marked neighbor
    1209     // first go up:
    1210     for (int iy = PS_MIN(yo, mask->numRows-2); iy >= 0; iy--) {
    1211         // mark the pixels in this row to the left, then the right
    1212         for (int ix = 0; ix < pixels->numCols; ix++) {
    1213             float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);
    1214             if (SN < SN_LIMIT) continue;
    1215 
    1216             bool valid = false;
    1217             valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix] & crMask);
    1218             valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix-1] & crMask) : 0;
    1219             valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy+1][ix+1] & crMask) : 0;
    1220 
    1221             if (!valid) continue;
    1222             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1223         }
    1224     }
    1225     // next go down:
    1226     for (int iy = PS_MIN(yo+1, mask->numRows-1); iy < pixels->numRows; iy++) {
    1227         // mark the pixels in this row to the left, then the right
    1228         for (int ix = 0; ix < pixels->numCols; ix++) {
    1229             float SN = pixels->data.F32[iy][ix] / sqrt(variance->data.F32[iy][ix]);
    1230             if (SN < SN_LIMIT) continue;
    1231 
    1232             bool valid = false;
    1233             valid |= (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix] & crMask);
    1234             valid |= (ix > 0) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix-1] & crMask) : 0;
    1235             valid |= (ix <= mask->numCols) ? (mask->data.PS_TYPE_IMAGE_MASK_DATA[iy-1][ix+1] & crMask) : 0;
    1236 
    1237             if (!valid) continue;
    1238             mask->data.PS_TYPE_IMAGE_MASK_DATA[iy][ix] |= crMask;
    1239         }
    1240     }
    1241     return true;
    1242 }
    1243 
    1244 // given the PSF ellipse parameters, navigate around the 1sigma contour, return the total
    1245 // deviation in sigmas.  This is measured on the residual image - should we ignore negative
    1246 // deviations?  NOTE: This function was an early attempt to classify extended objects, and is
    1247 // no longer used by psphot.
    1248 float psphotModelContour(const psImage *image, const psImage *variance, const psImage *mask,
    1249                          psImageMaskType maskVal, const pmModel *model, float Ro)
    1250 {
    1251     psF32 *PAR = model->params->data.F32; // Model parameters
    1252     float sxx = PAR[PM_PAR_SXX], sxy = PAR[PM_PAR_SXY], syy = PAR[PM_PAR_SYY]; // Ellipse parameters
    1253 
    1254     // We treat the contour as an ellipse:
    1255     // Ro = (x / SXX)^2 + (y / SYY)^2 + x y SXY
    1256     // y^2 (1/SYY^2) + y (x SXY) + (x / SXX)^2 - Ro = 0;
    1257     // This is a quadratic, Ay^2 + By + C with A = 1/SYY^2, B = x*SXY, C = (x / SXX)^2 - Ro
    1258     // The solution is y = [-B +/- sqrt (B^2 - 4 A C)] / [2 A], so:
    1259     // y = [-(x SXY) +/- sqrt ((x SXY)^2 - 4 (1/SYY^2) ((x/SXX)^2 - Ro))] * [SYY^2 / 2]
    1260 
    1261     // min/max value of x is where B^2 - 4AC = 0; solve this for x
    1262     float Q = Ro * PS_SQR(sxx) / (1.0 - PS_SQR(sxx * syy * sxy) / 4.0);
    1263     if (Q < 0.0) {
    1264         // ellipse is imaginary
    1265         return NAN;
    1266     }
    1267 
    1268     int radius = sqrtf(Q) + 0.5;        // Radius of ellipse
    1269     int nPts = 0;                       // Number of points in ellipse
    1270     float nSigma = 0.0;                 //
    1271 
    1272     for (int x = -radius; x <= radius; x++) {
    1273         // Polynomial coefficients
    1274         // XXX Should we be using the centre of the pixel as x or x+0.5?
    1275         float A = PS_SQR (1.0 / syy);
    1276         float B = x * sxy;
    1277         float C = PS_SQR (x / sxx) - Ro;
    1278         float T = PS_SQR(B) - 4*A*C;
    1279         if (T < 0.0) {
    1280             continue;
    1281         }
    1282 
    1283         // y position in source frame
    1284         float yP = (-B + sqrt (T)) / (2.0 * A);
    1285         float yM = (-B - sqrt (T)) / (2.0 * A);
    1286 
    1287         // Get the closest pixel positions (image frame)
    1288         int xPix  = x  + PAR[PM_PAR_XPOS] - image->col0 + 0.5;
    1289         int yPixM = yM + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
    1290         int yPixP = yP + PAR[PM_PAR_YPOS] - image->row0 + 0.5;
    1291 
    1292         if (xPix < 0 || xPix >= image->numCols) {
    1293             continue;
    1294         }
    1295 
    1296         if (yPixM >= 0 && yPixM < image->numRows &&
    1297             !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixM][xPix] & maskVal))) {
    1298             float dSigma = image->data.F32[yPixM][xPix] / sqrtf(variance->data.F32[yPixM][xPix]);
    1299             nSigma += dSigma;
    1300             nPts++;
    1301         }
    1302 
    1303         if (yPixM == yPixP) {
    1304             continue;
    1305         }
    1306 
    1307         if (yPixP >= 0 && yPixP < image->numRows &&
    1308             !(mask && (mask->data.PS_TYPE_IMAGE_MASK_DATA[yPixP][xPix] & maskVal))) {
    1309             float dSigma = image->data.F32[yPixP][xPix] / sqrtf(variance->data.F32[yPixP][xPix]);
    1310             nSigma += dSigma;
    1311             nPts++;
    1312         }
    1313     }
    1314     nSigma /= nPts;
    1315     return nSigma;
    1316 }
    1317 
    1318 // this was an old attempt to identify cosmic rays based on the peak curvature
    1319 bool psphotSourcePeakCurvature (pmReadout *readout, psArray *sources, psphotSourceSizeOptions *options) {
    1320 
    1321     // classify the sources based on the CR test (place this in a function?)
    1322     // XXX use an internal flag to mark sources which have already been measured
    1323     for (int i = 0; i < sources->n; i++) {
    1324         pmSource *source = sources->data[i];
    1325 
    1326         // skip source if it was already measured
    1327         if (source->tmpFlags & PM_SOURCE_TMPF_SIZE_MEASURED) {
    1328             psTrace("psphot", 7, "Not calculating source size since it has already been measured\n");
    1329             continue;
    1330         }
    1331 
    1332         // source must have been subtracted
    1333         if (!(source->tmpFlags & PM_SOURCE_TMPF_SUBTRACTED)) {
    1334             source->mode |= PM_SOURCE_MODE_SIZE_SKIPPED;
    1335             psTrace("psphot", 7, "Not calculating source size since source is not subtracted\n");
    1336             continue;
    1337         }
    1338 
    1339         psF32 **resid  = source->pixels->data.F32;
    1340         psF32 **variance = source->variance->data.F32;
    1341         psImageMaskType **mask = source->maskObj->data.PS_TYPE_IMAGE_MASK_DATA;
    1342 
    1343         // Integer position of peak
    1344         int xPeak = source->peak->xf - source->pixels->col0 + 0.5;
    1345         int yPeak = source->peak->yf - source->pixels->row0 + 0.5;
    1346 
    1347         // Skip sources which are too close to a boundary.  These are mostly caught as DEFECT
    1348         if (xPeak < 1 || xPeak > source->pixels->numCols - 2 ||
    1349             yPeak < 1 || yPeak > source->pixels->numRows - 2) {
    1350             psTrace("psphot", 7, "Not calculating crNsigma due to edge\n");
    1351             continue;
    1352         }
    1353 
    1354         // Skip sources with masked pixels.  These are mostly caught as DEFECT
    1355         bool keep = true;
    1356         for (int iy = -1; (iy <= +1) && keep; iy++) {
    1357             for (int ix = -1; (ix <= +1) && keep; ix++) {
    1358                 if (mask[yPeak+iy][xPeak+ix] & options->maskVal) {
    1359                     keep = false;
    1360                 }
    1361             }
    1362         }
    1363         if (!keep) {
    1364             psTrace("psphot", 7, "Not calculating crNsigma due to masked pixels\n");
    1365             continue;
    1366         }
    1367 
    1368         // Compare the central pixel with those on either side, for the four possible lines through it.
    1369 
    1370         // Soften variances (add systematic error)
    1371         float softening = options->soft * PS_SQR(source->peak->rawFlux); // Softening for variances
    1372 
    1373         // Across the middle: y = 0
    1374         float cX = 2*resid[yPeak][xPeak]   - resid[yPeak+0][xPeak-1]  - resid[yPeak+0][xPeak+1];
    1375         float dcX = 4*variance[yPeak][xPeak] + variance[yPeak+0][xPeak-1] + variance[yPeak+0][xPeak+1];
    1376         float nX = cX / sqrtf(dcX + softening);
    1377 
    1378         // Up the centre: x = 0
    1379         float cY = 2*resid[yPeak][xPeak]   - resid[yPeak-1][xPeak+0]  - resid[yPeak+1][xPeak+0];
    1380         float dcY = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak+0] + variance[yPeak+1][xPeak+0];
    1381         float nY = cY / sqrtf(dcY + softening);
    1382 
    1383         // Diagonal: x = y
    1384         float cL = 2*resid[yPeak][xPeak]   - resid[yPeak-1][xPeak-1]  - resid[yPeak+1][xPeak+1];
    1385         float dcL = 4*variance[yPeak][xPeak] + variance[yPeak-1][xPeak-1] + variance[yPeak+1][xPeak+1];
    1386         float nL = cL / sqrtf(dcL + softening);
    1387 
    1388         // Diagonal: x = - y
    1389         float cR = 2*resid[yPeak][xPeak]   - resid[yPeak+1][xPeak-1]  - resid[yPeak-1][xPeak+1];
    1390         float dcR = 4*variance[yPeak][xPeak] + variance[yPeak+1][xPeak-1] + variance[yPeak-1][xPeak+1];
    1391         float nR = cR / sqrtf(dcR + softening);
    1392 
    1393         // P(chisq > chisq_obs; Ndof) = gamma_Q (Ndof/2, chisq/2)
    1394         // Ndof = 4 ? (four measurements, no free parameters)
    1395         // XXX this value is going to be biased low because of systematic errors.
    1396         // we need to calibrate it somehow
    1397         // source->psfProb = gsl_sf_gamma_inc_Q (2, 0.5*chisq);
    1398 
    1399         // not strictly accurate: overcounts the chisq contribution from the center pixel (by
    1400         // factor of 4); also biases a bit low if any pixels are masked
    1401         // XXX I am not sure I want to keep this value...
    1402         source->psfChisq = PS_SQR(nX) + PS_SQR(nY) + PS_SQR(nL) + PS_SQR(nR);
    1403 
    1404         float fCR = 0.0;
    1405         int nCR = 0;
    1406         if (nX > 0.0) {
    1407             fCR += nX;
    1408             nCR ++;
    1409         }
    1410         if (nY > 0.0) {
    1411             fCR += nY;
    1412             nCR ++;
    1413         }
    1414         if (nL > 0.0) {
    1415             fCR += nL;
    1416             nCR ++;
    1417         }
    1418         if (nR > 0.0) {
    1419             fCR += nR;
    1420             nCR ++;
    1421         }
    1422         source->crNsigma  = (nCR > 0)  ? fCR / nCR : 0.0;
    1423         source->tmpFlags |= PM_SOURCE_TMPF_SIZE_MEASURED;
    1424 
    1425         if (!isfinite(source->crNsigma)) {
    1426             continue;
    1427         }
    1428 
    1429         // this source is thought to be a cosmic ray.  flag the detection and mask the pixels
    1430         if (source->crNsigma > options->nSigmaCR) {
    1431             source->mode |= PM_SOURCE_MODE_CR_LIMIT;
    1432             // XXX still testing... : psphotMaskCosmicRay (readout->mask, source, maskVal, crMask);
    1433             // XXX acting strange... psphotMaskCosmicRay_Old (source, maskVal, crMask);
    1434         }
    1435     }
    1436 
    1437     // now that we have masked pixels associated with CRs, we can grow the mask
    1438     if (options->grow > 0) {
    1439         bool oldThreads = psImageConvolveSetThreads(true); // Old value of threading for psImageConvolveMask
    1440         psImage *newMask = psImageConvolveMask(NULL, readout->mask, options->crMask, options->crMask, -options->grow, options->grow, -options->grow, options->grow);
    1441         psImageConvolveSetThreads(oldThreads);
    1442         if (!newMask) {
    1443             psError(PS_ERR_UNKNOWN, false, "Unable to grow CR mask");
    1444             return false;
    1445         }
    1446         psFree(readout->mask);
    1447         readout->mask = newMask;
    1448     }
    1449     return true;
    1450 }
    1451 
    14521087float psphotSourceSizeFindThreshold (psVector *value, psVector *mask, int maskValue, float minValue, float maxValue, float delta, float guess, float fraction) {
    14531088
  • trunk/psphot/src/psphotSourceStats.c

    r35112 r36375  
    5858    pmDetections *detections = psMetadataLookupPtr (&status, readout->analysis, "PSPHOT.DETECTIONS");
    5959    psAssert (detections, "missing detections?");
    60 
    61     // XXX TEST:
    62     if (detections->allSources) {
    63         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    64     }
    65     if (detections->newSources) {
    66         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    67     }
    6860
    6961    // determine the number of allowed threads
     
    246238    psphotVisualShowMoments (sources);
    247239
    248     // clear the mark bits
    249     // psImageMaskPixels (readout->mask, "AND", PS_NOT_IMAGE_MASK(markVal));
    250 
    251     if (detections->allSources) {
    252         psphotMaskCosmicRayFootprintCheck(detections->allSources);
    253     }
    254     if (detections->newSources) {
    255         psphotMaskCosmicRayFootprintCheck(detections->newSources);
    256     }
    257 
    258240    return true;
    259241}
     
    572554
    573555            // measure basic source moments (no S/N clipping on input pixels)
     556            // sources with (mode & MODE_EXTERNAL) or (mode2 & MODE2_MATCHED) use the
     557            // supplied Mx,My value for the centroid (not recalculated)
    574558            status = pmSourceMoments (source, 4*sigma[i], sigma[i], 0.0, 0.0, maskVal);
    575559        }
  • trunk/psphot/src/psphotStackImageLoop.c

  • trunk/psphot/src/psphotStackReadout.c

    r36124 r36375  
    124124        return psphotReadoutCleanup (config, view, STACK_RAW);
    125125    }
    126 
    127 // XXX TEST for background:
    128     if (!psphotModelBackground (config, view, STACK_RAW)) {
    129         return psphotReadoutCleanup (config, view, STACK_RAW);
    130     }
    131     if (!psphotSubtractBackground (config, view, STACK_RAW)) {
    132         return psphotReadoutCleanup (config, view, STACK_RAW);
    133     }
    134     if (!psphotModelBackground (config, view, STACK_RAW)) {
    135         return psphotReadoutCleanup (config, view, STACK_RAW);
    136     }
    137     if (!psphotSubtractBackground (config, view, STACK_RAW)) {
    138         return psphotReadoutCleanup (config, view, STACK_RAW);
    139     }
    140 // XXX TEST END
    141126
    142127#ifdef MAKE_CHISQ_IMAGE
     
    319304    psphotStackObjectsUnifyPosition (objects);
    320305
    321     psphotStackObjectsSelectForAnalysis (config, view, STACK_RAW, objects);
     306    // psphotStackObjectsSelectForAnalysis (config, view, STACK_RAW, objects);
    322307
    323308    // final linear fit. NOTE: if splitLinearFit is true above, this pass will only fit
     
    346331    // measure kron fluxes for the matched sources only
    347332    psphotKronIterate(config, view, STACK_RAW, 3);
     333
     334    // decide which source(s) are to be fitted with the extended source analysis code.
     335    psphotChooseAnalysisOptionsByObject (config, view, STACK_RAW, objects);
    348336
    349337    // measure elliptical apertures, petrosians (objects sorted by S/N)
  • trunk/psphot/test/tap_psphot_galaxygrid.pro

    r36086 r36375  
    3030$RefOptions = $RefOptions -nx 3000 -ny 3000
    3131
     32if (not($?PSFMODEL))
     33  $PSFMODEL = PS1_V1
     34end
     35
     36macro reset.options
    3237# options for the simulated images (using the refimage for the stars)
    3338$FakeOptions = $BaseOptions
    3439$FakeOptions = $FakeOptions -exptime 30.0
    35 $FakeOptions = $FakeOptions -D PSF.MODEL PS_MODEL_GAUSS
     40# $FakeOptions = $FakeOptions -D PSF.MODEL PS_MODEL_GAUSS
     41$FakeOptions = $FakeOptions -D PSF.MODEL PS_MODEL_$PSFMODEL
    3642$FakeOptions = $FakeOptions -nx 3000 -ny 3000
    3743 
     
    6975$FakeConfig = $FakeConfig -Di GALAXY.GRID.DX 300
    7076$FakeConfig = $FakeConfig -Di GALAXY.GRID.DY 300
     77end
     78
     79if (not($?FakeConfig)) reset.options
    7180
    7281list fwhm
     
    7584 1.2
    7685 1.5
     86end
     87
     88if (not($?CONVOLVE_NSIGMA)) set CONVOLVE_NSIGMA = 5.0
     89
     90# generate fake images and run psphot on them
     91macro mkexp.devexp.single
     92  if ($0 != 5)
     93    echo "USAGE: mkexp.devexp.single (basename) (type) (Rmajor) (fwhm)" 
     94    break
     95  end
     96
     97  $basename = $1
     98  $type = $2
     99  $Rmajor = $3
     100  $fwhm = $4
     101
     102  $Aratio = 1.0
     103
     104  $FakeConfig = -camera SIMTEST
     105  $FakeConfig = $FakeConfig -recipe PPSIM STACKTEST.RUN
     106  $FakeConfig = $FakeConfig -D PSASTRO:PSASTRO.CATDIR catdir.ref
     107  $FakeConfig = $FakeConfig -Db STARS.FAKE F                         ; # only use stars from catdir.ref
     108  $FakeConfig = $FakeConfig -Db MATCH.DENSITY F
     109  $FakeConfig = $FakeConfig -Db PSF.CONVOLVE T
     110  $FakeConfig = $FakeConfig -Db GALAXY.FAKE T                        ; # generate a "realistic" distribution of galaxies
     111  $FakeConfig = $FakeConfig -Df GALAXY.MAG 17.0
     112  $FakeConfig = $FakeConfig -Df GALAXY.GRID.MAG 14.5
     113  $FakeConfig = $FakeConfig -Db GALAXY.GRID T                        ; # generate a grid of galaxies (constant mag)
     114  $FakeConfig = $FakeConfig -Df GALAXY.THETA.MIN 0
     115  $FakeConfig = $FakeConfig -Df GALAXY.THETA.MAX 180
     116  $FakeConfig = $FakeConfig -Di GALAXY.GRID.DX 300
     117  $FakeConfig = $FakeConfig -Di GALAXY.GRID.DY 300
     118  $FakeConfig = $FakeConfig -Df GALAXY.INDEX.MIN 1.0
     119  $FakeConfig = $FakeConfig -Df GALAXY.INDEX.MAX 1.0
     120  $FakeConfig = $FakeConfig -Df CONVOLVE.NSIGMA $CONVOLVE_NSIGMA
     121  $BaseConfig = $FakeConfig
     122
     123  $FakeConfig = $BaseConfig
     124  $FakeConfig = $FakeConfig -Df GALAXY.RMAJOR.MIN $Rmajor
     125  $FakeConfig = $FakeConfig -Df GALAXY.RMAJOR.MAX $Rmajor
     126  $FakeConfig = $FakeConfig -Df GALAXY.ARATIO.MIN $Aratio
     127  $FakeConfig = $FakeConfig -Df GALAXY.ARATIO.MAX $Aratio
     128         
     129  mkexp $basename $fwhm $type
    77130end
    78131
     
    272325  label -x sequence -y "M_out| - M_in|"
    273326  resize 700 320
     327
     328  # check on magnitude
     329  set dI = Iot_s - Iin_s
     330  lim -n 4$1 n -1.0 1.0; clear; box; plot n dI
     331  label -x sequence -y "I_out| - I_in|"
     332  resize 700 320
     333end
     334
     335macro grid.plot.stars
     336  if ($0 != 2)
     337    echo "USAGE: grid.plot.stars (version)"
     338    break
     339  end
     340  # things to examine: theta, Rmajor, AR
     341
     342  # go.grid.check.devexp
     343
     344  # check on position
     345  set dX = Xot_s - int(Xin_s) - 0.5
     346  set dY = Yot_s - int(Yin_s) - 0.5
     347  set ARin = rin_s / Rin_s
     348  set dR = Rin_s - Rot_s
     349
     350  create n 0 dR[]
     351  set dRf = dR / Rin_s
     352  lim -n 1$1 n -0.5 0.5; clear; box; plot n dRf
     353  label -x sequence -y "1 - R_out| / R_in|"
     354  resize 700 320
     355
     356  # check on A.Ratio
     357  set ARot = rot_s / Rot_s
     358  # lim ARin ARot; clear; box; plot ARin ARot
     359  set fAR = ARot / ARin
     360  lim -n 2$1 n 0.5 1.5; clear; box; plot n fAR
     361  label -x sequence -y "AR_out| / AR_in|"
     362  resize 700 320
     363
     364  # check on magnitude
     365  set dM = Mot_s - Min_s
     366  lim -n 3$1 n -0.5 0.5; clear; box; plot n dM   
     367  label -x sequence -y "M_out| - M_in|"
     368  resize 700 320
     369
     370  lim -n 4$1 n -1.5 1.5; clear; box; plot n dX
     371  label -x sequence -y "X_out| - X_in|"
     372  resize 700 320
     373
     374  lim -n 5$1 n -1.5 1.5; clear; box; plot n dY
     375  label -x sequence -y "Y_out| - Y_in|"
     376  resize 700 320
    274377end
    275378
     
    487590end
    488591
     592if (not($?NSIGMA_CONV)) set NSIGMA_CONV = 5.0
     593
    489594# create a realistic distribution of fake stars, GAUSS PSF
    490595macro fitexp
     
    507612  $psphotConfig = $psphotConfig -Db PSPHOT:SAVE.RESID T
    508613  $psphotConfig = $psphotConfig -D  PSPHOT:EXTENDED_SOURCE_MODELS_SELECTION $fitModel
     614  $psphotConfig = $psphotConfig -D  PSPHOT:PSF_MODEL PS_MODEL_$PSFMODEL
     615
     616  $psphotConfig = $psphotConfig -Db PSPHOT:PSF.RESIDUALS F
     617  $psphotConfig = $psphotConfig -Db PSPHOT:POISSON.ERRORS.PHOT.LMM F
     618  $psphotConfig = $psphotConfig -Db PSPHOT:EXTENDED_SOURCE_FITS_POISSON F
     619  $psphotConfig = $psphotConfig -Di PSPHOT:EXT_FIT_ITER 15
     620  $psphotConfig = $psphotConfig -Df PSPHOT:PSF_FIT_RADIUS_SCALE 3.75
     621  $psphotConfig = $psphotConfig -Df PSPHOT:EXT_FIT_NSIGMA_CONV $NSIGMA_CONV
    509622
    510623  # ppImage / psphot on the output
     
    516629end
    517630
     631macro cmf.load.reset
     632  $fields = X Y M T R r MT I
     633  foreach field $fields
     634    foreach set in ot
     635      delete -q $field\$set\_s
     636    end
     637  end
     638
     639  delete -q min_S Min_S
     640end
     641
    518642macro cmf.load.concat
    519643  if ($0 != 4)
    520     echo "USAGE: cmf.load.concat (dat) (cmf) (type)"
     644    echo "USAGE: cmf.load.concat (dat) (cmf) (inType)"
    521645    break
    522646  end
     
    525649  read Xin_all 1 Yin_all 2 Fin_all 3 Type 4 Min_all 5 RmajIn_all 7 RminIn_all 8 ThetaIn_all 9 IndexIn_all 10
    526650
     651  $TYPE_S = 83
     652  $TYPE_D = 68
     653  $TYPE_E = 69
     654  if ("$3" == "SERSIC")
     655    $InType = $TYPE_S
     656  end
     657  if ("$3" == "DEV")
     658    $InType = $TYPE_D
     659    set IndexIn_all = 0.125 + zero(Xin_all)
     660  end
     661  if ("$3" == "EXP")
     662    $InType = $TYPE_E
     663    set IndexIn_all = 0.5 + zero(Xin_all)
     664  end
     665
     666  # select only the galaxies
    527667  subset Xin = Xin_all if (Type == 1)
    528668  subset Yin = Yin_all if (Type == 1)
     
    539679  subset IndexIn = IndexIn_all if (Type == 1)
    540680
    541   $TYPE_S = 83
    542   $TYPE_D = 68
    543   $TYPE_E = 69
    544   if ("$3" == "SERSIC")
    545     $InType = $TYPE_S
    546   end
    547   if ("$3" == "DEV")
    548     $InType = $TYPE_D
    549   end
    550   if ("$3" == "EXP")
    551     $InType = $TYPE_E
    552   end
    553 
    554681  data $2
    555682
    556683  break -auto off
     684  output -err /dev/null
    557685  read -fits Chip.xfit X_EXT Y_EXT EXT_INST_MAG EXT_WIDTH_MAJ EXT_WIDTH_MIN EXT_THETA MODEL_TYPE EXT_PAR_07
    558686  $reread = not($STATUS)
     687  output -err stderr
    559688  break -auto on
    560689  if ($reread)
    561690    read -fits Chip.xfit X_EXT Y_EXT EXT_INST_MAG EXT_WIDTH_MAJ EXT_WIDTH_MIN EXT_THETA MODEL_TYPE
    562     set EXT_PAR_07 = (MODEL_TYPE:9 == 68)*4 + (MODEL_TYPE:9 == 69)
     691    set EXT_PAR_07 = (MODEL_TYPE:9 == 68)*0.125 + (MODEL_TYPE:9 == 69)*0.5
    563692  end
    564693
     
    589718  reindex rin_m = RminIn using index2
    590719 
    591   if ("$3" == "SERSIC")
    592     reindex Iot_m = EXT_PAR_07 using index1
    593     reindex Iin_m = IndexIn using index2
    594    $fields = X Y M T R r MT I
    595   else
    596    $fields = X Y M T R r MT
    597   end
     720  reindex Iot_m = EXT_PAR_07 using index1
     721  reindex Iin_m = IndexIn using index2
     722  $fields = X Y M T R r MT I
    598723 
    599724  foreach field $fields
     
    605730  concat min min_S
    606731  concat Min Min_S
     732end
     733
     734macro cmf.load.stars.concat
     735  if ($0 != 3)
     736    echo "USAGE: cmf.load.concat (dat) (cmf)"
     737    break
     738  end
     739
     740  data $1
     741  read Xin_all 1 Yin_all 2 Type 4 Min_all 5 RmajIn_all 7 RminIn_all 8 ThetaIn_all 9 IndexIn_all 10
     742
     743  subset Xin     = Xin_all     if (Type == 0)
     744  subset Yin     = Yin_all     if (Type == 0)
     745  subset Min     = Min_all     if (Type == 0)
     746  subset RmajIn  = RmajIn_all  if (Type == 0)
     747  subset RminIn  = RminIn_all  if (Type == 0)
     748  subset IndexIn = IndexIn_all if (Type == 0)
     749  subset Tin_rad = ThetaIn_all if (Type == 0)
     750  set Tin = Tin_rad * 180 / 3.14159265
     751
     752  data $2
     753
     754  break -auto off
     755  read -fits Chip.psf X_PSF Y_PSF PSF_INST_MAG PSF_MAJOR PSF_MINOR PSF_THETA
     756  set PSF_THETA_ALT = PSF_THETA * (PSF_THETA >= 0.0) + (PSF_THETA + 3.14159265) * (PSF_THETA < 0.0)
     757  set PSF_THETA = PSF_THETA_ALT * 180 / 3.14159265
     758 
     759  match2d X_PSF Y_PSF Xin Yin 1.0 -index1 index1 -index2 index2
     760
     761  reindex Xot_m = X_PSF using index1
     762  reindex Yot_m = Y_PSF using index1
     763
     764  reindex Xin_m = Xin using index2
     765  reindex Yin_m = Yin using index2
     766
     767  reindex Mot_m = PSF_INST_MAG using index1
     768  reindex Tot_m = PSF_THETA using index1
     769
     770  reindex Min_m = Min using index2
     771  reindex Tin_m = Tin using index2
     772
     773  reindex Rot_m = PSF_MAJOR using index1
     774  reindex rot_m = PSF_MINOR using index1
     775
     776  reindex Rin_m = RmajIn using index2
     777  reindex rin_m = RminIn using index2
     778 
     779  $fields = X Y M T R r
     780  foreach field $fields
     781    foreach set in ot
     782      concat $field\$set\_m $field\$set\_s
     783    end
     784  end
    607785end
    608786
     
    10781256
    10791257macro load.normdata
    1080   if ($0 != 2)
    1081     echo "USAGE: load.normdata (file)"
     1258  if ($0 != 3)
     1259    echo "USAGE: load.normdata (file) [clear/noclear]"
    10821260    break
    10831261  end
     
    10901268  set dm = mg - Mg
    10911269  set n = ramp(dm)
    1092   lim n dm; clear; box; plot n dm
     1270  if ("$2" == "clear")
     1271    lim n dm; clear; box;
     1272  end
     1273  plot n dm
    10931274end
    10941275
     
    10971278  exit 0
    10981279end
     1280
     1281# note that t1 = original confi
     1282# t2 = no residuals
     1283# t3 = const weight PSF fit
     1284# t4 = const weight galaxy fits
     1285
     1286macro run.radius.loop
     1287  local radius Nrun
     1288
     1289  if (1)
     1290    $Nrun = 0
     1291    foreach radius 1.0 1.5 2.0 2.5 3.0 4.0 6.0 8.0
     1292      mkexp.devexp.single tests.20131120/testrad.ps1v1.exp.$Nrun EXP $radius 1.0
     1293      fitexp tests.20131120/testrad.ps1v1.exp.$Nrun tests.20131120/testrad.ps1v1.exp.$Nrun.t4b EXP_CONV
     1294      $Nrun ++
     1295    end
     1296  end
     1297
     1298  $Nrun = 0
     1299  foreach radius 1.0 1.5 2.0 2.5 3.0 4.0 6.0 8.0
     1300    cmf.load.concat tests.20131120/testrad.ps1v1.exp.$Nrun.dat tests.20131120/testrad.ps1v1.exp.$Nrun.t4b.cmf EXP
     1301    echo -no-return $radius ""
     1302    check.fit tests.20131120/testrad.ps1v1.exp.$Nrun.dat tests.20131120/testrad.ps1v1.exp.$Nrun.t4b.cmf EXP
     1303    $Nrun ++
     1304  end
     1305
     1306  grid.plots.devexp a
     1307end
     1308
     1309macro check.radius.loop
     1310  if ($0 != 2)
     1311    echo "USAGE: check.radius.loop (ext)"
     1312    break
     1313  end
     1314
     1315  # cmf.load.reset
     1316
     1317  local radius Nrun
     1318
     1319  $Nrun = 0
     1320  foreach radius 1.0 1.5 2.0 2.5 3.0 4.0 6.0 8.0
     1321    echo -no-return $radius ""
     1322    check.fit tests.20131120/testrad.ps1v1.exp.$Nrun.dat tests.20131120/testrad.ps1v1.exp.$Nrun.$1.cmf EXP
     1323    $Nrun ++
     1324  end
     1325
     1326  grid.plots.devexp a
     1327end
     1328
     1329macro check.fit
     1330  if ($0 != 4)
     1331    echo "USAGE: check.fit (dat) (cmf) (type)"
     1332    break
     1333  end
     1334
     1335  cmf.load.concat $1 $2 $3
     1336  set dM_m = Mot_m - Min_m
     1337  vstat -q dM_m
     1338  $mag_off = $MEDIAN
     1339  set dR_m = Rot_m - Rin_m
     1340  vstat -q dR_m
     1341  $rad_off = $MEDIAN
     1342  echo $mag_off $rad_off
     1343end
     1344
     1345macro make.circles
     1346
     1347  delete Xo Yo Ro
     1348
     1349  for ix 0 16
     1350    for iy $ix 16
     1351      $r2 = $ix^2 + $iy^2
     1352      if ($r2 > 15^2) continue
     1353      concat $ix Xo
     1354      concat $iy Yo
     1355      concat $r2 Ro
     1356    end
     1357  end
     1358
     1359  sort Ro Xo Yo
     1360  $Rold = -1
     1361  $N = -1
     1362  for i 0 Ro[]
     1363    if (Ro[$i] != $Rold)
     1364      $N ++
     1365      $Rold = Ro[$i]
     1366    end
     1367    if ((Xo[$i] == 0) && (Yo[$i] == 0))
     1368      fprintf "// center is 0,0"
     1369      continue
     1370    end
     1371    if (Xo[$i] == 0)
     1372      fprintf "ADD_AXIS (%3d, %2d)     // r^2 = %3d" $N Yo[$i] Ro[$i]
     1373      continue
     1374    end
     1375    if (Xo[$i] == Yo[$i])
     1376      fprintf "ADD_DIAG (%3d, %2d)     // r^2 = %3d" $N Xo[$i] Ro[$i]
     1377      continue
     1378    end
     1379
     1380    fprintf "ADD_RAND (%3d, %2d, %2d) // r^2 = %3d" $N Xo[$i] Yo[$i] Ro[$i]
     1381 end
     1382end
     1383
     1384# EXP : tests.20131120/test.nsig
     1385# DEV : tests.20131120/test.dev
     1386
     1387# run.convolve.loop tests.20131120/test.nsig tests.20131120/test.nsig   EXP EXP_CONV
     1388# run.convolve.loop tests.20131120/test.dev  tests.20131120/test.dev    DEV DEV_CONV
     1389# run.convolve.loop tests.20131120/test.nsig tests.20131120/test.serexp EXP SER_CONV
     1390# run.convolve.loop tests.20131120/test.dev  tests.20131120/test.serdev DEV SER_CONV
     1391
     1392macro run.convolve.loop
     1393  if ($0 != 5)
     1394    echo "run.convolve.loop (inName) (fitName) (inType) (fitType)"
     1395    break
     1396  end
     1397
     1398  local radius
     1399  $radius = 3.0
     1400  cmf.load.reset
     1401
     1402  # foreach Cin 3 5 7 9 11
     1403  foreach Cin 11
     1404    $CONVOLVE_NSIGMA = $Cin
     1405    sprintf nameIn %s.%02d $1 $Cin
     1406    mkexp.devexp.single $nameIn $3 $radius 1.0
     1407    foreach Cot 3 5 7 9 11
     1408      $NSIGMA_CONV = $Cot
     1409      sprintf nameOt %s.%02d.%02d $2 $Cin $Cot
     1410      fitexp $nameIn $nameOt $4
     1411    end
     1412  end
     1413
     1414  # foreach Cin 3 5 7 9 11
     1415  foreach Cin 11
     1416    sprintf nameIn %s.%02d $1 $Cin
     1417    foreach Cot 3 5 7 9 11
     1418      sprintf nameOt %s.%02d.%02d $2 $Cin $Cot
     1419      check.fit $nameIn.dat $nameOt.cmf
     1420    end
     1421  end
     1422  grid.plots.devexp a
     1423end
     1424
     1425macro check.convolve.loop
     1426  if ($0 != 4)
     1427    echo "run.convolve.loop (inName) (fitName) (inType)"
     1428    break
     1429  end
     1430
     1431  local radius
     1432  $radius = 3.0
     1433  cmf.load.reset
     1434
     1435  # foreach Cin 3 5 7 9 11
     1436  foreach Cin 11
     1437    sprintf nameIn %s.%02d $1 $Cin
     1438    foreach Cot 3 5 7 9 11
     1439      sprintf nameOt %s.%02d.%02d $2 $Cin $Cot
     1440      echo -no-return $Cin $Cot " "
     1441      check.fit $nameIn.dat $nameOt.cmf $3
     1442    end
     1443  end
     1444  grid.plots.devexp a
     1445end
  • trunk/pstamp/scripts

  • trunk/psvideophot

Note: See TracChangeset for help on using the changeset viewer.