IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15318


Ignore:
Timestamp:
Oct 15, 2007, 4:49:27 PM (19 years ago)
Author:
bills
Message:

Using mosaic was problematic because coordinate system changes,
so process readouts directly. Various other changes.

Location:
trunk/ppstamp/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppstamp/src/ppstampCleanup.c

    r15280 r15318  
    2020
    2121    // psMemCheckLeaks (0, NULL, stderr, false);
    22     // fprintf (stderr, "Found %d leaks in %s\n", psMemCheckLeaks (0, NULL, NULL, false), "ppstamp");
     22    fprintf (stderr, "Found %d leaks in %s\n", psMemCheckLeaks (0, NULL, NULL, false), "ppstamp");
    2323
    2424    return;
  • trunk/ppstamp/src/ppstampMakeStamp.c

    r15280 r15318  
    55#include "ppstamp.h"
    66#include "pmFPAAstrometry.h"
    7 
    8 #define USE_MOSAIC
     7#include "pmAstrometryUtils.h"
     8
     9#define WCS_NONLIN_TOL 0.001            // Non-linear tolerance for header WCS
    910
    1011typedef enum {
    11     PPSTAMP_OFF_CHIP,
    12     PPSTAMP_PARTIALLY_ON_CHIP,
    13     PPSTAMP_ON_CHIP,
     12    PPSTAMP_OFF,
     13    PPSTAMP_PARTIALLY_ON,
     14    PPSTAMP_ON,
    1415    PPSTAMP_ERROR
    1516} ppstampOverlap;
     
    1718static bool regionContainsPoint(psRegion *region, psPlane *point);
    1819static bool regionContainsRegion(psRegion *outer, psRegion *inner);
    19 static bool copyMetadata(pmFPAfile *output, pmFPAfile *input, pmChip *inChip);
    20 
    21 static pmFPAfile *buildMosaic(pmConfig *config, pmFPAfile *input, pmFPAview *view, pmFPAview *mosaicView)
    22 {
    23     bool    status;
    24 
    25     pmFPAfile *mosaic =  psMetadataLookupPtr(&status, config->files, "PPSTAMP.CHIP");
    26     if (!status)  {
    27         psErrorStackPrint(stderr, "can't find mosaic i/o file\n");
    28         exit(EXIT_FAILURE);
    29     }
    30 
    31     pmChip  *mChip  = pmFPAviewThisChip(mosaicView, mosaic->fpa);
    32     pmChip  *inChip = pmFPAviewThisChip(view, input->fpa);
    33     if (!mChip->hdu && !mChip->parent->hdu) {
    34         const char *name = psMetadataLookupStr(&status, input->fpa->concepts, "FPA.NAME"); // Name of FPA
    35         pmFPAAddSourceFromView(mosaic->fpa, name, mosaicView, mosaic->format);
    36     }
    37 
    38     psMaskType blankMask = pmConfigMask("BLANK", config);
    39 
    40     status = pmChipMosaic(mChip, inChip, true, blankMask);
    41     if (status) {
    42         return mosaic;
    43     } else {
    44         return NULL;
    45     }
     20static bool copyMetadata(pmFPAfile *output, pmFPAfile *input, pmChip *inChip, pmCell *inCell,
     21                        psRegion *roi);
     22
     23
     24static ppstampOverlap findCell(pmFPAview *view, ppstampOptions *options, pmFPAfile *input,
     25                                pmAstromObj *center, pmCell **ppCell)
     26{
     27    pmCell *cell;
     28
     29    view->cell = -1;
     30    while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
     31        psRegion *cellExtent = pmCellExtent(cell);
     32        if (regionContainsPoint(cellExtent, center->chip)) {
     33            if (regionContainsRegion(cellExtent, &options->roi)) {
     34                *ppCell = cell;
     35                psFree(cellExtent);
     36                return PPSTAMP_ON;
     37            } else {
     38                fprintf(stderr, "ROI must be confined to single cell. Partial overlap cell %d\n",
     39                    view->cell);
     40                psFree(cellExtent);
     41                return PPSTAMP_PARTIALLY_ON;
     42            }
     43        }
     44        psFree(cellExtent);
     45    }
     46
     47    // This shouldn't ever happen since ROI is on the chip, it must at least partially overlap
     48    // one of the cells
     49    psError(PS_ERR_PROGRAMMING, false, "findCell couldn't find a cell containing the center\n");
     50
     51    return PPSTAMP_OFF;
    4652}
    4753
    4854static bool makeStamp(pmConfig *config, ppstampOptions *options, pmFPAfile *input,
    49                 pmChip *chip, pmFPAview *view)
     55                pmChip *inChip, pmCell *inCell, pmFPAview *view)
    5056{
    5157    int status = false;
     58
    5259    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSTAMP.OUTPUT");
    5360    if (!output) {
     
    6673    outview = NULL;
    6774
     75    //    psMetadataPrint(stderr, inChip->concepts, 0);
     76    //   psMetadataPrint(stderr, inCell->concepts, 0);
    6877    // these default to zero would that be ok?
    6978    psMetadataAddS32(target->concepts, PS_LIST_TAIL, "CELL.XBIN", PS_META_REPLACE, "Binning in x", 1);
    7079    psMetadataAddS32(target->concepts, PS_LIST_TAIL, "CELL.YBIN", PS_META_REPLACE, "Binning in y", 1);
    7180
    72     // we extract our postage stamp from a mosaic so that
    73     // pmChipMosaic can handle all of the complexities of parity, binning, etc.
    74     pmFPAview *mosaicView = pmFPAviewAlloc(0);
    75     mosaicView->chip = 0;
    76     pmFPAfile *mosaic = buildMosaic(config, input, view, mosaicView);
    77     if (mosaic == NULL) {
    78         psFree(mosaicView);
    79         return false;
    80     }
    81 
    82     mosaicView->cell = 0;
    8381    pmReadout *readout;
    84     while ((readout = pmFPAviewNextReadout (mosaicView, mosaic->fpa, 1)) != NULL) {
     82    while ((readout = pmFPAviewNextReadout (view, input->fpa, 1)) != NULL) {
    8583        if (!readout->data_exists) {
    86             // HMM, this probably means something is wrong
     84            // XXX if this happens something is wrong
    8785            continue;
    8886        }
     
    9492        }
    9593
    96         // define a subset of the mosaic's readout
     94        // XXX Do we have to do somethign to deal with negative parity
    9795        psImage *subsetImage = psImageSubset(readout->image, options->roi);
    9896        if (subsetImage) {
     
    10199            psFree(subsetImage);
    102100            if (outReadout->image) {
    103                 // TODO: put this into a function in psImage
    104                 // (What I really needed was a function to "create a copy of this portion of an image)
     101                // XXX put this into a function in psImage
     102                // (What I really needed was a function to "create a copy of this portion of an image")
    105103                P_PSIMAGE_SET_COL0(outReadout->image, 0);
    106104                P_PSIMAGE_SET_ROW0(outReadout->image, 0);
     
    121119    }
    122120
    123     psFree(mosaicView);
    124 
    125121    if (status) {
    126         status = copyMetadata(output, input, chip);
     122        status = copyMetadata(output, input, inChip, inCell, &options->roi);
    127123    }
    128124    return status;
    129125}
    130126
    131 static bool copyMetadata(pmFPAfile *output, pmFPAfile *input, pmChip *inChip)
     127
     128static bool copyWCS(pmHDU *outHDU, pmFPA *outFPA, pmChip *outChip, pmChip *inChip, psRegion *roi)
     129{
     130    pmHDU *hdu = pmHDUFromChip(inChip);
     131    PS_ASSERT_PTR_NON_NULL(hdu, 1)
     132    PS_ASSERT_PTR_NON_NULL(hdu->header, 1)
     133
     134#ifdef BRUTE_FORCE
     135    outChip->toFPA = inChip->toFPA;
     136    outChip->fromFPA = inChip->fromFPA;
     137    inChip->toFPA = 0;
     138    inChip->fromFPA = 0;
     139
     140    // This gets us within one pixel of the correct answer
     141    psMetadataItemSupplement(outHDU->header, hdu->header, "CD1_1");
     142    psMetadataItemSupplement(outHDU->header, hdu->header, "CD1_2");
     143    psMetadataItemSupplement(outHDU->header, hdu->header, "CD2_1");
     144    psMetadataItemSupplement(outHDU->header, hdu->header, "CD2_2");
     145    psMetadataItemSupplement(outHDU->header, hdu->header, "CRVAL1");
     146    psMetadataItemSupplement(outHDU->header, hdu->header, "CRVAL2");
     147
     148    double crpix1 = psMetadataLookupF64(NULL, hdu->header, "CRPIX1");
     149    double crpix2 = psMetadataLookupF64(NULL, hdu->header, "CRPIX2");
     150
     151    crpix1 -= roi->x0;
     152    crpix2 -= roi->y0;
     153    psMetadataAddF64(outHDU->header, PS_LIST_TAIL, "CRPIX1", PS_META_REPLACE, "", crpix1);
     154    psMetadataAddF64(outHDU->header, PS_LIST_TAIL, "CRPIX2", PS_META_REPLACE, "", crpix2);
     155
     156
     157#else
     158
     159    bool combineTransform = false;
     160    if (combineTransform) {
     161        // translation from output chip coordinates to input chip coordinates
     162        psPlaneTransform *trans = psPlaneTransformAlloc(1, 1);
     163
     164        trans->x->coeff[0][0] = roi->x0;
     165        trans->x->coeff[0][1] = 0;
     166        trans->x->coeff[1][0] = 1.0;
     167        trans->x->coeff[1][1] = 0;
     168
     169        trans->y->coeff[0][0] = roi->y0;
     170        trans->y->coeff[0][1] = 1.0;
     171        trans->y->coeff[1][0] = 0;
     172        trans->y->coeff[1][1] = 0;
     173
     174        // combine the translation with the input's transform
     175        // Note: the region and magic number are not actually used by psPlaneTransformCombine
     176        outChip->toFPA = psPlaneTransformCombine(NULL, trans, inChip->toFPA, *roi, 50);
     177
     178        // for completeness we set fromFPA, but since we don't use it ...
     179        outChip->fromFPA = psPlaneTransformInvert(NULL, outChip->toFPA, *roi, 50);
     180
     181        // psFree(region);
     182        psFree(trans);
     183    } else {
     184        outChip->toFPA = psPlaneTransformSetCenter(NULL, inChip->toFPA, roi->x0, roi->y0);
     185        outChip->fromFPA = psPlaneTransformInvert(NULL, outChip->toFPA, *roi, 50);
     186    }
     187
     188
     189    if (!pmAstromWriteWCS(outHDU->header, outFPA, outChip, WCS_NONLIN_TOL)) {
     190        psError(PS_ERR_UNKNOWN, false, "Failed to write WCS\n");
     191        return false;
     192    }
     193#endif
     194
     195    return true;
     196}
     197
     198
     199static bool copyMetadata(pmFPAfile *output, pmFPAfile *input, pmChip *inChip, pmCell *inCell, psRegion *roi)
    132200{
    133201    pmChip    *outChip;
     
    141209    outChip->parent->concepts = psMetadataCopy(outChip->parent->concepts, inChip->parent->concepts);
    142210
    143     pmHDU *inHDU = pmHDUGetHighest(input->fpa, inChip, NULL);
     211    pmHDU *inHDU  = pmHDUGetHighest(input->fpa, inChip, NULL);
    144212    pmHDU *outHDU = pmHDUGetHighest(output->fpa, outChip, NULL);
    145213
     
    149217        outHDU->header = psMetadataAlloc();
    150218    }
    151     // TODO set up the astrometry related information
     219
     220    // steal the input fpa's transforms
     221    output->fpa->toTPA = input->fpa->toTPA;
     222    output->fpa->fromTPA = input->fpa->fromTPA;
     223    output->fpa->toSky = input->fpa->toSky;
     224    // drop references
     225    input->fpa->toTPA = 0;
     226    input->fpa->fromTPA = 0;
     227    input->fpa->toSky = 0;
     228
     229    if (!copyWCS(outHDU, output->fpa, outChip, inChip, roi)) {
     230        return false;
     231    }
     232
    152233    return true;
    153234}
    154235
    155236
    156 ppstampOverlap findROI(ppstampOptions *options, pmFPAfile *input, pmChip *chip,
    157                 pmAstromObj *center, psRegion *roi)
     237// findROI: find whether the region of interest is completely contained in a cell on a given chip.
     238//  If so return the cell
     239ppstampOverlap findROI(ppstampOptions *options, pmFPAview *view, pmFPAfile *input, pmChip *chip,
     240                pmAstromObj *center, psRegion *roi, pmCell **ppCell)
    158241{
    159242    psRegion    *chipExtent = pmChipPixels(chip);
    160243    bool        onChip = false;
    161     ppstampOverlap   returnval = PPSTAMP_OFF_CHIP;
     244    ppstampOverlap   returnval = PPSTAMP_OFF;
    162245    psString chipName = psMetadataLookupStr(NULL, chip->concepts, "CHIP.NAME");
    163246
    164     if (options->celestialCenter || options->celestialRange) {
    165         // set up the astrometry
    166         pmHDU *hdu = pmHDUFromChip(chip);
    167         PS_ASSERT_PTR_NON_NULL(hdu, 1)
    168         PS_ASSERT_PTR_NON_NULL(hdu->header, 1)
    169 
    170         if (!pmAstromReadWCS(input->fpa, chip, hdu->header, 1.0)) {
    171             psError(PS_ERR_UNKNOWN, false, "Failed to Read WCS\n");
    172             psFree(chipExtent);
    173             psFree(center);
    174             return PPSTAMP_ERROR;
    175         }
     247    // set up the astrometry
     248    pmHDU *hdu = pmHDUFromChip(chip);
     249    PS_ASSERT_PTR_NON_NULL(hdu, 1)
     250    PS_ASSERT_PTR_NON_NULL(hdu->header, 1)
     251
     252    if (!pmAstromReadWCS(input->fpa, chip, hdu->header, 1.0)) {
     253        psError(PS_ERR_UNKNOWN, false, "Failed to Read WCS\n");
     254        psFree(chipExtent);
     255        psFree(center);
     256        return PPSTAMP_ERROR;
    176257    }
    177258
     
    191272
    192273        if (regionContainsPoint(chipExtent, center->chip)) {
    193             psLogMsg("ppstampMakeStamp", 3, "Found center on chip: %s\n", chipName);
     274            psLogMsg("ppstampMakeStamp", 3, "Found center (%f %f) on chip: %s\n",
     275                center->chip->x, center->chip->y, chipName);
    194276            onChip = true;
    195277        }
     
    227309
    228310            if (regionContainsRegion(chipExtent, roi)) {
    229                 returnval = PPSTAMP_ON_CHIP;
     311                returnval = findCell(view, options, input, center, ppCell);
    230312            } else {
    231                 returnval = PPSTAMP_PARTIALLY_ON_CHIP;
     313                fprintf(stderr, "Partial Overlap chip %s\n", chipName);
     314                fprintf(stderr, "ChipExtent: %s\n", psRegionToString(*chipExtent));
     315                fprintf(stderr, "ROI:        %s\n", psRegionToString(*roi));
     316
     317                returnval = PPSTAMP_PARTIALLY_ON;
    232318            }
    233319        }
     
    255341    // files associated with the science image
    256342    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    257         // TODO log error
    258343        psError(PS_ERR_UNKNOWN, false, "Failed to load input.");
    259344        psFree(center);
     
    272357
    273358        if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    274             // TODO log error
    275359            psError(PS_ERR_UNKNOWN, false, "failed to load chip");
    276360            status = false;
     
    278362        }
    279363
    280         ppstampOverlap overlap = findROI(options, input, chip, center, &options->roi);
    281 
    282         if (overlap == PPSTAMP_ON_CHIP) {
    283 
    284             returnval = makeStamp(config, options, input, chip, view);
     364        pmCell *cell;
     365        ppstampOverlap overlap = findROI(options, view, input, chip, center, &options->roi, &cell);
     366
     367        if (overlap == PPSTAMP_ON) {
     368
     369            returnval = makeStamp(config, options, input, chip, cell, view);
    285370
    286371            allDone = true;
    287         } else if (overlap == PPSTAMP_PARTIALLY_ON_CHIP) {
    288             psError(PS_ERR_UNKNOWN, false, "Region of interest must be confined to a single chip\n");
     372        } else if (overlap == PPSTAMP_PARTIALLY_ON) {
     373            psError(PS_ERR_UNKNOWN, false, "Region of interest must be confined to a single cell\n");
    289374            // XXX: perhaps print a helpful message about what coordinates would be valid
    290375            returnval = false;
     
    301386            view->cell = -1;
    302387            break;
     388        } else {
     389            // Remove the transformations from the fpa so that they will be
     390            // recalculated from scratch for the next chip.
     391            // If I don't do this the calculation of the astrometry parameters for the output file
     392            // don't come out correctly. See the code on the false side of the test
     393            // if (fpa->toSky == NULL) in the function pmAstromWCStoFPA
     394            psFree(input->fpa->fromTPA);
     395            psFree(input->fpa->toTPA);
     396            psFree(input->fpa->toSky);
     397            input->fpa->fromTPA = NULL;
     398            input->fpa->toTPA = NULL;
     399            input->fpa->toSky = NULL;
    303400        }
    304401    }
Note: See TracChangeset for help on using the changeset viewer.