IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 5795


Ignore:
Timestamp:
Dec 16, 2005, 5:18:39 PM (21 years ago)
Author:
Paul Price
Message:

Importing PAP code from phase 2. NOTE: Reverted files in detrend/ and imsubtract/ to a previous version. DO NOT merge these files back!

Location:
branches/pap_branch_051214/psModules/src
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • branches/pap_branch_051214/psModules/src/astrom/Makefile.am

    r5674 r5795  
    44libpsmoduleastrom_la_LDFLAGS  = -release $(PACKAGE_VERSION)
    55libpsmoduleastrom_la_SOURCES  = \
    6     pmAstrometry.c \
    7     pmAstrometryObjects.c
     6        pmAstrometry.c \
     7        pmAstrometryObjects.c \
     8        pmChipMosaic.c \
     9        pmFPAConceptsGet.c \
     10        pmFPAConceptsSet.c \
     11        pmFPAConstruct.c \
     12        pmFPARead.c \
     13        pmFPAWrite.c \
     14        pmReadout.c \
     15        psAdditionals.c
    816
    917psmoduleincludedir = $(includedir)
    1018psmoduleinclude_HEADERS = \
    11   pmAstrometry.h \
    12   pmAstrometryObjects.h
     19        pmAstrometry.h \
     20        pmAstrometryObjects.h \
     21        pmChipMosaic.h \
     22        pmFPAConceptsGet.h \
     23        pmFPAConceptsSet.h \
     24        pmFPAConstruct.h \
     25        pmFPARead.h \
     26        pmFPAWrite.h \
     27        pmReadout.h \
     28        psAdditionals.h
  • branches/pap_branch_051214/psModules/src/astrom/pmAstrometry.c

    r5739 r5795  
    1010* XXX: We should review the extent of the warning messages on these functions
    1111* when the transformations are not successful.
    12 * 
     12*
    1313* XXX: Should we implement non-linear cell->chip transforms?
    14 * 
    15 *  @version $Revision: 1.11 $ $Name: not supported by cvs2svn $
    16 *  @date $Date: 2005-12-08 00:00:57 $
     14*
     15*  @version $Revision: 1.11.2.1 $ $Name: not supported by cvs2svn $
     16*  @date $Date: 2005-12-17 03:18:38 $
    1717*
    1818*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    6060        psFree(readout->mask);
    6161        psFree(readout->weight);
    62         //
    63         // XXX: Not sure if this is the right way to do things.  Currently the psListAdd()
    64         // increase the memory reference counter to the list data.  So, we
    65         // iterate through the list, and decrement the reference counters.
    66         //
    67         if (1) {
    68             if ((readout->bias != NULL) && (readout->bias->head != NULL)) {
    69                 psListElem *tmpElem = (psListElem *) readout->bias->head;
    70                 while (NULL != tmpElem) {
    71                     psMemDecrRefCounter((psImage *) tmpElem->data);
    72                     tmpElem = tmpElem->next;
    73                 }
    74             }
    75         }
    76         psFree(readout->bias);
    7762        psFree(readout->analysis);
    7863        psFree(readout->parent);
     
    8873        psFree(cell->concepts);
    8974        psFree(cell->analysis);
     75        psFree(cell->camera);
    9076        //
    9177        // Set the parent to NULL in all cell->readouts before psFree(cell->readouts)
     
    10187        psFree(cell->readouts);
    10288        psFree(cell->parent);
    103         psFree(cell->private);
     89        psFree(cell->hdu);
    10490    }
    10591}
     
    125111        psFree(chip->cells);
    126112        psFree(chip->parent);
    127         psFree(chip->private);
     113        psFree(chip->hdu);
    128114    }
    129115}
     
    151137        }
    152138        psFree(fpa->chips);
    153         psFree(fpa->private);
     139        psFree(fpa->hdu);
    154140        psFree(fpa->phu);
    155141    }
    156142}
    157143
     144void p_pmHDUFree(p_pmHDU *hdu)
     145{
     146    if (hdu) {
     147        psFree(hdu->extname);
     148        psFree(hdu->header);
     149        psFree(hdu->images);
     150        psFree(hdu->masks);
     151        psFree(hdu->weights);
     152    }
     153}
     154
    158155// XXX: Verify these default values for row0, col0, rowBins, colBins
     156// PAP: These values may disappear in the future in favour of values in parent->concepts?
    159157pmReadout *pmReadoutAlloc(pmCell *cell)
    160158{
    161159    pmReadout *tmpReadout = (pmReadout *) psAlloc(sizeof(pmReadout));
    162160
    163     tmpReadout->col0 = -1;
    164     tmpReadout->row0 = -1;
    165     tmpReadout->colBins = -1;
    166     tmpReadout->rowBins = -1;
     161    tmpReadout->col0 = 0;
     162    tmpReadout->row0 = 0;
     163    tmpReadout->colBins = 0;
     164    tmpReadout->rowBins = 0;
    167165    tmpReadout->image = NULL;
    168166    tmpReadout->mask = NULL;
    169167    tmpReadout->weight = NULL;
    170     tmpReadout->bias = NULL;
    171168    tmpReadout->analysis = psMetadataAlloc();
    172169    tmpReadout->parent = cell;
     
    179176
    180177// XXX: Verify these default values for row0, col0.
     178// PAP: These values may disappear in the future in favour of values in the "concepts"?
    181179pmCell *pmCellAlloc(
    182180    pmChip *chip,
    183     psMetadata *cameradata,
    184     psString name)
     181    psMetadata *cameraData,
     182    const char *name)
    185183{
    186184    pmCell *tmpCell = (pmCell *) psAlloc(sizeof(pmCell));
    187185
    188     tmpCell->col0 = -1;
    189     tmpCell->row0 = -1;
     186    tmpCell->col0 = 0;
     187    tmpCell->row0 = 0;
    190188    tmpCell->toChip = NULL;
    191189    tmpCell->toFPA = NULL;
     
    196194        psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not add CELL.NAME to metadata.\n");
    197195    }
    198     tmpCell->camera = cameradata;
    199     tmpCell->analysis = NULL;
     196    tmpCell->camera = psMemIncrRefCounter(cameraData);
     197    tmpCell->analysis = psMetadataAlloc();
    200198    tmpCell->readouts = psArrayAlloc(0);
    201     tmpCell->parent = chip;
     199    tmpCell->parent = psMemIncrRefCounter(chip);
    202200    if (chip != NULL) {
    203201        chip->cells = psArrayAdd(chip->cells, 1, (psPtr) tmpCell);
    204202    }
    205     tmpCell->valid = false;
    206     tmpCell->private = NULL;
     203    tmpCell->valid = true;              // All cells are valid by default
     204    tmpCell->hdu = NULL;
    207205
    208206    psMemSetDeallocator(tmpCell, (psFreeFunc) cellFree);
     
    211209
    212210// XXX: Verify these default values for row0, col0.
     211// PAP: row0, col0 may disappear in the future in favour of storing values in the "concepts".
    213212pmChip *pmChipAlloc(
    214213    pmFPA *fpa,
    215     psString name)
     214    const char *name)
    216215{
    217216    pmChip *tmpChip = (pmChip *) psAlloc(sizeof(pmChip));
    218217
    219     tmpChip->col0 = -1;
    220     tmpChip->row0 = -1;
     218    tmpChip->col0 = 0;
     219    tmpChip->row0 = 0;
    221220    tmpChip->toFPA = NULL;
    222221    tmpChip->fromFPA = NULL;
     
    226225        psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not add CHIP.NAME to metadata.\n");
    227226    }
    228     tmpChip->analysis = NULL;
     227    tmpChip->analysis = psMetadataAlloc();
    229228    tmpChip->cells = psArrayAlloc(0);
    230     tmpChip->parent = fpa;
     229    tmpChip->parent = psMemIncrRefCounter(fpa);
    231230    if (fpa != NULL) {
    232231        fpa->chips = psArrayAdd(fpa->chips, 1, (psPtr) tmpChip);
    233232    }
    234     tmpChip->valid = false;
    235     tmpChip->private = NULL;
     233    tmpChip->valid = true;              // Work on all chips, by default
     234    tmpChip->hdu = NULL;
    236235
    237236    psMemSetDeallocator(tmpChip, (psFreeFunc) chipFree);
     
    248247    tmpFPA->concepts = psMetadataAlloc();
    249248    tmpFPA->analysis = NULL;
    250     tmpFPA->camera = camera;
     249    tmpFPA->camera = psMemIncrRefCounter((psPtr)camera);
    251250    tmpFPA->chips = psArrayAlloc(0);
    252     tmpFPA->private = NULL;
     251    tmpFPA->hdu = NULL;
    253252    tmpFPA->phu = NULL;
    254253
    255254    psMemSetDeallocator(tmpFPA, (psFreeFunc) FPAFree);
    256255    return(tmpFPA);
     256}
     257
     258p_pmHDU *p_pmHDUAlloc(const char *extname)
     259{
     260    p_pmHDU *hdu = psAlloc(sizeof(p_pmHDU));
     261    psMemSetDeallocator(hdu, (psFreeFunc)p_pmHDUFree);
     262
     263    hdu->extname = psStringCopy(extname);
     264    hdu->header = NULL;
     265    hdu->images = NULL;
     266    hdu->masks = NULL;
     267    hdu->weights = NULL;
     268
     269    return hdu;
    257270}
    258271
     
    800813}
    801814
     815
     816/*****************************************************************************
     817 *****************************************************************************/
     818
     819// Set cells within a chip to a specified validity
     820static bool setCellsValid(const pmChip *chip, // Chip of interest
     821                          bool valid    // Valid?
     822                         )
     823{
     824    PS_ASSERT_PTR_NON_NULL(chip, false);
     825
     826    psArray *cells = chip->cells;       // Component cells
     827    if (! cells) {
     828        return false;
     829    }
     830    for (int i = 0; i < cells->n; i++) {
     831        pmCell *tmpCell = cells->data[i]; // Cell of interest
     832        if (tmpCell) {
     833            tmpCell->valid = valid;
     834        }
     835    }
     836
     837    return true;
     838}
     839
    802840/*****************************************************************************
    803841 *****************************************************************************/
     
    807845{
    808846    PS_ASSERT_PTR_NON_NULL(fpa, false);
    809     if ((fpa->chips == NULL) || (chipNum >= fpa->chips->n)) {
     847
     848    psArray *chips = fpa->chips;        // Component chips
     849    if ((chips == NULL) || (chipNum >= chips->n)) {
    810850        return(false);
    811851    }
    812     psBool rc = true;
    813 
    814     for (psS32 i = 0 ; i < fpa->chips->n ; i++) {
    815         pmChip *tmpChip = (pmChip *) fpa->chips->data[i];
     852
     853    for (int i = 0 ; i < chips->n ; i++) {
     854        pmChip *tmpChip = (pmChip *) chips->data[i];
    816855        if (tmpChip == NULL) {
    817             rc = false;
     856            continue;
     857        }
     858        if (i == chipNum) {
     859            tmpChip->valid = true;
     860            setCellsValid(tmpChip, true);
    818861        } else {
    819             if (i == chipNum) {
    820                 tmpChip->valid = true;
    821             } else {
    822                 tmpChip->valid = false;
    823             }
    824         }
    825     }
    826 
    827     return(rc);
     862            tmpChip->valid = false;
     863            setCellsValid(tmpChip, false);
     864        }
     865
     866    }
     867
     868    return true;
    828869}
    829870
     
    831872/*****************************************************************************
    832873XXX: The SDRS is ambiguous on a few things:
    833     Whether or not the other chips should be set valid=true.
    834     Should we return the number of chip valid=true before or after they're set,
     874    Whether or not the other chips should be set valid=true. [PAP: No]
     875    Should we return the number of chip valid=true before or after they're set, [PAP: After]
    835876 *****************************************************************************/
    836877/**
    837  * 
     878 *
    838879 * pmFPAExcludeChip shall set valid to false only for the specified chip
    839880 * number (chipNum). In the event that the specified chip number does not exist
     
    841882 * The function shall return the number of chips within the fpa that have valid
    842883 * set to true.
    843  * 
     884 *
    844885 */
    845886int pmFPAExcludeChip(
     
    849890    PS_ASSERT_PTR_NON_NULL(fpa, false);
    850891
    851     if (fpa->chips == NULL) {
     892    psArray *chips = fpa->chips;        // Component chips
     893    if (chips == NULL) {
    852894        psLogMsg(__func__, PS_LOG_WARN, "WARNING: fpa->chips == NULL\n");
    853895        return(0);
    854896    }
    855     if ((chipNum >= fpa->chips->n) || (NULL == (pmChip *) fpa->chips->data[chipNum])) {
     897    if ((chipNum >= chips->n) || (NULL == (pmChip *) chips->data[chipNum])) {
    856898        psLogMsg(__func__, PS_LOG_WARN, "WARNING: the specified chip (%d) does not exist.\n", chipNum);
    857899        return(0);
    858900    }
    859901
    860     psS32 numChips = 0;
    861     for (psS32 i = 0 ; i < fpa->chips->n ; i++) {
    862         pmChip *tmpChip = (pmChip *) fpa->chips->data[i];
     902    int numChips = 0;                   // Number of valid chips
     903    for (int i = 0 ; i < chips->n ; i++) {
     904        pmChip *tmpChip = (pmChip *) chips->data[i]; // Chip of interest
    863905        if (tmpChip != NULL) {
    864906            if (i == chipNum) {
    865907                tmpChip->valid = false;
    866             } else {
    867                 tmpChip->valid = true;
     908                setCellsValid(tmpChip, false); // Wipe out the cell as well
     909            } else if (tmpChip->valid) {
    868910                numChips++;
    869911            }
  • branches/pap_branch_051214/psModules/src/astrom/pmAstrometry.h

    r5739 r5795  
    88*  @author GLG, MHPCC
    99*
    10 *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2005-12-08 00:00:57 $
     10*  @version $Revision: 1.5.2.1 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2005-12-17 03:18:38 $
    1212*
    1313*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    3030{
    3131    const char *extname;                // Extension name, if it corresponds to this level
    32     psArray *pixels;                    // The pixel data, if it corresponds to this level
    3332    psMetadata *header;                 // The FITS header, if it corresponds to this level
     33    psArray *images;                    // The pixel data, if it corresponds to this level
     34    psArray *masks;                     // The mask data, if it corresponds to this level
     35    psArray *weights;                   // The weight data, if it corresponds to this level
    3436}
    3537p_pmHDU;
    3638
    3739/** Focal plane data structure
    38  * 
     40 *
    3941 *  A focal plane consists of one or more chips (according to the number of
    4042 *  pieces of contiguous silicon). It contains metadata containers for the
     
    4951 *  transformation which will be derived from numerically inverting the forward
    5052 *  transformation.
    51  * 
     53 *
    5254 */
    5355typedef struct
     
    6264    const psMetadata *camera;           ///< Camera configuration
    6365    psArray *chips;                     ///< The chips
    64     p_pmHDU *private;                   ///< FITS data
     66    p_pmHDU *hdu;                       ///< FITS data
    6567    psMetadata *phu;                    ///< Primary Header
    6668}
     
    6870
    6971/** Chip data structure
    70  * 
     72 *
    7173 *  A chip consists of one or more cells (according to the number of amplifiers
    7274 *  on the device). The chip contains metadata containers for the concepts and
     
    7981 *  inverting the forward transformation. A boolean indicates whether the chip is
    8082 *  of interest, allowing it to be excluded from analysis.
    81  * 
     83 *
    8284 */
    8385typedef struct
     
    9597    pmFPA *parent;                      ///< Parent FPA
    9698    bool valid;                         ///< Do we bother about reading and working with this chip?
    97     p_pmHDU *private;                   ///< FITS data
     99    p_pmHDU *hdu;                       ///< FITS data
    98100}
    99101pmChip;
     
    124126    pmChip *parent;                     ///< Parent chip
    125127    bool valid;                         ///< Do we bother about reading and working with this cell?
    126     p_pmHDU *private;                   ///< FITS data
     128    p_pmHDU *hdu;                       ///< FITS data
    127129}
    128130pmCell;
     
    141143{
    142144    // Position on the cell
     145    // XXX: These may be removed in the future; use parent->concepts instead?
    143146    int col0;                           ///< Offset from the left of chip.
    144147    int row0;                           ///< Offset from the bottom of chip.
     
    149152    psImage *mask;                      ///< Mask of input image
    150153    psImage *weight;                    ///< Weight of input image
    151     psList *bias;                       ///< List of bias section (sub-)images
    152154    psMetadata *analysis;               ///< Readout-level analysis metadata
    153155    pmCell *parent;                     ///< Parent cell
     
    180182 */
    181183pmCell *pmCellAlloc(
    182     pmChip *chip,                        ///< Parent chip
    183     psMetadata *cameradata,
    184     psString name
     184    pmChip *chip,       ///< Parent chip
     185    psMetadata *cameraData, ///< Camera data
     186    const char *name    ///< Name of cell
    185187);
    186188
    187189/** Allocates a pmChip
    188  * 
     190 *
    189191 *  The constructor shall make an empty pmChip. If the parent fpa is not NULL,
    190192 *  the parent link is made and the chip shall be placed in the parent's array
     
    196198 */
    197199pmChip *pmChipAlloc(
    198     pmFPA *fpa,
    199     psString name
    200 
     200    pmFPA *fpa,                         ///< FPA to which the chip belongs
     201    const char *name                    ///< Name of chip
    201202);
    202203
    203204/** Allocates a pmFPA
    204  * 
     205 *
    205206 *  The constructor shall make an empty pmFPA. The chips array shall be
    206207 *  allocated with a zero size, the camera and db pointers set to the values
    207208 *  provided, and the concepts metadata constructed. All other pointers in the
    208209 *  structure shall be initialized to NULL.
    209  * 
     210 *
    210211 */
    211212pmFPA *pmFPAAlloc(
     
    213214);
    214215
     216/** Allocates a p_pmHDU
     217 *
     218 * XXX: More detailed description
     219 *
     220 * @return p_pmHDU*    newly allocated p_pmHDU
     221 */
     222p_pmHDU *p_pmHDUAlloc(const char *extname // Extension name
     223                     );
     224
    215225
    216226/** Verify parent links.
    217  * 
     227 *
    218228 *  This function checks the validity of the parent links in the FPA hierarchy.
    219229 *  If a parent link is not set (or not set correctly), it is corrected, and the
    220230 *  function shall return false. If all the parent pointers were correct, the
    221231 *  function shall return true.
    222  * 
     232 *
    223233 */
    224234bool pmFPACheckParents(
     
    229239
    230240/** FUNC DESC
    231  *
    232  *
    233  *
    234  *
    235  */
    236 
     241 *
     242 *
     243 *
     244 *
     245 */
     246
     247
     248
     249/**
     250 *
     251 * pmFPASelectChip shall set valid to true for the specified chip number
     252 * (chipNum), and all other chips shall have valid set to false. In the event
     253 * that the specified chip number does not exist within the fpa, the function
     254 * shall return false.
     255 *
     256 */
     257bool pmFPASelectChip(
     258    pmFPA *fpa,
     259    int chipNum
     260);
     261
     262/**
     263 *
     264 * pmFPAExcludeChip shall set valid to false only for the specified chip
     265 * number (chipNum). In the event that the specified chip number does not exist
     266 * within the fpa, the function shall generate a warning, and perform no action.
     267 * The function shall return the number of chips within the fpa that have valid
     268 * set to true.
     269 *
     270 */
     271int pmFPAExcludeChip(
     272    pmFPA *fpa,
     273    int chipNum
     274);
    237275
    238276
     
    423461);
    424462
    425 /**
    426  *
    427  * pmFPASelectChip shall set valid to true for the specified chip number
    428  * (chipNum), and all other chips shall have valid set to false. In the event
    429  * that the specified chip number does not exist within the fpa, the function
    430  * shall return false.
    431  * 
    432  */
    433 bool pmFPASelectChip(
    434     pmFPA *fpa,
    435     int chipNum
    436 );
    437 
    438 /**
    439  *
    440  * pmFPAExcludeChip shall set valid to false only for the specified chip
    441  * number (chipNum). In the event that the specified chip number does not exist
    442  * within the fpa, the function shall generate a warning, and perform no action.
    443  * The function shall return the number of chips within the fpa that have valid
    444  * set to true.
    445  * 
    446  */
    447 int pmFPAExcludeChip(
    448     pmFPA *fpa,
    449     int chipNum
    450 );
    451 
    452463
    453464#endif // #ifndef PS_ASTROMETRY_H
  • branches/pap_branch_051214/psModules/src/camera/Makefile.am

    r5170 r5795  
    33libpsmodulecamera_la_CPPFLAGS = $(SRCINC) $(PSMODULE_CFLAGS)
    44libpsmodulecamera_la_LDFLAGS  = -release $(PACKAGE_VERSION)
    5 libpsmodulecamera_la_SOURCES  =
     5libpsmodulecamera_la_SOURCES  = \
     6        pmChipMosaic.c \
     7        pmFPAConceptsGet.c \
     8        pmFPAConceptsSet.c \
     9        pmFPAConstruct.c \
     10        pmFPAMorph.c \
     11        pmFPARead.c \
     12        pmFPAWrite.c
    613
    714psmoduleincludedir = $(includedir)
    8 psmoduleinclude_HEADERS =
    9 
     15psmoduleinclude_HEADERS = \
     16        pmChipMosaic.h \
     17        pmFPAConceptsGet.h \
     18        pmFPAConceptsSet.h \
     19        pmFPAConstruct.h \
     20        pmFPAMorph.h \
     21        pmFPARead.h \
     22        pmFPAWrite.h
  • branches/pap_branch_051214/psModules/src/detrend/pmFlatField.c

    r5543 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
     6
    17/** @file  pmFlatField.c
    28 *
     
    1824 *  @author Ross Harman, MHPCC
    1925 *
    20  *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
    21  *  @date $Date: 2005-11-18 19:43:14 $
     26 *  @version $Revision: 1.4.8.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2005-12-17 03:18:39 $
    2228 *
    2329 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3036#include<stdio.h>
    3137#include<math.h>
    32 #include <string.h>
     38#include <strings.h>
    3339
    3440#include "pslib.h"
     
    3642#include "pmMaskBadPixels.h"
    3743#include "pmFlatFieldErrors.h"
    38 #include "pmSubtractBias.h"
    3944
    40 // XXX: This should be removed when the autoconf stuff handles psConstants.h correctly.
    41 #define PS_WARN_PTR_NON_NULL(NAME) \
    42 if ((NAME) == NULL) { \
    43     psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \
    44 } \
    4545
    46 bool pmFlatField(
    47     pmReadout *in,
    48     const pmReadout *flat)
     46bool pmFlatField(pmReadout *in, pmReadout *mask, const pmReadout *flat)
    4947{
    50     // XXX: Use the proper image and readout asserts.
    51     PS_ASSERT_PTR_NON_NULL(in, true);
    52     PS_ASSERT_PTR_NON_NULL(in->image, false);
    53     PS_ASSERT_PTR_NON_NULL(in->mask, false);
    54     PS_ASSERT_PTR_NON_NULL(flat, false);
    55     PS_ASSERT_PTR_NON_NULL(flat->image, false);
    56     if (in == NULL)
    57         printf("XXX: NULL\n");
    58 
    5948    // XXX: Not sure if this is correct.  Must consult with IfA.
    60     PS_ASSERT_PTR_NON_NULL(in->mask, false);
    61 
    62     PS_WARN_PTR_NON_NULL(in->parent);
    63     if (in->parent != NULL) {
    64         PS_WARN_PTR_NON_NULL(in->parent->concepts);
    65     }
     49    PS_ASSERT_PTR_NON_NULL(mask, false);
    6650    int i = 0;
    6751    int j = 0;
     
    7155    psElemType flatType;
    7256    psElemType maskType;
     57    psImage *inImage = NULL;
    7358    psImage *inMask = NULL;
    7459    psImage *flatImage = NULL;
    7560
    76     //
    77     // Determine trimmed image from metadata.
    78     //
    79     psImage *trimmedImg = p_psDetermineTrimmedImage(in);
     61
     62    // Check for nulls
     63    if (in == NULL) {
     64        return true;       // Readout may not have data in it
     65    } else if(flat==NULL) {
     66        psError( PS_ERR_BAD_PARAMETER_NULL, true,
     67                 PS_ERRORTEXT_pmFlatField_NULL_FLAT_READOUT);
     68        return false;
     69    }
     70
     71    inImage = in->image;
    8072    flatImage = flat->image;
    81     inMask = in->mask;
     73    if (inImage == NULL) {
     74        psError( PS_ERR_BAD_PARAMETER_NULL, true,
     75                 PS_ERRORTEXT_pmFlatField_NULL_INPUT_IMAGE);
     76        return false;
     77    } else if(flatImage == NULL) {
     78        psError( PS_ERR_BAD_PARAMETER_NULL, true,
     79                 PS_ERRORTEXT_pmFlatField_NULL_FLAT_IMAGE);
     80        return false;
     81    }
     82    inMask = mask->image;
    8283
    8384    // Check input image and its mask are not larger than flat image
    8485
    85     if (trimmedImg == NULL)
    86         printf("XXX: 00\n");
    87     if (flatImage == NULL)
    88         printf("XXX 01\n");
    89 
    90     if (trimmedImg->numRows>flatImage->numRows || trimmedImg->numCols>flatImage->numCols) {
     86    if (inImage->numRows>flatImage->numRows || inImage->numCols>flatImage->numCols) {
    9187        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    9288                 PS_ERRORTEXT_pmFlatField_SIZE_INPUT_IMAGE,
    93                  trimmedImg->numRows, trimmedImg->numCols, flatImage->numRows, flatImage->numCols);
     89                 inImage->numRows, inImage->numCols, flatImage->numRows, flatImage->numCols);
    9490        return false;
    9591    }
     
    10298
    10399    // Determine total offset based on image offset with chip offset
    104     totOffCol = trimmedImg->col0 + in->col0;
    105     totOffRow = trimmedImg->row0 + in->row0;
     100    totOffCol = inImage->col0 + in->col0;
     101    totOffRow = inImage->row0 + in->row0;
    106102
    107103    // Check that offsets are within image limits
     
    111107                 totOffRow, totOffCol, flatImage->numRows, flatImage->numCols);
    112108        return false;
    113     } else if(totOffRow>=trimmedImg->numRows || totOffCol>=trimmedImg->numCols) {
     109    } else if(totOffRow>=inImage->numRows || totOffCol>=inImage->numCols) {
    114110        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    115111                 PS_ERRORTEXT_pmFlatField_OFFSET_INPUT_IMAGE,
    116                  totOffRow, totOffCol, trimmedImg->numRows, trimmedImg->numCols);
     112                 totOffRow, totOffCol, inImage->numRows, inImage->numCols);
    117113        return false;
    118114    } else if(totOffRow>=inMask->numRows || totOffCol>=inMask->numCols) {
     
    124120
    125121    // Check for incorrect types
    126     inType = trimmedImg->type.type;
     122    inType = inImage->type.type;
    127123    flatType = flatImage->type.type;
    128124    maskType = inMask->type.type;
     
    153149case PS_TYPE_##TYPE:                                                                                         \
    154150    /* Per Eugene's request, use two sets of loops: first to fill mask, second to avoid div with bad pix */  \
    155     for(j = totOffRow; j < trimmedImg->numRows; j++) {                                                          \
    156         for(i = totOffCol; i < trimmedImg->numCols; i++) {                                                      \
     151    for(j = totOffRow; j < inImage->numRows; j++) {                                                          \
     152        for(i = totOffCol; i < inImage->numCols; i++) {                                                      \
    157153            if(flatImage->data.TYPE[j][i] <= 0.0) {                                                          \
    158154                /* Negative or zero flat pixels shall be masked in input image as  PM_MASK_FLAT */           \
     
    162158        }                                                                                                    \
    163159    }                                                                                                        \
    164     for(j = totOffRow; j < trimmedImg->numRows; j++) {                                                          \
    165         for(i = totOffCol; i < trimmedImg->numCols; i++) {                                                      \
     160    for(j = totOffRow; j < inImage->numRows; j++) {                                                          \
     161        for(i = totOffCol; i < inImage->numCols; i++) {                                                      \
    166162            if(!inMask->data.PS_TYPE_MASK_DATA[j][i]) {                                                      \
    167163                /* Module shall divide the input image by the flat-fielded image */                          \
    168                 trimmedImg->data.TYPE[j][i] /= flatImage->data.TYPE[j][i];                                      \
     164                inImage->data.TYPE[j][i] /= flatImage->data.TYPE[j][i];                                      \
    169165            }                                                                                                \
    170166        }                                                                                                    \
  • branches/pap_branch_051214/psModules/src/detrend/pmFlatField.h

    r5435 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
     6
    17/** @file  pmFlatField.h
    28 *
     
    1824 *  @author Ross Harman, MHPCC
    1925 *
    20  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    21  *  @date $Date: 2005-10-20 23:06:24 $
     26 *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2005-12-17 03:18:39 $
    2228 *
    2329 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3743bool pmFlatField(
    3844    pmReadout *in,          ///< Readout with input image
     45    pmReadout *mask,        ///< Input image mask
    3946    const pmReadout *flat   ///< Readout with flat image
    4047);
  • branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixels.c

    r5543 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmMaskBadPixels.c
    27 *
     
    1924 *  @author Ross Harman, MHPCC
    2025 *
    21  *  @version $Revision: 1.3 $ $Name: not supported by cvs2svn $
    22  *  @date $Date: 2005-11-18 19:43:14 $
     26 *  @version $Revision: 1.3.8.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2005-12-17 03:18:39 $
    2328 *
    2429 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3136#include<stdio.h>
    3237#include<math.h>
    33 #include<string.h>
     38#include<strings.h>
    3439
    3540#include "pmMaskBadPixels.h"
    3641#include "pmMaskBadPixelsErrors.h"
    37 #include "pmSubtractBias.h"
    3842
    39 //XXX: REmove, autoconf is broken.
    40 #define PS_WARN_PTR_NON_NULL(NAME) \
    41 if ((NAME) == NULL) { \
    42     psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \
    43 } \
     43bool pmMaskBadPixels(pmReadout *in, const psImage *mask, unsigned int maskVal, float sat,
     44                     unsigned int growVal, int grow)
     45{
     46    int i = 0;
     47    int j = 0;
     48    int jj = 0;
     49    int ii = 0;
     50    int rRound = 0;
     51    int rowMin = 0;
     52    int rowMax = 0;
     53    int colMin = 0;
     54    int colMax = 0;
     55    int totOffCol = 0;
     56    int totOffRow = 0;
     57    float r = 0.0f;
     58    psElemType inType;
     59    psElemType maskType;
     60    psImage *inImage = NULL;
     61    psImage *inMask = NULL;
    4462
    4563
    46 /******************************************************************************
    47 GrowPixel(inMask, row, col, radius, maskVal): This private routine takes an
    48 input image mask and a pixel location, then sets (logical or) all pixels with
    49 parameter radius if that pixel to maskVal parameter.
    50 *****************************************************************************/
    51 psBool GrowPixel(
    52     psImage *inMask,
    53     psS32 col,
    54     psS32 row,
    55     psS32 radius,
    56     psU32 maskVal)
    57 {
    58     psS32 rowMin = PS_MAX(row-radius, 0);
    59     psS32 rowMax = PS_MIN(row+radius+1, inMask->numRows);
    60     psS32 colMin = PS_MAX(col-radius, 0);
    61     psS32 colMax = PS_MIN(col+radius+1, inMask->numCols);
    62     psF32 squareRadius = PS_SQR(radius);
     64    // Check for nulls
     65    if (in == NULL) {
     66        return true;   // Readout may not have data in it
     67    } else if(mask==NULL) {
     68        psError( PS_ERR_BAD_PARAMETER_NULL, true,
     69                 PS_ERRORTEXT_pmMaskBadPixels_NULL_MASK_IMAGE);
     70        return false;
     71    }
    6372
    64 
    65     for(psS32 i=rowMin; i<rowMax; i++) {
    66         for(psS32 j=colMin; j<colMax; j++) {
    67             // Old code:
    68             //            psF32 rRound = 0.5 + sqrtf((psF32) (((col-j)*(col-j)) + ((row-i)*(row-i))));
    69             //            if(rRound <= radius) {
    70             psF32 squareDis = (psF32) (((col-j)*(col-j)) + ((row-i)*(row-i)));
    71             if (squareDis <= squareRadius) {
    72                 inMask->data.U8[i][j] |= maskVal;
    73             }
    74         }
    75     }
    76     return(true);
    77 }
    78 
    79 /******************************************************************************
    80 GetRadius(inImg, col, row, sat, growVal, grow): This private routine takes an
    81 input image and pixel location and determines what radius that pixel must grow
    82 by.
    83  
    84 //XXX: Inline this or macro it for speed.
    85  *****************************************************************************/
    86 static psS32 GetRadius(
    87     psImage *inImg,
    88     psS32 col,
    89     psS32 row,
    90     psF32 sat,
    91     psU32 growVal,
    92     psS32 grow)
    93 {
    94     psS32 growRadius = 0;
    95     if (inImg->type.type == PS_TYPE_F32) {
    96         if(inImg->data.F32[row][col] == growVal) {
    97             growRadius = grow;
    98         }
    99         if (inImg->data.F32[row][col] > sat) {
    100             growRadius = PS_MAX(growRadius+1, 2);
    101         }
    102     } else if (inImg->type.type == PS_TYPE_S32) {
    103         if(inImg->data.S32[row][col] == growVal) {
    104             growRadius = grow;
    105         }
    106         if (inImg->data.S32[row][col] > sat) {
    107             growRadius = PS_MAX(growRadius+1, 2);
    108         }
    109     } else if (inImg->type.type == PS_TYPE_U16) {
    110         if(inImg->data.U16[row][col] == growVal) {
    111             growRadius = grow;
    112         }
    113         if (inImg->data.U16[row][col] > sat) {
    114             growRadius = PS_MAX(growRadius+1, 2);
    115         }
    116     } else {
    117         psError( PS_ERR_BAD_PARAMETER_TYPE, true,
    118                  PS_ERRORTEXT_pmMaskBadPixels_TYPE_MASK_IMAGE,
    119                  inImg->type.type);
    120     }
    121     return(growRadius);
    122 }
    123 
    124 
    125 bool pmMaskBadPixels(
    126     pmReadout *in,
    127     const pmReadout *mask,
    128     unsigned int maskVal,
    129     float sat,
    130     unsigned int growVal,
    131     int grow)
    132 {
    133     // XXX: Review this code then put all asserts at the top.
    134     PS_ASSERT_PTR_NON_NULL(in, true);
    135     PS_ASSERT_PTR_NON_NULL(in->image, false);
    136     PS_WARN_PTR_NON_NULL(in->parent);
    137     if (in->parent != NULL) {
    138         PS_WARN_PTR_NON_NULL(in->parent->concepts);
    139     }
    140     PS_ASSERT_PTR_NON_NULL(mask, false);
    141     int i = 0;
    142     int j = 0;
    143     int totOffCol = 0;
    144     int totOffRow = 0;
    145     psElemType inType;
    146     psElemType maskType;
    147     psImage *inMask = NULL;
    148 
    149     //
    150     // Determine trimmed image from metadata.
    151     //
    152     psImage *trimmedImg = p_psDetermineTrimmedImage(in);
    153     if(in->mask == NULL) {
    154         in->mask = psImageAlloc(trimmedImg->numCols, trimmedImg->numRows, PS_TYPE_MASK);
    155         PS_IMAGE_SET_U8(in->mask, 0);
     73    inImage = in->image;
     74    if (inImage == NULL) {
     75        psError( PS_ERR_BAD_PARAMETER_NULL, true,
     76                 PS_ERRORTEXT_pmMaskBadPixels_NULL_INPUT_IMAGE);
     77        return false;
     78    } else if(in->mask == NULL) {
     79        in->mask = psImageAlloc(inImage->numCols, inImage->numRows, PS_TYPE_MASK);
     80        memset(in->mask->data.V[0], 0, inImage->numCols*inImage->numRows*PSELEMTYPE_SIZEOF(PS_TYPE_MASK));
    15681    }
    15782    inMask = in->mask;
    15883
    15984    // Check input image and its mask are not larger than mask
    160     if(trimmedImg->numRows > mask->image->numRows || trimmedImg->numCols > mask->image->numCols) {
     85    if(inImage->numRows > mask->numRows || inImage->numCols > mask->numCols) {
    16186        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    16287                 PS_ERRORTEXT_pmMaskBadPixels_SIZE_INPUT_IMAGE,
    163                  trimmedImg->numRows, trimmedImg->numCols, mask->image->numRows, mask->image->numCols);
     88                 inImage->numRows, inImage->numCols, mask->numRows, mask->numCols);
    16489        return false;
    165     } else if(inMask->numRows > mask->image->numRows || inMask->numCols > mask->image->numCols) {
     90    } else if(inMask->numRows>mask->numRows || inMask->numCols>mask->numCols) {
    16691        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    16792                 PS_ERRORTEXT_pmMaskBadPixels_SIZE_MASK_IMAGE,
    168                  inMask->numRows, inMask->numCols, mask->image->numRows, mask->image->numCols);
     93                 inMask->numRows, inMask->numCols, mask->numRows, mask->numCols);
    16994        return false;
    17095    }
    17196
    17297    // Determine total offset based on image offset with chip offset
    173     totOffCol = trimmedImg->col0 + in->col0;
    174     totOffRow = trimmedImg->row0 + in->row0;
     98    totOffCol = inImage->col0 + in->col0;
     99    totOffRow = inImage->row0 + in->row0;
    175100
    176101    // Check that offsets are within image limits
    177     if(totOffRow>=mask->image->numRows || totOffCol>=mask->image->numCols) {
     102    if(totOffRow>=mask->numRows || totOffCol>=mask->numCols) {
    178103        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    179104                 PS_ERRORTEXT_pmMaskBadPixels_OFFSET_MASK_IMAGE,
    180                  totOffRow, totOffCol, mask->image->numRows, mask->image->numCols);
     105                 totOffRow, totOffCol, mask->numRows, mask->numCols);
    181106        return false;
    182     } else if(totOffRow>=trimmedImg->numRows || totOffCol>=trimmedImg->numCols) {
     107    } else if(totOffRow>=inImage->numRows || totOffCol>=inImage->numCols) {
    183108        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    184109                 PS_ERRORTEXT_pmMaskBadPixels_OFFSET_INPUT_IMAGE,
    185                  totOffRow, totOffCol, trimmedImg->numRows, trimmedImg->numCols);
     110                 totOffRow, totOffCol, inImage->numRows, inImage->numCols);
    186111        return false;
    187112    } else if(totOffRow>=inMask->numRows || totOffCol>=inMask->numCols) {
     
    193118
    194119    // Check for incorrect types
    195     inType = trimmedImg->type.type;
    196     maskType = mask->image->type.type;
     120    inType = inImage->type.type;
     121    maskType = mask->type.type;
    197122    if(PS_IS_PSELEMTYPE_COMPLEX(inType)) {
    198123        psError( PS_ERR_BAD_PARAMETER_TYPE, true,
     
    207132    }
    208133
    209     //
    210     // This is the main loop which examines each pixel and masks pixels if
    211     //    A: The mask matches the maskValue
    212     //    B: The pixel is larger than the saturation value
    213     //    C: The pixel equals the grow value (in which case a circle is masked)
    214     //
    215     for(i=totOffRow; i<trimmedImg->numRows; i++) {
    216         for(j=totOffCol; j<trimmedImg->numCols; j++) {
    217             //
    218             // A: Pixels which satisfy maskVal shall be masked
    219             //
    220             if (mask->image->data.U8[i][j] == maskVal) {
    221                 in->mask->data.U8[i][j] |= maskVal;
    222             }
     134    // Macro for all PS types
     135    #define PM_BAD_PIXELS(TYPE)                                                                              \
     136case PS_TYPE_##TYPE:                                                                                         \
     137    for(j=totOffRow; j<inImage->numRows; j++) {                                                              \
     138        for(i=totOffCol; i<inImage->numCols; i++) {                                                          \
     139            \
     140            /* Pixels with flux greater than sat shall be masked */                                          \
     141            if(inImage->data.TYPE[j][i] > sat) {                                                             \
     142                inMask->data.PS_TYPE_MASK_DATA[j][i] |= PM_MASK_SAT;                                         \
     143            }                                                                                                \
     144            \
     145            /* Pixels which satisfy maskVal shall be masked */                                               \
     146            inMask->data.PS_TYPE_MASK_DATA[j][i] |= (mask->data.PS_TYPE_MASK_DATA[j][i]&maskVal);            \
     147            \
     148            /* Pixels which satisfy growVal and within the grow radius shall be masked */                    \
     149            if(mask->data.PS_TYPE_MASK_DATA[j][i] & growVal) {                                               \
     150                rowMin = MAX(j-grow, 0);                                                                     \
     151                rowMax = MIN(j+grow+1, inImage->numRows);                                                    \
     152                colMin = MAX(i-grow, 0);                                                                     \
     153                colMax = MIN(i+grow+1, inImage->numCols);                                                    \
     154                for(jj=rowMin; jj<rowMax; jj++) {                                                            \
     155                    for(ii=colMin; ii<colMax; ii++) {                                                        \
     156                        r = sqrtf((ii-i)*(ii-i)+(jj-j)*(jj-j));                                              \
     157                        rRound = r + 0.5;                                                                    \
     158                        if(rRound <= grow) {                                                                 \
     159                            inMask->data.PS_TYPE_MASK_DATA[jj][ii] |=                                        \
     160                                    (mask->data.PS_TYPE_MASK_DATA[j][i]&growVal);                            \
     161                        }                                                                                    \
     162                    }                                                                                        \
     163                }                                                                                            \
     164            }                                                                                                \
     165        }                                                                                                    \
     166    }                                                                                                        \
     167    break;
    223168
    224             //
    225             // We first determine how much we need to grow by and store this in
    226             // growRadius.
    227             //
    228             psS32 growRadius = GetRadius(trimmedImg, j, i, sat, growVal, grow);
    229 
    230             //
    231             // Grow the pixel mask if necessary.
    232             //
    233             if (growRadius != 0) {
    234                 GrowPixel(in->mask, j, i, growRadius, maskVal);
    235             }
    236         }
     169    // Switch to call bad pixel masking macro defined above
     170    switch(inType) {
     171        PM_BAD_PIXELS(U8);
     172        PM_BAD_PIXELS(U16);
     173        PM_BAD_PIXELS(U32);
     174        PM_BAD_PIXELS(U64);
     175        PM_BAD_PIXELS(S8);
     176        PM_BAD_PIXELS(S16);
     177        PM_BAD_PIXELS(S32);
     178        PM_BAD_PIXELS(S64);
     179        PM_BAD_PIXELS(F32);
     180        PM_BAD_PIXELS(F64);
     181    default:
     182        psError( PS_ERR_BAD_PARAMETER_TYPE, true,
     183                 PS_ERRORTEXT_pmMaskBadPixels_TYPE_UNSUPPORTED,
     184                 inType);
    237185    }
    238186
    239     return true;
     187    return false;
    240188}
  • branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixels.h

    r5516 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmMaskBadPixels.h
    27 *
     
    1924 *  @author Ross Harman, MHPCC
    2025 *
    21  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    22  *  @date $Date: 2005-11-15 20:09:03 $
     26 *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2005-12-17 03:18:39 $
    2328 *
    2429 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3641} pmMaskValue;
    3742
    38 // XXX: Use PS_MIN, PS_MAX
    3943/** Macro to find maximum of two numbers */
    4044#define MAX(A,B)((A)>=(B)?(A):(B))
     
    5458bool pmMaskBadPixels(
    5559    pmReadout *in,          ///< Readout containing input image data.
    56     const pmReadout *mask,   ///< Mask data to be added to readout mask data.
     60    const psImage *mask,    ///< Mask data to be added to readout mask data.
    5761    unsigned int maskVal,   ///< Mask value to determine what to add to input mask.
    5862    float sat,              ///< Saturation limit to mask bad pixels.
  • branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixelsErrors.h

    r5170 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmMaskBadPixelsErrors.h
    27 *
     
    712 *  @author Ross Harman, MHPCC
    813 *
    9  *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2005-09-28 20:43:52 $
     14 *  @version $Revision: 1.1.16.1 $ $Name: not supported by cvs2svn $
     15 *  @date $Date: 2005-12-17 03:18:39 $
    1116 *
    1217 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2328 *     $2  The error text (rest of the line in pmMaskBadPixelsErrors.h)
    2429 *     $n  The order of the source line in pmMaskBadPixelsErrors.h (comments excluded)
    25  * 
     30 *
    2631 * DO NOT EDIT THE LINES BETWEEN //~Start and //~End!  ANY CHANGES WILL BE OVERWRITTEN.
    2732 */
  • branches/pap_branch_051214/psModules/src/detrend/pmNonLinear.c

    r5675 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmNonLinear.c
    27 *
     
    510 *  @author GLG, MHPCC
    611 *
    7  *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
    8  *  @date $Date: 2005-12-05 20:49:40 $
     12 *  @version $Revision: 1.5.8.1 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-12-17 03:18:39 $
    914 *
    1015 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2227
    2328#include "pmNonLinear.h"
    24 #include "pmSubtractBias.h"
    2529
    26 // XXX: Remove, autoconf must be
    27 #define PS_WARN_PTR_NON_NULL(NAME) \
    28 if ((NAME) == NULL) { \
    29     psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \
    30 } \
    3130/******************************************************************************
    3231pmNonLinearityLookup(): This routine will take an pmReadout image as input
    3332and a 1-D polynomial.  For each pixel in the input image, the polynomial will
    34 be evaluated at that pixels value, and the image pixel will then be set
    35 to
     33be evaluated at that pixels value, and the image pixel will then be set to
    3634that value.
    37 *****************************************************************************/
     35 *****************************************************************************/
    3836
    39 pmReadout *pmNonLinearityPolynomial(
    40     pmReadout *inputReadout,
    41     const psPolynomial1D *input1DPoly)
     37pmReadout *pmNonLinearityPolynomial(pmReadout *inputReadout,
     38                                    const psPolynomial1D *input1DPoly)
    4239{
    4340    PS_ASSERT_PTR_NON_NULL(inputReadout, NULL);
     
    4542    PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL);
    4643    PS_ASSERT_PTR_NON_NULL(input1DPoly, NULL);
    47     PS_WARN_PTR_NON_NULL(inputReadout->parent);
    48     if (inputReadout->parent != NULL) {
    49         PS_WARN_PTR_NON_NULL(inputReadout->parent->concepts);
    50     }
    5144
    52     //
    53     // Determine trimmed image from metadata.
    54     //
    55     psImage *trimmedImg = p_psDetermineTrimmedImage(inputReadout);
     45    psS32 i;
     46    psS32 j;
    5647
    57     for (psS32 i=0;i<trimmedImg->numRows;i++) {
    58         for (psS32 j=0;j<trimmedImg->numCols;j++) {
    59             trimmedImg->data.F32[i][j] = psPolynomial1DEval(input1DPoly,
    60                                          trimmedImg->data.F32[i][j]);
     48    for (i=0;i<inputReadout->image->numRows;i++) {
     49        for (j=0;j<inputReadout->image->numCols;j++) {
     50            inputReadout->image->data.F32[i][j] = psPolynomial1DEval(input1DPoly, inputReadout->image->data.F32[i][j]);
    6151        }
    6252    }
     
    7161inFluxe, and the corresponding value in outFlux.  The image pixel will then
    7262be set to the value from outFlux.
    73  
    74 XXX: Must assert that filename exists.  This should probably happen in
    75 the lookup files.
    7663 *****************************************************************************/
    77 pmReadout *pmNonLinearityLookup(
    78     pmReadout *inputReadout,
    79     const char *filename
    80 )
     64pmReadout *pmNonLinearityLookup(pmReadout *inputReadout,
     65                                const psVector *inFlux,
     66                                const psVector *outFlux)
    8167{
    8268    PS_ASSERT_PTR_NON_NULL(inputReadout,NULL);
    8369    PS_ASSERT_PTR_NON_NULL(inputReadout->image,NULL);
    8470    PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL);
    85     PS_WARN_PTR_NON_NULL(inputReadout->parent);
    86     if (inputReadout->parent != NULL) {
    87         PS_WARN_PTR_NON_NULL(inputReadout->parent->concepts);
     71    PS_ASSERT_PTR_NON_NULL(inFlux,NULL);
     72    if (inFlux->n < 2) {
     73        psError(PS_ERR_UNKNOWN,true, "pmNonLinearityLookup(): input vector less than 2 elements.  Returning inputReadout image.");
     74        return(inputReadout);
    8875    }
    89     //
    90     // Determine trimmed image from metadata.
    91     //
    92     psImage *trimmedImg = p_psDetermineTrimmedImage(inputReadout);
     76    PS_ASSERT_PTR_NON_NULL(outFlux,NULL);
     77    psS32 tableSize = inFlux->n;
     78    if (inFlux->n != outFlux->n) {
     79        tableSize = PS_MIN(inFlux->n, outFlux->n);
     80        psLogMsg(__func__, PS_LOG_WARN,
     81                 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): input vectors have different sizes (%d, %d)\n", inFlux->n, outFlux->n);
     82    }
     83    PS_ASSERT_VECTOR_TYPE(inFlux, PS_TYPE_F32, NULL);
     84    PS_ASSERT_VECTOR_TYPE(outFlux, PS_TYPE_F32, NULL);
    9385
    94     psLookupTable *tmpLT = psLookupTableAlloc(filename, "%f %f", 0);
    95     psS32 numLines = psLookupTableRead(tmpLT);
     86    psS32 i;
     87    psS32 j;
     88    psS32 binNum;
     89    psScalar x;
    9690    psS32 numPixels = 0;
    97     if (numLines < 2) {
    98         psLogMsg(__func__, PS_LOG_WARN,
    99                  "WARNING: Lookup Table is too small.  Returning original pmReadout.\n");
    100     } else {
    101         for (psS32 i=0;i<trimmedImg->numRows;i++) {
    102             for (psS32 j=0;j<trimmedImg->numCols;j++) {
    103                 psF64 tmpD = psLookupTableInterpolate(tmpLT, trimmedImg->data.F32[i][j], 1);
    104                 if (!isnan(tmpD)) {
    105                     trimmedImg->data.F32[i][j] = tmpD;
    106                 } else {
    107                     numPixels++;
    108                 }
     91    psF32 slope;
     92
     93    x.type.type = PS_TYPE_F32;
     94    for (i=0;i<inputReadout->image->numRows;i++) {
     95        for (j=0;j<inputReadout->image->numCols;j++) {
     96            x.data.F32 = inputReadout->image->data.F32[i][j];
     97            binNum = p_psVectorBinDisect((psVector *)inFlux, &x);
     98
     99            if (binNum == -2) {
     100                // We get here if x is below the table lookup range.
     101                inputReadout->image->data.F32[i][j] = outFlux->data.F32[0];
     102                numPixels++;
     103
     104            } else if (binNum == -1) {
     105                // We get here if x is above the table lookup range.
     106                inputReadout->image->data.F32[i][j] = outFlux->data.F32[tableSize-1];
     107                numPixels++;
     108
     109            } else if (binNum < -2) {
     110                // We get here if there was some other problem.
     111                psError(PS_ERR_UNKNOWN,true, "pmNonLinearityLookup(): Could not perform p_psVectorBinDisect().  Returning inputReadout image.");
     112                return(inputReadout);
     113                numPixels++;
     114            } else {
     115                // Perform linear interpolation.
     116                slope = (outFlux->data.F32[binNum+1] - outFlux->data.F32[binNum]) /
     117                        (inFlux->data.F32[binNum+1]  - inFlux->data.F32[binNum]);
     118                inputReadout->image->data.F32[i][j] = outFlux->data.F32[binNum] +
     119                                                      ((x.data.F32 - inFlux->data.F32[binNum]) * slope);
    109120            }
    110121        }
    111         if (numPixels > 0) {
    112             psLogMsg(__func__, PS_LOG_WARN,
    113                      "WARNING: pmNonLinear.c: pmNonLinearityLookup(): %d pixels outside table.", numPixels);
    114         }
    115122    }
    116 
     123    if (numPixels > 0) {
     124        psLogMsg(__func__, PS_LOG_WARN,
     125                 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): %d pixels outside table.", numPixels);
     126    }
    117127    return(inputReadout);
    118128}
  • branches/pap_branch_051214/psModules/src/detrend/pmNonLinear.h

    r5435 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmNonLinear.h
    27 *
     
    510 *  @author GLG, MHPCC
    611 *
    7  *  @version $Revision: 1.2 $ $Name: not supported by cvs2svn $
    8  *  @date $Date: 2005-10-20 23:06:24 $
     12 *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2005-12-17 03:18:39 $
    914 *
    1015 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1823#include "pmAstrometry.h"
    1924
    20 pmReadout *pmNonLinearityPolynomial(
    21     pmReadout *in,
    22     const psPolynomial1D *coeff
    23 );
     25pmReadout *pmNonLinearityPolynomial(pmReadout *in,
     26                                    const psPolynomial1D *coeff);
    2427
    25 pmReadout *pmNonLinearityLookup(
    26     pmReadout *in,
    27     const char *filename
    28 );
     28pmReadout *pmNonLinearityLookup(pmReadout *in,
     29                                const psVector *inFlux,
     30                                const psVector *outFlux);
    2931
    3032#endif
  • branches/pap_branch_051214/psModules/src/imsubtract/Makefile.am

    r5170 r5795  
    44libpsmoduleimsubtract_la_LDFLAGS  = -release $(PACKAGE_VERSION)
    55libpsmoduleimsubtract_la_SOURCES  = pmImageSubtract.c \
    6     pmSubtractBias.c \
    7     pmSubtractSky.c
     6    pmSubtractBias.c
     7#    pmSubtractSky.c
    88
    99psmoduleincludedir = $(includedir)
    1010psmoduleinclude_HEADERS = \
    1111    pmImageSubtract.h \
    12     pmSubtractBias.h \
    13     pmSubtractSky.h
     12    pmSubtractBias.h
     13#    pmSubtractSky.h
  • branches/pap_branch_051214/psModules/src/imsubtract/pmSubtractBias.c

    r5552 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmSubtractBias.c
    27 *
     
    611 *  @author GLG, MHPCC
    712 *
    8  *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2005-11-19 00:55:18 $
     13 *  @version $Revision: 1.6.8.1 $ $Name: not supported by cvs2svn $
     14 *  @date $Date: 2005-12-17 03:18:39 $
    1015 *
    1116 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
    1217 *
    1318 */
    14 /*****************************************************************************/
    15 /* INCLUDE FILES                                                             */
    16 /*****************************************************************************/
    17 #include <stdio.h>
    18 #include <math.h>
    19 #include <string.h>
    20 #include "pslib.h"
     19
    2120#if HAVE_CONFIG_H
    2221#include <config.h>
    2322#endif
     23
    2424#include "pmSubtractBias.h"
    2525
    26 /*****************************************************************************/
    27 /* DEFINE STATEMENTS                                                         */
    28 /*****************************************************************************/
     26#define PM_SUBTRACT_BIAS_POLYNOMIAL_ORDER 2
     27#define PM_SUBTRACT_BIAS_SPLINE_ORDER 3
     28
    2929// XXX: put these in psConstants.h
    30 void PS_POLY1D_PRINT(
    31     psPolynomial1D *poly)
     30void PS_POLY1D_PRINT(psPolynomial1D *poly)
    3231{
    3332    printf("-------------- PS_POLY1D_PRINT() --------------\n");
     
    5756}\
    5857
    59 /*****************************************************************************/
    60 /* TYPE DEFINITIONS                                                          */
    61 /*****************************************************************************/
    62 
    63 /*****************************************************************************/
    64 /* GLOBAL VARIABLES                                                          */
    65 /*****************************************************************************/
    66 psS32 currentId = 0;                // XXX: remove
    67 psS32 memLeaks = 0;                 // XXX: remove
    68 //PRINT_MEMLEAKS(8); XXX
    69 /*****************************************************************************/
    70 /* FILE STATIC VARIABLES                                                     */
    71 /*****************************************************************************/
    72 
    73 /*****************************************************************************/
    74 /* FUNCTION IMPLEMENTATION - LOCAL                                           */
    75 /*****************************************************************************/
    76 
    7758/******************************************************************************
    78 psSubtractFrame(): this routine will take as input the pmReadout for the input
    79 image and a pmReadout for the bias image.  The bias image is subtracted in
    80 place from the input image.  We assume that sizes and types are checked
    81 elsewhere.
    82  
    83 XXX: Verify that the image and readout offsets are being used the right way.
    84  
    85 XXX: Ensure that it does the correct thing with image size.
     59psSubtractFrame(): this routine will take as input a readout for the input
     60image and a readout for the bias image.  The bias image is subtracted in
     61place from the input image.
    8662*****************************************************************************/
    87 static pmReadout *SubtractFrame(
    88     pmReadout *in,
    89     const pmReadout *bias)
     63static pmReadout *SubtractFrame(pmReadout *in,
     64                                const pmReadout *bias)
    9065{
    91     // XXX: When did the ->row0 and ->col0 offsets get coded?
    92     for (psS32 i=0;i<in->image->numRows;i++) {
    93         for (psS32 j=0;j<in->image->numCols;j++) {
     66    psS32 i;
     67    psS32 j;
     68
     69    if (bias == NULL) {
     70        psLogMsg(__func__, PS_LOG_WARN,
     71                 "WARNING: pmSubtractBias.c: SubtractFrame(): bias frame is NULL.  Returning original image.\n");
     72        return(in);
     73    }
     74
     75
     76    if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) {
     77        psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows.  Returning in image\n");
     78        return(in);
     79    }
     80    if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) {
     81        psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns.  Returning in image\n");
     82        return(in);
     83    }
     84
     85    for (i=0;i<in->image->numRows;i++) {
     86        for (j=0;j<in->image->numCols;j++) {
    9487            in->image->data.F32[i][j]-=
    9588                bias->image->data.F32[i+in->row0-bias->row0][j+in->col0-bias->col0];
    96 
    9789            if ((in->mask != NULL) && (bias->mask != NULL)) {
    9890                (in->mask->data.U8[i][j])|=
     
    10597}
    10698
    107 
    108 /******************************************************************************
    109 psSubtractDarkFrame(): this routine will take as input the pmReadout for the
    110 input image and a pmReadout for the dark image.  The dark image is scaled and
    111 subtracted in place from the input image.
    112  
    113 XXX: Verify that the image and readout offsets are being used the right way.
    114  
    115 XXX: Ensure that it does the correct thing with image size.
    116 *****************************************************************************/
    117 static pmReadout *SubtractDarkFrame(
    118     pmReadout *in,
    119     const pmReadout *dark,
    120     psF32 scale)
    121 {
    122     // XXX: When did the ->row0 and ->col0 offsets get coded?
    123     if (fabs(scale) > FLT_EPSILON) {
    124         for (psS32 i=0;i<in->image->numRows;i++) {
    125             for (psS32 j=0;j<in->image->numCols;j++) {
    126                 in->image->data.F32[i][j]-=
    127                     (scale * dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0]);
    128 
    129                 if ((in->mask != NULL) && (dark->mask != NULL)) {
    130                     (in->mask->data.U8[i][j])|=
    131                         dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0];
    132                 }
    133             }
    134         }
    135     } else {
    136         for (psS32 i=0;i<in->image->numRows;i++) {
    137             for (psS32 j=0;j<in->image->numCols;j++) {
    138                 in->image->data.F32[i][j]-=
    139                     dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0];
    140 
    141                 if ((in->mask != NULL) && (dark->mask != NULL)) {
    142                     (in->mask->data.U8[i][j])|=
    143                         dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0];
    144                 }
    145             }
    146         }
    147     }
    148 
    149     return(in);
    150 }
    151 
    15299/******************************************************************************
    153100ImageSubtractScalar(): subtract a scalar from the input image.
    154101 
    155 XXX: Is there a psLib function for this?
     102XXX: Use a psLib function for this.
     103 
     104XXX: This should
    156105 *****************************************************************************/
    157 static psImage *ImageSubtractScalar(
    158     psImage *image,
    159     psF32 scalar)
     106static psImage *ImageSubtractScalar(psImage *image,
     107                                    psF32 scalar)
    160108{
    161109    for (psS32 i=0;i<image->numRows;i++) {
     
    221169
    222170    if (numOptions == 0) {
    223         psError(PS_ERR_UNKNOWN,true, "No allowable statistics options have been specified.\n");
     171        psError(PS_ERR_UNKNOWN,true, "No statistics options have been specified.\n");
    224172    }
    225173    if (numOptions != 1) {
     
    230178}
    231179
    232 /******************************************************************************
    233 Polynomial1DCopy(): This private function copies the members of the existing
    234 psPolynomial1D "in" into the existing psPolynomial1D "out".  The previous
    235 members of the existing psPolynomial1D "out" are psFree'ed.
    236  *****************************************************************************/
    237 static psBool Polynomial1DCopy(
    238     psPolynomial1D *out,
    239     psPolynomial1D *in)
    240 {
    241     psFree(out->coeff);
    242     psFree(out->coeffErr);
    243     psFree(out->mask);
    244 
    245     out->type = in->type;
    246     out->nX = in->nX;
    247 
    248     out->coeff = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64));
    249     // XXX: use memcpy
    250     for (psS32 i = 0 ; i < (in->nX + 1) ; i++) {
    251         out->coeff[i] = in->coeff[i];
    252     }
    253 
    254     out->coeffErr = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64));
    255     // XXX: use memcpy
    256     for (psS32 i = 0 ; i < (in->nX + 1) ; i++) {
    257         out->coeffErr[i] = in->coeffErr[i];
    258     }
    259 
    260     out->mask = (psMaskType *) psAlloc((in->nX + 1) * sizeof(psMaskType));
    261     // XXX: use memcpy
    262     for (psS32 i = 0 ; i < (in->nX + 1) ; i++) {
    263         out->mask[i] = in->mask[i];
    264     }
    265 
    266     return(true);
    267 }
    268 
    269 /******************************************************************************
    270 Polynomial1DDup(): This private function duplicates and then returns the input
    271 psPolynomial1D "in".
    272  *****************************************************************************/
    273 static psPolynomial1D *Polynomial1DDup(
    274     psPolynomial1D *in)
    275 {
    276     psPolynomial1D *out = psPolynomial1DAlloc(in->nX, in->type);
    277     Polynomial1DCopy(out, in);
    278     return(out);
    279 }
    280 
    281 
    282 /******************************************************************************
    283 SplineCopy(): This private function copies the members of the existing
    284 psSpline in into the existing psSpline out.
    285  *****************************************************************************/
    286 static psBool SplineCopy(
    287     psSpline1D *out,
    288     psSpline1D *in)
    289 {
    290     PS_ASSERT_PTR_NON_NULL(out, false);
    291     PS_ASSERT_PTR_NON_NULL(in, false);
    292 
    293     for (psS32 i = 0 ; i < out->n ; i++) {
    294         psFree(out->spline[i]);
    295     }
    296     psFree(out->spline);
    297     psFree(out->knots);
    298     psFree(out->p_psDeriv2);
    299 
    300     out->n = in->n;
    301     out->spline = (psPolynomial1D **) psAlloc(in->n * sizeof(psPolynomial1D *));
    302     for (psS32 i = 0 ; i < in->n ; i++) {
    303         out->spline[i] = Polynomial1DDup(in->spline[i]);
    304     }
    305 
    306     // XXX: use psVectorCopy if they get it working.
    307     out->knots = psVectorAlloc(in->knots->n, in->knots->type.type);
    308     for (psS32 i = 0 ; i < in->knots->n ; i++) {
    309         out->knots->data.F32[i] = in->knots->data.F32[i];
    310     }
    311     /*
    312         out->knots = psVectorCopy(out->knots, in->knots, in->knots->type.type);
    313     */
    314 
    315     out->p_psDeriv2 = (psF32 *) psAlloc((in->n + 1) * sizeof(psF32));
    316     // XXX: use memcpy
    317     for (psS32 i = 0 ; i < (in->n + 1) ; i++) {
    318         out->p_psDeriv2[i] = in->p_psDeriv2[i];
    319     }
    320 
    321     return(true);
    322 }
     180
    323181
    324182/******************************************************************************
     
    328186    PM_FIT_POLYNOMIAL: fit a polynomial to the entire input vector data.
    329187    PM_FIT_SPLINE: fit splines to the input vector data.
    330 The resulting spline or polynomial is set in the fitSpec argument.
     188XXX: Doesn't it make more sense to do polynomial interpolation on a few
     189elements of the input vector, rather than fit a polynomial to the entire
     190vector?
    331191 *****************************************************************************/
    332 static psVector *ScaleOverscanVector(
    333     psVector *overscanVector,
    334     psS32 n,
    335     void *fitSpec,
    336     pmFit fit)
     192static psVector *ScaleOverscanVector(psVector *overscanVector,
     193                                     psS32 n,
     194                                     void *fitSpec,
     195                                     pmFit fit)
    337196{
    338197    psTrace(".psModule.pmSubtracBias.ScaleOverscanVector", 4,
    339198            "---- ScaleOverscanVector() begin (%d -> %d) ----\n", overscanVector->n, n);
     199    //    PS_VECTOR_PRINT_F32(overscanVector);
    340200
    341201    if (NULL == overscanVector) {
     
    350210    //
    351211    if (n == overscanVector->n) {
    352         return(psVectorCopy(newVec, overscanVector, PS_TYPE_F32));
    353     }
     212        for (psS32 i = 0 ; i < n ; i++) {
     213            newVec->data.F32[i] = overscanVector->data.F32[i];
     214        }
     215        return(newVec);
     216    }
     217    psPolynomial1D *myPoly;
     218    psSpline1D *mySpline;
    354219    psF32 x;
    355 
     220    psS32 i;
    356221    if (fit == PM_FIT_POLYNOMIAL) {
    357222        // Fit a polynomial to the old overscan vector.
    358         psPolynomial1D *myPoly = (psPolynomial1D *) fitSpec;
     223        myPoly = (psPolynomial1D *) fitSpec;
    359224        PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    360         PS_ASSERT_POLY1D(myPoly, NULL);
    361225        myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL);
    362226        if (myPoly == NULL) {
    363             psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the psVector.\n");
     227            psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector()(1): Could not fit a polynomial to the psVector.\n");
    364228            return(NULL);
    365229        }
     
    368232        // of the old vector, use the fitted polynomial to determine the
    369233        // interpolated value at that point, and set the new vector.
    370         for (psS32 i=0;i<n;i++) {
     234        for (i=0;i<n;i++) {
    371235            x = ((psF32) i) * ((psF32) overscanVector->n) / ((psF32) n);
    372236            newVec->data.F32[i] = psPolynomial1DEval(myPoly, x);
    373237        }
    374238    } else if (fit == PM_FIT_SPLINE) {
     239        psS32 mustFreeSpline = 0;
     240        // Fit a spline to the old overscan vector.
     241        mySpline = (psSpline1D *) fitSpec;
     242        // XXX: Does it make any sense to have a psSpline argument?
     243        if (mySpline == NULL) {
     244            mustFreeSpline = 1;
     245        }
     246
    375247        //
    376248        // NOTE: Since the X arg in the psVectorFitSpline1D() function is NULL,
     
    378250        // properly when doing the spline eval.
    379251        //
    380         psSpline1D *mySpline = psVectorFitSpline1D(NULL, overscanVector);
     252        //        mySpline = psVectorFitSpline1D(mySpline, NULL, overscanVector, NULL);
     253        mySpline = psVectorFitSpline1D(NULL, overscanVector);
    381254        if (mySpline == NULL) {
    382             psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to the psVector.\n");
     255            psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector()(2): Could not fit a spline to the psVector.\n");
    383256            return(NULL);
    384257        }
     258        //        PS_PRINT_SPLINE(mySpline);
    385259
    386260        // For each element of the new vector, convert the x-ordinate to that
    387         // of the old vector, use the fitted spline to determine the
     261        // of the old vector, use the fitted polynomial to determine the
    388262        // interpolated value at that point, and set the new vector.
    389         for (psS32 i=0;i<n;i++) {
     263        for (i=0;i<n;i++) {
    390264            // Scale to [0 : overscanVector->n - 1]
    391265            x = ((psF32) i) * ((psF32) (overscanVector->n-1)) / ((psF32) n);
    392266            newVec->data.F32[i] = psSpline1DEval(mySpline, x);
    393267        }
    394 
    395         psSpline1D *ptrSpline = (psSpline1D *) fitSpec;
    396         if (ptrSpline != NULL) {
    397             // Copy the resulting spline fit into ptrSpline.
    398             PS_ASSERT_SPLINE(ptrSpline, NULL);
    399             SplineCopy(ptrSpline, mySpline);
    400         }
    401         psFree(mySpline);
     268        if (mustFreeSpline ==1) {
     269            psFree(mySpline);
     270        }
     271        //        PS_VECTOR_PRINT_F32(newVec);
     272
     273
    402274    } else {
    403275        psError(PS_ERR_UNKNOWN, true, "unknown fit type.  Returning NULL.\n");
     
    412284
    413285/******************************************************************************
     286XXX: The SDRS does not specify type support.  F32 is implemented here.
    414287 *****************************************************************************/
    415 static psS32 GetOverscanSize(
    416     psImage *inImg,
    417     pmOverscanAxis overScanAxis)
    418 {
    419     if (overScanAxis == PM_OVERSCAN_ROWS) {
    420         return(inImg->numCols);
    421     } else if (overScanAxis == PM_OVERSCAN_COLUMNS) {
    422         return(inImg->numRows);
    423     } else if (overScanAxis == PM_OVERSCAN_ALL) {
    424         return(1);
    425     }
    426     return(0);
    427 }
    428 
    429 /******************************************************************************
    430 GetOverscanAxis(in) this private routine determines the appropiate overscan
    431 axis from the parent cell metadata.
    432  
    433 XXX: Verify the READDIR corresponds with my overscan axis.
    434  *****************************************************************************/
    435 static pmOverscanAxis GetOverscanAxis(pmReadout *in)
    436 {
    437     psBool rc;
    438     if ((in->parent != NULL) && (in->parent->concepts)) {
    439         psS32 dir = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.READDIR");
    440         if (rc == true) {
    441             if (dir == 1) {
    442                 return(PM_OVERSCAN_ROWS);
    443             } else if (dir == 2) {
    444                 return(PM_OVERSCAN_COLUMNS);
    445             } else if (dir == 3) {
    446                 return(PM_OVERSCAN_ALL);
    447             }
    448         }
    449     }
    450 
    451     psLogMsg(__func__, PS_LOG_WARN,
    452              "WARNING: pmSubtractBias.(): could not determine CELL.READDIR from in->parent metadata.  Setting overscan axis to PM_OVERSCAN_NONE.\n");
    453     return(PM_OVERSCAN_NONE);
    454 }
    455 
    456 /******************************************************************************
    457 psListLength(list): determine the length of a psList.
    458  
    459 XXX: Put this elsewhere.
    460  *****************************************************************************/
    461 static psS32 psListLength(
    462     psList *list)
    463 {
    464     psS32 length = 0;
    465     psListElem *tmpElem = (psListElem *) list->head;
    466     while (NULL != tmpElem) {
    467         tmpElem = tmpElem->next;
    468         length++;
    469     }
    470     return(length);
    471 }
    472 
    473 /******************************************************************************
    474 Note: this isn't needed anymore as of psModule SDRS 12-09.
    475  *****************************************************************************/
    476 static psBool OverscanReducePixel(
    477     psImage *in,
    478     psList *bias,
    479     psStats *myStats)
    480 {
    481     PS_ASSERT_PTR_NON_NULL(in, NULL);
    482     PS_ASSERT_PTR_NON_NULL(bias, NULL);
    483     PS_ASSERT_PTR_NON_NULL(bias->head, NULL);
    484     PS_ASSERT_PTR_NON_NULL(myStats, NULL);
    485 
    486     // Allocate a psVector with one element per overscan image.
    487     psS32 numOverscanImages = psListLength(bias);
    488     psVector *statsAll = psVectorAlloc(numOverscanImages, PS_TYPE_F32);
    489     psListElem *tmpOverscan = (psListElem *) bias->head;
    490     psS32 i = 0;
    491     psF64 statValue;
    492     //
    493     // We loop through each overscan image, calculating the specified
    494     // statistic on that image.
    495     //
    496     while (NULL != tmpOverscan) {
    497         psImage *myOverscanImage = (psImage *) tmpOverscan->data;
    498 
    499         PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL);
    500         myStats = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff);
    501         if (myStats == NULL) {
    502             psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation.  Returning in image.\n");
    503             psFree(statsAll);
    504             return(false);
    505         }
    506         if (false == p_psGetStatValue(myStats, &statValue)) {
    507             psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
    508             psFree(statsAll);
    509             return(false);
    510         }
    511         statsAll->data.F32[i] = statValue;
    512         i++;
    513         tmpOverscan = tmpOverscan->next;
    514     }
    515 
    516     //
    517     // We reduce the individual stats for each overscan image to
    518     // a single psF32.
    519     //
    520     myStats = psVectorStats(myStats, statsAll, NULL, NULL, 0);
    521     if (myStats == NULL) {
    522         psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation.  Returning in image.\n");
    523         psFree(statsAll);
    524         return(false);
    525     }
    526     if (false == p_psGetStatValue(myStats, &statValue)) {
    527         psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
    528         psFree(statsAll);
    529         return(false);
    530     }
    531 
    532     //
    533     // Subtract the result and return.
    534     //
    535     ImageSubtractScalar(in, statValue);
    536     psFree(statsAll);
    537     return(in);
    538 }
    539 
    540 /******************************************************************************
    541 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces
    542 a single psImage to a column by combining all pixels from each row into a
    543 single pixel via requested statistic in myStats.
    544  *****************************************************************************/
    545 static psVector *ReduceOverscanImageToCol(
    546     psImage *overscanImage,
    547     psStats *myStats)
    548 {
    549     psF64 statValue;
    550     psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32);
    551     psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32);
    552 
    553     //
    554     // For each row, we store all pixels in that row into a temporary psVector,
    555     // then we run psVectorStats() on that vector.
    556     //
    557     for (psS32 i=0;i<overscanImage->numRows;i++) {
    558         for (psS32 j=0;j<overscanImage->numCols;j++) {
    559             tmpRow->data.F32[j] = overscanImage->data.F32[i][j];
    560         }
    561 
    562         psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0);
    563         if (rc == NULL) {
    564             psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation.  Returning in image.\n");
    565             return(NULL);
    566         }
    567 
    568         if (false ==  p_psGetStatValue(rc, &statValue)) {
    569             psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation.  Returning in image.\n");
    570             return(NULL);
    571         }
    572 
    573         tmpCol->data.F32[i] = (psF32) statValue;
    574     }
    575     psFree(tmpRow);
    576 
    577     return(tmpCol);
    578 }
    579 
    580 /******************************************************************************
    581 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces
    582 a single psImage to a row by combining all pixels from each column into a
    583 single pixel via requested statistic in myStats.
    584  *****************************************************************************/
    585 static psVector *ReduceOverscanImageToRow(
    586     psImage *overscanImage,
    587     psStats *myStats)
    588 {
    589     psF64 statValue;
    590     psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32);
    591     psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32);
    592 
    593     //
    594     // For each column, we store all pixels in that column into a temporary psVector,
    595     // then we run psVectorStats() on that vector.
    596     //
    597     for (psS32 i=0;i<overscanImage->numCols;i++) {
    598         for (psS32 j=0;j<overscanImage->numRows;j++) {
    599             tmpCol->data.F32[j] = overscanImage->data.F32[j][i];
    600         }
    601 
    602         psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0);
    603         if (rc == NULL) {
    604             psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation.  Returning in image.\n");
    605             return(NULL);
    606         }
    607 
    608         if (false ==  p_psGetStatValue(rc, &statValue)) {
    609             psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation.  Returning in image.\n");
    610             return(NULL);
    611         }
    612 
    613         tmpRow->data.F32[i] = (psF32) statValue;
    614     }
    615     psFree(tmpCol);
    616 
    617     return(tmpRow);
    618 }
    619 
    620 /******************************************************************************
    621 OverscanReduce(vecSize, bias, myStats): This private routine takes a psList of
    622 overscan images (in bias) and reduces them to a single psVector via the
    623 specified psStats struct.  The vector is then scaled to the length or the
    624 row/column in inImg.
    625  *****************************************************************************/
    626 static psVector* OverscanReduce(
    627     psImage *inImg,
    628     pmOverscanAxis overScanAxis,
    629     psList *bias,
    630     void *fitSpec,
    631     pmFit fit,
    632     psStats *myStats)
    633 {
    634     if ((overScanAxis != PM_OVERSCAN_ROWS) && (overScanAxis != PM_OVERSCAN_COLUMNS)) {
    635         psError(PS_ERR_UNKNOWN, true, "overScanAxis must be PM_OVERSCAN_ROWS or PM_OVERSCAN_COLUMNS\n");
    636         return(NULL);
    637     }
    638     PS_ASSERT_PTR_NON_NULL(inImg, NULL);
    639     PS_ASSERT_PTR_NON_NULL(bias, NULL);
    640     PS_ASSERT_PTR_NON_NULL(bias->head, NULL);
    641     PS_ASSERT_PTR_NON_NULL(myStats, NULL);
    642     //
    643     // Allocate a psVector for the output of this routine.
    644     //
    645     psS32 vecSize = GetOverscanSize(inImg, overScanAxis);
    646     psVector *overscanVector = psVectorAlloc(vecSize, PS_TYPE_F32);
    647 
    648     //
    649     // Allocate an array of psVectors with one psVector per element of the
    650     // final oversan column vector.  These psVectors will be used with
    651     // psStats to reduce the multiple elements from each overscan column
    652     // vector to a single final column vector.
    653     //
    654     psS32 numOverscanImages = psListLength(bias);
    655     psVector **overscanVectors = (psVector **) psAlloc(numOverscanImages * sizeof(psVector *));
    656     for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    657         overscanVectors[i] = NULL;
    658     }
    659 
    660     //
    661     // We iterate through the list of overscan images.  For each image,
    662     // we reduce it to a single column or row.  Save the overscan vector
    663     // in overscanVectors[].
    664     //
    665     psListElem *tmpOverscan = (psListElem *) bias->head;
    666     psS32 overscanID = 0;
    667     while (tmpOverscan != NULL) {
    668         psImage *tmpOverscanImage = (psImage *) tmpOverscan->data;
    669         if (overScanAxis == PM_OVERSCAN_ROWS) {
    670             overscanVectors[overscanID] = ReduceOverscanImageToRow(tmpOverscanImage, myStats);
    671         } else if (overScanAxis == PM_OVERSCAN_COLUMNS) {
    672             overscanVectors[overscanID] = ReduceOverscanImageToCol(tmpOverscanImage, myStats);
    673         }
    674 
    675         tmpOverscan = tmpOverscan->next;
    676         overscanID++;
    677     }
    678 
    679     //
    680     // For each overscan vector, if necessary, we scale that column or
    681     // row to vecSize.  Note: we should have already ensured that the
    682     // fit is poly or spline.
    683     //
    684     for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    685         psVector *tmpOverscanVector = overscanVectors[i];
    686 
    687         if (tmpOverscanVector->n != vecSize) {
    688             overscanVectors[i] = ScaleOverscanVector(tmpOverscanVector, vecSize, fitSpec, fit);
    689             if (overscanVectors[i] == NULL) {
    690                 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector.\n");
    691                 for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    692                     psFree(overscanVectors[i]);
    693                 }
    694                 psFree(overscanVectors);
    695                 psFree(tmpOverscanVector);
    696                 return(NULL);
    697             }
    698             psFree(tmpOverscanVector);
    699         }
    700     }
    701 
    702     //
    703     // We collect all elements in the overscan vectors for the various
    704     // overscan images into a single psVector (tmpVec).  Then we call
    705     // psStats on that vector to determine the final values for the
    706     // overscan vector.
    707     //
    708     psVector *tmpVec = psVectorAlloc(numOverscanImages, PS_TYPE_F32);
    709     psF64 statValue;
    710     for (psS32 i = 0 ; i < vecSize ; i++) {
    711         // Collect the i-th elements from each overscan vector into a single vector.
    712         for (psS32 j = 0 ; j < numOverscanImages ; j++) {
    713             tmpVec->data.F32[j] = overscanVectors[j]->data.F32[i];
    714         }
    715 
    716         if (NULL == psVectorStats(myStats, tmpVec, NULL, NULL, 0)) {
    717             psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
    718             for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    719                 psFree(overscanVectors[i]);
    720             }
    721             psFree(overscanVectors);
    722             psFree(tmpVec);
    723             return(NULL);
    724         }
    725         if (false == p_psGetStatValue(myStats, &statValue)) {
    726             psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
    727             for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    728                 psFree(overscanVectors[i]);
    729             }
    730             psFree(overscanVectors);
    731             psFree(tmpVec);
    732             return(NULL);
    733         }
    734 
    735         overscanVector->data.F32[i] = (psF32) statValue;
    736     }
    737 
    738     //
    739     // We're done.  Free the intermediate overscan vectors.
    740     //
    741     psFree(tmpVec);
    742     for (psS32 i = 0 ; i < numOverscanImages ; i++) {
    743         psFree(overscanVectors[i]);
    744     }
    745     psFree(overscanVectors);
    746 
    747     //
    748     // Return the computed overscanVector
    749     //
    750     return(overscanVector);
    751 }
    752 
    753 /******************************************************************************
    754 RebinOverscanVector(overscanVector, nBinOrig, myStats): this private routine
    755 takes groups of nBinOrig elements in the input vector, combines them into a
    756 single pixel via myStats and psVectorStats(), and then outputs a vector of
    757 those pixels.
    758  *****************************************************************************/
    759 static psS32 RebinOverscanVector(
    760     psVector *overscanVector,
    761     psS32 nBinOrig,
    762     psStats *myStats)
    763 {
    764     psF64 statValue;
    765     psS32 nBin;
    766     if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) {
    767         psS32 numBins = 1+((overscanVector->n)/nBinOrig);
    768         psVector *myBin = psVectorAlloc(numBins, PS_TYPE_F32);
    769         psVector *binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32);
    770 
    771         for (psS32 i=0;i<numBins;i++) {
    772             for(psS32 j=0;j<nBinOrig;j++) {
    773                 if (overscanVector->n > ((i*nBinOrig)+j)) {
    774                     binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j];
    775                 } else {
    776                     // XXX: we get here if nBinOrig does not evenly divide
    777                     // the overscanVector vector.  This is the last bin.  Should
    778                     // we change the binVec->n to acknowledge that?
    779                     binVec->n = j;
    780                 }
    781             }
    782             psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0);
    783             if (rc == NULL) {
    784                 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
    785                 return(-1);
    786             }
    787             if (false ==  p_psGetStatValue(rc, &statValue)) {
    788                 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
    789                 return(-1);
    790             }
    791             myBin->data.F32[i] = statValue;
    792         }
    793 
    794         // Change the effective size of overscanVector.
    795         overscanVector->n = numBins;
    796         for (psS32 i=0;i<numBins;i++) {
    797             overscanVector->data.F32[i] = myBin->data.F32[i];
    798         }
    799         psFree(binVec);
    800         psFree(myBin);
    801         nBin = nBinOrig;
    802     } else {
    803         nBin = 1;
    804     }
    805 
    806     return(nBin);
    807 }
    808 
    809 /******************************************************************************
    810 FitOverscanVectorAndUnbin(inImg, overscanVector, overScanAxis, fitSpec, fit,
    811 nBin):  this private routine fits a psPolynomial or psSpline to the overscan
    812 vector.  It then creates a new vector, with a size determined by the input
    813 image, evaluates the psPolynomial or psSpline at each element in that vector,
    814 then returns that vector.
    815  *****************************************************************************/
    816 static psVector *FitOverscanVectorAndUnbin(
    817     psImage *inImg,
    818     psVector *overscanVector,
    819     pmOverscanAxis overScanAxis,
    820     void *fitSpec,
    821     pmFit fit,
    822     psS32 nBin)
    823 {
    824     psPolynomial1D* myPoly = NULL;
    825     psSpline1D *mySpline = NULL;
    826     //
    827     // Fit a polynomial or spline to the overscan vector.
    828     //
    829     if (fit == PM_FIT_POLYNOMIAL) {
    830         myPoly = (psPolynomial1D *) fitSpec;
    831         PS_ASSERT_POLY_NON_NULL(myPoly, NULL);
    832         PS_ASSERT_POLY1D(myPoly, NULL);
    833         myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL);
    834         if (myPoly == NULL) {
    835             psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to overscan vector.  Returning NULL.\n");
    836             return(NULL);
    837         }
    838     } else if (fit == PM_FIT_SPLINE) {
    839         mySpline = psVectorFitSpline1D(NULL, overscanVector);
    840         if (mySpline == NULL) {
    841             psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector.  Returning NULL.\n");
    842             return(NULL);
    843         }
    844         if (fitSpec != NULL) {
    845             // Copy the resulting spline fit into fitSpec.
    846             psSpline1D *ptrSpline = (psSpline1D *) fitSpec;
    847             PS_ASSERT_SPLINE(ptrSpline, NULL);
    848             SplineCopy(ptrSpline, mySpline);
    849         }
    850     }
    851 
    852     //
    853     // Evaluate the poly/spline at each pixel in the overscan row/column.
    854     //
    855     psS32 vecSize = GetOverscanSize(inImg, overScanAxis);
    856     psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32);
    857     if ((nBin > 1) && (nBin < overscanVector->n)) {
    858         for (psS32 i = 0 ; i < vecSize ; i++) {
    859             if (fit == PM_FIT_POLYNOMIAL) {
    860                 newVec->data.F32[i] = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin));
    861             } else if (fit == PM_FIT_SPLINE) {
    862                 newVec->data.F32[i] = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin));
    863             }
    864         }
    865     } else {
    866         for (psS32 i = 0 ; i < vecSize ; i++) {
    867             if (fit == PM_FIT_POLYNOMIAL) {
    868                 newVec->data.F32[i] = psPolynomial1DEval(myPoly, (psF32) i);
    869             } else if (fit == PM_FIT_SPLINE) {
    870                 newVec->data.F32[i] = psSpline1DEval(mySpline, (psF32) i);
    871             }
    872         }
    873     }
    874 
    875     psFree(mySpline);
    876     psFree(overscanVector);
    877     return(newVec);
    878 }
    879 
    880 
    881 
    882 /******************************************************************************
    883 UnbinOverscanVector(inImg, overscanVector, overScanAxis, nBin):  this private
    884 routine takes a psVector overscanVector that was previously binned by a factor
    885 of nBin, and then expands it to its original size, duplicated elements nBin
    886 times for each element in the input vector overscanVector.
    887  *****************************************************************************/
    888 static psVector *UnbinOverscanVector(
    889     psImage *inImg,
    890     psVector *overscanVector,
    891     pmOverscanAxis overScanAxis,
    892     psS32 nBin)
    893 {
    894     psS32 vecSize;
    895 
    896     if (overScanAxis == PM_OVERSCAN_ROWS) {
    897         vecSize = inImg->numCols;
    898     } else if (overScanAxis == PM_OVERSCAN_COLUMNS) {
    899         vecSize = inImg->numRows;
    900     }
    901 
    902     psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32);
    903     for (psS32 i = 0 ; i < vecSize ; i++) {
    904         newVec->data.F32[i] = overscanVector->data.F32[i/nBin];
    905     }
    906 
    907     psFree(overscanVector);
    908     return(newVec);
    909 }
    910 
    911 
    912 /******************************************************************************
    913 SubtractVectorFromImage(inImg, overscanVector, overScanAxis):  this private
    914 routine subtracts the overscanVector column-wise or row-wise from inImg.
    915  *****************************************************************************/
    916 static psImage *SubtractVectorFromImage(
    917     psImage *inImg,
    918     psVector *overscanVector,
    919     pmOverscanAxis overScanAxis)
    920 {
    921     //
    922     // Subtract overscan vector row-wise from the image.
    923     //
    924     if (overScanAxis == PM_OVERSCAN_ROWS) {
    925         for (psS32 i=0;i<inImg->numCols;i++) {
    926             for (psS32 j=0;j<inImg->numRows;j++) {
    927                 inImg->data.F32[j][i]-= overscanVector->data.F32[i];
    928             }
    929         }
    930     }
    931 
    932     //
    933     // Subtract overscan vector column-wise from the image.
    934     //
    935     if (overScanAxis == PM_OVERSCAN_COLUMNS) {
    936         for (psS32 i=0;i<inImg->numRows;i++) {
    937             for (psS32 j=0;j<inImg->numCols;j++) {
    938                 inImg->data.F32[i][j]-= overscanVector->data.F32[i];
    939             }
    940         }
    941     }
    942 
    943     return(inImg);
    944 }
    945 
    946 
    947 
    948 typedef enum {
    949     PM_ERROR_NO_SUBTRACTION,
    950     PM_WARNING_NO_SUBTRACTION,
    951     PM_ERROR_NO_BIAS_SUBTRACT,
    952     PM_WARNING_NO_BIAS_SUBTRACT,
    953     PM_ERROR_NO_DARK_SUBTRACT,
    954     PM_WARNING_NO_DARK_SUBTRACT,
    955     PM_OKAY
    956 } pmSubtractBiasAssertStatus;
    957 /******************************************************************************
    958 AssertCodeOverscan(....) this private routine verifies that the various input
    959 parameters to pmSubtractBias() are correct for overscan subtraction.
    960  *****************************************************************************/
    961 pmSubtractBiasAssertStatus AssertCodeOverscan(
    962     pmReadout *in,
    963     void *fitSpec,
    964     pmFit fit,
    965     bool overscan,
    966     psStats *stat,
    967     int nBinOrig,
    968     const pmReadout *bias,
    969     const pmReadout *dark)
    970 {
    971 
    972     PS_ASSERT_READOUT_NON_NULL(in, PM_ERROR_NO_SUBTRACTION);
    973     PS_ASSERT_READOUT_NON_EMPTY(in, PM_ERROR_NO_SUBTRACTION);
    974     PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION);
    975     PS_WARN_PTR_NON_NULL(in->parent);
    976     if (in->parent != NULL) {
    977         PS_WARN_PTR_NON_NULL(in->parent->concepts);
    978     }
    979 
    980     if (overscan == true) {
    981         pmOverscanAxis overScanAxis = GetOverscanAxis(in);
    982         PS_ASSERT_PTR_NON_NULL(stat, PM_ERROR_NO_SUBTRACTION);
    983         PS_ASSERT_PTR_NON_NULL(in->bias, PM_ERROR_NO_SUBTRACTION);
    984         PS_ASSERT_PTR_NON_NULL(in->bias->head, PM_ERROR_NO_SUBTRACTION);
    985         //
    986         // Check the type, size of each bias image.
    987         //
    988         psListElem *tmpOverscan = (psListElem *) in->bias->head;
    989         psS32 numOverscans = 0;
    990         while (NULL != tmpOverscan) {
    991             numOverscans++;
    992             psImage *myOverscanImage = (psImage *) tmpOverscan->data;
    993             PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION);
    994             // XXX: Get this right with the rows and columns.
    995             if (overScanAxis == PM_OVERSCAN_ROWS) {
    996                 if (myOverscanImage->numRows != in->image->numRows) {
    997                     psLogMsg(__func__, PS_LOG_WARN,
    998                              "WARNING: pmSubtractBias.(): overscan image (# %d) has %d rows, input image has %d rows\n",
    999                              numOverscans, myOverscanImage->numCols, in->image->numRows);
    1000                     if (fit == PM_FIT_NONE) {
    1001                         psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors.  Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n");
    1002                         return(PM_ERROR_NO_SUBTRACTION);
    1003                     }
    1004                 }
    1005             } else if (overScanAxis == PM_OVERSCAN_COLUMNS) {
    1006                 if (myOverscanImage->numCols != in->image->numCols) {
    1007                     psLogMsg(__func__, PS_LOG_WARN,
    1008                              "WARNING: pmSubtractBias.(): overscan image (# %d) has %d columns, input image has %d columns\n",
    1009                              numOverscans, myOverscanImage->numCols, in->image->numCols);
    1010                     if (fit == PM_FIT_NONE) {
    1011                         psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors.  Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n");
    1012                         return(PM_ERROR_NO_SUBTRACTION);
    1013                     }
    1014                 }
    1015             } else if (overScanAxis != PM_OVERSCAN_ALL) {
    1016                 psError(PS_ERR_UNKNOWN, true, "Must specify and overscan axis.\n");
    1017                 return(PM_ERROR_NO_SUBTRACTION);
    1018             }
    1019             tmpOverscan = tmpOverscan->next;
    1020         }
    1021     } else {
    1022         if (fit != PM_FIT_NONE) {
    1023             psLogMsg(__func__, PS_LOG_WARN,
    1024                      "WARNING: pmSubtractBias.(): overscan is FALSE and fit is not PM_FIT_NONE.\n");
    1025             return(PM_WARNING_NO_SUBTRACTION);
    1026         }
    1027     }
    1028 
    1029     // XXX: I do not like the following spec since it's useless to specify
    1030     // a psSpline as the fitSpec.
    1031     if (0) {
    1032         if ((fitSpec == NULL) &&
    1033                 ((fit != PM_FIT_NONE) || (overscan == true))) {
    1034             psError(PS_ERR_UNKNOWN, true, "fitSpec is NULL and fit is not PM_FIT_NONE or overscan is TRUE.\n");
    1035             return(PM_ERROR_NO_SUBTRACTION);
    1036         }
    1037     }
    1038 
    1039     return(PM_OKAY);
    1040 }
    1041 
    1042 /******************************************************************************
    1043 AssertCodeBias(....) this private routine verifies that the various input
    1044 parameters to pmSubtractBias() are correct for bias subtraction.
    1045  *****************************************************************************/
    1046 static pmSubtractBiasAssertStatus AssertCodeBias(
    1047     pmReadout *in,
    1048     void *fitSpec,
    1049     pmFit fit,
    1050     bool overscan,
    1051     psStats *stat,
    1052     int nBinOrig,
    1053     const pmReadout *bias,
    1054     const pmReadout *dark)
    1055 {
    1056     if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) {
    1057         psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows.  Returning in image\n");
    1058         return(PM_ERROR_NO_BIAS_SUBTRACT);
    1059     }
    1060     if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) {
    1061         psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns.  Returning in image\n");
    1062         return(PM_ERROR_NO_BIAS_SUBTRACT);
    1063     }
    1064 
    1065     if (bias != NULL) {
    1066         PS_ASSERT_READOUT_NON_EMPTY(bias, PM_ERROR_NO_BIAS_SUBTRACT);
    1067         PS_ASSERT_READOUT_TYPE(bias, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT);
    1068     }
    1069     return(PM_OKAY);
    1070 }
    1071 
    1072 /******************************************************************************
    1073 AssertCodeDark(....) this private routine verifies that the various input
    1074 parameters to pmSubtractBias() are correct for dark subtraction.
    1075  *****************************************************************************/
    1076 pmSubtractBiasAssertStatus AssertCodeDark(
    1077     pmReadout *in,
    1078     void *fitSpec,
    1079     pmFit fit,
    1080     bool overscan,
    1081     psStats *stat,
    1082     int nBinOrig,
    1083     const pmReadout *bias,
    1084     const pmReadout *dark)
    1085 {
    1086     if ((in->image->numRows + in->row0 - dark->row0) > dark->image->numRows) {
    1087         psError(PS_ERR_UNKNOWN, true, "dark image does not have enough rows.  Returning in image\n");
    1088         return(PM_ERROR_NO_DARK_SUBTRACT);
    1089     }
    1090     if ((in->image->numCols + in->col0 - dark->col0) > dark->image->numCols) {
    1091         psError(PS_ERR_UNKNOWN, true, "dark image does not have enough columns.  Returning in image\n");
    1092         return(PM_ERROR_NO_DARK_SUBTRACT);
    1093     }
    1094 
    1095     if (dark != NULL) {
    1096         PS_ASSERT_READOUT_NON_EMPTY(dark, PM_ERROR_NO_DARK_SUBTRACT);
    1097         PS_ASSERT_READOUT_TYPE(dark, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT);
    1098     }
    1099     return(PM_OKAY);
    1100 }
    1101 
    1102 /******************************************************************************
    1103 p_psDetermineTrimmedImage(): global routine: determines the region of the
    1104 input pmReadout which will be operated on by the various detrend modules.  It
    1105 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout.
    1106  
    1107 Use it this way:
    1108     PS_WARN_PTR_NON_NULL(in->parent);
    1109     if (in->parent != NULL) {
    1110         PS_WARN_PTR_NON_NULL(in->parent->concepts);
    1111     }
    1112     //
    1113     // Determine trimmed image from metadata.
    1114     //
    1115     psImage *trimmedImg = p_psDetermineTrimmedImage(in);
    1116  
    1117 XXX: Create a pmUtils.c file and put this routine there.
    1118  *****************************************************************************/
    1119 psImage *p_psDetermineTrimmedImage(pmReadout *in)
    1120 {
    1121     if ((in->parent == NULL) || (in->parent->concepts == NULL)) {
    1122         psLogMsg(__func__, PS_LOG_WARN,
    1123                  "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata (NULL).\n");
    1124         return(in->image);
    1125     }
    1126 
    1127     psBool rc = false;
    1128     psImage *trimmedImg = NULL;
    1129     psRegion *trimRegion = psMetadataLookupPtr(&rc, in->parent->concepts,
    1130                            "CELL.TRIMSEC");
    1131     if (rc == false) {
    1132         psLogMsg(__func__, PS_LOG_WARN,
    1133                  "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata.\n");
    1134         trimmedImg = in->image;
    1135     } else {
    1136         trimmedImg = psImageSubset(in->image, *trimRegion);
    1137     }
    1138 
    1139     return(trimmedImg);
    1140 }
    1141 
    1142 
    1143 
    1144 
    1145 
    1146 
    1147 
    1148 
    1149 
    1150 
    1151 
    1152 
    1153 
    1154 
    1155 
    1156 
    1157 
    1158 
    1159 /******************************************************************************
    1160 pmSubtractBias(....): see SDRS for complete specification.
    1161  
    1162 XXX: Code and assert type support: U16, S32, F32.
    1163 XXX: Add trace messages.
    1164  *****************************************************************************/
    1165 pmReadout *pmSubtractBias(
    1166     pmReadout *in,
    1167     void *fitSpec,
    1168     pmFit fit,
    1169     bool overscan,
    1170     psStats *stat,
    1171     int nBin,
    1172     const pmReadout *bias,
    1173     const pmReadout *dark)
     288pmReadout *pmSubtractBias(pmReadout *in,
     289                          void *fitSpec,
     290                          const psList *overscans,
     291                          pmOverscanAxis overScanAxis,
     292                          psStats *stat,
     293                          psS32 nBinOrig,
     294                          pmFit fit,
     295                          const pmReadout *bias)
    1174296{
    1175297    psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4,
    1176298            "---- pmSubtractBias() begin ----\n");
    1177     //
    1178     // Check input parameters, generate warnings and errors.
    1179     //
    1180     if (PM_OKAY != AssertCodeOverscan(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) {
    1181         return(in);
    1182     }
    1183     //
    1184     // Determine trimmed image from metadata.
    1185     //
    1186     psImage *trimmedImg = p_psDetermineTrimmedImage(in);
    1187 
    1188     //
    1189     // Subtract overscan frames if necessary.
    1190     //
    1191     if (overscan == true) {
    1192         pmOverscanAxis overScanAxis = GetOverscanAxis(in);
     299    PS_ASSERT_READOUT_NON_NULL(in, NULL);
     300    PS_ASSERT_READOUT_NON_EMPTY(in, NULL);
     301    PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL);
     302
     303    //
     304    // If the overscans != NULL, then check the type of each image.
     305    //
     306    if (overscans != NULL) {
     307        psListElem *tmpOverscan = (psListElem *) overscans->head;
     308        while (NULL != tmpOverscan) {
     309            psImage *myOverscanImage = (psImage *) tmpOverscan->data;
     310            PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL);
     311            tmpOverscan = tmpOverscan->next;
     312        }
     313    }
     314
     315    if ((overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE)) {
     316        psError(PS_ERR_UNKNOWN,true, "(overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE).  Returning in image\n");
     317        return(in);
     318    }
     319
     320    // Check for an unallowable pmFit.
     321    if ((fit != PM_OVERSCAN_NONE) &&
     322            (fit != PM_OVERSCAN_ROWS) &&
     323            (fit != PM_OVERSCAN_COLUMNS) &&
     324            (fit != PM_OVERSCAN_ALL)) {
     325        psError(PS_ERR_UNKNOWN, true, "fit is unallowable (%d).  Returning in image.\n", fit);
     326        return(in);
     327    }
     328    // Check for an unallowable pmOverscanAxis.
     329    if ((overScanAxis != PM_OVERSCAN_NONE) &&
     330            (overScanAxis != PM_OVERSCAN_ROWS) &&
     331            (overScanAxis != PM_OVERSCAN_COLUMNS) &&
     332            (overScanAxis != PM_OVERSCAN_ALL)) {
     333        psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d).  Returning in image.\n", overScanAxis);
     334        return(in);
     335    }
     336    psS32 i;
     337    psS32 j;
     338    psS32 numBins = 0;
     339    static psVector *overscanVector = NULL;
     340    psVector *tmpRow = NULL;
     341    psVector *tmpCol = NULL;
     342    psVector *myBin = NULL;
     343    psVector *binVec = NULL;
     344    psListElem *tmpOverscan = NULL;
     345    double statValue;
     346    psImage *myOverscanImage = NULL;
     347    psPolynomial1D *myPoly = NULL;
     348    psSpline1D *mySpline = NULL;
     349    psS32 nBin;
     350
     351    //
     352    //  Create a static stats data structure and determine the highest
     353    //  priority stats option.
     354    //
     355    static psStats *myStats = NULL;
     356    if (myStats == NULL) {
     357        myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
     358        p_psMemSetPersistent(myStats, true);
     359    }
     360    if (stat != NULL) {
     361        myStats->options = GenNewStatOptions(stat);
     362    }
     363
     364
     365    if (overScanAxis == PM_OVERSCAN_NONE) {
     366        if (fit != PM_FIT_NONE) {
     367            psLogMsg(__func__, PS_LOG_WARN,
     368                     "WARNING: pmSubtractBias.(): overScanAxis equals NONE, and fit does not equal NONE.  Proceeding to full fram subtraction.\n");
     369        }
     370
     371        if (overscans != NULL) {
     372            psLogMsg(__func__, PS_LOG_WARN,
     373                     "WARNING: pmSubtractBias.(): overScanAxis equals NONE and overscans does not equal NULL.  Proceeding to full fram subtraction.\n");
     374        }
     375        return(SubtractFrame(in, bias));
     376    }
     377
     378    if ((overScanAxis == PM_OVERSCAN_ALL) && (fit != PM_FIT_NONE)) {
     379        psLogMsg(__func__, PS_LOG_WARN,
     380                 "WARNING: pmSubtractBias.(): overScanAxis equals ALL, and fit does not equal NONE.  Proceeding with the rest of the module.\n");
     381    }
     382
     383
     384    //
     385    // We subtract each overscan region from the image data.
     386    // If we get here we know that overscans != NULL.
     387    //
     388
     389    if (overScanAxis == PM_OVERSCAN_ALL) {
     390        tmpOverscan = (psListElem *) overscans->head;
     391        while (NULL != tmpOverscan) {
     392            myOverscanImage = (psImage *) tmpOverscan->data;
     393
     394            PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL);
     395            psStats *rc = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff);
     396            if (rc == NULL) {
     397                psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation.  Returning in image.\n");
     398                return(in);
     399            }
     400            if (false == p_psGetStatValue(myStats, &statValue)) {
     401                psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
     402                return(in);
     403            }
     404            ImageSubtractScalar(in->image, statValue);
     405
     406            tmpOverscan = tmpOverscan->next;
     407        }
     408        return(in);
     409    }
     410
     411    // This check is redundant with above code.
     412    if (!((overScanAxis == PM_OVERSCAN_ROWS) || (overScanAxis == PM_OVERSCAN_COLUMNS))) {
     413        psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d).\nReturning in image.\n", overScanAxis);
     414        return(in);
     415    }
     416
     417    tmpOverscan = (psListElem *) overscans->head;
     418    while (NULL != tmpOverscan) {
     419        //        PS_IMAGE_PRINT_F32_HIDEF(in->image);
     420        myOverscanImage = (psImage *) tmpOverscan->data;
     421
     422        if (overScanAxis == PM_OVERSCAN_ROWS) {
     423            if (myOverscanImage->numCols != (in->image)->numCols) {
     424                psLogMsg(__func__, PS_LOG_WARN,
     425                         "WARNING: pmSubtractBias.(): overscan image has %d columns, input image has %d columns\n",
     426                         myOverscanImage->numCols, in->image->numCols);
     427            }
     428
     429            // We create a row vector and subtract this vector from image.
     430            // XXX: Is there a better way to extract a psVector from a psImage without
     431            // having to copy every element in that vector?
     432            overscanVector = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32);
     433            for (i=0;i<overscanVector->n;i++) {
     434                overscanVector->data.F32[i] = 0.0;
     435            }
     436            tmpRow = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32);
     437
     438            // For each column of the input image, loop through every row,
     439            // collect the pixel in that row, then performed the specified
     440            // statistical op on those pixels.  Store this in overscanVector.
     441            for (i=0;i<myOverscanImage->numCols;i++) {
     442                for (j=0;j<myOverscanImage->numRows;j++) {
     443                    tmpRow->data.F32[j] = myOverscanImage->data.F32[j][i];
     444                }
     445                psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0);
     446                if (rc == NULL) {
     447                    psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
     448                    return(in);
     449                }
     450                if (false ==  p_psGetStatValue(rc, &statValue)) {
     451                    psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
     452                    return(in);
     453                }
     454                overscanVector->data.F32[i] = statValue;
     455            }
     456            psFree(tmpRow);
     457
     458            // Scale the overscan vector to the size of the input image.
     459            if (overscanVector->n != in->image->numCols) {
     460                if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) {
     461                    psVector *newVec = ScaleOverscanVector(overscanVector,
     462                                                           in->image->numCols,
     463                                                           fitSpec, fit);
     464                    if (newVec == NULL) {
     465                        psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector.  Returning in image.\n");
     466                        return(in);
     467                    }
     468                    psFree(overscanVector);
     469                    overscanVector = newVec;
     470                } else {
     471                    psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector.  Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL.  Returning in image.\n");
     472                    psFree(overscanVector);
     473                    return(in);
     474                }
     475            }
     476        }
     477
     478        if (overScanAxis == PM_OVERSCAN_COLUMNS) {
     479            if (myOverscanImage->numRows != (in->image)->numRows) {
     480                psLogMsg(__func__, PS_LOG_WARN,
     481                         "WARNING: pmSubtractBias.(): overscan image has %d rows, input image has %d rows\n",
     482                         myOverscanImage->numRows, in->image->numRows);
     483            }
     484
     485            // We create a column vector and subtract this vector from image.
     486            overscanVector = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32);
     487            for (i=0;i<overscanVector->n;i++) {
     488                overscanVector->data.F32[i] = 0.0;
     489            }
     490            tmpCol = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32);
     491
     492            // For each row of the input image, loop through every column,
     493            // collect the pixel in that row, then performed the specified
     494            // statistical op on those pixels.  Store this in overscanVector.
     495            for (i=0;i<myOverscanImage->numRows;i++) {
     496                for (j=0;j<myOverscanImage->numCols;j++) {
     497                    tmpCol->data.F32[j] = myOverscanImage->data.F32[i][j];
     498                }
     499                psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0);
     500                if (rc == NULL) {
     501                    psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
     502                    return(in);
     503                }
     504                if (false ==  p_psGetStatValue(rc, &statValue)) {
     505                    psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
     506                    return(in);
     507                }
     508                overscanVector->data.F32[i] = statValue;
     509            }
     510            psFree(tmpCol);
     511
     512            // Scale the overscan vector to the size of the input image.
     513            if (overscanVector->n != in->image->numRows) {
     514                if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) {
     515                    psVector *newVec = ScaleOverscanVector(overscanVector,
     516                                                           in->image->numRows,
     517                                                           fitSpec, fit);
     518                    if (newVec == NULL) {
     519                        psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector.  Returning in image.\n");
     520                        return(in);
     521                    }
     522                    psFree(overscanVector);
     523                    overscanVector = newVec;
     524                } else {
     525                    psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector.  Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL.  Returning in image.\n");
     526                    psFree(overscanVector);
     527                    return(in);
     528                }
     529            }
     530        }
     531
    1193532        //
    1194         //  Create a psStats data structure and determine the highest
    1195         //  priority stats option.
     533        // Re-bin the overscan vector (change its length).
    1196534        //
    1197         psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN);
    1198         if (stat != NULL) {
    1199             myStats->options = GenNewStatOptions(stat);
    1200         }
    1201 
     535        // Only if nBinOrig > 1.
     536        if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) {
     537            numBins = 1+((overscanVector->n)/nBinOrig);
     538            myBin = psVectorAlloc(numBins, PS_TYPE_F32);
     539            binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32);
     540
     541            for (i=0;i<numBins;i++) {
     542                for(j=0;j<nBinOrig;j++) {
     543                    if (overscanVector->n > ((i*nBinOrig)+j)) {
     544                        binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j];
     545                    } else {
     546                        // XXX: we get here if nBinOrig does not evenly divide
     547                        // the overscanVector vector.  This is the last bin.  Should
     548                        // we change the binVec->n to acknowledge that?
     549                        binVec->n = j;
     550                    }
     551                }
     552                psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0);
     553                if (rc == NULL) {
     554                    psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation.  Returning in image.\n");
     555                    return(in);
     556                }
     557                if (false ==  p_psGetStatValue(rc, &statValue)) {
     558                    psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning in image.\n");
     559                    return(in);
     560                }
     561                myBin->data.F32[i] = statValue;
     562            }
     563
     564            // Change the effective size of overscanVector.
     565            overscanVector->n = numBins;
     566            for (i=0;i<numBins;i++) {
     567                overscanVector->data.F32[i] = myBin->data.F32[i];
     568            }
     569            psFree(binVec);
     570            psFree(myBin);
     571            nBin = nBinOrig;
     572        } else {
     573            nBin = 1;
     574        }
     575
     576        // At this point the number of data points in overscanVector should be
     577        // equal to the number of rows/columns (whatever is appropriate) in the
     578        // image divided by numBins.
    1202579        //
    1203         // Reduce overscan images to a single pixel, then subtract.
    1204         // This code is no longer required as of SDRS 12-09.
     580
     581
    1205582        //
    1206         if (overScanAxis == PM_OVERSCAN_ALL) {
    1207             if (false == OverscanReducePixel(trimmedImg, in->bias, myStats)) {
    1208                 return(in);
    1209             }
    1210             psFree(myStats);
     583        // This doesn't seem right.  The only way to do a spline fit is if,
     584        // by SDRS requirements, fitSpec is not-NULL>  But in order for it
     585        // to be non-NULL, someone must have called psSpline1DAlloc() with
     586        // the min, max, and number of splines.
     587        //
     588        if (!((fitSpec == NULL) || (fit == PM_FIT_NONE))) {
     589            //
     590            // Fit a polynomial or spline to the overscan vector.
     591            //
     592            if (fit == PM_FIT_POLYNOMIAL) {
     593                myPoly = (psPolynomial1D *) fitSpec;
     594                myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL);
     595                if (myPoly == NULL) {
     596                    psError(PS_ERR_UNKNOWN, false, "(3) Could not fit a polynomial to overscan vector.  Returning in image.\n");
     597                    psFree(overscanVector);
     598                    return(in);
     599                }
     600            } else if (fit == PM_FIT_SPLINE) {
     601                // XXX: This makes no sense
     602                // XXX: must free mySpline?
     603                mySpline = (psSpline1D *) fitSpec;
     604                mySpline = psVectorFitSpline1D(NULL, overscanVector);
     605                if (mySpline == NULL) {
     606                    psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector.  Returning in image.\n");
     607                    psFree(overscanVector);
     608                    return(in);
     609                }
     610            }
     611
     612            //
     613            // Subtract fitted overscan vector row-wise from the image.
     614            //
     615            if (overScanAxis == PM_OVERSCAN_ROWS) {
     616                for (i=0;i<(in->image)->numCols;i++) {
     617                    psF32 tmpF32 = 0.0;
     618                    if (fit == PM_FIT_POLYNOMIAL) {
     619                        tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin));
     620                    } else if (fit == PM_FIT_SPLINE) {
     621                        tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin));
     622                    }
     623                    for (j=0;j<(in->image)->numRows;j++) {
     624                        (in->image)->data.F32[j][i]-= tmpF32;
     625                    }
     626                }
     627            }
     628
     629            //
     630            // Subtract fitted overscan vector column-wise from the image.
     631            //
     632            if (overScanAxis == PM_OVERSCAN_COLUMNS) {
     633                for (i=0;i<(in->image)->numRows;i++) {
     634                    psF32 tmpF32 = 0.0;
     635                    if (fit == PM_FIT_POLYNOMIAL) {
     636                        tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin));
     637                    } else if (fit == PM_FIT_SPLINE) {
     638                        tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin));
     639                    }
     640
     641                    for (j=0;j<(in->image)->numCols;j++) {
     642                        (in->image)->data.F32[i][j]-= tmpF32;
     643                    }
     644                }
     645            }
    1211646        } else {
    1212647            //
    1213             // Reduce the overscan images to a single overscan vector.
    1214             //
    1215             psVector *overscanVector = OverscanReduce(in->image, overScanAxis,
    1216                                        in->bias, fitSpec,
    1217                                        fit, myStats);
    1218             if (overscanVector == NULL) {
    1219                 psError(PS_ERR_UNKNOWN, false, "Could not reduce overscan images to a single overscan vector.  Returning in image\n");
    1220                 psFree(myStats);
    1221                 return(in);
    1222             }
    1223 
    1224             //
    1225             // Rebin the overscan vector if necessary.
    1226             //
    1227             psS32 newBin = RebinOverscanVector(overscanVector, nBin, myStats);
    1228             if (newBin < 0) {
    1229                 psError(PS_ERR_UNKNOWN, false, "Could rebin the overscan vector.  Returning in image\n");
    1230                 psFree(myStats);
    1231                 return(in);
    1232             }
    1233 
    1234             //
    1235             // If necessary, fit a psPolynomial or psSpline to the overscan vector.
    1236             // Then, unbin the overscan vector to appropriate length for the in image.
    1237             //
    1238             if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) {
    1239                 overscanVector = FitOverscanVectorAndUnbin(trimmedImg, overscanVector, overScanAxis, fitSpec, fit, newBin);
    1240                 if (overscanVector == NULL) {
    1241                     psError(PS_ERR_UNKNOWN, false, "Could not fit the polynomial or spline to the overscan vector.  Returning in image\n");
    1242                     psFree(myStats);
    1243                     return(in);
    1244                 }
    1245             } else {
    1246                 overscanVector = UnbinOverscanVector(trimmedImg, overscanVector, overScanAxis, newBin);
    1247             }
    1248 
    1249             //
    1250             // Subtract the overscan vector from the input image.
    1251             //
    1252             SubtractVectorFromImage(trimmedImg, overscanVector, overScanAxis);
    1253             psFree(myStats);
    1254             psFree(overscanVector);
    1255         }
    1256     }
    1257 
    1258     //
    1259     // Perform bias subtraction if necessary.
    1260     //
    1261     if (bias != NULL) {
    1262         if (PM_OKAY == AssertCodeBias(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) {
    1263             SubtractFrame(in, bias);
    1264         }
    1265     }
    1266 
    1267     //
    1268     // Perform dark subtraction if necessary.
    1269     //
    1270     if (dark != NULL) {
    1271         if (PM_OKAY == AssertCodeDark(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) {
    1272             psBool rc;
    1273             psF32 scale = 0.0;
    1274             if (in->parent != NULL) {
    1275                 scale = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.DARKTIME");
    1276                 if (rc == false) {
    1277                     psLogMsg(__func__, PS_LOG_WARN,
    1278                              "WARNING: pmSubtractBias.(): could not determine CELL.FARKTIME from in->parent metadata.\n");
    1279                 }
    1280             }
    1281             SubtractDarkFrame(in, dark, scale);
    1282         }
    1283     }
    1284 
    1285     //
    1286     // All done.
    1287     //
     648            // If we get here, then no polynomials were fit to the overscan
     649            // vector.  We simply subtract it, taking into account binning,
     650            // from the image.
     651            //
     652
     653            //
     654            // Subtract overscan vector row-wise from the image.
     655            //
     656            if (overScanAxis == PM_OVERSCAN_ROWS) {
     657                for (i=0;i<(in->image)->numCols;i++) {
     658                    for (j=0;j<(in->image)->numRows;j++) {
     659                        (in->image)->data.F32[j][i]-= overscanVector->data.F32[i/nBin];
     660                    }
     661                }
     662            }
     663
     664            //
     665            // Subtract overscan vector column-wise from the image.
     666            //
     667            if (overScanAxis == PM_OVERSCAN_COLUMNS) {
     668                for (i=0;i<(in->image)->numRows;i++) {
     669                    for (j=0;j<(in->image)->numCols;j++) {
     670                        (in->image)->data.F32[i][j]-= overscanVector->data.F32[i/nBin];
     671                    }
     672                }
     673            }
     674        }
     675
     676        psFree(overscanVector);
     677
     678        tmpOverscan = tmpOverscan->next;
     679    }
     680
    1288681    psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4,
    1289682            "---- pmSubtractBias() exit ----\n");
     683
     684    if (bias != NULL) {
     685        return(SubtractFrame(in, bias));
     686    }
    1290687    return(in);
    1291688}
  • branches/pap_branch_051214/psModules/src/imsubtract/pmSubtractBias.h

    r5587 r5795  
     1//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     2// XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the
     3// one that was being worked on.
     4//////////////////////////////////////////////////////////////////////////////////////////////////////////////
     5
    16/** @file  pmSubtractBias.h
    27 *
     
    611 *  @author GLG, MHPCC
    712 *
    8  *  @version $Revision: 1.4 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2005-11-23 23:54:30 $
     13 *  @version $Revision: 1.4.8.1 $ $Name: not supported by cvs2svn $
     14 *  @date $Date: 2005-12-17 03:18:39 $
    1015 *
    1116 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2328#include<math.h>
    2429#include "pslib.h"
     30
    2531#include "pmAstrometry.h"
    2632
     
    3844} pmFit;
    3945
    40 pmReadout *pmSubtractBias(
    41     pmReadout *in,                      ///< The input pmReadout image
    42     void *fitSpec,                      ///< A polynomial or spline, defining the fit type.
    43     pmFit fit,                          ///< PM_FIT_SPLINE, PM_FIT_POLYNOMIAL, or PM_FIT_NONE
    44     bool overscan,
    45     psStats *stat,                      ///< The statistic to be used in combining overscan data
    46     int nBin,                           ///< The amount of binning to be done image pixels.
    47     const pmReadout *bias,              ///< A possibly NULL bias pmReadout which is to be subtracted
    48     const pmReadout *dark               ///< A possibly NULL bias pmReadout which is to be subtracted
    49 );
    50 
    51 /******************************************************************************
    52 DetermineTrimmedImageg() This private routine determines the region of the
    53 input pmReadout which will be operated on by the various detrend modules.  It
    54 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout.
    55  
    56 XXX: Consider making a pmUtils.c file and put this routine there.
    57  *****************************************************************************/
    58 psImage *p_psDetermineTrimmedImage(
    59     pmReadout *in
    60 );
     46pmReadout *pmSubtractBias(pmReadout *in,                ///< The input pmReadout image
     47                          void *fitSpec,                ///< A polynomial or spline, defining the fit type.
     48                          const psList *overscans,      ///< A psList of overscan images
     49                          pmOverscanAxis overScanAxis,  ///< Defines how overscans are applied
     50                          psStats *stat,                ///< The statistic to be used in combining overscan data
     51                          int nBin,                     ///< The amount of binning to be done image pixels.
     52                          pmFit fit,                    ///< PM_FIT_SPLINE, PM_FIT_POLYNOMIAL, or PM_FIT_NONE
     53                          const pmReadout *bias);       ///< A possibly NULL bias pmReadout which is to be subtracted
    6154
    6255#endif
Note: See TracChangeset for help on using the changeset viewer.