IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Feb 22, 2008, 9:28:00 AM (18 years ago)
Author:
Paul Price
Message:

Merging in branch development. ppStack now works with incremental reads. Needs some cleanup, but it works.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ppStack/src/ppStackLoop.c

    r15224 r16605  
    1111#include "ppStack.h"
    1212
     13// Here follows lists of files for activation/deactivation at various stages.  Each must be NULL-terminated.
     14
     15#if 0
     16// All files in the system
     17static char *allFiles[] = { "PPSTACK.INPUT", "PPSTACK.INPUT.MASK", "PPSTACK.INPUT.WEIGHT",
     18                            "PPSTACK.OUTPUT", "PPSTACK.OUTPUT.MASK", "PPSTACK.OUTPUT.WEIGHT",
     19                            "PSPHOT.PSF.SAVE", "PSPHOT.PSF.LOAD", "PPSTACK.SOURCES",
     20                            "PSPHOT.OUTPUT", "PSPHOT.RESID", "PSPHOT.BACKMDL", "PSPHOT.BACKMDL.STDEV",
     21                            "PSPHOT.BACKGND", "PSPHOT.BACKSUB", "SOURCE.PLOT.MOMENTS",
     22                            "SOURCE.PLOT.PSFMODEL", "SOURCE.PLOT.APRESID", "PSPHOT.INPUT.CMF",
     23                            0 };
     24#endif
     25
     26// Files required in preparation for convolution
     27static char *prepareFiles[] = { "PSPHOT.PSF.LOAD", "PPSTACK.SOURCES", 0 };
     28
     29// Files required for the convolution
     30static char *convolveFiles[] = { "PPSTACK.INPUT", "PPSTACK.INPUT.MASK", "PPSTACK.INPUT.WEIGHT", 0 };
     31
     32// Output files for the combination
     33static char *combineFiles[] = { "PPSTACK.OUTPUT", "PPSTACK.OUTPUT.MASK", "PPSTACK.OUTPUT.WEIGHT", 0 };
     34
     35// Files for photometry
     36static char *photFiles[] = { "PSPHOT.OUTPUT", "PSPHOT.RESID", "PSPHOT.BACKMDL",
     37                             "PSPHOT.BACKMDL.STDEV", "PSPHOT.BACKGND", "PSPHOT.BACKSUB",
     38                             "SOURCE.PLOT.MOMENTS", "SOURCE.PLOT.PSFMODEL", "SOURCE.PLOT.APRESID",
     39                             "PSPHOT.INPUT.CMF", 0 };
     40
     41//#define CONVOLVED_ALREADY               // Already have the convolution products --- testing
     42
     43
     44// Activate/deactivate a list of files
     45static void fileActivation(pmConfig *config, // Configuration
     46                           char **files, // Files to turn on/off
     47                           bool state   // Activation state
     48    )
     49{
     50    assert(config);
     51    assert(files);
     52
     53    for (int i = 0; files[i] != NULL; i++) {
     54        pmFPAfileActivate(config->files, state, files[i]);
     55    }
     56    return;
     57}
     58
     59// Activate/deactivate a single element for a list; return array of files
     60static psArray *fileActivationSingle(pmConfig *config, // Configuration
     61                                     char **files, // Files to turn on/off
     62                                     bool state,   // Activation state
     63                                     int num // Number of file in sequence
     64                                     )
     65{
     66    assert(config);
     67    assert(files);
     68
     69    psList *list = psListAlloc(NULL);   // List of files
     70
     71    for (int i = 0; files[i] != NULL; i++) {
     72        pmFPAfile *file = pmFPAfileActivateSingle(config->files, state, files[i], num); // Activated file
     73        psListAdd(list, PS_LIST_TAIL, file);
     74    }
     75
     76    psArray *array = psListToArray(list);
     77    psFree(list);
     78
     79    return array;
     80}
     81
     82#if 0
     83// Set the data level for a list of files
     84static void fileSetDataLevel(pmConfig *config, // Configuration
     85                             char **files, // Files for which to set level
     86                             pmFPALevel level // Level to set
     87                             )
     88{
     89    assert(config);
     90    assert(files);
     91
     92    for (int i = 0; files[i] != NULL; i++) {
     93        psArray *selected = pmFPAfileSelect(config->files, files[i]); // Selected files of interest
     94        for (int j = 0; j < selected->n; j++) {
     95            pmFPAfile *file = selected->data[j];
     96            assert(file);
     97            file->dataLevel = level;
     98        }
     99        psFree(selected);
     100    }
     101    return;
     102}
     103#endif
     104
     105// Iterate down the hierarchy, loading files; we can get away with this because we're working on skycells
     106static pmFPAview *filesIterateDown(pmConfig *config // Configuration
     107                                  )
     108{
     109    assert(config);
     110
     111    pmFPAview *view = pmFPAviewAlloc(0);// Pointer into FPA hierarchy
     112    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     113        return NULL;
     114    }
     115    view->chip = 0;
     116    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     117        return NULL;
     118    }
     119    view->cell = 0;
     120    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     121        return NULL;
     122    }
     123    view->readout = 0;
     124    if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     125        return NULL;
     126    }
     127    return view;
     128}
     129
     130// Iterate up the hierarchy, writing files; we can get away with this because we're working on skycells
     131static bool filesIterateUp(pmConfig *config // Configuration
     132                           )
     133{
     134    assert(config);
     135
     136    pmFPAview *view = pmFPAviewAlloc(0);// Pointer into FPA hierarchy
     137    view->chip = view->cell = view->readout = 0;
     138    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     139        return false;
     140    }
     141    view->readout = -1;
     142    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     143        return false;
     144    }
     145    view->cell = -1;
     146    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     147        return false;
     148    }
     149    view->chip = -1;
     150    if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     151        return false;
     152    }
     153    return true;
     154}
     155
     156#ifndef CONVOLVED_ALREADY
     157// Write an image to a FITS file
     158static bool writeImage(const char *name, // Name of image
     159                       psMetadata *header, // Header
     160                       const psImage *image // Image
     161                       )
     162{
     163    assert(name);
     164    assert(image);
     165
     166    psFits *fits = psFitsOpen(name, "w");
     167    if (!fits) {
     168        psError(PS_ERR_IO, false, "Unable to open FITS file to write image.");
     169        return false;
     170    }
     171    if (!psFitsWriteImage(fits, header, image, 0, NULL)) {
     172        psError(PS_ERR_IO, false, "Unable to write FITS image.");
     173        return false;
     174    }
     175    psFitsClose(fits);
     176    return true;
     177}
     178#endif
     179
     180
    13181bool ppStackLoop(pmConfig *config)
    14182{
     183    assert(config);
     184
    15185    psMaskType maskBlank = psMetadataLookupU8(NULL, config->arguments, "MASK.BLANK"); // Mask for blank reg.
    16186
     
    32202    }
    33203
    34     pmFPAfile *input = psMetadataLookupPtr(NULL, config->files, "PPSTACK.INPUT"); // Token input file
    35     if (!input) {
    36         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find input data!\n");
    37         return false;
    38     }
    39204    pmFPAfile *output = psMetadataLookupPtr(NULL, config->files, "PPSTACK.OUTPUT"); // Output file
    40205    if (!output) {
    41         psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find output data!\n");
    42         return false;
    43     }
    44 
    45     pmFPAview *view = pmFPAviewAlloc(0); // Pointer into FPA hierarchy
    46     pmHDU *lastHDU = NULL;              // Last HDU that was updated
    47 
    48     // Iterate over the FPA hierarchy
    49     if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    50         return false;
    51     }
    52 
    53     pmChip *chip;                       // Chip of interest
    54     while ((chip = pmFPAviewNextChip(view, input->fpa, 1)) != NULL) {
    55         if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    56             return false;
    57         }
    58 
    59         pmCell *cell;                // Cell of interest
    60         while ((cell = pmFPAviewNextCell(view, input->fpa, 1)) != NULL) {
    61             if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     206        psError(PS_ERR_UNEXPECTED_NULL, false, "Can't find output data!");
     207        return false;
     208    }
     209    int num = psMetadataLookupS32(NULL, config->arguments, "INPUTS.NUM"); // Number of inputs
     210    int numScans = psMetadataLookupS32(NULL, config->arguments, "ROWS"); // Number of scans to read at once
     211    psMetadata *ppsub = psMetadataLookupMetadata(NULL, config->recipes, "PPSUB"); // PPSUB recipe
     212    int overlap = 2 * psMetadataLookupS32(NULL, ppsub, "KERNEL.SIZE"); // Overlap by kernel size between consecutive scans
     213
     214    // Preparation iteration: Load the sources, and get a target PSF model
     215    pmReadout *sources = NULL;          // Readout with sources to use for PSF matching
     216    pmPSF *targetPSF = NULL;            // Target PSF
     217    {
     218        pmFPAfileActivate(config->files, false, NULL);
     219        fileActivation(config, prepareFiles, true);
     220        pmFPAview *view = filesIterateDown(config);
     221        if (!view) {
     222            return false;
     223        }
     224
     225        // We want to hang on to the 'sources' even when its host FPA is blown away
     226        sources = psMemIncrRefCounter(pmFPAfileThisReadout(config->files, view, "PPSTACK.SOURCES"));
     227        if (!sources) {
     228            psError(PS_ERR_UNKNOWN, true, "Unable to find sources.");
     229            psFree(view);
     230            return false;
     231        }
     232
     233        // Generate list of PSFs
     234        psMetadataIterator *fileIter = psMetadataIteratorAlloc(config->files, PS_LIST_HEAD,
     235                                                               "^PPSTACK.INPUT$"); // Iterator
     236        psMetadataItem *fileItem; // Item from iteration
     237        psList *psfList = psListAlloc(NULL); // List of PSFs for PSF envelope
     238        int numCols = 0, numRows = 0;   // Size of image
     239        while ((fileItem = psMetadataGetAndIncrement(fileIter))) {
     240            assert(fileItem->type == PS_DATA_UNKNOWN);
     241            pmFPAfile *inputFile = fileItem->data.V; // An input file
     242            pmChip *chip = pmFPAviewThisChip(view, inputFile->fpa); // The chip: holds the PSF
     243            pmPSF *psf = psMetadataLookupPtr(NULL, chip->analysis, "PSPHOT.PSF"); // PSF
     244            if (!psf) {
     245                psError(PS_ERR_UNKNOWN, false, "Unable to find PSF.");
     246                psFree(view);
     247                psFree(sources);
     248                psFree(fileIter);
     249                psFree(psfList);
    62250                return false;
    63251            }
    64 
    65             // Put version information into the header
     252            psListAdd(psfList, PS_LIST_TAIL, psf);
     253
     254            pmCell *cell = pmFPAviewThisCell(view, inputFile->fpa); // Cell of interest
    66255            pmHDU *hdu = pmHDUFromCell(cell);
    67             if (hdu && hdu != lastHDU) {
    68                 if (!hdu->header) {
    69                     hdu->header = psMetadataAlloc();
    70                 }
    71                 ppStackVersionMetadata(hdu->header);
    72                 lastHDU = hdu;
    73             }
    74 
    75             pmReadout *readout;         // Readout of interest
    76             while ((readout = pmFPAviewNextReadout(view, input->fpa, 1))) {
    77                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
     256            assert(hdu && hdu->header);
     257            int naxis1 = psMetadataLookupS32(NULL, hdu->header, "NAXIS1"); // Number of columns
     258            int naxis2 = psMetadataLookupS32(NULL, hdu->header, "NAXIS2"); // Number of rows
     259            if (naxis1 <= 0 || naxis2 <= 0) {
     260                psError(PS_ERR_UNKNOWN, false, "Unable to determine size of image from PSF.");
     261                psFree(view);
     262                psFree(sources);
     263                psFree(fileIter);
     264                psFree(psfList);
     265                return false;
     266            }
     267            if (numCols == 0 && numRows == 0) {
     268                numCols = naxis1;
     269                numRows = naxis2;
     270            }
     271        }
     272        psFree(fileIter);
     273        psFree(view);
     274
     275        targetPSF = ppStackPSF(config, numCols, numRows, psfList);
     276        psFree(psfList);
     277        if (!targetPSF) {
     278            psError(PS_ERR_UNKNOWN, false, "Unable to determine output PSF.");
     279            psFree(sources);
     280            return false;
     281        }
     282
     283        filesIterateUp(config);
     284    }
     285
     286    const char *suffix = "conv.fits";   // Suffix for convolved images; ultimately this will be from recipe
     287    const char *outName = psMetadataLookupStr(NULL, config->arguments, "OUTPUT"); // Output root
     288    assert(outName);
     289    psArray *imageNames = psArrayAlloc(num);
     290    psArray *maskNames = psArrayAlloc(num);
     291    psArray *weightNames = psArrayAlloc(num);
     292    for (int i = 0; i < num; i++) {
     293        psString imageName = NULL, maskName = NULL, weightName = NULL; // Names for convolved images
     294        psStringAppend(&imageName, "%s.im-%d.%s", outName, i, suffix);
     295        psStringAppend(&maskName, "%s.mk-%d.%s", outName, i, suffix);
     296        psStringAppend(&weightName, "%s.wt-%d.%s", outName, i, suffix);
     297        imageNames->data[i] = imageName;
     298        maskNames->data[i] = maskName;
     299        weightNames->data[i] = weightName;
     300    }
     301
     302    // Generate convolutions and write them to disk
     303    psArray *cells = psArrayAlloc(num); // Cells for convolved images --- a handle for reading again
     304    psArray *subKernels = psArrayAlloc(num); // Subtraction kernels --- required in the stacking
     305    psArray *subRegions = psArrayAlloc(num); // Subtraction regions --- required in the stacking
     306    for (int i = 0; i < num; i++) {
     307        pmFPAfileActivate(config->files, false, NULL);
     308        psArray *files = fileActivationSingle(config, convolveFiles, true, i);
     309        pmFPAview *view = filesIterateDown(config);
     310        if (!view) {
     311            psFree(sources);
     312            psFree(targetPSF);
     313            return false;
     314        }
     315
     316        pmReadout *readout = pmFPAviewThisReadout(view, ((pmFPAfile*)files->data[0])->fpa); // Input readout
     317        psFree(view);
     318
     319#ifndef CONVOLVED_ALREADY
     320        // Background subtraction, scaling and normalisation is performed automatically by the image matching
     321        psArray *regions = NULL, *kernels = NULL; // Regions and kernels used in subtraction
     322        if (!ppStackMatch(readout, &regions, &kernels, sources, targetPSF, config)) {
     323            psError(PS_ERR_UNKNOWN, false, "Unable to match image %d --- ignoring.", i);
     324            psFree(sources);
     325            psFree(targetPSF);
     326            return false;
     327        }
     328
     329        subRegions->data[i] = regions;
     330        subKernels->data[i] = kernels;
     331
     332        // Write the temporary convolved files
     333        pmHDU *hdu = readout->parent->parent->parent->hdu; // HDU for convolved image
     334        assert(hdu);
     335        writeImage(imageNames->data[i],  hdu->header, readout->image);
     336        writeImage(maskNames->data[i],   hdu->header, readout->mask);
     337        writeImage(weightNames->data[i], hdu->header, readout->weight);
     338#endif
     339
     340        cells->data[i] = psMemIncrRefCounter(readout->parent);
     341        filesIterateUp(config);
     342    }
     343    psFree(sources);
     344    psFree(targetPSF);
     345
     346    // Stack the convolved files
     347    {
     348        pmFPAfileActivate(config->files, false, NULL);
     349        fileActivation(config, combineFiles, true);
     350        if (psMetadataLookupBool(&mdok, config->arguments, "PHOTOMETRY")) {
     351            fileActivation(config, photFiles, true);
     352        }
     353        pmFPAview *view = filesIterateDown(config);
     354        if (!view) {
     355            psFree(cells);
     356            psFree(subKernels);
     357            psFree(subRegions);
     358            return false;
     359        }
     360        pmCell *outCell = pmFPAfileThisCell(config->files, view, "PPSTACK.OUTPUT"); // Output cell
     361        pmReadout *outRO = pmReadoutAlloc(outCell); // Output readout
     362
     363        psArray *readouts = psArrayAlloc(num); // Readouts for convolved images
     364        for (int i = 0; i < num; i++) {
     365            readouts->data[i] = pmReadoutAlloc(cells->data[i]); // Readout into which to read
     366        }
     367        psFree(cells);
     368
     369        // FITS files
     370        psArray *imageFits  = psArrayAlloc(num);
     371        psArray *maskFits   = psArrayAlloc(num);
     372        psArray *weightFits = psArrayAlloc(num);
     373        for (int i = 0; i < num; i++) {
     374            imageFits->data[i] = psFitsOpen(imageNames->data[i], "r");
     375            maskFits->data[i] = psFitsOpen(maskNames->data[i], "r");
     376            weightFits->data[i] = psFitsOpen(weightNames->data[i], "r");
     377        }
     378
     379        // Read convolutions by chunks
     380        bool more = true;               // More to read?
     381        for (int numChunk = 0; more; numChunk++) {
     382            for (int i = 0; i < num; i++) {
     383                pmReadout *readout = readouts->data[i];
     384                assert(readout);
     385
     386                if (!pmReadoutReadChunk(readout, imageFits->data[i], 0, numScans, overlap) ||
     387                    !pmReadoutReadChunkMask(readout, maskFits->data[i], 0, numScans, overlap) ||
     388                    !pmReadoutReadChunkWeight(readout, weightFits->data[i], 0, numScans, overlap)) {
     389                    psError(PS_ERR_IO, false, "Unable to read chunk %d for file %d", numChunk, i);
     390                    psFree(readouts);
     391                    psFree(subKernels);
     392                    psFree(subRegions);
     393                    psFree(outRO);
     394                    psFree(view);
    78395                    return false;
    79396                }
    80 
    81                 // Perform the analysis
    82                 if (!ppStackReadout(config, view)) {
    83                     psError(PS_ERR_UNKNOWN, false, "Unable to stack images.\n");
    84                     return false;
    85                 }
    86 
    87                 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) {
    88                     return false;
    89                 }
    90             }
    91 
    92             // Perform statistics on the cell
    93             if (stats) {
    94                 ppStatsFPA(stats, output->fpa, view, maskBlank, config);
    95             }
    96 
    97             if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
     397            }
     398
     399#ifdef TESTING
     400            {
     401                pmReadout *ro = readouts->data[0];
     402                psTrace("ppStack", 1, "Stack: [%d:%d,%d:%d]\n", ro->col0, ro->col0 + ro->image->numCols,
     403                        ro->row0, ro->row0 + ro->image->numRows);
     404            }
     405#endif
     406
     407            if (!ppStackReadout(config, outRO, readouts, subRegions, subKernels)) {
     408                psError(PS_ERR_UNKNOWN, false, "Unable to stack images.\n");
     409                psFree(readouts);
     410                psFree(subKernels);
     411                psFree(subRegions);
     412                psFree(outRO);
     413                psFree(view);
    98414                return false;
    99415            }
    100         }
    101 
    102         if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    103             return false;
    104         }
    105     }
    106 
    107     if (!pmFPAfileIOChecks(config, view, PM_FPA_AFTER)) {
    108         return false;
    109     }
    110 
    111     psFree(view);
     416
     417            for (int i = 0; i < num && more; i++) {
     418                pmReadout *readout = readouts->data[i];
     419                assert(readout);
     420                more &= pmReadoutMore(readout, imageFits->data[i], 0, numScans);
     421                more &= pmReadoutMoreMask(readout, maskFits->data[i], 0, numScans);
     422                more &= pmReadoutMoreWeight(readout, weightFits->data[i], 0, numScans);
     423            }
     424        }
     425
     426        psFree(readouts);
     427        psFree(subKernels);
     428        psFree(subRegions);
     429        for (int i = 0; i < num; i++) {
     430            psFitsClose(imageFits->data[i]);
     431            psFitsClose(maskFits->data[i]);
     432            psFitsClose(weightFits->data[i]);
     433        }
     434
     435        if (psMetadataLookupBool(&mdok, config->arguments, "PHOTOMETRY") &&
     436            !ppStackPhotometry(config, outRO, view)) {
     437            psError(PS_ERR_UNKNOWN, false, "Unable to perform photometry on output.");
     438            psFree(outRO);
     439            psFree(view);
     440            return false;
     441        }
     442
     443        // Statistics on output
     444        if (stats) {
     445            ppStatsFPA(stats, outCell->parent->parent, view, maskBlank, config);
     446        }
     447
     448        // Put version information into the header
     449        pmHDU *hdu = pmHDUFromCell(outRO->parent);
     450        if (!hdu) {
     451            psError(PS_ERR_UNKNOWN, false, "Unable to find HDU for output.");
     452            return false;
     453        }
     454        if (!hdu->header) {
     455            hdu->header = psMetadataAlloc();
     456        }
     457        ppStackVersionMetadata(hdu->header);
     458
     459        // Write out the output files
     460        fileActivation(config, combineFiles, true);
     461        filesIterateUp(config);
     462
     463        psFree(outRO);
     464        psFree(view);
     465    }
     466
    112467
    113468    // Write out summary statistics
Note: See TracChangeset for help on using the changeset viewer.