IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 5648


Ignore:
Timestamp:
Nov 30, 2005, 3:43:10 PM (21 years ago)
Author:
jhoblitt
Message:

astyle

Location:
branches/neb/archive/scripts/src/phase2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/neb/archive/scripts/src/phase2/pmFPARead.c

    r5633 r5648  
    77#include "pmFPARead.h"
    88
    9 #include "papStuff.h"                   // For "split"
     9#include "papStuff.h"   // For "split"
    1010
    1111// NOTE: Need to deal with header inheritance
     
    1717
    1818// Read a FITS extension into a chip
    19 static bool readExtension(p_pmHDU *hdu, // Pixel data into which to read
    20                           psFits *fits  // The FITS file from which to read
    21     )
     19static bool readExtension(p_pmHDU *hdu,  // Pixel data into which to read
     20                          psFits *fits // The FITS file from which to read
     21                         )
    2222{
    2323    const char *extName = hdu->extname; // Extension name
    2424
    2525    psTrace(__func__, 7, "Moving to extension %s...\n", extName);
    26     if (strncmp(extName, "PHU", 3) == 0) {
    27         if (!psFitsMoveExtNum(fits, 0, false)) {
    28             psError(PS_ERR_IO, false, "Unable to find PHU in FITS file!\n");
    29             return false;
    30         }
    31     } else if (! psFitsMoveExtName(fits, extName)) {
    32         psError(PS_ERR_IO, false, "Unable to find extension %s in FITS file!\n", extName);
    33         return false;
     26    if (strncmp(extName, "PHU", 3) == 0)
     27    {
     28        if (!psFitsMoveExtNum(fits, 0, false))
     29        {
     30            psError(PS_ERR_IO, false, "Unable to find PHU in FITS file!\n");
     31            return false;
     32        }
     33    }
     34    else if (! psFitsMoveExtName(fits, extName))
     35    {
     36        psError(PS_ERR_IO, false, "Unable to find extension %s in FITS file!\n", extName);
     37        return false;
    3438    }
    3539    psTrace(__func__, 7, "Reading header....\n");
    3640    psMetadata *header = psFitsReadHeader(NULL, fits); // Header
    37     if (! header) {
    38         psError(PS_ERR_IO, false, "Unable to read FITS header!\n");
    39         return false;
     41    if (! header)
     42    {
     43        psError(PS_ERR_IO, false, "Unable to read FITS header!\n");
     44        return false;
    4045    }
    4146
     
    4348    bool mdStatus = false;
    4449    int nAxis = psMetadataLookupS32(&mdStatus, header, "NAXIS");
    45     if (!mdStatus) {
    46         psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header of extension %s!\n",
    47                  extName);
    48     }
    49     if (nAxis != 2 && nAxis != 3) {
    50         psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into a single image "
    51                  "anyway.\n");
     50    if (!mdStatus)
     51    {
     52        psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header of extension %s!\n",
     53                 extName);
     54    }
     55    if (nAxis != 2 && nAxis != 3)
     56    {
     57        psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into a single image "
     58                 "anyway.\n");
    5259    }
    5360    psTrace(__func__, 9, "NAXIS = %d\n", nAxis);
    5461
    55     int numPlanes = 1;                  // Number of planes
    56     if (nAxis == 3) {
    57         numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
    58         if (!mdStatus) {
    59             psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
    60             return false;
    61         }
    62     }
    63     psRegion region = {0, 0, 0, 0};     // Region to read is everything
     62    int numPlanes = 1;   // Number of planes
     63    if (nAxis == 3)
     64    {
     65        numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
     66        if (!mdStatus)
     67        {
     68            psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
     69            return false;
     70        }
     71    }
     72    psRegion region = {0, 0, 0, 0}; // Region to read is everything
    6473
    6574    // Read each plane into the array
    6675    psTrace(__func__, 7, "Reading %d planes into array....\n", numPlanes);
    6776    psArray *pixels = psArrayAlloc(numPlanes); // Array of images
    68     for (int i = 0; i < numPlanes; i++) {
    69         psTrace(__func__, 9, "Reading plane %d\n", i);
    70         psMemCheckCorruption(true);
    71         psImage *image = psFitsReadImage(NULL, fits, region, i);
    72 
    73         // XXX: Type conversion here to support the modules, which don't have multiple type support yet
    74         if (image->type.type != PS_TYPE_F32) {
    75             pixels->data[i] = psImageCopy(NULL, image, PS_TYPE_F32);
     77    for (int i = 0; i < numPlanes; i++)
     78    {
     79        psTrace(__func__, 9, "Reading plane %d\n", i);
     80        psMemCheckCorruption(true);
     81        psImage *image = psFitsReadImage(NULL, fits, region, i);
     82
     83        // XXX: Type conversion here to support the modules, which don't have multiple type support yet
     84        if (image->type.type != PS_TYPE_F32)
     85        {
     86            pixels->data[i] = psImageCopy(NULL, image, PS_TYPE_F32);
    7687
    7788#ifndef PRODUCTION
    78             // XXX: Temporary fix for writing images, until psFits gets cleaned up
    79             psMetadataItem *bitpixItem = psMetadataLookup(header, "BITPIX");
    80             bitpixItem->data.S32 = -32;
    81             psMetadataRemove(header, 0, "BZERO");
    82             psMetadataRemove(header, 0, "BSCALE");
     89            // XXX: Temporary fix for writing images, until psFits gets cleaned up
     90            psMetadataItem *bitpixItem = psMetadataLookup(header, "BITPIX");
     91            bitpixItem->data.S32 = -32;
     92            psMetadataRemove(header, 0, "BZERO");
     93            psMetadataRemove(header, 0, "BSCALE");
    8394#endif
    8495
    85             psFree(image);
    86         } else {
    87             pixels->data[i] = image;
    88         }
    89         psTrace(__func__, 10, "Done\n");
    90         if (! pixels->data[i]) {
    91             psError(PS_ERR_IO, false, "Unable to read image for extension %s, plane %d\n", extName, i);
    92             return false;
    93         }
     96            psFree(image);
     97        }
     98        else
     99        {
     100            pixels->data[i] = image;
     101        }
     102        psTrace(__func__, 10, "Done\n");
     103        if (! pixels->data[i])
     104        {
     105            psError(PS_ERR_IO, false, "Unable to read image for extension %s, plane %d\n", extName, i);
     106            return false;
     107        }
    94108    }
    95109
     
    104118
    105119// Portion out an image into the cell
    106 static bool generateReadouts(pmCell *cell, // The cell that gets its bits
    107                              p_pmHDU *hdu // Pixel data, containing image, mask, weights
    108     )
     120static bool generateReadouts(pmCell *cell,  // The cell that gets its bits
     121                             p_pmHDU *hdu // Pixel data, containing image, mask, weights
     122                            )
    109123{
    110     psArray *images = hdu->images;      // Array of images (each of which is a readout)
    111     psArray *masks = hdu->masks;        // Array of masks (one for each readout)
     124    psArray *images = hdu->images; // Array of images (each of which is a readout)
     125    psArray *masks = hdu->masks; // Array of masks (one for each readout)
    112126    // Iterate over each of the image planes
    113     for (int i = 0; i < images->n; i++) {
    114         psImage *image = images->data[i]; // The i-th plane
    115         psImage *mask = NULL;           // The mask
    116         if (masks) {
    117             mask = masks->data[i];
    118         }
    119 
    120         pmReadout *readout = pmReadoutAlloc(cell, image, mask, 0,0,1,1);
    121         psFree(readout);                // This seems silly, but the alloc registers it with the cell, so we
    122                                         // don't have to do anything with it.  Perhaps we should change
    123                                         // pmReadoutAlloc to pmReadoutAdd?
     127    for (int i = 0; i < images->n; i++)
     128    {
     129        psImage *image = images->data[i]; // The i-th plane
     130        psImage *mask = NULL;  // The mask
     131        if (masks)
     132        {
     133            mask = masks->data[i];
     134        }
     135
     136        pmReadout *readout = pmReadoutAlloc(cell, image, mask, 0, 0, 1, 1);
     137        psFree(readout);  // This seems silly, but the alloc registers it with the cell, so we
     138        // don't have to do anything with it.  Perhaps we should change
     139        // pmReadoutAlloc to pmReadoutAdd?
    124140    }
    125141
     
    131147//////////////////////////////////////////////////////////////////////////////////////////////////////////////
    132148
    133 bool pmFPARead(pmFPA *fpa,              // FPA to read into
    134                psFits *fits,            // FITS file from which to read
    135                psMetadata *phu,         // Primary header
    136                psDB *db                 // Database handle, for concept ingest
    137     )
     149bool pmFPARead(pmFPA *fpa,   // FPA to read into
     150               psFits *fits,   // FITS file from which to read
     151               psMetadata *phu,   // Primary header
     152               psDB *db   // Database handle, for concept ingest
     153              )
    138154{
    139     p_pmHDU *hdu = NULL;        // Pixel data from FITS file
     155    p_pmHDU *hdu = NULL; // Pixel data from FITS file
    140156
    141157    // Read the PHU, if required
    142     if (! phu) {
    143         if (! psFitsMoveExtNum(fits, 0, false)) {
    144             psError(PS_ERR_IO, false, "Unable to find PHU in FITS file!\n");
    145             return false;
    146         }
    147         psTrace(__func__, 7, "Reading PHU....\n");
    148         psMetadata *phu = psFitsReadHeader(NULL, fits); // Primary header
     158    if (! phu)
     159    {
     160        if (! psFitsMoveExtNum(fits, 0, false))
     161        {
     162            psError(PS_ERR_IO, false, "Unable to find PHU in FITS file!\n");
     163            return false;
     164        }
     165        psTrace(__func__, 7, "Reading PHU....\n");
     166        psMetadata *phu = psFitsReadHeader(NULL, fits); // Primary header
    149167    }
    150168    fpa->phu = phu;
     
    152170    // Read in....
    153171    psTrace(__func__, 1, "Working on FPA...\n");
    154     if (fpa->hdu) {
    155         hdu = fpa->hdu;
    156         psTrace(__func__, 3, "Reading pixels from extension %s into FPA.\n", hdu->extname);
    157         if (! readExtension(hdu, fits)) {
    158             psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n", hdu->extname);
    159             return false;
    160         }
     172    if (fpa->hdu)
     173    {
     174        hdu = fpa->hdu;
     175        psTrace(__func__, 3, "Reading pixels from extension %s into FPA.\n", hdu->extname);
     176        if (! readExtension(hdu, fits))
     177        {
     178            psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n", hdu->extname);
     179            return false;
     180        }
    161181    }
    162182    pmFPAIngestConcepts(fpa, db);
    163183
    164     psArray *chips = fpa->chips;        // Array of chips
     184    psArray *chips = fpa->chips; // Array of chips
    165185    // Iterate over the FPA
    166     for (int i = 0; i < chips->n; i++) {
    167         pmChip *chip = chips->data[i]; // The chip
    168 
    169         // Only read chips marked "valid"
    170         if (! chip->valid) {
    171             psTrace(__func__, 2, "Ignoring chip %d...\n", i);
    172             continue;
    173         }
    174         psTrace(__func__, 2, "Reading in chip %d...\n", i);
    175 
    176         if (chip->hdu) {
    177             hdu = chip->hdu;
    178             psTrace(__func__, 3, "Reading pixels from extension %s into chip %d.\n", hdu->extname, i);
    179             if (! readExtension(hdu, fits)) {
    180                 psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n", hdu->extname);
    181                 return false;
    182             }
    183         }
    184         pmChipIngestConcepts(chip, db);
    185 
    186         // Iterate over the chip
    187         psArray *cells = chip->cells;   // Array of cells
    188         for (int j = 0; j < cells->n; j++) {
    189             pmCell *cell = cells->data[j]; // The cell
    190 
    191             // Only read cells marked "valid"
    192             if (! cell->valid) {
    193                 psTrace(__func__, 3, "Ignoring chip %d...\n", i);
    194                 continue;
    195             }
    196             psTrace(__func__, 3, "Reading in cell %d...\n", j);
    197 
    198             if (cell->hdu) {
    199                 hdu = cell->hdu;
    200                 psTrace(__func__, 5, "Reading pixels from extension %s into cell %d.\n", hdu->extname,
    201                         j);
    202                 if (! readExtension(hdu, fits)) {
    203                     psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n",
    204                             hdu->extname);
    205                     return false;
    206                 }
    207             }
    208             pmCellIngestConcepts(cell, db);
    209 
    210             psTrace(__func__, 5, "Allocating readouts for chip %d cell %d...\n",
    211                     i, j);
    212             generateReadouts(cell, hdu);
    213         }
     186    for (int i = 0; i < chips->n; i++)
     187    {
     188        pmChip *chip = chips->data[i]; // The chip
     189
     190        // Only read chips marked "valid"
     191        if (! chip->valid)
     192        {
     193            psTrace(__func__, 2, "Ignoring chip %d...\n", i);
     194            continue;
     195        }
     196        psTrace(__func__, 2, "Reading in chip %d...\n", i);
     197
     198        if (chip->hdu)
     199        {
     200            hdu = chip->hdu;
     201            psTrace(__func__, 3, "Reading pixels from extension %s into chip %d.\n", hdu->extname, i);
     202            if (! readExtension(hdu, fits))
     203            {
     204                psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n", hdu->extname);
     205                return false;
     206            }
     207        }
     208        pmChipIngestConcepts(chip, db);
     209
     210        // Iterate over the chip
     211        psArray *cells = chip->cells; // Array of cells
     212        for (int j = 0; j < cells->n; j++)
     213        {
     214            pmCell *cell = cells->data[j]; // The cell
     215
     216            // Only read cells marked "valid"
     217            if (! cell->valid)
     218            {
     219                psTrace(__func__, 3, "Ignoring chip %d...\n", i);
     220                continue;
     221            }
     222            psTrace(__func__, 3, "Reading in cell %d...\n", j);
     223
     224            if (cell->hdu)
     225            {
     226                hdu = cell->hdu;
     227                psTrace(__func__, 5, "Reading pixels from extension %s into cell %d.\n", hdu->extname,
     228                        j);
     229                if (! readExtension(hdu, fits))
     230                {
     231                    psError(PS_ERR_IO, false, "Unable to read pixels from extension %s\n",
     232                            hdu->extname);
     233                    return false;
     234                }
     235            }
     236            pmCellIngestConcepts(cell, db);
     237
     238            psTrace(__func__, 5, "Allocating readouts for chip %d cell %d...\n",
     239                    i, j);
     240            generateReadouts(cell, hdu);
     241        }
    214242    }
    215243
     
    218246
    219247// Translate a name from the configuration file, containing something like "%a_%d" to a real value
    220 psString p_pmFPATranslateName(psString name, // The name to translate
    221                               pmCell *cell // The cell for which to translate
    222     )
     248psString p_pmFPATranslateName(psString name,  // The name to translate
     249                              pmCell *cell // The cell for which to translate
     250                             )
    223251{
    224252    // %a is the FPA.NAME
     
    230258
    231259    psString translation = psMemIncrRefCounter(name); // The translated string
    232     char *temp = NULL;                  // Temporary string
    233 
    234     pmChip *chip = cell->parent;        // Chip of interest
    235     pmFPA *fpa = chip->parent;          // FPA of interest
     260    char *temp = NULL;   // Temporary string
     261
     262    pmChip *chip = cell->parent; // Chip of interest
     263    pmFPA *fpa = chip->parent;  // FPA of interest
    236264
    237265    // FPA.NAME
    238     if (temp = strstr(translation, "%a")) {
    239         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    240         // and there's not much of it anyway...
    241         psFree(translation);
    242         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    243         psString fpaName = psMetadataLookupString(NULL, fpa->concepts, "FPA.NAME"); // The value of FPA.NAME
    244         psStringAppend(&translation, "%s%s", fpaName, temp + 2);
    245         // So "translation" now contains the first part, the replaced string, and the last part.
     266    if (temp = strstr(translation, "%a"))
     267    {
     268        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     269        // and there's not much of it anyway...
     270        psFree(translation);
     271        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     272        psString fpaName = psMetadataLookupString(NULL, fpa->concepts, "FPA.NAME"); // The value of FPA.NAME
     273        psStringAppend(&translation, "%s%s", fpaName, temp + 2);
     274        // So "translation" now contains the first part, the replaced string, and the last part.
    246275    }
    247276
    248277    // CHIP.NAME
    249     if (temp = strstr(translation, "%b")) {
    250         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    251         // and there's not much of it anyway...
    252         psFree(translation);
    253         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    254         psString chipName = psMetadataLookupString(NULL, chip->concepts, "CHIP.NAME"); // CHIP.NAME's value
    255         psStringAppend(&translation, "%s%s", chipName, temp + 2);
    256         // So "translation" now contains the first part, the replaced string, and the last part.
     278    if (temp = strstr(translation, "%b"))
     279    {
     280        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     281        // and there's not much of it anyway...
     282        psFree(translation);
     283        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     284        psString chipName = psMetadataLookupString(NULL, chip->concepts, "CHIP.NAME"); // CHIP.NAME's value
     285        psStringAppend(&translation, "%s%s", chipName, temp + 2);
     286        // So "translation" now contains the first part, the replaced string, and the last part.
    257287    }
    258288
    259289    // CELL.NAME
    260     if (temp = strstr(translation, "%c")) {
    261         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    262         // and there's not much of it anyway...
    263         psFree(translation);
    264         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    265         psString cellName = psMetadataLookupString(NULL, cell->concepts, "CELL.NAME"); // CELL.NAME's value
    266         psStringAppend(&translation, "%s%s", cellName, temp + 2);
    267         // So "translation" now contains the first part, the replaced string, and the last part.
     290    if (temp = strstr(translation, "%c"))
     291    {
     292        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     293        // and there's not much of it anyway...
     294        psFree(translation);
     295        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     296        psString cellName = psMetadataLookupString(NULL, cell->concepts, "CELL.NAME"); // CELL.NAME's value
     297        psStringAppend(&translation, "%s%s", cellName, temp + 2);
     298        // So "translation" now contains the first part, the replaced string, and the last part.
    268299    }
    269300
    270301    // Chip number
    271     if (temp = strstr(translation, "%d")) {
    272         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    273         // and there's not much of it anyway...
    274         psFree(translation);
    275         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    276         // Search for the pointer to get the chip number
    277         int chipNum = -1;
    278         psArray *chips = fpa->chips;    // The array of chips
    279         for (int i = 0; i < chips->n && chipNum < 0; i++) {
    280             if (chips->data[i] == chip) {
    281                 chipNum = i;
    282             }
    283         }
    284         if (chipNum < 0) {
    285             psError(PS_ERR_IO, true, "Unable to find chip to get name: %s\n", name);
    286             // Try to muddle on by leaving the number out
    287             psStringAppend(&translation, "%s", temp + 2);
    288         } else {
    289             psStringAppend(&translation, "%d%s", chipNum, temp + 2);
    290         }
    291         // So "translation" now contains the first part, the replaced string, and the last part.
     302    if (temp = strstr(translation, "%d"))
     303    {
     304        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     305        // and there's not much of it anyway...
     306        psFree(translation);
     307        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     308        // Search for the pointer to get the chip number
     309        int chipNum = -1;
     310        psArray *chips = fpa->chips; // The array of chips
     311        for (int i = 0; i < chips->n && chipNum < 0; i++)
     312        {
     313            if (chips->data[i] == chip)
     314            {
     315                chipNum = i;
     316            }
     317        }
     318        if (chipNum < 0)
     319        {
     320            psError(PS_ERR_IO, true, "Unable to find chip to get name: %s\n", name);
     321            // Try to muddle on by leaving the number out
     322            psStringAppend(&translation, "%s", temp + 2);
     323        }
     324        else
     325        {
     326            psStringAppend(&translation, "%d%s", chipNum, temp + 2);
     327        }
     328        // So "translation" now contains the first part, the replaced string, and the last part.
    292329    }
    293330
    294331    // Cell number
    295     if (temp = strstr(translation, "%e")) {
    296         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    297         // and there's not much of it anyway...
    298         psFree(translation);
    299         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    300         // Search for the pointer to get the cell number
    301         int cellNum = -1;
    302         psArray *cells = chip->cells;   // The array of cells
    303         for (int i = 0; i < cells->n && cellNum < 0; i++) {
    304             if (cells->data[i] == cell) {
    305                 cellNum = i;
    306             }
    307         }
    308         if (cellNum < 0) {
    309             psError(PS_ERR_IO, true, "Unable to find cell to get name: %s\n", name);
    310             // Try to muddle on by leaving the number out
    311             psStringAppend(&translation, "%s", temp + 2);
    312         } else {
    313             psStringAppend(&translation, "%d%s", cellNum, temp + 2);
    314         }
    315         // So "translation" now contains the first part, the replaced string, and the last part.
     332    if (temp = strstr(translation, "%e"))
     333    {
     334        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     335        // and there's not much of it anyway...
     336        psFree(translation);
     337        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     338        // Search for the pointer to get the cell number
     339        int cellNum = -1;
     340        psArray *cells = chip->cells; // The array of cells
     341        for (int i = 0; i < cells->n && cellNum < 0; i++)
     342        {
     343            if (cells->data[i] == cell)
     344            {
     345                cellNum = i;
     346            }
     347        }
     348        if (cellNum < 0)
     349        {
     350            psError(PS_ERR_IO, true, "Unable to find cell to get name: %s\n", name);
     351            // Try to muddle on by leaving the number out
     352            psStringAppend(&translation, "%s", temp + 2);
     353        }
     354        else
     355        {
     356            psStringAppend(&translation, "%d%s", cellNum, temp + 2);
     357        }
     358        // So "translation" now contains the first part, the replaced string, and the last part.
    316359    }
    317360
    318361    // Extension name
    319     if (temp = strstr(translation, "%f")) {
    320         // This is not particularly friendly to the memory allocation, but the cache should make it OK,
    321         // and there's not much of it anyway...
    322         psFree(translation);
    323         translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
    324         const char *extname = NULL;
    325         if (cell->hdu) {
    326             extname = cell->hdu->extname;
    327         } else if (chip->hdu) {
    328             extname = chip->hdu->extname;
    329         } else if (fpa->hdu) {
    330             extname = fpa->hdu->extname;
    331         }
    332         psStringAppend(&translation, "%s%s", extname, temp + 2);
    333         // So "translation" now contains the first part, the replaced string, and the last part.
     362    if (temp = strstr(translation, "%f"))
     363    {
     364        // This is not particularly friendly to the memory allocation, but the cache should make it OK,
     365        // and there's not much of it anyway...
     366        psFree(translation);
     367        translation = psStringNCopy(name, strlen(name) - strlen(temp)); // Copy first part of string
     368        const char *extname = NULL;
     369        if (cell->hdu)
     370        {
     371            extname = cell->hdu->extname;
     372        }
     373        else if (chip->hdu)
     374        {
     375            extname = chip->hdu->extname;
     376        }
     377        else if (fpa->hdu)
     378        {
     379            extname = fpa->hdu->extname;
     380        }
     381        psStringAppend(&translation, "%s%s", extname, temp + 2);
     382        // So "translation" now contains the first part, the replaced string, and the last part.
    334383    }
    335384
     
    338387
    339388// Read a mask into the FPA
    340 bool pmFPAReadMask(pmFPA *fpa,          // FPA to read into
    341                    psFits *source       // Source FITS file (for the original data)
    342     )
     389bool pmFPAReadMask(pmFPA *fpa,   // FPA to read into
     390                   psFits *source // Source FITS file (for the original data)
     391                  )
    343392{
    344393    const psMetadata *camera = fpa->camera; // Camera configuration for FPA
    345     bool mdok = false;                  // Status of MD lookup
     394    bool mdok = false;   // Status of MD lookup
    346395
    347396    // Get the required information from the camera configuration
    348397    psMetadata *supps = psMetadataLookupMD(&mdok, camera, "SUPPLEMENTARY"); // Rules for supplementary data
    349     if (! mdok || ! supps) {
    350         psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
    351         return false;
     398    if (! mdok || ! supps)
     399    {
     400        psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
     401        return false;
    352402    }
    353403    psString sourceType = psMetadataLookupString(&mdok, supps, "MASK.SOURCE"); // Type of source: EXT | FILE
    354     if (! mdok || strlen(sourceType) <= 0) {
    355         psError(PS_ERR_IO, false, "Unable to find MASK.SOURCE in SUPPLEMENTARY section of camera "
    356                 "configuration!\n");
    357         return false;
     404    if (! mdok || strlen(sourceType) <= 0)
     405    {
     406        psError(PS_ERR_IO, false, "Unable to find MASK.SOURCE in SUPPLEMENTARY section of camera "
     407                "configuration!\n");
     408        return false;
    358409    }
    359410    psString name = psMetadataLookupString(&mdok, supps, "MASK.NAME"); // Name of mask
    360     if (! mdok || strlen(sourceType) <= 0) {
    361         psError(PS_ERR_IO, false, "Unable to find MASK.NAME in SUPPLEMENTARY section of camera "
    362                 "configuration!\n");
    363         return false;
     411    if (! mdok || strlen(sourceType) <= 0)
     412    {
     413        psError(PS_ERR_IO, false, "Unable to find MASK.NAME in SUPPLEMENTARY section of camera "
     414                "configuration!\n");
     415        return false;
    364416    }
    365417
    366418    // Go through the FPA to each cell/readout to get the mask
    367     p_pmHDU *hdu = fpa->hdu;            // The HDU into which we will read the mask
    368     psArray *chips = fpa->chips;        // Array of chips
    369     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
    370         pmChip *chip = chips->data[chipNum]; // The current chip of interest
    371         if (chip->valid) {
    372             if (chip->hdu) {
    373                 hdu = chip->hdu;
    374             }
    375             psArray *cells = chip->cells;       // Array of cells
    376             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
    377                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
    378                 if (cell->valid) {
    379                     if (cell->hdu) {
    380                         hdu = cell->hdu;
    381                     }
    382 
    383                     // Now, need to find out where to get the pixels
    384                     psFits *maskSource = source;        // Source of mask image
    385                     if (strcasecmp(sourceType, "FILE") == 0) {
    386                         // Source is a file (with optional extension, e.g., "myMaskFile.fits:thisExt"
    387                         psString filenameExt = p_pmFPATranslateName(name, cell);
    388                         char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
    389                         psString filename = NULL; // The filename
    390                         psString extname = NULL;// The extenstion name
    391                         if (colon) {
    392                             filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
    393                             if (strlen(colon) > 1) {
    394                                 extname = psStringCopy(colon + 1);
    395                             }
    396                         } else {
    397                             filename = psMemIncrRefCounter(filenameExt);
    398                         }
    399                        
    400                         maskSource = psFitsAlloc(filename);
    401                         if (extname) {
    402                             if (! psFitsMoveExtName(maskSource, extname)) {
    403                                 psLogMsg(__func__, PS_LOG_WARN, "Unable to find extension %s to read mask.\n",
    404                                          extname);
    405                                 return false;
    406                             }
    407                         }
    408                         psFree(filename);
    409                         psFree(extname);
    410                         psFree(filenameExt);
    411                     } else if (strncasecmp(sourceType, "EXT", 3) == 0) {
    412                         // Source is an extension in the original file
    413                         psString extname = p_pmFPATranslateName(name, cell);
    414                         psFitsMoveExtName(maskSource, extname);
    415                     }
    416                    
    417                     // We've arrived where the pixels are.  Now we need to read them in.
    418                     psMetadata *header = psFitsReadHeader(NULL, maskSource); // The header
    419                     bool mdStatus = false;
    420                     int nAxis = psMetadataLookupS32(&mdStatus, header, "NAXIS");
    421                     if (!mdStatus) {
    422                         psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header for "
    423                                  "mask (%s)!\n", name);
    424                     }
    425                     if (nAxis != 2 && nAxis != 3) {
    426                         psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into "
    427                                  "a single image anyway.\n");
    428                     }
    429            
    430                     int numPlanes = 1;  // Number of planes
    431                     if (nAxis == 3) {
    432                         numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
    433                         if (!mdStatus) {
    434                             psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
    435                             // Try to proceed by taking only the first plane
    436                             numPlanes = 1;
    437                         }
    438                         if (numPlanes != 1 && numPlanes != cell->readouts->n) {
    439                             psError(PS_ERR_IO, false, "Number of masks (%d) does not match number of "
    440                                     "readouts (%d)\n", numPlanes, cell->readouts->n);
    441                             // Try to proceed by taking only the first plane
    442                             numPlanes = 1;
    443                         }
    444                     }
    445 
    446                     hdu->masks = psArrayAlloc(hdu->images->n);
    447                    
    448                     // Read each plane into the array
    449                     psArray *readouts = cell->readouts; // The array of readouts
    450                     for (int i = 0; i < hdu->masks->n; i++) {
    451                         psImage *mask = NULL; // The mask to be added
    452                         if (i < numPlanes) {
    453                             // Read the mask from the file
    454                             psTrace(__func__, 9, "Reading plane %d\n", i);
    455                             psRegion region = {0, 0, 0, 0};
    456                             mask = psFitsReadImage(NULL, maskSource, region, i);
    457                         } else {
    458                             // One mask in the file is provided for all planes in the original image
    459                             psTrace(__func__, 9, "Copying plane 0 into plane %d\n", i);
    460                             psImage *original = hdu->masks->data[0];
    461                             mask = psImageCopy(NULL, original, original->type.type);
    462                         }
    463                         hdu->masks->data[0] = mask;
    464                         pmReadout *readout = readouts->data[i];
    465                         readout->mask = mask;
    466                         // Check the dimensions
    467                         // XXX: Perhaps this check should be against the CELL.TRIMSEC, not the image size?
    468                         if (mask->numCols < readout->image->numCols ||
    469                             mask->numRows < readout->image->numRows)
    470                         {
    471                             psError(PS_ERR_IO, false, "Mask size (%dx%d) not compatible with image (%dx%d)\n",
    472                                     mask->numCols, mask->numRows, readout->image->numCols,
    473                                     readout->image->numRows);
    474                             return false;
    475                         }
    476                     } // Iterating over readouts
    477                 } // Valid cells
    478             } // Iterating over cells
    479         } // Valid chips
     419    p_pmHDU *hdu = fpa->hdu;  // The HDU into which we will read the mask
     420    psArray *chips = fpa->chips; // Array of chips
     421    for (int chipNum = 0; chipNum < chips->n; chipNum++)
     422    {
     423        pmChip *chip = chips->data[chipNum]; // The current chip of interest
     424        if (chip->valid)
     425        {
     426            if (chip->hdu)
     427            {
     428                hdu = chip->hdu;
     429            }
     430            psArray *cells = chip->cells; // Array of cells
     431            for (int cellNum = 0; cellNum < cells->n; cellNum++)
     432            {
     433                pmCell *cell = cells->data[cellNum]; // The current cell of interest
     434                if (cell->valid)
     435                {
     436                    if (cell->hdu)
     437                    {
     438                        hdu = cell->hdu;
     439                    }
     440
     441                    // Now, need to find out where to get the pixels
     442                    psFits *maskSource = source; // Source of mask image
     443                    if (strcasecmp(sourceType, "FILE") == 0)
     444                    {
     445                        // Source is a file (with optional extension, e.g., "myMaskFile.fits:thisExt"
     446                        psString filenameExt = p_pmFPATranslateName(name, cell);
     447                        char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
     448                        psString filename = NULL; // The filename
     449                        psString extname = NULL; // The extenstion name
     450                        if (colon)
     451                        {
     452                            filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
     453                            if (strlen(colon) > 1)
     454                            {
     455                                extname = psStringCopy(colon + 1);
     456                            }
     457                        }
     458                        else
     459                        {
     460                            filename = psMemIncrRefCounter(filenameExt);
     461                        }
     462
     463                        maskSource = psFitsAlloc(filename);
     464                        if (extname)
     465                        {
     466                            if (! psFitsMoveExtName(maskSource, extname))
     467                            {
     468                                psLogMsg(__func__, PS_LOG_WARN, "Unable to find extension %s to read mask.\n",
     469                                         extname);
     470                                return false;
     471                            }
     472                        }
     473                        psFree(filename);
     474                        psFree(extname);
     475                        psFree(filenameExt);
     476                    }
     477                    else if (strncasecmp(sourceType, "EXT", 3) == 0)
     478                    {
     479                        // Source is an extension in the original file
     480                        psString extname = p_pmFPATranslateName(name, cell);
     481                        psFitsMoveExtName(maskSource, extname);
     482                    }
     483
     484                    // We've arrived where the pixels are.  Now we need to read them in.
     485                    psMetadata *header = psFitsReadHeader(NULL, maskSource); // The header
     486                    bool mdStatus = false;
     487                    int nAxis = psMetadataLookupS32(&mdStatus, header, "NAXIS");
     488                    if (!mdStatus)
     489                    {
     490                        psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header for "
     491                                 "mask (%s)!\n", name);
     492                    }
     493                    if (nAxis != 2 && nAxis != 3)
     494                    {
     495                        psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into "
     496                                 "a single image anyway.\n");
     497                    }
     498
     499                    int numPlanes = 1; // Number of planes
     500                    if (nAxis == 3)
     501                    {
     502                        numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
     503                        if (!mdStatus)
     504                        {
     505                            psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
     506                            // Try to proceed by taking only the first plane
     507                            numPlanes = 1;
     508                        }
     509                        if (numPlanes != 1 && numPlanes != cell->readouts->n)
     510                        {
     511                            psError(PS_ERR_IO, false, "Number of masks (%d) does not match number of "
     512                                    "readouts (%d)\n", numPlanes, cell->readouts->n);
     513                            // Try to proceed by taking only the first plane
     514                            numPlanes = 1;
     515                        }
     516                    }
     517
     518                    hdu->masks = psArrayAlloc(hdu->images->n);
     519
     520                    // Read each plane into the array
     521                    psArray *readouts = cell->readouts; // The array of readouts
     522                    for (int i = 0; i < hdu->masks->n; i++)
     523                    {
     524                        psImage *mask = NULL; // The mask to be added
     525                        if (i < numPlanes)
     526                        {
     527                            // Read the mask from the file
     528                            psTrace(__func__, 9, "Reading plane %d\n", i);
     529                            psRegion region = {0, 0, 0, 0};
     530                            mask = psFitsReadImage(NULL, maskSource, region, i);
     531                        }
     532                        else
     533                        {
     534                            // One mask in the file is provided for all planes in the original image
     535                            psTrace(__func__, 9, "Copying plane 0 into plane %d\n", i);
     536                            psImage *original = hdu->masks->data[0];
     537                            mask = psImageCopy(NULL, original, original->type.type);
     538                        }
     539                        hdu->masks->data[0] = mask;
     540                        pmReadout *readout = readouts->data[i];
     541                        readout->mask = mask;
     542                        // Check the dimensions
     543                        // XXX: Perhaps this check should be against the CELL.TRIMSEC, not the image size?
     544                        if (mask->numCols < readout->image->numCols ||
     545                            mask->numRows < readout->image->numRows)
     546                        {
     547                            psError(PS_ERR_IO, false, "Mask size (%dx%d) not compatible with image (%dx%d)\n",
     548                                    mask->numCols, mask->numRows, readout->image->numCols,
     549                                    readout->image->numRows);
     550                            return false;
     551                        }
     552                    } // Iterating over readouts
     553                } // Valid cells
     554            } // Iterating over cells
     555        } // Valid chips
    480556    } // Iterating over chips
    481557
     
    486562// Read a mask into the FPA
    487563// This is just a copy of the above pmFPAReadMask, replacing "mask" with "weight" throughout.
    488 bool pmFPAReadWeight(pmFPA *fpa,        // FPA to read into
    489                      psFits *source     // Source FITS file (for the original data)
    490     )
     564bool pmFPAReadWeight(pmFPA *fpa,  // FPA to read into
     565                     psFits *source // Source FITS file (for the original data)
     566                    )
    491567{
    492568    const psMetadata *camera = fpa->camera; // Camera configuration for FPA
    493     bool mdok = false;                  // Status of MD lookup
     569    bool mdok = false;   // Status of MD lookup
    494570
    495571    // Get the required information from the camera configuration
    496572    psMetadata *supps = psMetadataLookupMD(&mdok, camera, "SUPPLEMENTARY"); // Rules for supplementary data
    497     if (! mdok || ! supps) {
    498         psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
    499         return false;
     573    if (! mdok || ! supps)
     574    {
     575        psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
     576        return false;
    500577    }
    501578    psString sourceType = psMetadataLookupString(&mdok, supps, "WEIGHT.SOURCE"); // Type of source: EXT | FILE
    502     if (! mdok || strlen(sourceType) <= 0) {
    503         psError(PS_ERR_IO, false, "Unable to find WEIGHT.SOURCE in SUPPLEMENTARY section of camera "
    504                 "configuration!\n");
    505         return false;
     579    if (! mdok || strlen(sourceType) <= 0)
     580    {
     581        psError(PS_ERR_IO, false, "Unable to find WEIGHT.SOURCE in SUPPLEMENTARY section of camera "
     582                "configuration!\n");
     583        return false;
    506584    }
    507585    psString name = psMetadataLookupString(&mdok, supps, "WEIGHT.NAME"); // Name of weight
    508     if (! mdok || strlen(sourceType) <= 0) {
    509         psError(PS_ERR_IO, false, "Unable to find WEIGHT.NAME in SUPPLEMENTARY section of camera "
    510                 "configuration!\n");
    511         return false;
     586    if (! mdok || strlen(sourceType) <= 0)
     587    {
     588        psError(PS_ERR_IO, false, "Unable to find WEIGHT.NAME in SUPPLEMENTARY section of camera "
     589                "configuration!\n");
     590        return false;
    512591    }
    513592
    514593    // Go through the FPA to each cell/readout to get the weight
    515     p_pmHDU *hdu = fpa->hdu;            // The HDU into which we will read the weight
    516     psArray *chips = fpa->chips;        // Array of chips
    517     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
    518         pmChip *chip = chips->data[chipNum]; // The current chip of interest
    519         if (chip->valid) {
    520             if (chip->hdu) {
    521                 hdu = chip->hdu;
    522             }
    523             psArray *cells = chip->cells;       // Array of cells
    524             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
    525                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
    526                 if (cell->valid) {
    527                     if (cell->hdu) {
    528                         hdu = cell->hdu;
    529                     }
    530 
    531                     // Now, need to find out where to get the pixels
    532                     psFits *weightSource = source;      // Source of weight image
    533                     if (strcasecmp(sourceType, "FILE") == 0) {
    534                         // Source is a file (with optional extension, e.g., "myWeightFile.fits:thisExt"
    535                         psString filenameExt = p_pmFPATranslateName(name, cell);
    536                         char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
    537                         psString filename = NULL; // The filename
    538                         psString extname = NULL;// The extenstion name
    539                         if (colon) {
    540                             filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
    541                             if (strlen(colon) > 1) {
    542                                 extname = psStringCopy(colon + 1);
    543                             }
    544                         } else {
    545                             filename = psMemIncrRefCounter(filenameExt);
    546                         }
    547                        
    548                         weightSource = psFitsAlloc(filename);
    549                         if (extname) {
    550                             if (! psFitsMoveExtName(weightSource, extname)) {
    551                                 psLogMsg(__func__, PS_LOG_WARN, "Unable to find extension %s to read "
    552                                          "weight.\n", extname);
    553                                 return false;
    554                             }
    555                         }
    556                         psFree(filename);
    557                         psFree(extname);
    558                         psFree(filenameExt);
    559                     } else if (strncasecmp(sourceType, "EXT", 3) == 0) {
    560                         // Source is an extension in the original file
    561                         psString extname = p_pmFPATranslateName(name, cell);
    562                         psFitsMoveExtName(weightSource, extname);
    563                     }
    564                    
    565                     // We've arrived where the pixels are.  Now we need to read them in.
    566                     psMetadata *header = psFitsReadHeader(NULL, weightSource); // The header
    567                     bool mdStatus = false;
    568                     int nAxis = psMetadataLookupS32(&mdStatus, header, "NAXIS");
    569                     if (!mdStatus) {
    570                         psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header for "
    571                                  "weight (%s)!\n", name);
    572                     }
    573                     if (nAxis != 2 && nAxis != 3) {
    574                         psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into "
    575                                  "a single image anyway.\n");
    576                     }
    577            
    578                     int numPlanes = 1;  // Number of planes
    579                     if (nAxis == 3) {
    580                         numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
    581                         if (!mdStatus) {
    582                             psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
    583                             // Try to proceed by taking only the first plane
    584                             numPlanes = 1;
    585                         }
    586                         if (numPlanes != 1 && numPlanes != cell->readouts->n) {
    587                             psError(PS_ERR_IO, false, "Number of weights (%d) does not match number of "
    588                                     "readouts (%d)\n", numPlanes, cell->readouts->n);
    589                             // Try to proceed by taking only the first plane
    590                             numPlanes = 1;
    591                         }
    592                     }
    593 
    594                     hdu->weights = psArrayAlloc(hdu->images->n);
    595                    
    596                     // Read each plane into the array
    597                     psArray *readouts = cell->readouts; // The array of readouts
    598                     for (int i = 0; i < hdu->weights->n; i++) {
    599                         psImage *weight = NULL; // The weight to be added
    600                         if (i < numPlanes) {
    601                             // Read the weight from the file
    602                             psTrace(__func__, 9, "Reading plane %d\n", i);
    603                             psRegion region = {0, 0, 0, 0};
    604                             weight = psFitsReadImage(NULL, weightSource, region, i);
    605                         } else {
    606                             // One weight in the file is provided for all planes in the original image
    607                             psTrace(__func__, 9, "Copying plane 0 into plane %d\n", i);
    608                             psImage *original = hdu->weights->data[0];
    609                             weight = psImageCopy(NULL, original, original->type.type);
    610                         }
    611                         hdu->weights->data[0] = weight;
    612                         pmReadout *readout = readouts->data[i];
    613                         readout->weight = weight;
    614                         // Check the dimensions
    615                         // XXX: Perhaps this check should be against the CELL.TRIMSEC, not the image size?
    616                         if (weight->numCols < readout->image->numCols ||
    617                             weight->numRows < readout->image->numRows)
    618                         {
    619                             psError(PS_ERR_IO, false, "Weight size (%dx%d) not compatible with image "
    620                                     "(%dx%d)\n", weight->numCols, weight->numRows, readout->image->numCols,
    621                                     readout->image->numRows);
    622                             return false;
    623                         }
    624                     } // Iterating over readouts
    625                 } // Valid cells
    626             } // Iterating over cells
    627         } // Valid chips
     594    p_pmHDU *hdu = fpa->hdu;  // The HDU into which we will read the weight
     595    psArray *chips = fpa->chips; // Array of chips
     596    for (int chipNum = 0; chipNum < chips->n; chipNum++)
     597    {
     598        pmChip *chip = chips->data[chipNum]; // The current chip of interest
     599        if (chip->valid)
     600        {
     601            if (chip->hdu)
     602            {
     603                hdu = chip->hdu;
     604            }
     605            psArray *cells = chip->cells; // Array of cells
     606            for (int cellNum = 0; cellNum < cells->n; cellNum++)
     607            {
     608                pmCell *cell = cells->data[cellNum]; // The current cell of interest
     609                if (cell->valid)
     610                {
     611                    if (cell->hdu)
     612                    {
     613                        hdu = cell->hdu;
     614                    }
     615
     616                    // Now, need to find out where to get the pixels
     617                    psFits *weightSource = source; // Source of weight image
     618                    if (strcasecmp(sourceType, "FILE") == 0)
     619                    {
     620                        // Source is a file (with optional extension, e.g., "myWeightFile.fits:thisExt"
     621                        psString filenameExt = p_pmFPATranslateName(name, cell);
     622                        char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
     623                        psString filename = NULL; // The filename
     624                        psString extname = NULL; // The extenstion name
     625                        if (colon)
     626                        {
     627                            filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
     628                            if (strlen(colon) > 1)
     629                            {
     630                                extname = psStringCopy(colon + 1);
     631                            }
     632                        }
     633                        else
     634                        {
     635                            filename = psMemIncrRefCounter(filenameExt);
     636                        }
     637
     638                        weightSource = psFitsAlloc(filename);
     639                        if (extname)
     640                        {
     641                            if (! psFitsMoveExtName(weightSource, extname))
     642                            {
     643                                psLogMsg(__func__, PS_LOG_WARN, "Unable to find extension %s to read "
     644                                         "weight.\n", extname);
     645                                return false;
     646                            }
     647                        }
     648                        psFree(filename);
     649                        psFree(extname);
     650                        psFree(filenameExt);
     651                    }
     652                    else if (strncasecmp(sourceType, "EXT", 3) == 0)
     653                    {
     654                        // Source is an extension in the original file
     655                        psString extname = p_pmFPATranslateName(name, cell);
     656                        psFitsMoveExtName(weightSource, extname);
     657                    }
     658
     659                    // We've arrived where the pixels are.  Now we need to read them in.
     660                    psMetadata *header = psFitsReadHeader(NULL, weightSource); // The header
     661                    bool mdStatus = false;
     662                    int nAxis = psMetadataLookupS32(&mdStatus, header, "NAXIS");
     663                    if (!mdStatus)
     664                    {
     665                        psLogMsg(__func__, PS_LOG_WARN, "There is no NAXIS keyword in the FITS header for "
     666                                 "weight (%s)!\n", name);
     667                    }
     668                    if (nAxis != 2 && nAxis != 3)
     669                    {
     670                        psLogMsg(__func__, PS_LOG_WARN, "Image is not 2- or 3-dimensional --- reading into "
     671                                 "a single image anyway.\n");
     672                    }
     673
     674                    int numPlanes = 1; // Number of planes
     675                    if (nAxis == 3)
     676                    {
     677                        numPlanes = psMetadataLookupS32(&mdStatus, header, "NAXIS3");
     678                        if (!mdStatus)
     679                        {
     680                            psError(PS_ERR_IO, false, "Unable to read NAXIS3 for 3-dimensional image!\n");
     681                            // Try to proceed by taking only the first plane
     682                            numPlanes = 1;
     683                        }
     684                        if (numPlanes != 1 && numPlanes != cell->readouts->n)
     685                        {
     686                            psError(PS_ERR_IO, false, "Number of weights (%d) does not match number of "
     687                                    "readouts (%d)\n", numPlanes, cell->readouts->n);
     688                            // Try to proceed by taking only the first plane
     689                            numPlanes = 1;
     690                        }
     691                    }
     692
     693                    hdu->weights = psArrayAlloc(hdu->images->n);
     694
     695                    // Read each plane into the array
     696                    psArray *readouts = cell->readouts; // The array of readouts
     697                    for (int i = 0; i < hdu->weights->n; i++)
     698                    {
     699                        psImage *weight = NULL; // The weight to be added
     700                        if (i < numPlanes)
     701                        {
     702                            // Read the weight from the file
     703                            psTrace(__func__, 9, "Reading plane %d\n", i);
     704                            psRegion region = {0, 0, 0, 0};
     705                            weight = psFitsReadImage(NULL, weightSource, region, i);
     706                        }
     707                        else
     708                        {
     709                            // One weight in the file is provided for all planes in the original image
     710                            psTrace(__func__, 9, "Copying plane 0 into plane %d\n", i);
     711                            psImage *original = hdu->weights->data[0];
     712                            weight = psImageCopy(NULL, original, original->type.type);
     713                        }
     714                        hdu->weights->data[0] = weight;
     715                        pmReadout *readout = readouts->data[i];
     716                        readout->weight = weight;
     717                        // Check the dimensions
     718                        // XXX: Perhaps this check should be against the CELL.TRIMSEC, not the image size?
     719                        if (weight->numCols < readout->image->numCols ||
     720                            weight->numRows < readout->image->numRows)
     721                        {
     722                            psError(PS_ERR_IO, false, "Weight size (%dx%d) not compatible with image "
     723                                    "(%dx%d)\n", weight->numCols, weight->numRows, readout->image->numCols,
     724                                    readout->image->numRows);
     725                            return false;
     726                        }
     727                    } // Iterating over readouts
     728                } // Valid cells
     729            } // Iterating over cells
     730        } // Valid chips
    628731    } // Iterating over chips
    629732
  • branches/neb/archive/scripts/src/phase2/pmFPAWrite.c

    r5633 r5648  
    77#include "pmFPARead.h"
    88
    9 static bool writeHDU(psFits *fits,      // FITS file to which to write
    10                      p_pmHDU *hdu       // Pixel data to write
    11     )
     9static bool writeHDU(psFits *fits,  // FITS file to which to write
     10                     p_pmHDU *hdu // Pixel data to write
     11                    )
    1212{
    13     bool status = true;                 // Status of write, to return
    14     for (int i = 0; i < hdu->images->n; i++) {
    15         status &= psFitsWriteImage(fits, hdu->header, hdu->images->data[i], i);
    16         // XXX: Insert here the writing on mask and weight images
     13    bool status = true;   // Status of write, to return
     14    for (int i = 0; i < hdu->images->n; i++)
     15    {
     16        status &= psFitsWriteImage(fits, hdu->header, hdu->images->data[i], i);
     17        // XXX: Insert here the writing on mask and weight images
    1718    }
    1819
     
    2122
    2223
    23 bool pmFPAWrite(psFits *fits,           // FITS file to which to write
    24                 pmFPA *fpa,             // FPA to write
    25                 psDB *db                // Database to update
    26     )
     24bool pmFPAWrite(psFits *fits,   // FITS file to which to write
     25                pmFPA *fpa,   // FPA to write
     26                psDB *db  // Database to update
     27               )
    2728{
    28     bool status = true;                 // Status of writing, to return
     29    bool status = true;   // Status of writing, to return
    2930
    3031    pmFPAOutgestConcepts(fpa, db);
    3132
    3233    // Write the primary header
    33     if (fpa->phu) {
    34         status &= psFitsMoveExtNum(fits, 0, false);
    35         status &= psFitsWriteHeader(fpa->phu, fits);
    36     }
    37 
    38     psArray *chips = fpa->chips;        // Array of component chips
    39     for (int i = 0; i < chips->n; i++) {
    40         pmChip *chip = chips->data[i];  // The component chip
    41         if (chip->valid) {
    42             pmChipOutgestConcepts(chip, db);
    43 
    44             psArray *cells = chip->cells;       // Array of component cells
    45             for (int j = 0; j < cells->n; j++) {
    46                 pmCell *cell = cells->data[j]; // The component cell
    47                 if (cell->valid) {
    48                     pmCellOutgestConcepts(cell, db);
    49 
    50                     if (cell->hdu && strlen(cell->hdu->extname) > 0) {
    51                         status &= writeHDU(fits, cell->hdu);
    52                     }
    53                 }
    54             }
    55            
    56             if (chip->hdu && strlen(chip->hdu->extname) > 0) {
    57                 status &= writeHDU(fits, chip->hdu);
    58             }
    59         }
    60 
    61     }
    62 
    63     if (fpa->hdu && strlen(fpa->hdu->extname) > 0) {
    64         status &= writeHDU(fits, fpa->hdu);
    65     }
    66 
    67 
     34    if (fpa->phu)
     35    {
     36        status &= psFitsMoveExtNum(fits, 0, false);
     37        status &= psFitsWriteHeader(fpa->phu, fits);
     38    }
     39
     40    psArray *chips = fpa->chips; // Array of component chips
     41    for (int i = 0; i < chips->n; i++)
     42    {
     43        pmChip *chip = chips->data[i]; // The component chip
     44        if (chip->valid)
     45        {
     46            pmChipOutgestConcepts(chip, db);
     47
     48            psArray *cells = chip->cells; // Array of component cells
     49            for (int j = 0; j < cells->n; j++)
     50            {
     51                pmCell *cell = cells->data[j]; // The component cell
     52                if (cell->valid)
     53                {
     54                    pmCellOutgestConcepts(cell, db);
     55
     56                    if (cell->hdu && strlen(cell->hdu->extname) > 0)
     57                    {
     58                        status &= writeHDU(fits, cell->hdu);
     59                    }
     60                }
     61            }
     62
     63            if (chip->hdu && strlen(chip->hdu->extname) > 0)
     64            {
     65                status &= writeHDU(fits, chip->hdu);
     66            }
     67        }
     68
     69    }
     70
     71    if (fpa->hdu && strlen(fpa->hdu->extname) > 0)
     72    {
     73        status &= writeHDU(fits, fpa->hdu);
     74    }
    6875
    6976    return status;
     
    7178
    7279
    73 bool pmFPAWriteMask(pmFPA *fpa,         // FPA containing mask to write
    74                     psFits *fits        // FITS file for image
    75     )
     80bool pmFPAWriteMask(pmFPA *fpa,   // FPA containing mask to write
     81                    psFits *fits // FITS file for image
     82                   )
    7683{
    7784    const psMetadata *camera = fpa->camera; // Camera configuration for FPA
    78     bool mdok = false;                  // Status of MD lookup
     85    bool mdok = false;   // Status of MD lookup
    7986
    8087    // Get the required information from the camera configuration
    8188    psMetadata *supps = psMetadataLookupMD(&mdok, camera, "SUPPLEMENTARY"); // Rules for supplementary data
    82     if (! mdok || ! supps) {
    83         psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
    84         return false;
     89    if (! mdok || ! supps)
     90    {
     91        psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
     92        return false;
    8593    }
    8694    psString sourceType = psMetadataLookupString(&mdok, supps, "MASK.SOURCE"); // Type of source: EXT | FILE
    87     if (! mdok || strlen(sourceType) <= 0) {
    88         psError(PS_ERR_IO, false, "Unable to find MASK.SOURCE in SUPPLEMENTARY section of camera "
    89                 "configuration!\n");
    90         return false;
     95    if (! mdok || strlen(sourceType) <= 0)
     96    {
     97        psError(PS_ERR_IO, false, "Unable to find MASK.SOURCE in SUPPLEMENTARY section of camera "
     98                "configuration!\n");
     99        return false;
    91100    }
    92101    psString name = psMetadataLookupString(&mdok, supps, "MASK.NAME"); // Name of mask
    93     if (! mdok || strlen(sourceType) <= 0) {
    94         psError(PS_ERR_IO, false, "Unable to find MASK.NAME in SUPPLEMENTARY section of camera "
    95                 "configuration!\n");
    96         return false;
     102    if (! mdok || strlen(sourceType) <= 0)
     103    {
     104        psError(PS_ERR_IO, false, "Unable to find MASK.NAME in SUPPLEMENTARY section of camera "
     105                "configuration!\n");
     106        return false;
    97107    }
    98108
    99109    // Go through the FPA to each cell/readout to get the mask
    100     p_pmHDU *hdu = fpa->hdu;            // The HDU into which we will read the mask
    101     psArray *chips = fpa->chips;        // Array of chips
    102     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
    103         pmChip *chip = chips->data[chipNum]; // The current chip of interest
    104         if (chip->valid) {
    105             if (chip->hdu) {
    106                 hdu = chip->hdu;
    107             }
    108             psArray *cells = chip->cells;       // Array of cells
    109             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
    110                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
    111                 if (cell->valid) {
    112                     if (cell->hdu) {
    113                         hdu = cell->hdu;
    114                     }
    115 
    116                     // Now, need to find out where to write the pixels
    117                     psFits *maskDest = psMemIncrRefCounter(fits); // Destination of mask image
    118                     psMetadata *header = psMetadataAlloc(); // A dummy header, containing the extension name
    119                     if (strcasecmp(sourceType, "FILE") == 0) {
    120                         // Source is a file (with optional extension, e.g., "myMaskFile.fits:thisExt"
    121                         psString filenameExt = p_pmFPATranslateName(name, cell);
    122                         char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
    123                         psString filename = NULL; // The filename
    124                         psString extname = NULL;// The extenstion name
    125                         if (colon) {
    126                             filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
    127                             if (strlen(colon) > 1) {
    128                                 extname = psStringCopy(colon + 1);
    129                             }
    130                         } else {
    131                             filename = psMemIncrRefCounter(filenameExt);
    132                         }
    133 
    134                         psFree(maskDest);
    135                         maskDest = psFitsAlloc(filename);
    136                         if (extname) {
    137                             psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
    138                         }
    139                         psFree(filename);
    140                         psFree(extname);
    141                         psFree(filenameExt);
    142                     } else if (strncasecmp(sourceType, "EXT", 3) == 0) {
    143                         // Source is an extension in the original file
    144                         psString extname = p_pmFPATranslateName(name, cell);
    145                         psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
    146                         psFree(extname);
    147                     }
    148                    
    149                     // We've arrived where the pixels are.  Now we need to write them out.
    150                     psArray *readouts = cell->readouts; // The array of readouts
    151                     for (int readNum = 0; readNum < readouts->n; readNum++) {
    152                         pmReadout *readout = readouts->data[readNum]; // The readout of interest
    153                         if (! readout->mask) {
    154                             psLogMsg(__func__, PS_LOG_WARN, "No mask to write out in %d,%d,%d\n",
    155                                      chipNum, cellNum, readNum);
    156                         } else {
    157                             // XXX: Need to add the extname to the existing header
    158                             if (! psFitsWriteImage(maskDest, header, readout->mask, readNum)) {
    159                                 psError(PS_ERR_IO, false, "Unable to write mask plane %d in extension %s\n",
    160                                         readNum, hdu->extname);
    161                                 return false;
    162                             }
    163                         }
    164                     } // Iterating over readouts
    165                     psFree(header);
    166                     psFree(maskDest);
    167                 } // Valid cells
    168             } // Iterating over cells
    169         } // Valid chips
     110    p_pmHDU *hdu = fpa->hdu;  // The HDU into which we will read the mask
     111    psArray *chips = fpa->chips; // Array of chips
     112    for (int chipNum = 0; chipNum < chips->n; chipNum++)
     113    {
     114        pmChip *chip = chips->data[chipNum]; // The current chip of interest
     115        if (chip->valid)
     116        {
     117            if (chip->hdu)
     118            {
     119                hdu = chip->hdu;
     120            }
     121            psArray *cells = chip->cells; // Array of cells
     122            for (int cellNum = 0; cellNum < cells->n; cellNum++)
     123            {
     124                pmCell *cell = cells->data[cellNum]; // The current cell of interest
     125                if (cell->valid)
     126                {
     127                    if (cell->hdu)
     128                    {
     129                        hdu = cell->hdu;
     130                    }
     131
     132                    // Now, need to find out where to write the pixels
     133                    psFits *maskDest = psMemIncrRefCounter(fits); // Destination of mask image
     134                    psMetadata *header = psMetadataAlloc(); // A dummy header, containing the extension name
     135                    if (strcasecmp(sourceType, "FILE") == 0)
     136                    {
     137                        // Source is a file (with optional extension, e.g., "myMaskFile.fits:thisExt"
     138                        psString filenameExt = p_pmFPATranslateName(name, cell);
     139                        char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
     140                        psString filename = NULL; // The filename
     141                        psString extname = NULL; // The extenstion name
     142                        if (colon)
     143                        {
     144                            filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
     145                            if (strlen(colon) > 1)
     146                            {
     147                                extname = psStringCopy(colon + 1);
     148                            }
     149                        }
     150                        else
     151                        {
     152                            filename = psMemIncrRefCounter(filenameExt);
     153                        }
     154
     155                        psFree(maskDest);
     156                        maskDest = psFitsAlloc(filename);
     157                        if (extname)
     158                        {
     159                            psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
     160                        }
     161                        psFree(filename);
     162                        psFree(extname);
     163                        psFree(filenameExt);
     164                    }
     165                    else if (strncasecmp(sourceType, "EXT", 3) == 0)
     166                    {
     167                        // Source is an extension in the original file
     168                        psString extname = p_pmFPATranslateName(name, cell);
     169                        psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
     170                        psFree(extname);
     171                    }
     172
     173                    // We've arrived where the pixels are.  Now we need to write them out.
     174                    psArray *readouts = cell->readouts; // The array of readouts
     175                    for (int readNum = 0; readNum < readouts->n; readNum++)
     176                    {
     177                        pmReadout *readout = readouts->data[readNum]; // The readout of interest
     178                        if (! readout->mask)
     179                        {
     180                            psLogMsg(__func__, PS_LOG_WARN, "No mask to write out in %d,%d,%d\n",
     181                                     chipNum, cellNum, readNum);
     182                        }
     183                        else
     184                        {
     185                            // XXX: Need to add the extname to the existing header
     186                            if (! psFitsWriteImage(maskDest, header, readout->mask, readNum))
     187                            {
     188                                psError(PS_ERR_IO, false, "Unable to write mask plane %d in extension %s\n",
     189                                        readNum, hdu->extname);
     190                                return false;
     191                            }
     192                        }
     193                    } // Iterating over readouts
     194                    psFree(header);
     195                    psFree(maskDest);
     196                } // Valid cells
     197            } // Iterating over cells
     198        } // Valid chips
    170199    } // Iterating over chips
    171200
     
    174203
    175204
    176 bool pmFPAWriteWeight(pmFPA *fpa,       // FPA containing mask to write
    177                       psFits *fits      // FITS file for image
    178     )
     205bool pmFPAWriteWeight(pmFPA *fpa,   // FPA containing mask to write
     206                      psFits *fits // FITS file for image
     207                     )
    179208{
    180209    const psMetadata *camera = fpa->camera; // Camera configuration for FPA
    181     bool mdok = false;                  // Status of MD lookup
     210    bool mdok = false;   // Status of MD lookup
    182211
    183212    // Get the required information from the camera configuration
    184213    psMetadata *supps = psMetadataLookupMD(&mdok, camera, "SUPPLEMENTARY"); // Rules for supplementary data
    185     if (! mdok || ! supps) {
    186         psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
    187         return false;
     214    if (! mdok || ! supps)
     215    {
     216        psError(PS_ERR_IO, false, "Unable to find SUPPLEMENTARY in camera configuration!\n");
     217        return false;
    188218    }
    189219    psString sourceType = psMetadataLookupString(&mdok, supps, "WEIGHT.SOURCE"); // Type of source: EXT | FILE
    190     if (! mdok || strlen(sourceType) <= 0) {
    191         psError(PS_ERR_IO, false, "Unable to find WEIGHT.SOURCE in SUPPLEMENTARY section of camera "
    192                 "configuration!\n");
    193         return false;
     220    if (! mdok || strlen(sourceType) <= 0)
     221    {
     222        psError(PS_ERR_IO, false, "Unable to find WEIGHT.SOURCE in SUPPLEMENTARY section of camera "
     223                "configuration!\n");
     224        return false;
    194225    }
    195226    psString name = psMetadataLookupString(&mdok, supps, "WEIGHT.NAME"); // Name of weight
    196     if (! mdok || strlen(sourceType) <= 0) {
    197         psError(PS_ERR_IO, false, "Unable to find WEIGHT.NAME in SUPPLEMENTARY section of camera "
    198                 "configuration!\n");
    199         return false;
     227    if (! mdok || strlen(sourceType) <= 0)
     228    {
     229        psError(PS_ERR_IO, false, "Unable to find WEIGHT.NAME in SUPPLEMENTARY section of camera "
     230                "configuration!\n");
     231        return false;
    200232    }
    201233
    202234    // Go through the FPA to each cell/readout to get the weight
    203     p_pmHDU *hdu = fpa->hdu;            // The HDU into which we will read the weight
    204     psArray *chips = fpa->chips;        // Array of chips
    205     for (int chipNum = 0; chipNum < chips->n; chipNum++) {
    206         pmChip *chip = chips->data[chipNum]; // The current chip of interest
    207         if (chip->valid) {
    208             if (chip->hdu) {
    209                 hdu = chip->hdu;
    210             }
    211             psArray *cells = chip->cells;       // Array of cells
    212             for (int cellNum = 0; cellNum < cells->n; cellNum++) {
    213                 pmCell *cell = cells->data[cellNum]; // The current cell of interest
    214                 if (cell->valid) {
    215                     if (cell->hdu) {
    216                         hdu = cell->hdu;
    217                     }
    218 
    219                     // Now, need to find out where to write the pixels
    220                     psFits *weightDest = psMemIncrRefCounter(fits); // Destination of weight image
    221                     psMetadata *header = psMetadataAlloc(); // A dummy header, containing the extension name
    222                     if (strcasecmp(sourceType, "FILE") == 0) {
    223                         // Source is a file (with optional extension, e.g., "myWeightFile.fits:thisExt"
    224                         psString filenameExt = p_pmFPATranslateName(name, cell);
    225                         char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
    226                         psString filename = NULL; // The filename
    227                         psString extname = NULL;// The extenstion name
    228                         if (colon) {
    229                             filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
    230                             if (strlen(colon) > 1) {
    231                                 extname = psStringCopy(colon + 1);
    232                             }
    233                         } else {
    234                             filename = psMemIncrRefCounter(filenameExt);
    235                         }
    236 
    237                         psFree(weightDest);
    238                         weightDest = psFitsAlloc(filename);
    239                         if (extname) {
    240                             psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
    241                         }
    242                         psFree(filename);
    243                         psFree(extname);
    244                         psFree(filenameExt);
    245                     } else if (strncasecmp(sourceType, "EXT", 3) == 0) {
    246                         // Source is an extension in the original file
    247                         psString extname = p_pmFPATranslateName(name, cell);
    248                         psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
    249                         psFree(extname);
    250                     }
    251 
    252                     // We've arrived where the pixels are.  Now we need to write them out.
    253                     psArray *readouts = cell->readouts; // The array of readouts
    254                     for (int readNum = 0; readNum < readouts->n; readNum++) {
    255                         pmReadout *readout = readouts->data[readNum]; // The readout of interest
    256                         if (! readout->weight) {
    257                             psLogMsg(__func__, PS_LOG_WARN, "No weight image to write out in %d,%d,%d\n",
    258                                      chipNum, cellNum, readNum);
    259                         } else {
    260                             if (! psFitsWriteImage(weightDest, header, readout->weight, readNum)) {
    261                                 psError(PS_ERR_IO, false, "Unable to write weight plane %d in extension %s\n",
    262                                         readNum, hdu->extname);
    263                                 return false;
    264                             }
    265                         }
    266                     } // Iterating over readouts
    267                     psFree(header);
    268                     psFree(weightDest);
    269                 } // Valid cells
    270             } // Iterating over cells
    271         } // Valid chips
     235    p_pmHDU *hdu = fpa->hdu;  // The HDU into which we will read the weight
     236    psArray *chips = fpa->chips; // Array of chips
     237    for (int chipNum = 0; chipNum < chips->n; chipNum++)
     238    {
     239        pmChip *chip = chips->data[chipNum]; // The current chip of interest
     240        if (chip->valid)
     241        {
     242            if (chip->hdu)
     243            {
     244                hdu = chip->hdu;
     245            }
     246            psArray *cells = chip->cells; // Array of cells
     247            for (int cellNum = 0; cellNum < cells->n; cellNum++)
     248            {
     249                pmCell *cell = cells->data[cellNum]; // The current cell of interest
     250                if (cell->valid)
     251                {
     252                    if (cell->hdu)
     253                    {
     254                        hdu = cell->hdu;
     255                    }
     256
     257                    // Now, need to find out where to write the pixels
     258                    psFits *weightDest = psMemIncrRefCounter(fits); // Destination of weight image
     259                    psMetadata *header = psMetadataAlloc(); // A dummy header, containing the extension name
     260                    if (strcasecmp(sourceType, "FILE") == 0)
     261                    {
     262                        // Source is a file (with optional extension, e.g., "myWeightFile.fits:thisExt"
     263                        psString filenameExt = p_pmFPATranslateName(name, cell);
     264                        char *colon = strchr(filenameExt, ':'); // Pointer to a colon in the filename-extn
     265                        psString filename = NULL; // The filename
     266                        psString extname = NULL; // The extenstion name
     267                        if (colon)
     268                        {
     269                            filename = psStringNCopy(filenameExt, strlen(filenameExt) - strlen(colon));
     270                            if (strlen(colon) > 1)
     271                            {
     272                                extname = psStringCopy(colon + 1);
     273                            }
     274                        }
     275                        else
     276                        {
     277                            filename = psMemIncrRefCounter(filenameExt);
     278                        }
     279
     280                        psFree(weightDest);
     281                        weightDest = psFitsAlloc(filename);
     282                        if (extname)
     283                        {
     284                            psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
     285                        }
     286                        psFree(filename);
     287                        psFree(extname);
     288                        psFree(filenameExt);
     289                    }
     290                    else if (strncasecmp(sourceType, "EXT", 3) == 0)
     291                    {
     292                        // Source is an extension in the original file
     293                        psString extname = p_pmFPATranslateName(name, cell);
     294                        psMetadataAddStr(header, PS_LIST_TAIL, "EXTNAME", 0, "Extension name", extname);
     295                        psFree(extname);
     296                    }
     297
     298                    // We've arrived where the pixels are.  Now we need to write them out.
     299                    psArray *readouts = cell->readouts; // The array of readouts
     300                    for (int readNum = 0; readNum < readouts->n; readNum++)
     301                    {
     302                        pmReadout *readout = readouts->data[readNum]; // The readout of interest
     303                        if (! readout->weight)
     304                        {
     305                            psLogMsg(__func__, PS_LOG_WARN, "No weight image to write out in %d,%d,%d\n",
     306                                     chipNum, cellNum, readNum);
     307                        }
     308                        else
     309                        {
     310                            if (! psFitsWriteImage(weightDest, header, readout->weight, readNum))
     311                            {
     312                                psError(PS_ERR_IO, false, "Unable to write weight plane %d in extension %s\n",
     313                                        readNum, hdu->extname);
     314                                return false;
     315                            }
     316                        }
     317                    } // Iterating over readouts
     318                    psFree(header);
     319                    psFree(weightDest);
     320                } // Valid cells
     321            } // Iterating over cells
     322        } // Valid chips
    272323    } // Iterating over chips
    273324
Note: See TracChangeset for help on using the changeset viewer.