IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 7168


Ignore:
Timestamp:
May 22, 2006, 2:23:08 PM (20 years ago)
Author:
Paul Price
Message:

Adding pmHDUGenerate to make an HDU (image) from the cells contained below. Altered pmFPACopy to use pmHDUGenerate functions. The motivation for pmHDUGenerate is that when we go through an FPA bit by bit, creating an output FPA, we don't know the size of the resultant output images until we're done with the whole lot. So we simply create the cells, and call pmHDUGenerateFromFPA (etc) to generate the HDU image which is then written out. It takes care of the TRIMSEC, BIASSEC, etc.

Location:
trunk/psModules/src/camera
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/camera/Makefile.am

    r7017 r7168  
    1313        pmHDU.c \
    1414        pmHDUUtils.c \
     15        pmHDUGenerate.c \
    1516        pmReadout.c \
    1617        pmChipMosaic.c \
     
    3334        pmHDU.h \
    3435        pmHDUUtils.h \
     36        pmHDUGenerate.h \
    3537        pmReadout.h \
    3638        pmChipMosaic.h \
  • trunk/psModules/src/camera/pmFPAConstruct.c

    r7017 r7168  
    1010#include "pmFPAview.h"
    1111#include "pmFPAUtils.h"
     12#include "pmHDUUtils.h"
    1213
    1314//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    690691    psTrace(__func__, 1, "FPA:\n");
    691692    if (fpa->hdu) {
    692         psTrace(__func__, 2, "---> FPA is extension %s.\n", fpa->hdu->extname);
    693         if (! fpa->hdu->images) {
    694             psTrace(__func__, 2, "---> NO PIXELS read in for extension %s\n", fpa->hdu->extname);
    695         }
    696         if (header) {
    697             if (fpa->hdu->header) {
    698                 psTrace(__func__, 2, "---> Header:\n");
    699                 psMetadataPrint(fpa->hdu->header, 8);
    700             } else {
    701                 psTrace(__func__, 2, "---> NO HEADER read in for extension %s\n", fpa->hdu->extname);
    702             }
    703         }
     693        pmHDUPrint(fpa->hdu, 2, header);
    704694    }
    705695    if (concepts) {
     
    713703        pmChip *chip = chips->data[i]; // The chip
    714704        if (chip->hdu) {
    715             psTrace(__func__, 4, "---> Chip is extension %s.\n", chip->hdu->extname);
    716             if (header) {
    717                 if (chip->hdu->header) {
    718                     psTrace(__func__, 4, "---> Header:\n");
    719                     psMetadataPrint(chip->hdu->header, 8);
    720                 } else {
    721                     psTrace(__func__, 4, "---> NO HEADER read in for extension %s\n", chip->hdu->extname);
    722                 }
    723             }
    724             if (! chip->hdu->images) {
    725                 psTrace(__func__, 4, "---> NO PIXELS read in for extension %s\n", chip->hdu->extname);
    726             }
     705            pmHDUPrint(chip->hdu, 4, header);
    727706        }
    728707        if (concepts) {
     
    736715            pmCell *cell = cells->data[j]; // The cell
    737716            if (cell->hdu) {
    738                 psTrace(__func__, 6, "---> Cell is extension %s.\n", cell->hdu->extname);
    739                 if (header) {
    740                     if (cell->hdu->header) {
    741                         psTrace(__func__, 6, "---> Header:\n");
    742                         psMetadataPrint(cell->hdu->header, 8);
    743                     } else {
    744                         psTrace(__func__, 6, "---> NO HEADER read in for extension %s\n", cell->hdu->extname);
    745                     }
    746                 }
    747                 if (! cell->hdu->images) {
    748                     psTrace(__func__, 6, "---> NO PIXELS read in for extension %s\n", cell->hdu->extname);
    749                 }
     717                pmHDUPrint(cell->hdu, 6, header);
    750718            }
    751719            if (concepts) {
     
    753721            }
    754722
    755             psTrace(__func__, 7, "Readouts:\n");
    756723            psArray *readouts = cell->readouts; // Array of readouts
    757724            for (int k = 0; k < readouts->n; k++) {
    758725                pmReadout *readout = readouts->data[k]; // The readout
    759                 psTrace(__func__, 8, "row0: %d\n", readout->row0);
     726                psTrace(__func__, 6, "Readout %d:\n", k);
     727                psTrace(__func__, 7, "row0: %d\n", readout->row0);
     728                psTrace(__func__, 7, "col0: %d\n", readout->col0);
    760729                psImage *image = readout->image; // The image
    761730                psList *bias = readout->bias; // The list of bias images
    762731                if (image) {
    763                     psTrace(__func__, 8, "Image: [%d:%d,%d:%d] (%dx%d)\n", image->col0, image->col0 +
     732                    psTrace(__func__, 7, "Image: [%d:%d,%d:%d] (%dx%d)\n", image->col0, image->col0 +
    764733                            image->numCols, image->row0, image->row0 + image->numRows, image->numCols,
    765734                            image->numRows);
     
    769738                    psImage *biasImage = NULL; // Bias image from iteration
    770739                    while ((biasImage = psListGetAndIncrement(biasIter))) {
    771                         psTrace(__func__, 8, "Bias:  [%d:%d,%d:%d] (%dx%d)\n", biasImage->col0,
     740                        psTrace(__func__, 7, "Bias:  [%d:%d,%d:%d] (%dx%d)\n", biasImage->col0,
    772741                                biasImage->col0 + biasImage->numCols, biasImage->row0,
    773742                                biasImage->row0 + biasImage->numRows, biasImage->numCols, biasImage->numRows);
  • trunk/psModules/src/camera/pmFPACopy.c

    r7017 r7168  
    1010#include "pmHDU.h"
    1111#include "pmHDUUtils.h"
     12#include "pmHDUGenerate.h"
     13
    1214#include "pmFPACopy.h"
    1315
    14 #define MAX(x,y) ((x) > (y) ? (x) : (y))
    15 
    16 
    1716//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1817// File-static functions
    1918//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2019
    21 // Add cells in a chip to a list
    22 static bool addCellsFromChip(psList *list, // List of cells
    23                              const pmChip *chip // The chip from which to add cells
    24                             )
    25 {
    26     assert(list);
    27     assert(chip);
    28 
    29     psArray *cells = chip->cells;       // Array of cells
    30     bool result = true;                 // Result of adding cells
    31     for (int i = 0; i < cells->n; i++) {
    32         pmCell *cell = cells->data[i];  // A cell
    33         result |= psListAdd(list, PS_LIST_TAIL, cell);
    34     }
    35 
    36     return result;
    37 }
    38 
    39 // Add cells in an FPA to a list
    40 static bool addCellsFromFPA(psList *list, // List of cells
    41                             const pmFPA *fpa // The FPA from which to add cells
    42                            )
    43 {
    44     assert(list);
    45     assert(fpa);
    46 
    47     psArray *chips = fpa->chips;        // Array of chips
    48     bool result = true;                 // Result of adding cells
    49     for (int i = 0; i < chips->n; i++) {
    50         pmChip *chip = chips->data[i];  // A chip
    51         result |= addCellsFromChip(list, chip);
    52     }
    53 
    54     return result;
    55 }
    56 
    57 // Get a list of cells that share the HDU for the target cell
    58 static bool cellList(psList *targets,   // The list of target cells
    59                      psList *sources,   // The list of source cells
    60                      pmCell *targetCell, // The target cell
    61                      pmCell *sourceCell // The source cell
    62                     )
    63 {
    64     assert(targetCell);
    65     assert(sourceCell);
    66 
    67     if (targetCell->hdu) {
    68         if (targets) {
    69             psListAdd(targets, PS_LIST_TAIL, targetCell);
    70         }
    71         if (sources) {
    72             psListAdd(sources, PS_LIST_TAIL, sourceCell);
    73         }
    74     } else {
    75         pmChip *targetChip = targetCell->parent; // The target parent chip
    76         pmChip *sourceChip = sourceCell->parent; // The source parent chip
    77         if (targetChip->hdu) {
    78             if (targets) {
    79                 addCellsFromChip(targets, targetChip);
    80             }
    81             if (sources) {
    82                 addCellsFromChip(sources, sourceChip);
    83             }
    84         } else {
    85             pmFPA *targetFPA = targetChip->parent; // The target parent FPA
    86             pmFPA *sourceFPA = sourceChip->parent; // The source parent FPA
    87             if (targetFPA->hdu) {
    88                 if (targets) {
    89                     addCellsFromFPA(targets, targetFPA);
    90                 }
    91                 if (sources) {
    92                     addCellsFromFPA(sources, sourceFPA);
    93                 }
    94             } else {
    95                 psError(PS_ERR_IO, true, "Unable to find HDU for cell to generate list!\n");
    96                 return false;
    97             }
    98         }
    99     }
    100 
    101     return true;
    102 }
    103 
    104 // Get the maximum extent of the HDU from the trimsec and biassecs
    105 static bool sizeHDU(int *xSize, int *ySize, // Size of HDU
    106                     psList *cells       // List of cells
    107                    )
    108 {
    109     psListIterator *cellsIter = psListIteratorAlloc(cells, PS_LIST_HEAD, false); // Iterator for cells
    110     pmCell *cell = NULL;                // The cell from iteration
    111     bool mdok = true;                   // Status of MD lookup
    112     *xSize = 0;
    113     *ySize = 0;
    114     while ((cell = psListGetAndIncrement(cellsIter))) {
    115         psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section
    116         if (mdok && trimsec && !psRegionIsBad(*trimsec)) {
    117             *xSize = MAX(trimsec->x1, *xSize);
    118             *ySize = MAX(trimsec->y1, *ySize);
    119         } else {
    120             psFree(cellsIter);
    121             return false;
    122         }
    123         psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections
    124         if (mdok && biassecs) {
    125             psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
    126             psRegion *biassec = NULL;   // The bias section
    127             while ((biassec = psListGetAndIncrement(biassecsIter))) {
    128                 if (!psRegionIsBad(*trimsec)) {
    129                     *xSize = MAX(biassec->x1, *xSize);
    130                     *ySize = MAX(biassec->y1, *ySize);
    131                 } else {
    132                     psFree(biassecsIter);
    133                     psFree(cellsIter);
    134                     return false;
    135                 }
    136             }
    137             psFree(biassecsIter);
    138         }
    139     }
    140     psFree(cellsIter);
    141 
    142     return (*xSize != 0 && *ySize != 0);
    143 }
    144 
    145 
    146 static psRegion sectionForImage(int *position, // Position on the output image, updated
    147                                 const psImage *image, // Image containing the sizes and offsets
    148                                 int readdir // Read direction, 1=rows, 2=cols
    149                                )
    150 {
    151     psRegion region;
    152     switch (readdir) {
    153     case 1:                           // Read direction is rows
    154         region = psRegionSet(*position, *position + image->numCols, image->row0,
    155                              image->row0 + image->numRows);
    156         *position += image->numCols;
    157         break;
    158     case 2:                           // Read direction is columns
    159         region = psRegionSet(image->col0, image->col0 + image->numCols, *position,
    160                              *position + image->numRows);
    161         *position += image->numRows;
    162         break;
    163     default:
    164         psAbort(__func__, "Shouldn't ever get here!\n");
    165     }
    166 
    167     return region;
    168 }
    169 
    170 static bool doBiasSections(int *position, // Position on the output image, updated
    171                            pmCell *target, // Target cell
    172                            const pmCell *source // Source cell
     20// Copy pixels from a target image to a source image, with flips
     21static psImage *copyPixels(psImage *source, // Source image (from source cell)
     22                           bool xFlip,      // Flip in x?
     23                           bool yFlip       // Flip in y?
    17324                          )
    17425{
    175     psMetadataItem *biassecItem = psMetadataLookup(target->concepts, "CELL.BIASSEC"); // Bias sections
    176     if (!biassecItem) {
    177         psLogMsg(__func__, PS_LOG_WARN, "CELL.BIASSEC has not been initialised in target cell --- "
    178                  "ignored.\n");
    179         return false;
    180     }
    181     psFree(biassecItem->data.V);        // Blow away the old list
    182     psList *biassecs = psListAlloc(NULL);
    183     biassecItem->data.V = biassecs;
    184 
    185     bool mdok = true;                   // Status of MD lookup
    186     int readdir = psMetadataLookupS32(&mdok, source->concepts, "CELL.READDIR"); // Read direction
    187     if (!mdok || (readdir != 1 && readdir != 2)) {
    188         // Probably unnecessary, but just in case....
    189         psLogMsg(__func__, PS_LOG_WARN, "CELL.READDIR is not set in source cell --- ignored.\n");
    190         return false;
    191     }
    192 
    193     pmReadout *readout = source->readouts->data[0]; // The first source readout, as representative
    194     psList *biases = readout->bias; // The bias images from the source readout
    195 
    196     psListIterator *biasIter = psListIteratorAlloc(biases, PS_LIST_HEAD, true); // Iterator for biases
    197     psImage *bias = NULL;       // Bias image from iteration
    198     while ((bias = psListGetAndIncrement(biasIter))) {
    199         // Construct a region
    200         psRegion *biassec = psAlloc(sizeof(psRegion)); // The new region; need a psMemBlock
    201         *biassec = sectionForImage(position, bias, readdir);
    202         psListAdd(biassecs, PS_LIST_TAIL, biassec);
    203         psFree(biassec);        // Drop reference
    204     }
    205     psFree(biasIter);
    206 
    207     return true;
    208 }
    209 
    210 // Generate CELL.TRIMSEC and CELL.BIASSEC for the target cells
    211 static bool generateTrimBias(psList *targets, // List of target cells
    212                              psList *sources // List of source cells
    213                             )
    214 {
    215     pmCell *target = NULL, *source = NULL; // Cells from iteration
    216     int numCells = targets->n;          // Number of cells
    217     int cellNum = 0;                    // The cell number
    218     int position = 0;                   // Position on the image
    219     bool mdok = true;                   // Status of MD lookup
    220 
    221     // First run through to do the LHS biases
    222     psListIterator *targetsIter = psListIteratorAlloc(targets, PS_LIST_HEAD, false); // Iterator for targets
    223     psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources
    224     bool done = false;                   // Done with iteration?
    225     while ((target = psListGetAndIncrement(targetsIter)) && (source = psListGetAndIncrement(sourcesIter)) &&
    226             !done) {
    227         if (cellNum <= numCells/2 - 1) {
    228             doBiasSections(&position, target, source);
    229             cellNum++;
    230         } else {
    231             done = true;
    232         }
    233     }
    234 
    235     // Second run through to do the trim sections
    236     psListIteratorSet(targetsIter, PS_LIST_HEAD);
    237     psListIteratorSet(sourcesIter, PS_LIST_HEAD);
    238     while ((target = psListGetAndIncrement(targetsIter)) && (source = psListGetAndIncrement(sourcesIter))) {
    239         psRegion *trimsec = psMetadataLookupPtr(&mdok, target->concepts, "CELL.TRIMSEC"); // Trim section
    240         if (!mdok || !trimsec) {
    241             psLogMsg(__func__, PS_LOG_WARN, "CELL.TRIMSEC has not been initialised in target cell --- "
    242                      "ignored.\n");
    243             continue;
    244         }
    245 
    246         int readdir = psMetadataLookupS32(&mdok, source->concepts, "CELL.READDIR"); // Read direction
    247         if (!mdok || (readdir != 1 && readdir != 2)) {
    248             // Probably unnecessary, but just in case....
    249             psLogMsg(__func__, PS_LOG_WARN, "CELL.READDIR is not set in source cell --- ignored.\n");
    250             continue;
    251         }
    252 
    253         pmReadout *readout = source->readouts->data[0]; // The first source readout, as representative
    254         psImage *image = readout->image;// The proper image
    255         *trimsec = sectionForImage(&position, image, readdir);
    256     }
    257 
    258     // A final run through to do the RHS biases
    259     psListIteratorSet(targetsIter, cellNum);
    260     psListIteratorSet(sourcesIter, cellNum);
    261     while ((target = psListGetAndIncrement(targetsIter)) && (source = psListGetAndIncrement(sourcesIter))) {
    262         doBiasSections(&position, target, source);
    263     }
    264 
    265     // Clean up
    266     psFree(targetsIter);
    267     psFree(sourcesIter);
    268 
    269     return (position > 0);
    270 }
    271 
    272 
    273 // Generate an HDU with the pixels
    274 static bool generateHDU(pmCell *target,  // The target cell
    275                         pmCell *source, // The source cell
    276                         int xBin, int yBin // Binning in x and y
    277                        )
    278 {
    279     // Get the HDU and a list of cells below it
    280     pmHDU *hdu = pmHDUFromCell(target); // The HDU in the target cell
    281     psList *targetCells = psListAlloc(NULL); // List of target cells below the target HDU
    282     psList *sourceCells = psListAlloc(NULL); // List of source cells below the target HDU
    283     if (! cellList(targetCells, sourceCells, target, source)) {
    284         psError(PS_ERR_IO, true, "Unable to find cells to generate HDU!\n");
    285         return false;
    286     }
    287 
    288     // Check the number of readouts
    289     int numReadouts = -1;               // Number of readouts
    290     {
    291         psListIterator *iter = psListIteratorAlloc(sourceCells, PS_LIST_HEAD, false); // Iterator for cells
    292         pmCell *cell = NULL;                // The cell from iteration
    293         while ((cell = psListGetAndIncrement(iter)))
    294         {
    295             psArray *readouts = cell->readouts;
    296             if (numReadouts == -1) {
    297                 numReadouts = readouts->n;
    298             } else if (readouts->n != numReadouts) {
    299                 psError(PS_ERR_IO, true, "Number of readouts doesn't match: %d vs %d\n", readouts->n,
    300                         numReadouts);
    301                 return false;
    302             }
    303 
    304         }
    305         psFree(iter);
    306     }
    307 
    308     // Get the size of the HDU, either from existing trimsec and biassec, or generate these and try again
    309     int xSize = 0, ySize = 0;           // Size of HDU
    310     if (!sizeHDU(&xSize, &ySize, targetCells) && !(generateTrimBias(targetCells, sourceCells) &&
    311             sizeHDU(&xSize, &ySize, targetCells))) {
    312         psError(PS_ERR_IO, true, "Unable to determine size of HDU!\n");
    313         return false;
    314     }
    315     psFree(targetCells);
    316     psFree(sourceCells);
    317 
    318     xSize = (int)ceilf((float)xSize/(float)xBin);
    319     ySize = (int)ceilf((float)ySize/(float)yBin);
    320 
    321     hdu->images = psArrayAlloc(numReadouts);
    322     hdu->images->n = numReadouts;
    323     for (int i = 0; i < numReadouts; i++) {
    324         psImage *image = psImageAlloc(xSize, ySize, PS_TYPE_F32);
    325         psImageInit(image, 0.0);
    326         hdu->images->data[i] = image;
    327     }
    328 
    329     return true;
    330 }
    331 
    332 // Copy pixels from a target image to a source image, with flips
    333 static bool copyPixels(psImage *target, // Target image (HDU pixels)
    334                        psImage *source, // Source image (from source cell)
    335                        psRegion region, // Region for pasting
    336                        bool xFlip,      // Flip in x?
    337                        bool yFlip       // Flip in y?
    338                       )
    339 {
    340     psImage *overlay = psMemIncrRefCounter(source);
     26    psImage *copy = psMemIncrRefCounter(source);
     27    bool copied = false;                // Have the pixels been copied?
    34128    if (xFlip) {
    342         psImage *temp = psImageFlipX(overlay);
    343         psFree(overlay);
    344         overlay = temp;
     29        psImage *temp = psImageFlipX(copy); // Flipped version
     30        psFree(copy);
     31        copy = temp;
     32        copied = true;
    34533    }
    34634    if (yFlip) {
    347         psImage *temp = psImageFlipY(overlay);
    348         psFree(overlay);
    349         overlay = temp;
    350     }
    351     int numPix = psImageOverlaySection(target, overlay, region.x0, region.y0, "=");
    352     psFree(overlay);
    353     return (numPix > 0);
     35        psImage *temp = psImageFlipY(copy); // Flipped version
     36        psFree(copy);
     37        copy = temp;
     38        copied = true;
     39    }
     40    if (!copied) {
     41        psFree(copy);
     42        copy = psImageCopy(NULL, source, source->type.type);
     43    }
     44
     45    return copy;
    35446}
    35547
     
    36759}
    36860
    369 
    37061static pmHDU *findPHU(const pmCell *cell// The cell for which to find the PHU
    37162                     )
     
    38778}
    38879
    389 
    390 static bool copyPHU(pmCell *targetCell, // The target cell
    391                     pmCell *sourceCell  // The source cell
    392                    )
    393 {
    394     // Find the respective PHUs
    395     pmHDU *targetPHU = findPHU(targetCell); // The target PHU
    396     if (targetPHU->header) {
    397         return false;                   // No work required
    398     }
    399     // Copy the header over
    400     pmHDU *sourcePHU = findPHU(sourceCell); // The source PHU
    401     targetPHU->header = psMetadataCopy(NULL, sourcePHU->header);
    402     return true;
    403 }
    404 
    405 
    40680//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    40781// File-static engine functions --- these do all the work.  Actually, cellCopy does all the work; the others
     
    40983//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    41084
    411 static int cellCopy(pmCell *target,     // The target cell
    412                     pmCell *source,     // The source cell, to be copied
    413                     bool pixels,        // Copy the pixels?
    414                     int xBin, int yBin  // (Relative) binning factors in x and y
    415                    )
     85static bool cellCopy(pmCell *target,     // The target cell
     86                     pmCell *source,     // The source cell, to be copied
     87                     bool pixels,        // Copy the pixels?
     88                     int xBin, int yBin  // (Relative) binning factors in x and y
     89                    )
    41690{
    41791    assert(target);
    41892    assert(source);
     93    assert(xBin > 0 && yBin > 0);
    41994
    42095    psArray *sourceReadouts = source->readouts; // The source readouts
    42196    int numReadouts = sourceReadouts->n; // Number of readouts copied
    42297
    423     // Copy any headers
    424     if (target->hdu && !target->hdu->phu) {
    425         pmHDU *sourceHDU = pmHDUFromCell(source);
    426         target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
    427     }
    428 
    429     pmHDU *hdu = pmHDUFromCell(target); // The target HDU; we need to fix this up
    430     if (!hdu->images) {
    431         generateHDU(target, source, xBin, yBin);
    432     }
    433     if (!hdu->header) {
    434         hdu->header = psMetadataAlloc();
    435     }
    436     // Copy the PHU over as well, if required
    437     copyPHU(target, source);
    438 
    43998    // Need to check/change CELL.XPARITY and CELL.YPARITY
    440     bool xFlip = (psMetadataLookupS32(NULL, target->concepts, "CELL.XPARITY") !=
    441                   psMetadataLookupS32(NULL, source->concepts, "CELL.XPARITY")); // Switch parity in x?
    442     bool yFlip = (psMetadataLookupS32(NULL, target->concepts, "CELL.YPARITY") !=
    443                   psMetadataLookupS32(NULL, source->concepts, "CELL.YPARITY")); // Switch parity in y?
    444     psTrace(__func__, 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip);
    445 
    44699    bool mdok = true;                   // Status of MD lookup
    447     psRegion *trimsec = psMetadataLookupPtr(&mdok, target->concepts, "CELL.TRIMSEC"); // The trim section
    448     if (!mdok || !trimsec || psRegionIsBad(*trimsec)) {
    449         psError(PS_ERR_IO, true, "CELL.TRIMSEC isn't set!\n");
    450         return 0;
    451     }
    452     psList *biassecs = psMetadataLookupPtr(&mdok, target->concepts, "CELL.BIASSEC"); // The bias sections
    453     if (!mdok || !biassecs) {
    454         psError(PS_ERR_IO, true, "CELL.BIASSEC isn't set!\n");
    455         return 0;
    456     }
    457 
     100    bool xFlip = false;                 // Switch parity in x?
     101    bool yFlip = false;                 // Switch parity in y?
     102    {
     103        int xParityTarget = psMetadataLookupS32(&mdok, target->concepts, "CELL.XPARITY"); // Target x parity
     104        if (mdok && (xParityTarget == 1 || xParityTarget == -1))
     105        {
     106            int xParitySource = psMetadataLookupS32(&mdok, source->concepts, "CELL.XPARITY"); // Source parity
     107            if (mdok && (xParitySource == 1 || xParitySource == -1) && xParityTarget != xParitySource) {
     108                xFlip = true;
     109            }
     110        }
     111        int yParityTarget = psMetadataLookupS32(&mdok, target->concepts, "CELL.YPARITY"); // Target y parity
     112        if (mdok && (yParityTarget == 1 || yParityTarget == -1))
     113        {
     114            int yParitySource = psMetadataLookupS32(&mdok, source->concepts, "CELL.YPARITY"); // Source parity
     115            if (mdok && (yParitySource == 1 || yParitySource == -1) && yParityTarget != yParitySource) {
     116                yFlip = true;
     117            }
     118        }
     119        psTrace(__func__, 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip);
     120    }
     121
     122    if (pixels && (xBin != 1 || yBin != 1)) {
     123        psLogMsg(__func__, PS_LOG_WARN, "Unable to copy pixels if binning is set --- copy turned off.\n");
     124        pixels = false;
     125    }
     126
     127    // Perform deep copy of the images.  I would prefer *not* to do a deep copy, in the interests of speed (we
     128    // still need to do another deep copy into the HDU for when we write out), but this is the only way I can
     129    // think of to provide security against copying a cell and then unknowingly changing the source when
     130    // manipulating the target.
    458131    for (int i = 0; i < numReadouts; i++) {
    459132        pmReadout *sourceReadout = sourceReadouts->data[i]; // The source readout
    460         psImage *sourceImage = sourceReadout->image; // The source image
    461133        pmReadout *targetReadout = pmReadoutAlloc(target); // The target readout; this adds it to the cell
    462         if (sourceImage->numCols != trimsec->x1 - trimsec->x0 ||
    463                 sourceImage->numRows != trimsec->y1 - trimsec->y0) {
    464             psString trimsecString = psRegionToString(*trimsec); // String with the trim section
    465             psLogMsg(__func__, PS_LOG_WARN, "Source image size (%dx%d) for readout %d doesn't match "
    466                      "CELL.TRIMSEC for target (%s) -- ignored.\n", sourceImage->numCols, sourceImage->numRows,
    467                      i, trimsecString);
    468             psFree(trimsecString);
    469         } else {
    470             binRegion(trimsec, xBin, yBin);
    471             if (pixels) {
    472                 copyPixels(hdu->images->data[i], sourceImage, *trimsec, xFlip, yFlip);
    473             }
    474             targetReadout->image = psImageSubset(hdu->images->data[i], *trimsec);
    475         }
    476 
    477         psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator
    478         psRegion *biassec = NULL;       // Bias section from iteration
    479         psListIterator *biasIter = psListIteratorAlloc(sourceReadout->bias, PS_LIST_HEAD, false); // Iterator
    480         psImage *bias = NULL;           // Bias image from iteration
    481         while ((biassec = psListGetAndIncrement(biassecsIter)) && (bias = psListGetAndIncrement(biasIter))) {
    482             if (psRegionIsBad(*biassec)) {
    483                 psString biassecString = psRegionToString(*biassec); // String for bias section
    484                 psLogMsg(__func__, PS_LOG_WARN, "Bias section (%s) isn't set --- ignored.\n", biassecString);
    485                 psFree(biassecString);
    486                 continue;
    487             }
    488             if (bias->numCols != biassec->x1 - biassec->x0 ||
    489                     bias->numRows != biassec->y1 - biassec->y0) {
    490                 psString biassecString = psRegionToString(*biassec); // String with the bias section
    491                 psLogMsg(__func__, PS_LOG_WARN, "Source image size (%dx%d) for readout %d doesn't match "
    492                          "CELL.BIASSEC for target (%s) -- ignored.\n", bias->numCols, bias->numRows, i,
    493                          biassecString);
    494                 psFree(biassecString);
    495             } else {
    496                 binRegion(biassec, xBin, yBin);
    497                 if (pixels) {
    498                     copyPixels(hdu->images->data[i], bias, *biassec, xFlip, yFlip);
     134
     135        // Copy attributes
     136        targetReadout->col0 = sourceReadout->col0;
     137        targetReadout->row0 = sourceReadout->row0;
     138        targetReadout->process = sourceReadout->process;
     139        targetReadout->file_exists = sourceReadout->file_exists;
     140        targetReadout->data_exists = sourceReadout->data_exists;
     141
     142        if (pixels) {
     143            // Copy image
     144            if (sourceReadout->image) {
     145                if (targetReadout->image) {
     146                    psFree(targetReadout->image);
    499147                }
    500                 psImage *newBias = psImageSubset(hdu->images->data[i], *biassec);
    501                 psListAdd(targetReadout->bias, PS_LIST_TAIL, newBias);
    502                 psFree(newBias);        // Drop reference
    503             }
     148                targetReadout->image = copyPixels(sourceReadout->image, xFlip, yFlip);
     149            }
     150
     151            // Copy mask
     152            if (sourceReadout->mask) {
     153                if (targetReadout->mask) {
     154                    psFree(targetReadout->mask);
     155                }
     156                targetReadout->mask = copyPixels(sourceReadout->mask, xFlip, yFlip);
     157            }
     158
     159            // Copy weight
     160            if (sourceReadout->weight) {
     161                if (targetReadout->weight) {
     162                    psFree(targetReadout->weight);
     163                }
     164                targetReadout->weight = copyPixels(sourceReadout->weight, xFlip, yFlip);
     165            }
     166
     167            // Copy bias
     168            while (targetReadout->bias->n > 0) {
     169                psListRemove(targetReadout->bias, PS_LIST_HEAD);
     170            }
     171            // Iterate over the biases
     172            psListIterator *biasIter = psListIteratorAlloc(sourceReadout->bias, PS_LIST_HEAD, false);
     173            psImage *bias = NULL;           // Bias image from iteration
     174            while ((bias = psListGetAndIncrement(biasIter))) {
     175                psImage *biasCopy = copyPixels(bias, xFlip, yFlip);
     176                psListAdd(targetReadout->bias, PS_LIST_TAIL, biasCopy);
     177                psFree(biasCopy);           // Drop reference
     178            }
     179            psFree(biasIter);
    504180        }
    505181        psFree(targetReadout);          // Drop reference
    506         psFree(biassecsIter);
    507         psFree(biasIter);
    508     }
    509 
    510     // Copy the remaining "concepts" over
     182    }
     183
     184    // Copy the remaining "concepts" over.  Don't copy the TRIMSEC or BIASSEC, since these will be created by
     185    // pmHDUGenerate if they don't already exist in the target.  Don't copy the XPARITY or YPARITY, since
     186    // we've used those to do the flips.  Don't copy the X0 and Y0 because they are updated below (and are
     187    // dependent upon the flips we've done above).
    511188    psMetadataIterator *conceptsIter = psMetadataIteratorAlloc(source->concepts, PS_LIST_HEAD, NULL);
    512189    psMetadataItem *conceptItem = NULL; // Item from iteration
     
    520197    }
    521198    psFree(conceptsIter);
     199
     200    // Need to update CELL.TRIMSEC and CELL.BIASSEC if we changed the binning and they exist already.
     201    if (xBin != 1 || yBin != 1) {
     202        psRegion *trimsec = psMetadataLookupPtr(&mdok, target->concepts, "CELL.TRIMSEC"); // The trim section
     203        if (mdok && trimsec && !psRegionIsBad(*trimsec)) {
     204            binRegion(trimsec, xBin, yBin);
     205        }
     206        psList *biassecs = psMetadataLookupPtr(&mdok, target->concepts, "CELL.BIASSEC"); // The bias sections
     207        if (mdok && biassecs && biassecs->n > 0) {
     208            psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator
     209            psRegion *biassec = NULL;   // Bias section, from iteration
     210            while ((biassec = psListGetAndIncrement(biassecsIter))) {
     211                if (!psRegionIsBad(*biassec)) {
     212                    binRegion(biassec, xBin, yBin);
     213                }
     214            }
     215            psFree(biassecsIter);
     216        }
     217    }
    522218
    523219    // Need to update CELL.X0 and CELL.Y0 if we flipped
     
    553249    binItem->data.S32 *= yBin;
    554250
    555     return numReadouts;
    556 }
    557 
    558 static int chipCopy(pmChip *target,          // The target chip
    559                     pmChip *source,          // The source chip, to be copied
    560                     bool pixels,             // Copy the pixels?
    561                     int xBin, int yBin       // (Relative) binning factors in x and y
    562                    )
     251
     252    // Copy any headers
     253    pmHDU *targetHDU = pmHDUFromCell(target); // The target HDU
     254    if (targetHDU && !targetHDU->header) {
     255        pmHDU *sourceHDU = pmHDUFromCell(source); // The source HDU
     256        targetHDU->header = psMetadataCopy(targetHDU->header, sourceHDU->header);
     257    }
     258    // Copy the PHU over as well, if required
     259    pmHDU *targetPHU = findPHU(target); // The target PHU
     260    if (targetPHU && targetPHU != targetHDU && !targetPHU->header) {
     261        pmHDU *sourcePHU = findPHU(source); // The source PHU
     262        targetPHU->header = psMetadataCopy(targetPHU->header, sourcePHU->header);
     263    }
     264
     265    return true;
     266}
     267
     268static bool chipCopy(pmChip *target,          // The target chip
     269                     pmChip *source,          // The source chip, to be copied
     270                     bool pixels,             // Copy the pixels?
     271                     int xBin, int yBin       // (Relative) binning factors in x and y
     272                    )
    563273{
    564274    assert(target);
     
    573283    }
    574284
    575     // Copy any headers
    576     if (target->hdu && !target->hdu->phu) {
    577         pmHDU *sourceHDU = pmHDUFromChip(source);
    578         target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
    579     }
    580 
    581     int numCells = 0;                   // Number of cells copied
     285    bool status = true;                 // Status of copy
    582286    for (int i = 0; i < targetCells->n; i++) {
    583287        pmCell *targetCell = targetCells->data[i]; // The target cell
     
    586290        if (cellNum >= 0) {
    587291            pmCell *sourceCell = sourceCells->data[cellNum]; // The source cell
    588             int numReadouts = cellCopy(targetCell, sourceCell, pixels, xBin, yBin); // Number of readouts
    589             // copied
    590             psTrace(__func__, 5, "Copied %d readouts for cell %s\n", numReadouts, cellName);
    591             numCells++;
     292            status &= cellCopy(targetCell, sourceCell, pixels, xBin, yBin);
    592293        }
    593294    }
     
    596297    psMetadataCopy(target->concepts, source->concepts);
    597298
    598     return numCells;
    599 
     299    return status;
    600300}
    601301
     
    617317    }
    618318
    619     // Copy any headers
    620     if (target->hdu && !target->hdu->phu) {
    621         pmHDU *sourceHDU = pmHDUFromFPA(source);
    622         target->hdu->header = psMetadataCopy(target->hdu->header, sourceHDU->header);
    623     }
    624 
    625     int numChips = 0;                   // Number of chips copied
     319    bool status = true;                 // Status of copy
    626320    for (int i = 0; i < targetChips->n; i++) {
    627321        pmChip *targetChip = targetChips->data[i]; // The target chip
     
    630324        if (chipNum >= 0) {
    631325            pmChip *sourceChip = sourceChips->data[chipNum]; // The source chip
    632             int numCells = chipCopy(targetChip, sourceChip, pixels, xBin, yBin); // Number of cells copied
    633             psTrace(__func__, 5, "Copied %d cells for chip %s\n", numCells, chipName);
    634             numChips++;
     326            status &= chipCopy(targetChip, sourceChip, pixels, xBin, yBin);
    635327        }
    636328    }
     
    639331    psMetadataCopy(target->concepts, source->concepts);
    640332
    641     return numChips;
     333    return status;
    642334}
    643335
     
    645337// Public functions
    646338//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    647 
    648339
    649340int pmFPACopy(pmFPA *target,            // The target FPA
  • trunk/psModules/src/camera/pmFPARead.c

    r7017 r7168  
    55
    66#include "pmFPA.h"
    7 #include "pmFPARead.h"
    87#include "pmHDU.h"
    98#include "pmHDUUtils.h"
     
    1110#include "psRegionIsBad.h"
    1211#include "pmFPAHeader.h"
     12
     13#include "pmFPARead.h"
    1314
    1415#define MAX(x,y) ((x) > (y) ? (x) : (y))
     
    7475}
    7576
     77// Read a component of a readout
     78psImage *readoutReadComponent(psFits *fits, // FITS file from which to read
     79                              const psRegion *region, // Region to read
     80                              int readdir, // Read direction (1=rows, 2=cols)
     81                              int min,  // Minimum row/col number to read
     82                              int max,   // Maximum row/col number to read
     83                              int z,     // Image plane to read
     84                              float bad // Bad value
     85                             )
     86{
     87    bool resize = false;                // Do we need to resize the image once read?
     88    psRegion toRead = psRegionSet(region->x0, region->x1, region->y0, region->y1); // Region to read
     89    psRegion fullSize = toRead;         // Full sized region
     90    if (readdir == 1) {
     91        if (toRead.y0 <= min) {
     92            toRead.y0 = min;
     93        } else {
     94            fullSize.y0 = min;
     95            resize = true;
     96        }
     97        if (toRead.y1 >= max) {
     98            toRead.y1 = max;
     99        } else {
     100            fullSize.y1 = max;
     101            resize = false;
     102        }
     103    } else if (readdir == 2) {
     104        if (toRead.x0 <= min) {
     105            toRead.x0 = min;
     106        } else {
     107            fullSize.x0 = min;
     108            resize = true;
     109        }
     110        if (toRead.x1 >= max) {
     111            toRead.x1 = max;
     112        } else {
     113            fullSize.x1 = max;
     114            resize = false;
     115        }
     116    } else {
     117        psAbort(__func__, "Read direction can only be 1 (rows) or 2 (cols).\n");
     118    }
     119
     120    psImage *image = psFitsReadImage(fits, toRead, z); // Desired pixels
     121
     122    if (resize) {
     123        // For some reason, the region of interest is smaller than the number of pixels we want.
     124        psImage *temp = psImageAlloc(fullSize.x1 - fullSize.x0, fullSize.y1 - fullSize.y0, image->type.type);
     125        psImageInit(temp, bad);
     126        psImageOverlaySection(temp, image, toRead.x0, toRead.y0, "=");
     127        psFree(image);
     128        image = temp;
     129    }
     130
     131    return image;
     132}
     133
    76134//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    77135// Public functions
     
    79137
    80138// Read the next readout; return true if we read pixels in.
     139//
     140// Note that this doesn't put pixels in the HDU.  It is therefore NOT COMPATIBLE with pmCellWrite,
     141// pmChipWrite, and pmFPAWrite.  Use pmReadoutWriteNext to write the data that's read by this function.
    81142bool pmReadoutReadNext(pmReadout *readout, // Readout into which to read
    82143                       psFits *fits,    // FITS file from which to read
     
    98159
    99160    // Make sure we have the information we need
    100     pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER, false, NULL);
     161    pmConceptsReadCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA | PM_CONCEPT_SOURCE_DEFAULTS,
     162                       false, NULL);
    101163
    102164    // Get the trim and bias sections
     
    113175    }
    114176    int readdir = psMetadataLookupS32(&mdok, cell->concepts, "CELL.READDIR"); // Read direction
    115     if (!mdok || readdir == 0 || (readdir != -1 && readdir != 1)) {
     177    if (!mdok || readdir == 0 || (readdir != 1 && readdir != 2)) {
    116178        psError(PS_ERR_IO, true, "CELL.READDIR is not set to -1 or +1.\n");
    117179        return false;
     180    }
     181    float bad = psMetadataLookupF32(&mdok, cell->concepts, "CELL.BAD"); // Bad level
     182    if (!mdok) {
     183        psLogMsg(__func__, PS_LOG_WARN, "CELL.BAD is not set --- assuming zero.\n");
     184        bad = 0.0;
    118185    }
    119186
     
    159226
    160227    // Read the FITS image
    161     int offset = readout->row0;         // The row number to read
     228    int offset = 0;                     // The offset from the start of the image to where we are now
    162229    if (readout->image) {
    163         if (readdir > 0) {
     230        if (readdir == 1) {
    164231            // Reading rows
    165             offset += readout->image->numRows;
     232            readout->row0 += readout->image->numRows;
     233            offset = readout->row0;
    166234        } else {
    167235            // Reading columns
    168             offset += readout->image->numCols;
    169         }
    170     }
    171     if ((readdir > 0 && offset >= naxis2) || (readdir < 0 && offset > naxis1)) {
     236            readout->col0 += readout->image->numCols;
     237            offset = readout->col0;
     238        }
     239    }
     240    if ((readdir == 1 && offset >= naxis2) || (readdir == 2 && offset > naxis1)) {
    172241        // We've read everything there is
    173242        return false;
    174243    }
    175244    int upper = offset + numScans;      // The upper limit for the pixel read
    176     if (readdir > 0 && upper > naxis2) {
     245    if (readdir == 1 && upper > naxis2) {
    177246        upper = naxis2;
    178     } else if (readdir < 0 && upper > naxis1) {
     247    } else if (readdir == 2 && upper > naxis1) {
    179248        upper = naxis1;
    180249    }
    181     psRegion region = {0, 0, 0, 0};     // Region to be read
    182     if (readdir > 0) {
    183         region = psRegionSet(0, naxis1, offset, upper); // Read rows
    184     } else {
    185         region = psRegionSet(offset, upper, 0, naxis2); // Read columns
    186     }
    187     psImage *image = psFitsReadImage(fits, region, z); // The image
    188 
    189     // Stick the image into the HDU and the readout
    190     if (!hdu->images) {
    191         hdu->images = psArrayAlloc(naxis3);
    192         hdu->images->n = naxis3;
    193     }
    194     if (hdu->images->nalloc != naxis3) {
    195         hdu->images = psArrayRealloc(hdu->images, naxis3);
    196         hdu->images->n = naxis3;
    197     }
    198     if (hdu->images->data[z]) {
    199         psFree(hdu->images->data[z]);
    200     }
    201     hdu->images->data[z] = image;
    202     readout->row0 = region.y0;
    203     readout->col0 = region.x0;
    204     readoutCarve(readout, image, trimsec, biassecs);
     250
     251    // Blow away existing data
     252    psFree(readout->image);
     253    while (readout->bias->n > 0) {
     254        psListRemove(readout->bias, PS_LIST_HEAD);
     255    }
     256
     257    // Get the new the trim section
     258    readout->image = readoutReadComponent(fits, trimsec, readdir, offset, upper, z, bad); // The image
     259
     260    // Get the new bias sections
     261    psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, false); // Iterator for BIASSEC
     262    psRegion *biassec = NULL;           // Bias section from iteration
     263    while ((biassec = psListGetAndIncrement(biassecsIter))) {
     264        psImage *bias = readoutReadComponent(fits, biassec, readdir, offset, upper, z, bad); // The bias
     265        psListAdd(readout->bias, PS_LIST_TAIL, bias);
     266    }
     267    psFree(biassecsIter);
    205268
    206269    return true;
  • trunk/psModules/src/camera/pmFPAWrite.c

    r7097 r7168  
    66#include "pmHDU.h"
    77#include "pmHDUUtils.h"
     8#include "pmHDUGenerate.h"
    89#include "pmConcepts.h"
    910
     11#include "pmFPAWrite.h"
    1012
    1113bool pmReadoutWriteNext(pmReadout *readout, // Readout to write
     
    5153        return false;
    5254    }
    53     psImage *image = hdu->images->data[z]; // The image from the HDU to write
     55    psImage *image = readout->image; // The image from the HDU to write
    5456    if (readout->row0 == 0 && readout->col0 == 0 && z == 0) {
    5557        // Then we can assume that nothing has been written to the FITS file for now
     
    6870
    6971    // We can simply update an existing HDU
    70     if (!psFitsMoveExtName(fits, hdu->extname)) {
     72    if (((hdu->phu || strcasecmp(hdu->extname, "PHU") == 0) && !psFitsMoveExtNum(fits, 0, false)) ||
     73            !psFitsMoveExtName(fits, hdu->extname)) {
    7174        psError(PS_ERR_IO, false, "Unable to move to extension %s\n", hdu->extname);
    7275        return false;
     
    8689    pmHDU *hdu = cell->hdu;             // The HDU
    8790    if (hdu && ((!pixels && hdu->phu) || pixels)) {
     91        if (pixels && !hdu->images && !pmHDUGenerateForCell(cell)) {
     92            psError(PS_ERR_IO, false, "Unable to generate HDU for cell.\n");
     93            return false;
     94        }
    8895        bool status = pmConceptsWriteCell(cell, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
    8996                                          PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
     
    107114    pmHDU *hdu = chip->hdu;             // The HDU
    108115    if (hdu && ((!pixels && hdu->phu) || pixels)) {
     116        if (pixels && !hdu->images && !pmHDUGenerateForChip(chip)) {
     117            psError(PS_ERR_IO, false, "Unable to generate HDU for chip.\n");
     118            return false;
     119        }
    109120        bool status = pmConceptsWriteChip(chip, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
    110121                                          PM_CONCEPT_SOURCE_DEFAULTS, false, NULL);
     
    130141
    131142
    132 
    133143bool pmFPAWrite(pmFPA *fpa,             // FPA to write
    134144                psFits *fits,           // FITS file to which to write
     
    139149    pmHDU *hdu = fpa->hdu;              // The HDU
    140150    if (hdu && ((!pixels && hdu->phu) || pixels)) {
     151        if (pixels && !hdu->images && !pmHDUGenerateForFPA(fpa)) {
     152            psError(PS_ERR_IO, false, "Unable to generate HDU for FPA.\n");
     153            return false;
     154        }
    141155        bool status = pmConceptsWriteFPA(fpa, PM_CONCEPT_SOURCE_HEADER | PM_CONCEPT_SOURCE_CAMERA |
    142156                                         PM_CONCEPT_SOURCE_DEFAULTS, NULL);
  • trunk/psModules/src/camera/pmHDU.c

    r7017 r7168  
    187187    // Only a header
    188188    if (!hdu->images && !hdu->table) {
     189        #if 0
    189190        // Tell CFITSIO there's nothing there
    190191        psMetadataItem *naxis = psMetadataLookup(hdu->header, "NAXIS");
     
    192193            naxis->data.S32 = 0;
    193194        }
     195        #endif
    194196
    195197        if (!psFitsWriteHeader(hdu->header, fits)) {
  • trunk/psModules/src/camera/pmHDUUtils.c

    r7017 r7168  
    5959}
    6060
     61void pmHDUPrint(pmHDU *hdu,             // HDU to print
     62                int level,              // Level at which to print
     63                bool header             // Print header?
     64               )
     65{
     66    if (hdu->phu) {
     67        psTrace(__func__, level, "HDU: %s (PHU)\n", hdu->extname);
     68    } else {
     69        psTrace(__func__, level, "HDU: %s\n", hdu->extname);
     70    }
     71
     72    psTrace(__func__, level + 1, "Format: %x\n", hdu->format);
     73    if (header) {
     74        if (hdu->header) {
     75            psTrace(__func__, level + 1, "Header:\n");
     76            psMetadataPrint(hdu->header, level + 2);
     77        } else {
     78            psTrace(__func__, level + 1, "No header.\n");
     79        }
     80    }
     81
     82    if (hdu->images) {
     83        psTrace(__func__, level + 1, "Images:\n");
     84        for (long i = 0; i < hdu->images->n; i++) {
     85            psImage *image = hdu->images->data[i]; // Image of interest
     86            psTrace(__func__, level + 2, "%ld: %dx%d\n", i, image->numCols, image->numRows);
     87        }
     88    } else {
     89        psTrace(__func__, level + 1, "NO images.\n");
     90    }
     91
     92    if (hdu->masks) {
     93        psTrace(__func__, level + 1, "Masks:\n");
     94        for (long i = 0; i < hdu->masks->n; i++) {
     95            psImage *mask = hdu->masks->data[i]; // Mask of interest
     96            psTrace(__func__, level + 2, "%ld: %dx%d\n", i, mask->numCols, mask->numRows);
     97        }
     98    } else {
     99        psTrace(__func__, level + 1, "NO masks.\n");
     100    }
     101
     102
     103    if (hdu->weights) {
     104        psTrace(__func__, level + 1, "Weights:\n");
     105        for (long i = 0; i < hdu->masks->n; i++) {
     106            psImage *weight = hdu->weights->data[i]; // Weight image of interest
     107            psTrace(__func__, level + 2, "%ld: %dx%d\n", i, weight->numCols, weight->numRows);
     108        }
     109    } else {
     110        psTrace(__func__, level + 1, "NO weights.\n");
     111    }
     112
     113
     114    return;
     115}
  • trunk/psModules/src/camera/pmHDUUtils.h

    r7017 r7168  
    2222                        );
    2323
     24// Print details about an HDU
     25void pmHDUPrint(pmHDU *hdu,             // HDU to print
     26                int level,              // Level at which to print
     27                bool header             // Print header?
     28               );
     29
    2430#endif
Note: See TracChangeset for help on using the changeset viewer.