IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 40624


Ignore:
Timestamp:
Feb 23, 2019, 10:23:16 AM (7 years ago)
Author:
eugene
Message:

updated mkobj so it generates a resonable fake object

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Ohana/src/opihi/mana/deimos_mkobj.c

    r40622 r40624  
    66
    77  // input parameters:
    8   //   trace       : spline fit of slit central x pos vs y-coord
    9   //   profile     : slit window profile (vector)
    10   //   object      : vector of object flux vs y-coord
    11   //   sky         : vector of local sky signal vs y-coord
    12   //   background  : vector of extra-slit background flux vs y-coord
    13   //   PSF         : point-spread function vector (flux normalized, x-dir)
    14   //   LSF         : sline-spread function vector (flux normalized, y-dir)
    15   //   stilt       : slit tilt response : 2D kernel?
     8  // * trace       : spline fit of slit central x pos vs y-coord
     9  // * profile     : slit window profile (vector)
     10  // * object      : vector of object flux vs y-coord
     11  // * sky         : vector of local sky signal vs y-coord
     12  // * background  : vector of extra-slit background flux vs y-coord
     13  // * PSF         : point-spread function vector (flux normalized, x-dir)
     14  // * LSF         : sline-spread function vector (flux normalized, y-dir)
     15  // * stilt       : slit tilt response : 2D kernel?
    1616
    1717  int N;
     
    3030  Buffer *output  = NULL;
    3131
     32  float stilt = 0.0; // angle of the slit
     33
    3234  if ((N = get_argument (argc, argv, "-trace"))) {
    3335    remove_argument (N, &argc, argv);
     
    6365    remove_argument (N, &argc, argv);
    6466    if ((lsf = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);
     67    remove_argument (N, &argc, argv);
     68  }
     69  if ((N = get_argument (argc, argv, "-stilt"))) {
     70    remove_argument (N, &argc, argv);
     71    stilt = atof (argv[N]);
    6572    remove_argument (N, &argc, argv);
    6673  }
     
    7481  }
    7582
    76   if (argc != 4) {
     83  if (argc != 3) {
    7784    gprint (GP_ERR, "USAGE: deimos mkobj (buffer) (Ncross) [-Nwave N] [-object vector] [-sky vector] [-backgnd vector] [-trace spline] [-profile vector]\n");
    7885    return FALSE;
     
    110117
    111118  if ((output = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
    112   int Nx = atoi(argv[2]);
     119  int NxBase = atoi(argv[2]);
     120  if (NxBase % 2 == 0) NxBase ++; // force Nx to be odd
     121  int Nx = NxBase;
    113122 
     123  // if we are appying a trace offset spline, we need to generate an output window which
     124  // is Nx + the full swing of the trace, then window back down
     125  if (trace) {
     126    float dXmin = +1000;
     127    float dXmax = -1000;
     128    for (int iy = 0; iy < Ny; iy++) {
     129      // evaluate the trace spline at this y-coord to find the x-coord offset of the profile center
     130      float dx = spline_apply_dbl (trace->xk, trace->yk, trace->y2, trace->Nknots, iy);
     131      dXmin = MIN (dx, dXmin);
     132      dXmax = MAX (dx, dXmax);
     133    }
     134    int dXrange = ceil(dXmax - dXmin);
     135    if (dXrange % 2) dXrange ++; // force dXrange to be even (so Nx will be odd)
     136    Nx += dXrange;
     137  }
     138
    114139  ResetBuffer (output, Nx, Ny, -32, 0.0, 1.0);
    115140
     
    117142  opihi_flt *skyV = (opihi_flt *) (sky    ? sky->elements.Flt : NULL);
    118143  opihi_flt *psfV = (opihi_flt *) (psf    ? psf->elements.Flt : NULL);
    119 
    120   float *out = (float *) output[0].matrix.buffer;
     144  opihi_flt *lsfV = (opihi_flt *) (lsf    ? lsf->elements.Flt : NULL);
    121145
    122146  // psf vector must have odd number of pixels:
    123147  int Npsf = 0;
    124   int Npof = floor(Nx/2);
     148  int NpsfFull = 0;
    125149  if (psf) {
    126150    if (psf->Nelements % 2 == 0) {
     
    128152      return FALSE;
    129153    }
    130     Npsf = psf->Nelements / 2;
    131     Npof -= Npsf;
    132   }
     154    NpsfFull = psf->Nelements;
     155    Npsf = NpsfFull / 2;
     156  }
     157
     158  // lsf vector must have odd number of pixels:
     159  int Nlsf = 0;
     160  int NlsfFull = 0;
     161  if (lsf) {
     162    if (lsf->Nelements % 2 == 0) {
     163      gprint (GP_ERR, "lsf vector must have an odd number of pixels\n");
     164      return FALSE;
     165    }
     166    NlsfFull = lsf->Nelements;
     167    Nlsf = NlsfFull / 2;
     168  }
     169
     170  // *** apply the PSF to the object flux, add in the sky flux
     171
     172  ALLOCATE_PTR (s1, float, Nx*Ny);
    133173
    134174  // loop over the y positions
     
    138178    opihi_flt skyVy = skyV ? skyV[iy] : 0.0; // if sky is not supplied, flux defaults to 0.0
    139179     
     180    int Npof = floor(Nx/2);
     181    if (psf) Npof -= Npsf;
     182
    140183    // flux = obj * PSF + sky
    141184    for (int ix = 0; ix < Nx; ix++) {
     
    144187
    145188      if (psfV) {
    146         int n = ix - Npof; // n is the pixel in the PSF corresponding to the ix pixel in the output image
    147         if (n < 0) continue;
    148         if (n >= Npsf) continue;
    149        
    150         value += objVy * psfV[n];
     189        int n = ix - Npof;
     190        // n is the pixel in the PSF corresponding to the ix pixel in the output image
     191        // only add in the flux if we are in range of the PSF
     192        if ((n >= 0) && (n < NpsfFull)) {
     193          value += objVy * psfV[n];
     194        }
    151195      } else {
    152196        if (ix == Nx / 2) value += objVy;
    153197      }   
    154       out[ix + iy*Nx] = value;
    155     }
    156   }
     198      s1[ix + iy*Nx] = value;
     199    }
     200  }
     201
     202  // *** apply the slit tilt & lsf
     203
     204  // first, generate the interpolation kernels.  For a slit tilt of theta, there is a
     205  // displacement in the y-direction of dy = dx sin(theta) where dx is the x-coord
     206  // relative to the slit window center (Nx / 2).  we thus need an image of size Nx,
     207  // Nx*sin(theta)
     208
     209  float sin_stilt = sin(stilt*RAD_DEG);
     210  int Nyk = ceil(Nx * fabs(sin_stilt));
     211  if (Nyk < 3) Nyk = 3; // minimum of 3 pixels (or kernel assumption below fails)
     212  Nyk += NlsfFull;
     213  if (Nyk % 2 == 0) Nyk ++; // force Nyk to be odd
     214  int Nyk2 = Nyk/2; // Nyk2 is the center pixel of the interpolations
     215  ALLOCATE_PTR (kernel, float, Nx*Nyk);
     216  int Nkpix = Nx*Nyk;
     217
     218  int Nx2 = floor(Nx/2);
     219  for (int ix = 0; ix < Nx; ix++) {
     220    for (int iy = 0; iy < Nyk; iy++) { kernel[ix + iy*Nx] = 0.0; }
     221
     222    // displacement in y-dir due to slit tilt:
     223    float dy = (ix - Nx2) * sin_stilt;
     224    int dyi = floor(dy);
     225    float dyf = dy - dyi;
     226
     227    if (lsf) {
     228      int Sy = Nyk2 - Nlsf + dyi;
     229      int doInterp = (fabs(dyf) < 1e-5) ? FALSE : TRUE;
     230      for (int iy = 0; iy < Nyk; iy++) {
     231        int py = iy - Sy;
     232        if (py < 0) continue;
     233        if (py >= NlsfFull) continue;
     234
     235        float vout = NAN;
     236        if (doInterp) {
     237          if ((py > 0) && (py < NlsfFull - 1)) {
     238            vout = lsfV[py]*(1 - dyf) + lsfV[py-1]*dyf;
     239          }
     240          if (py == 0) {
     241            vout = lsfV[py]*dyf;
     242          }
     243          if (py == NlsfFull - 1) {
     244            vout = lsfV[py]*(1.0 - dyf);
     245          }
     246        } else {
     247          vout = lsfV[py];
     248        }
     249        int Nkpix_i = ix + iy*Nx;
     250        myAssert (Nkpix_i < Nkpix, "oops");
     251        kernel[Nkpix_i] = vout;
     252      }
     253    } else {
     254      int Nkpix_i;
     255      Nkpix_i = ix + (dyi + Nyk2 + 0)*Nx;
     256      myAssert (Nkpix_i < Nkpix, "oops");
     257      kernel[Nkpix_i] = 1.0 - dyf;
     258
     259      Nkpix_i = ix + (dyi + Nyk2 + 1)*Nx;
     260      myAssert (Nkpix_i < Nkpix, "oops");
     261      kernel[Nkpix_i] = dyf;
     262      fprintf (stderr, "%d, %d: %f %f\n", ix, (dyi + Nyk2), kernel[ix + (dyi + Nyk2 + 0)*Nx], kernel[ix + (dyi + Nyk2 + 1)*Nx]);
     263    }
     264  }
     265
     266  float *out = (float *) output[0].matrix.buffer;
     267
     268  // next, apply the interpolation kernel to the image
     269
     270  // loop over the y positions
     271  for (int iy = 0; iy < Ny; iy++) {
     272
     273    // use the tilt kernel to interpolate to this x coordinate
     274    for (int ix = 0; ix < Nx; ix++) {
     275
     276      // if the LSF is defined, we cannot bypass the convolution
     277      if (!lsf && (fabs(stilt) < 1e-5)) {
     278        out[ix + iy*Nx] = s1[ix + iy*Nx];
     279      } else {
     280        opihi_flt g = 0.0, s = 0.0;
     281        for (int n = -Nyk2; n <= Nyk2; n++) {
     282          if (iy + n < 0) continue; // bottom edge of full image
     283          if (iy + n >= Ny) continue; // top edge of full image
     284          int Nkpix_i = ix + (n + Nyk2)*Nx;
     285          myAssert (Nkpix_i < Nkpix, "oops");
     286          s += kernel[Nkpix_i]*s1[ix + (iy + n)*Nx];
     287          g += kernel[Nkpix_i];
     288        }
     289        out[ix + iy*Nx] = s / g;
     290      }
     291    }
     292  }
     293  free (kernel);
     294  free (s1);
     295 
     296  // next, apply the profile (output = input * profile)
     297  opihi_flt *profileV = (opihi_flt *) (profile ? profile->elements.Flt : NULL);
     298  if (profile) {
     299    int Nprof = profile->Nelements;
     300    int Nprof2 = Nprof / 2;
     301
     302    // loop over the y positions
     303    for (int iy = 0; iy < Ny; iy++) {
     304     
     305      int Sx = (int)(Nx2 - Nprof2);
     306     
     307      for (int ix = 0; ix < Nx; ix++) {
     308       
     309        // equivalent coord in the profile:
     310        int px = ix - Sx;
     311        if ((px >= 0) && (px < Nprof)) {
     312          out[ix + iy*Nx] *= profileV[px];
     313        } else {
     314          out[ix + iy*Nx] = 0.0;
     315        }
     316      }
     317    }
     318  }
     319
     320  // add in the background
     321  opihi_flt *backgndV = (opihi_flt *) (backgnd ? backgnd->elements.Flt : NULL);
     322  if (backgnd) {
     323    for (int iy = 0; iy < Ny; iy++) {
     324      for (int ix = 0; ix < Nx; ix++) {
     325        out[ix + iy*Nx] += backgndV[iy];
     326      }
     327    }
     328  }
     329
     330  // shift pixels in x based on the trace
     331  if (trace) {
     332    ALLOCATE_PTR (outTraceBuffer, char, NxBase*Ny*sizeof(float));
     333    float *outTrace = (float *) outTraceBuffer;
     334    int NxBase2 = NxBase / 2;
     335
     336    for (int iy = 0; iy < Ny; iy++) {
     337
     338      // evaluate the trace spline at this y-coord to find the x-coord offset of the profile center
     339      float dx = -spline_apply_dbl (trace->xk, trace->yk, trace->y2, trace->Nknots, iy);
     340     
     341      // extract the integer pixel offset and the fractional offset
     342      int dxi = floor(dx); // -1.7 -> -2, -0.5 -> -1, +0.5 -> 0, +1.7 -> 1
     343      float dxf = dx - dxi;  // -1.7 -> +0.3, -0.5 -> +0.5, +0.5 ->+0.5, +1.7 -> +0.7
     344      float dxr = 1 - dxf;
     345
     346      // if fractional offset is small, do not interpolate
     347      int doInterp = fabs(dxf) < 1e-5 ? FALSE : TRUE;
     348     
     349      // How do I handle this?  define a temporary window which is a fraction of the full output window?
     350      int Sx = Nx2 - NxBase2 + dxi;
     351 
     352      // save the original output row
     353      // for (int ix = 0; ix < Nx; ix++) { tmprow[ix] = out[ix + iy*Nx]; }
     354
     355      for (int ix = 0; ix < NxBase; ix++) {
     356
     357        // equivalent coord in temporary buffer (Nx * Ny):
     358        int px = ix + Sx;
     359        if (px < 0) {
     360          outTrace[ix + iy*NxBase] = out[iy*Nx];
     361          continue;
     362        }
     363        if (px >= Nx) {
     364          outTrace[ix + iy*NxBase] = out[(Nx - 1) + iy*Nx];
     365          continue;
     366        }
     367       
     368        // a default value:
     369        float vout = NAN;
     370       
     371        int Npix = px + iy*Nx;
     372
     373        if (doInterp) {
     374          if ((px > 0) && (px < Nx - 1)) {
     375            vout = out[Npix]*dxr + out[Npix + 1]*dxf;
     376          }
     377          if (px == 0) {
     378            vout = out[Npix];
     379          }
     380          if (px == Nx - 1) {
     381            vout = out[Npix];
     382          }
     383        } else {
     384          vout = out[Npix];
     385        }
     386        outTrace[ix + iy*NxBase] = vout;
     387      }
     388    }
     389
     390    ResetBuffer (output, NxBase, Ny, -32, 0.0, 1.0);
     391    free (output[0].matrix.buffer);
     392    output[0].matrix.buffer = outTraceBuffer;
     393  }
     394
    157395  return TRUE;
    158396}
Note: See TracChangeset for help on using the changeset viewer.