IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 42653


Ignore:
Timestamp:
Apr 12, 2024, 2:49:40 PM (2 years ago)
Author:
eugene
Message:

added rudimentary 2D biassec mods

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/psModules.20240412/src/detrend/pmOverscan.c

    r42379 r42653  
    222222}
    223223
     224static int saveVectors = 1;
     225
    224226bool pmOverscanSubtract (pmReadout *input, pmOverscanOptions *overscanOpts) {
    225227
     
    339341    // We are performing a row-by-row overscan subtraction
    340342    int cellreaddir = psMetadataLookupS32(&mdok, input->parent->concepts, "CELL.READDIR"); // Read direction
    341     if ((cellreaddir != 1) && (cellreaddir != 2)) {
    342         psError(PS_ERR_UNKNOWN, true, "CELL.READDIR must be 1 (rows) or 2 (cols)\n");
     343    if ((cellreaddir != -1) && (cellreaddir != 1) && (cellreaddir != 2)) {
     344        psError(PS_ERR_UNKNOWN, true, "CELL.READDIR must be 1 (rows) or 2 (cols) or 0 (2D)\n");
    343345        return false;
    344346    }
     
    369371                values = psVectorRealloc(values, values->n + overscan->numCols);
    370372                values->n += overscan->numCols;
     373                // XXX double-check the range of values->n here
    371374                memcpy(&values->data.F32[index], overscan->data.F32[j],
    372375                       overscan->numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
     
    545548    }
    546549
     550    // 2D bias subtraction with x-dir readout direction: the
     551    // bias is constructed by combining a 1D pattern in the
     552    // readout direction from the top overscan region and a second
     553    // 1D pattern in the cross direction from the overscan
     554    if (cellreaddir == -1) {
     555        // we require 2 overscan regions, and they must match these directions:
     556        if (overscans->n != 2) {
     557            psLogMsg (__func__, PS_LOG_ERROR, "CELL.READDIR = -1, requires 2 overscan regions but %d supplied", (int) overscans->n);
     558            psLogMsg (__func__, PS_LOG_ERROR, "e.g.: CELL.BIASSEC STR [591:624,1:608],[1:590,598:608]");
     559            psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to generate overscan vector.\n");
     560            psFree(stats);
     561            return false;
     562        }
     563
     564        // the serial (fast readout) direction is columns (x-dir)
     565        psImage *yscan = psListGet (overscans, 0); // overscan region spanning all rows
     566        psImage *xscan = psListGet (overscans, 1); // overscan region spanning all columns
     567
     568        // Extract the y-dir overscan vector.  The overscan and image might not be aligned:
     569        // diff represents the offset between the rows in the image data and the overscan.
     570        // pixels->data represents the image row pixels. For example, the image region may be
     571        // inset in the y-direction but the overscan could cover the entire y-range
     572
     573        // The read direction is rows
     574        psArray *yscanPixels = psArrayAlloc(image->numRows); // Array of vectors containing pixels
     575        for (int i = 0; i < yscanPixels->n; i++) {
     576            yscanPixels->data[i] = psVectorAlloc(0, PS_TYPE_F32);
     577        }
     578
     579        // XXX this code allows multiple yscans to be appended, but this does not
     580        // match the concept of how they are assigned above: biassec[0] = yscan
     581        int yDiff = yscan->row0 - image->row0; // Offset between the two regions
     582        for (int i = PS_MAX(0,yDiff); i < PS_MIN(image->numRows, yscan->numRows + yDiff); i++) {
     583            int j = i - yDiff;
     584            // i is row on image, j is row on yscan
     585            psVector *values = yscanPixels->data[i];
     586            int index = values->n; // Index in the vector
     587            values = psVectorRealloc(values, values->n + yscan->numCols);
     588            values->n += yscan->numCols;
     589            // XXX double-check the range of values->n here
     590            memcpy(&values->data.F32[index], yscan->data.F32[j],
     591                   yscan->numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F32));
     592            index += yscan->numCols;
     593            yscanPixels->data[i] = values; // Update the pointer in case it's moved
     594        }
     595
     596        // Extract the x-dir overscan vector.  The overscan and image might not be aligned:
     597        // diff represents the offset between the rows in the image data and the overscan.
     598        // pixels->data represents the image row pixels. For example, the image region may be
     599        // inset in the x-direction but the overscan could cover the entire y-range
     600
     601        // Extract the top region as a vector of the columns
     602        psArray *xscanPixels = psArrayAlloc(image->numCols); // Array of vectors containing pixels
     603        for (int i = 0; i < xscanPixels->n; i++) {
     604            xscanPixels->data[i] = psVectorAlloc(0, PS_TYPE_F32);
     605        }
     606
     607        int xDiff = xscan->col0 - image->col0; // Offset between the two regions
     608        for (int ix = PS_MAX(0,xDiff); ix < PS_MIN(image->numCols, xscan->numCols + xDiff); ix++) {
     609            int jx = ix - xDiff;
     610            // ix is row on image, jx is column on xscan
     611            psVector *values = xscanPixels->data[ix];
     612            values = psVectorRealloc(values, xscan->numRows);
     613            values->n = xscan->numRows;
     614            for (int iy = 0; iy < xscan->numRows; iy++) {
     615                values->data.F32[iy] = xscan->data.F32[iy][jx];
     616            }
     617            xscanPixels->data[ix] = values; // Update the pointer in case it's moved
     618        }
     619
     620        // Reduce the overscans
     621        // XXX need to save 2 different chi-square values
     622        psVector *xReduced = pmOverscanVector(&chi2, overscanOpts, xscanPixels, stats);
     623        psFree(xscanPixels);
     624        if (!xReduced) {
     625            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate x-dir overscan vector.\n");
     626            psFree(stats);
     627            return false;
     628        }
     629
     630        // Reduce the overscans
     631        // XXX need to save 2 different chi-square values
     632        psVector *yReduced = pmOverscanVector(&chi2, overscanOpts, yscanPixels, stats);
     633        psFree(yscanPixels);
     634        if (!yReduced) {
     635            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to generate y-dir overscan vector.\n");
     636            psFree(stats);
     637            return false;
     638        }
     639
     640
     641        if (saveVectors) {
     642            FILE *foutX = fopen ("xdir.dat", "w");
     643            int fdX = fileno (foutX);
     644            p_psVectorPrint (fdX, xReduced, "xscan");
     645            fclose (foutX);
     646            FILE *foutY = fopen ("ydir.dat", "w");
     647            int fdY = fileno (foutY);
     648            p_psVectorPrint (fdY, yReduced, "yscan");
     649            fclose (foutY);
     650            saveVectors = 0;
     651        }
     652
     653        // write info about stats of y-dir overscan vector in header
     654        {
     655            psString comment = NULL;    // Comment to add
     656            psStats *vectorStats = psStatsAlloc (PS_STAT_SAMPLE_MEAN | PS_STAT_SAMPLE_STDEV);
     657            if (!psVectorStats (vectorStats, yReduced, NULL, NULL, 0)) {
     658                psError(PS_ERR_UNKNOWN, false, "failure to measure stats");
     659                return false;
     660            }
     661            psStringAppend(&comment, "Mean Overscan value: %f", vectorStats->sampleMean);
     662            psMetadataAddStr(hdu->header, PS_LIST_TAIL, "HISTORY", PS_META_DUPLICATE_OK, comment, "");
     663            psFree(comment);
     664
     665            // write metadata header value
     666            psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_VAL", PS_META_REPLACE, "Overscan mean", vectorStats->sampleMean);
     667            psMetadataAddF32(hdu->header, PS_LIST_TAIL, "OVER_SIG", PS_META_REPLACE, "Overscan stdev", vectorStats->sampleStdev);
     668
     669            // EAM 2022.03.29 : if the calculated overscan value is below the threshold,
     670            // declare the readout dead and mask
     671         
     672            if ((vectorStats->sampleMean < overscanOpts->minValid) || (vectorStats->sampleMean > overscanOpts->maxValid)) {
     673                fprintf (stderr, "bad overscan (2) %f, masking readout\n", vectorStats->sampleMean);
     674                psImage *mask = input->mask;
     675                for (int y = 0; y < mask->numRows; y++) {
     676                    for (int x = 0; x < mask->numCols; x++) {
     677                        mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] |= overscanOpts->maskVal;
     678                    }
     679                }
     680            }
     681            psFree (vectorStats);
     682        }
     683
     684        // XXX apply the 2D bias correction here
     685        for (int i = 0; i < image->numRows; i++) {
     686            for (int j = 0; j < image->numCols; j++) {
     687                image->data.F32[i][j] -= yReduced->data.F32[i];
     688            }
     689        }
     690
     691        // subtract the y-dir vector from the y-dir overscan regions (why?)
     692        {
     693            // the overscan and image might not be aligned.
     694            int diff = yscan->row0 - image->row0; // Offset between the two regions
     695            for (int i = PS_MAX(0,diff); i < PS_MIN(image->numRows, yscan->numRows + diff); i++) {
     696                int j = i - diff;
     697                // i is row on image (aligned with yReduced)
     698                // j is row on yscan
     699                for (int k = 0; k < yscan->numCols; k++) {
     700                    yscan->data.F32[j][k] -= yReduced->data.F32[i];
     701                }
     702            }
     703        }
     704
     705        // subtract the x-dir vector from the x-dir overscan regions (why?)
     706        {
     707            // the overscan and image might not be aligned.
     708            int diff = xscan->col0 - image->col0; // Offset between the two regions
     709            for (int i = PS_MAX(0,diff); i < PS_MIN(image->numCols, xscan->numCols + diff); i++) {
     710                int j = i - diff;
     711                // i is column on image (aligned with xReduced)
     712                // j is column on xscan
     713                for (int k = 0; k < xscan->numRows; k++) {
     714                    xscan->data.F32[k][j] -= xReduced->data.F32[i];
     715                }
     716            }
     717        }
     718        psFree(xReduced);
     719        psFree(yReduced);
     720    }
     721
    547722    pmOverscanUpdateHeader (hdu, overscanOpts, chi2);
    548723    psFree(stats);
Note: See TracChangeset for help on using the changeset viewer.