IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 6062


Ignore:
Timestamp:
Jan 19, 2006, 4:38:28 PM (20 years ago)
Author:
Paul Price
Message:

Getting a working ppImage

Location:
branches/eam_rel9_p0/psModules/src
Files:
4 added
31 edited

Legend:

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

    r5974 r6062  
    44libpsmoduleastrom_la_LDFLAGS  = -release $(PACKAGE_VERSION)
    55libpsmoduleastrom_la_SOURCES  = \
    6         pmAstrometry.c \
     6        pmFPA.c \
     7        pmFPAAstrometry.c \
    78        pmAstrometryObjects.c \
    89        pmFPAConstruct.c \
     
    1617        pmConceptsStandard.c \
    1718        pmChipMosaic.c
    18 ###     pmFPAConceptsGet.c
    19 ###     pmFPAConceptsSet.c
    2019
    2120psmoduleincludedir = $(includedir)
    2221psmoduleinclude_HEADERS = \
    23         pmAstrometry.h \
     22        pmFPA.h \
     23        pmFPAAstrometry.h \
    2424        pmAstrometryObjects.h \
    2525        pmFPAConstruct.h \
     
    3232        pmConceptsWrite.h \
    3333        pmConceptsStandard.h \
    34         pmChipMosaic.h
    35 ###     pmFPAConceptsGet.h
    36 ###     pmFPAConceptsSet.h
     34        pmChipMosaic.h
  • branches/eam_rel9_p0/psModules/src/astrom/pmAstrometry.c

    r5974 r6062  
    1313* XXX: Should we implement non-linear cell->chip transforms?
    1414*
    15 *  @version $Revision: 1.11.2.1.2.1 $ $Name: not supported by cvs2svn $
    16 *  @date $Date: 2006-01-14 03:10:19 $
     15*  @version $Revision: 1.11.2.1.2.2 $ $Name: not supported by cvs2svn $
     16*  @date $Date: 2006-01-20 02:36:41 $
    1717*
    1818*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    6363        psFree(readout->weight);
    6464        psFree(readout->analysis);
     65        #if 0
     66
    6567        psFree(readout->parent);
     68        #endif
     69
     70        readout->parent = NULL;
    6671    }
    6772}
     
    8085        // in order to avoid memory reference counter problems.
    8186        //
     87        #if 0
     88
    8289        for (psS32 i = 0 ; i < cell->readouts->n ; i++) {
    8390            pmReadout *tmpReadout = (pmReadout *) cell->readouts->data[i];
     
    8794            }
    8895        }
     96        psFree(cell->parent);
     97        #endif
     98
     99        cell->parent = NULL;
     100
    89101        psFree(cell->readouts);
    90         psFree(cell->parent);
    91102        psFree(cell->hdu);
     103
    92104    }
    93105}
     
    104116        // in order to avoid memory reference counter problems.
    105117        //
     118        #if 0
     119
    106120        for (psS32 i = 0 ; i < chip->cells->n ; i++) {
    107121            pmCell *tmpCell = (pmCell *) chip->cells->data[i];
     
    111125            }
    112126        }
     127        psFree(chip->parent);
     128        #endif
     129
     130        chip->parent = NULL;
    113131        psFree(chip->cells);
    114         psFree(chip->parent);
    115132        psFree(chip->hdu);
    116133    }
     
    131148        // in order to avoid memory reference counter problems.
    132149        //
     150        #if 0
     151
    133152        for (psS32 i = 0 ; i < fpa->chips->n ; i++) {
    134153            pmChip *tmpChip = (pmChip *) fpa->chips->data[i];
     
    138157            }
    139158        }
     159        #endif
    140160        psFree(fpa->chips);
    141161        psFree(fpa->hdu);
     
    199219    tmpCell->analysis = psMetadataAlloc();
    200220    tmpCell->readouts = psArrayAlloc(0);
    201     tmpCell->parent = psMemIncrRefCounter(chip);
     221    tmpCell->parent = chip;
    202222    if (chip != NULL) {
    203223        chip->cells = psArrayAdd(chip->cells, 1, (psPtr) tmpCell);
     
    232252    tmpChip->analysis = psMetadataAlloc();
    233253    tmpChip->cells = psArrayAlloc(0);
    234     tmpChip->parent = psMemIncrRefCounter(fpa);
     254    tmpChip->parent = fpa;
    235255    if (fpa != NULL) {
    236256        fpa->chips = psArrayAdd(fpa->chips, 1, (psPtr) tmpChip);
     
    338358}
    339359
    340 
    341 
    342 /*****************************************************************************/
    343 /* FUNCTION IMPLEMENTATION - PUBLIC                                          */
    344 /*****************************************************************************/
    345 
    346 pmCell* pmCellInFPA(
    347     const psPlane* fpaCoord,
    348     const pmFPA* FPA)
    349 {
    350     PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
    351     PS_ASSERT_PTR_NON_NULL(FPA, NULL);
    352 
    353     pmChip* tmpChip = NULL;
    354     psPlane chipCoord;
    355     pmCell* outCell = NULL;
    356 
    357     // Determine which chip contains the fpaCoords.
    358     tmpChip = pmChipInFPA(fpaCoord, FPA);
    359     if (tmpChip == NULL) {
    360         return(NULL);
    361     }
    362 
    363     // Convert to those chip coordinates.
    364     psPlane *rc = pmCoordFPAToChip(&chipCoord, fpaCoord, tmpChip);
    365     if (rc == NULL) {
    366         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine Chip coords.\n");
    367         return(NULL);
    368     }
    369 
    370     // Determine which cell contains those chip coordinates.
    371     outCell = pmCellInChip(&chipCoord, tmpChip);
    372     if (outCell == NULL) {
    373         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
    374         return(NULL);
    375     }
    376 
    377     return (outCell);
    378 }
    379 
    380 pmChip* pmChipInFPA(
    381     const psPlane* fpaCoord,
    382     const pmFPA* FPA)
    383 {
    384     PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
    385     PS_ASSERT_PTR_NON_NULL(FPA, NULL);
    386     PS_ASSERT_PTR_NON_NULL(FPA->chips, NULL);
    387 
    388     psArray* chips = FPA->chips;
    389     psS32 nChips = chips->n;
    390     psPlane chipCoord;
    391     pmCell *tmpCell = NULL;
    392 
    393     //
    394     // Loop through every chip in this FPA.  Convert the original FPA
    395     // coordinates to chip coordinates for that chip.  Then, determine if any
    396     // cells in that chip contain those chip coordinates.
    397     // XXX: Depending on the number of chips, and their topology, there may be
    398     // a much more efficient way of doing this.
    399     //
    400     for (psS32 i = 0; i < nChips; i++) {
    401         pmChip* tmpChip = chips->data[i];
    402         PS_ASSERT_PTR_NON_NULL(tmpChip, NULL);
    403         PS_ASSERT_PTR_NON_NULL(tmpChip->fromFPA, NULL);
    404 
    405         psPlaneTransformApply(&chipCoord, tmpChip->fromFPA, fpaCoord);
    406 
    407         tmpCell = pmCellInChip(&chipCoord, tmpChip);
    408         if (tmpCell != NULL) {
    409             return(tmpChip);
    410         }
    411     }
    412 
    413     psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the chip.\n");
    414     return (NULL);
    415 }
    416 
    417 
    418 pmCell* pmCellInChip(
    419     const psPlane* chipCoord,
    420     const pmChip* chip)
    421 {
    422     PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
    423     PS_ASSERT_PTR_NON_NULL(chip, NULL);
    424 
    425     psPlane cellCoord;
    426     psArray* cells;
    427 
    428     cells = chip->cells;
    429     if (cells == NULL) {
    430         return NULL;
    431     }
    432 
    433     //
    434     // We loop over each cell in the chip.  We transform the chipCoord into
    435     // a cellCoord for that cell and determine if that cellCoord is valid.
    436     // If so, then we return that cell.
    437     // XXX: Depending on the number of cells, and their topology, there may be
    438     // a much more efficient way of doing this.
    439     //
    440     for (psS32 i = 0; i < cells->n; i++) {
    441         pmCell* tmpCell = (pmCell* ) cells->data[i];
    442         PS_ASSERT_PTR_NON_NULL(tmpCell, NULL);
    443 
    444         psPlaneTransform *chipToCell = NULL;
    445         if (true ==  p_psIsProjectionLinear(tmpCell->toChip)) {
    446             chipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
    447         } else {
    448             psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
    449             //chipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
    450             chipToCell = NULL;
    451         }
    452         if (chipToCell == NULL) {
    453             psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
    454             return(NULL);
    455         }
    456         psArray* readouts = tmpCell->readouts;
    457 
    458         if (readouts != NULL) {
    459             for (psS32 j = 0; j < readouts->n; j++) {
    460                 pmReadout* tmpReadout = readouts->data[j];
    461                 PS_ASSERT_READOUT_NON_NULL(tmpReadout, NULL);
    462 
    463                 psPlaneTransformApply(&cellCoord,
    464                                       chipToCell,
    465                                       chipCoord);
    466 
    467                 if (checkValidImageCoords(cellCoord.x,
    468                                           cellCoord.y,
    469                                           tmpReadout->image)) {
    470                     psFree(chipToCell);
    471                     return (tmpCell);
    472                 }
    473             }
    474         }
    475         psFree(chipToCell);
    476     }
    477 
    478     //psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the cell.\n");
    479     return (NULL);
    480 }
    481 
    482 
    483 psPlane* pmCoordCellToFPA(
    484     psPlane* fpaCoord,
    485     const psPlane* cellCoord,
    486     const pmCell* cell)
    487 {
    488     PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
    489     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    490 
    491     psPlane *rc = psPlaneTransformApply(fpaCoord, cell->toFPA, cellCoord);
    492     if (rc == NULL) {
    493         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to FPA coords.\n");
    494     }
    495     return(rc);
    496 }
    497 
    498 
    499 psPlane* pmCoordChipToFPA(
    500     psPlane* outCoord,
    501     const psPlane* inCoord,
    502     const pmChip* chip)
    503 {
    504     PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
    505     PS_ASSERT_PTR_NON_NULL(chip, NULL);
    506 
    507     psPlane *rc = psPlaneTransformApply(outCoord, chip->toFPA, inCoord);
    508     if (rc == NULL) {
    509         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform chip coords to FPA coords.\n");
    510     }
    511     return(rc);
    512 }
    513 
    514 
    515 psPlane* pmCoordFPAToChip(
    516     psPlane* chipCoord,
    517     const psPlane* fpaCoord,
    518     const pmChip* chip)
    519 {
    520     PS_ASSERT_PTR_NON_NULL(fpaCoord, NULL);
    521     PS_ASSERT_PTR_NON_NULL(chip, NULL);
    522     PS_ASSERT_PTR_NON_NULL(chip->fromFPA, NULL);
    523 
    524     psPlane *rc = psPlaneTransformApply(chipCoord, chip->fromFPA, fpaCoord);
    525     if (rc == NULL) {
    526         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to Chip coords.\n");
    527     }
    528     return(rc);
    529 }
    530 
    531 psPlane* pmCoordCellToChip(
    532     psPlane* outCoord,
    533     const psPlane* inCoord,
    534     const pmCell* cell)
    535 {
    536     PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
    537     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    538 
    539     psPlane *rc = psPlaneTransformApply(outCoord, cell->toChip, inCoord);
    540     if (rc == NULL) {
    541         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Cell coords to Chip coords.\n");
    542     }
    543     return(rc);
    544 }
    545 
    546 psPlane* pmCoordChipToCell(
    547     psPlane* cellCoord,
    548     const psPlane* chipCoord,
    549     const pmCell* cell)
    550 {
    551     PS_ASSERT_PTR_NON_NULL(chipCoord, NULL);
    552     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    553     PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
    554 
    555     pmCell *tmpCell = pmCellInChip(chipCoord, cell->parent);
    556     if (tmpCell == NULL) {
    557         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine the proper cell.\n");
    558         return(NULL);
    559     }
    560 
    561     psPlaneTransform *tmpChipToCell = NULL;
    562     PS_ASSERT_PTR_NON_NULL(tmpCell->toChip, NULL);
    563     if (true ==  p_psIsProjectionLinear(tmpCell->toChip)) {
    564         tmpChipToCell = p_psPlaneTransformLinearInvert(tmpCell->toChip);
    565     } else {
    566         psLogMsg(__func__, PS_LOG_WARN, "WARNING: non-linear cell->chip transforms are not yet implemented.\n");
    567         // XXX: tmpChipToCell = psPlaneTransformInvert(NULL, tmpCell->toChip, NULL, -1);
    568         tmpChipToCell = NULL;
    569     }
    570     if (tmpChipToCell == NULL) {
    571         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not invert the Cell->toChip transform.\n");
    572         return(NULL);
    573     }
    574 
    575     psPlane *rc = psPlaneTransformApply(cellCoord, tmpChipToCell, chipCoord);
    576     if (rc == NULL) {
    577         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform Chip coords to Cell coords.\n");
    578     }
    579     psFree(tmpChipToCell);
    580     return(rc);
    581 }
    582 
    583 psPlane* pmCoordFPAToTP(
    584     psPlane* outCoord,
    585     const psPlane* inCoord,
    586     double color,
    587     double magnitude,
    588     const pmFPA* fpa)
    589 {
    590     PS_ASSERT_PTR_NON_NULL(inCoord, NULL);
    591     PS_ASSERT_PTR_NON_NULL(fpa, NULL);
    592 
    593     psPlane *rc = psPlaneDistortApply(outCoord, fpa->toTangentPlane, inCoord, color, magnitude);
    594     if (rc == NULL) {
    595         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform FPA coords to tangent plane coords.\n");
    596     }
    597     return(rc);
    598 }
    599 
    600 psPlane* pmCoordTPToFPA(
    601     psPlane* fpaCoord,
    602     const psPlane* tpCoord,
    603     double color,
    604     double magnitude,
    605     const pmFPA* fpa)
    606 {
    607     PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
    608     PS_ASSERT_PTR_NON_NULL(fpa, NULL);
    609     PS_ASSERT_PTR_NON_NULL(fpa->fromTangentPlane, NULL);
    610 
    611     psPlane *rc = psPlaneDistortApply(fpaCoord, fpa->fromTangentPlane, tpCoord, color, magnitude);
    612     if (rc == NULL) {
    613         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to FPA coords.\n");
    614     }
    615     return(rc);
    616 }
    617 
    618 
    619 /*****************************************************************************
    620 XXXDeproject(outSphere, coord, projection): This private routine is a wrapper
    621 for p_psDeproject().  The reason: p_psDeproject() and p_psProject() combined
    622 do not seem to produce the original coordinates when they even though they
    623 should.  XXXDeproject() simply negates the ->r and ->d members of the output
    624 psSphere if the input ->y is larger than 0.0.  I don't know why it works.
    625  
    626 I'm guessing the p_psProject() and p_psDeproject() functions have bugs.
    627  
    628 XXX: It appears that p_psProject() and p_psDeproject() have been fixed.
    629 Remove this.
    630  *****************************************************************************/
    631 psSphere* XXXDeproject(
    632     psSphere *outSphere,
    633     const psPlane* coord,
    634     const psProjection* projection)
    635 {
    636     psSphere *rc = p_psDeproject(outSphere, coord, projection);
    637 
    638     if (coord->y >= 0.0) {
    639         rc->d = -rc->d;
    640         rc->r = -rc->r;
    641     }
    642 
    643     return(rc);
    644 }
    645 
    646 /*****************************************************************************
    647   *****************************************************************************/
    648 psSphere* pmCoordTPToSky(
    649     psSphere* outSphere,
    650     const psPlane* tpCoord,
    651     const psProjection *projection)
    652 {
    653     PS_ASSERT_PTR_NON_NULL(tpCoord, NULL);
    654     PS_ASSERT_PTR_NON_NULL(projection, NULL);
    655 
    656     //    psSphere *rc = XXXDeproject(outSphere, tpCoord, projection);
    657     psSphere *rc = p_psDeproject(outSphere, tpCoord, projection);
    658     if (rc == NULL) {
    659         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform tangent plane coords to sky coords.\n");
    660     }
    661     return(rc);
    662 }
    663 
    664 /*****************************************************************************
    665  *****************************************************************************/
    666 psPlane* pmCoordSkyToTP(
    667     psPlane* tpCoord,
    668     const psSphere* in,
    669     const psProjection *projection)
    670 {
    671     PS_ASSERT_PTR_NON_NULL(in, NULL);
    672     PS_ASSERT_PTR_NON_NULL(projection, NULL);
    673 
    674     psPlane *rc = p_psProject(tpCoord, in, projection);
    675     if (rc == NULL) {
    676         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to tangent plane coords.\n");
    677     }
    678     return(rc);
    679 }
    680 
    681 /*****************************************************************************
    682  *****************************************************************************/
    683 psSphere* pmCoordCellToSky(
    684     psSphere* skyCoord,
    685     const psPlane* cellCoord,
    686     double color,
    687     double magnitude,
    688     const pmCell* cell)
    689 {
    690     PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
    691     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    692     PS_ASSERT_PTR_NON_NULL(cell->toFPA, NULL);
    693     PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
    694     PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
    695     PS_ASSERT_PTR_NON_NULL(cell->parent->parent->toTangentPlane, NULL);
    696     PS_ASSERT_PTR_NON_NULL(cell->parent->parent->projection, NULL);
    697     psPlane fpaCoord;
    698     psPlane tpCoord;
    699     psPlane *rc;
    700     pmFPA* parFPA = (cell->parent)->parent;
    701 
    702     // Convert the input cell coordinates to FPA coordinates.
    703     rc = psPlaneTransformApply(&fpaCoord, cell->toFPA, cellCoord);
    704     if (rc == NULL) {
    705         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to FPA coords.\n");
    706         return(NULL);
    707     }
    708 
    709     // Convert the FPA coordinates to tangent plane Coordinates.
    710     rc = psPlaneDistortApply(&tpCoord, parFPA->toTangentPlane, &fpaCoord, color, magnitude);
    711     if (rc == NULL) {
    712         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform FPA coords to tangent plane coords.\n");
    713         return(NULL);
    714     }
    715 
    716     // Convert the tangent plane Coordinates to sky coordinates.
    717     psSphere *rc2 = pmCoordTPToSky(skyCoord, &tpCoord, parFPA->projection);
    718     if (rc2 == NULL) {
    719         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform cell coords to sky coords.\n");
    720     }
    721 
    722     return(rc2);
    723 }
    724 
    725 /*****************************************************************************
    726  *****************************************************************************/
    727 psPlane* pmCoordSkyToCell(
    728     psPlane* cellCoord,
    729     const psSphere* skyCoord,
    730     float color,
    731     float magnitude,
    732     const pmCell* cell)
    733 {
    734     PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
    735     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    736     PS_ASSERT_PTR_NON_NULL(cell->parent, NULL);
    737     PS_ASSERT_PTR_NON_NULL(cell->parent->parent, NULL);
    738     pmChip *parChip = cell->parent;
    739     pmFPA *parFPA = parChip->parent;
    740     psPlane tpCoord;
    741     psPlane fpaCoord;
    742     psPlane chipCoord;
    743     psPlane *rc;
    744 
    745     // Convert the skyCoords to tangent plane coords.
    746     rc = pmCoordSkyToTP(&tpCoord, skyCoord, parFPA->projection);
    747     if (rc == NULL) {
    748         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine tangent plane coords.\n");
    749         return(NULL);
    750     }
    751 
    752     // Convert the tangent plane coords to FPA coords.
    753     rc = pmCoordTPToFPA(&fpaCoord, &tpCoord, color, magnitude, parFPA);
    754     if (rc == NULL) {
    755         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine FPA coords.\n");
    756         return(NULL);
    757     }
    758 
    759     // Convert the FPA coords to chip coords.
    760     rc = pmCoordFPAToChip(&chipCoord, &fpaCoord, parChip);
    761     if (rc == NULL) {
    762         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine chip coords.\n");
    763         return(NULL);
    764     }
    765 
    766     // Convert the chip coords to cell coords.
    767     rc = pmCoordChipToCell(cellCoord, &chipCoord, cell);
    768     if (rc == NULL) {
    769         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not determine cell coords.\n");
    770         return(NULL);
    771     }
    772 
    773     return (cellCoord);
    774 }
    775 
    776 /*****************************************************************************
    777  *****************************************************************************/
    778 psSphere* pmCoordCellToSkyQuick(
    779     psSphere* outSphere,
    780     const psPlane* cellCoord,
    781     const pmCell* cell)
    782 {
    783     PS_ASSERT_PTR_NON_NULL(cellCoord, NULL);
    784     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    785     PS_ASSERT_PTR_NON_NULL(cell->toSky, NULL);
    786     psPlane outPlane;
    787     psPlane *rc;
    788     rc = psPlaneTransformApply(&outPlane, cell->toSky, cellCoord);
    789     if (rc == NULL) {
    790         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could transform cell coords to sky coords.\n");
    791         return(NULL);
    792     }
    793 
    794     psSphere *out = outSphere;
    795     if (out == NULL) {
    796         out = psSphereAlloc();
    797     }
    798     out->r = outPlane.y;
    799     out->d = outPlane.x;
    800 
    801     return(out);
    802 }
    803 
    804 /*****************************************************************************
    805  *****************************************************************************/
    806 psPlane* pmCoordSkyToCellQuick(
    807     psPlane* cellCoord,
    808     const psSphere* skyCoord,
    809     const pmCell* cell)
    810 {
    811     PS_ASSERT_PTR_NON_NULL(skyCoord, NULL);
    812     PS_ASSERT_PTR_NON_NULL(cell, NULL);
    813     PS_ASSERT_PTR_NON_NULL(cell->toSky, NULL);
    814     psPlane skyPlane;
    815     skyPlane.y = skyCoord->r;
    816     skyPlane.x = skyCoord->d;
    817 
    818     psPlane *rc = psPlaneTransformApply(cellCoord, cell->toSky, &skyPlane);
    819     if (rc == NULL) {
    820         psLogMsg(__func__, PS_LOG_WARN, "WARNING: could not transform sky to cell coords.\n");
    821     }
    822     return(cellCoord);
    823 }
    824360
    825361
     
    925461    return(numChips);
    926462}
     463
     464
     465bool pmCellSetWeights(pmCell *cell // Cell for which to set weights
     466                     )
     467{
     468    float gain = psMetadataLookupF32(NULL, cell->concepts, "CELL.GAIN"); // Cell gain
     469    float readnoise = psMetadataLookupF32(NULL, cell->concepts, "CELL.READNOISE"); // Cell read noise
     470    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section
     471
     472    p_pmHDU *hdu = cell->hdu;           // The data unit, containing the weight and mask originals
     473    if (!hdu) {
     474        pmChip *chip = cell->parent;    // The parent chip
     475        if (chip->hdu) {
     476            hdu = chip->hdu;
     477        } else {
     478            pmFPA *fpa = chip->parent;  // The parent FPA
     479            hdu = fpa->hdu;
     480            if (!hdu) {
     481                psError(PS_ERR_UNKNOWN, true, "Unable to find the HDU in the hierarchy!\n");
     482                return false;
     483            }
     484        }
     485    }
     486
     487    psArray *pixels = hdu->images;      // Array of images
     488    psArray *weights = hdu->weights;    // Array of weight images
     489    psArray *masks = hdu->masks;        // Array of mask images
     490    // Generate the weights and masks if required
     491    if (! weights) {
     492        weights = psArrayAlloc(pixels->n);
     493        for (int i = 0; i < pixels->n; i++) {
     494            psImage *image = pixels->data[i];
     495            weights->data[i] = psImageAlloc(image->numCols, image->numRows, PS_TYPE_F32);
     496            psImageInit(weights->data[i], 0.0);
     497        }
     498        hdu->weights = weights;
     499    }
     500    if (! masks) {
     501        masks = psArrayAlloc(pixels->n);
     502        for (int i = 0; i < pixels->n; i++) {
     503            psImage *image = pixels->data[i];
     504            masks->data[i] = psImageAlloc(image->numCols, image->numRows, PS_TYPE_U8);
     505            psImageInit(masks->data[i], 0);
     506        }
     507        hdu->masks = masks;
     508    }
     509
     510    // Set the pixels
     511    psArray *readouts = cell->readouts; // Array of readouts
     512    for (int i = 0; i < readouts->n; i++) {
     513        pmReadout *readout = readouts->data[i]; // The readout of interest
     514
     515        if (! readout->weight) {
     516            readout->weight = weights->data[i];
     517        }
     518        if (! readout->mask) {
     519            readout->mask = masks->data[i];
     520        }
     521
     522        // Mask is already set to 0
     523
     524        // Set weight image to the variance = g*f + rn^2
     525        psImage *image = psImageSubset(readout->image, *trimsec); // The pixels
     526        psImage *weight = psImageSubset(readout->weight, *trimsec); // The weight map
     527        psBinaryOp(weight, image, "*", psScalarAlloc(gain, PS_TYPE_F32));
     528        psBinaryOp(weight, weight, "+", psScalarAlloc(readnoise*readnoise, PS_TYPE_F32));
     529    }
     530
     531    return true;
     532}
     533
     534
  • branches/eam_rel9_p0/psModules/src/astrom/pmAstrometryObjects.c

    r5989 r6062  
    88*  @author EAM, IfA
    99*
    10 *  @version $Revision: 1.1.10.1 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2006-01-15 18:19:38 $
     10*  @version $Revision: 1.1.10.2 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2006-01-20 02:36:41 $
    1212*
    1313*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2020#include <math.h>
    2121#include "pslib.h"
    22 #include "pmAstrometry.h"
     22#include "pmFPA.h"
    2323#include "pmAstrometryObjects.h"
    2424
  • branches/eam_rel9_p0/psModules/src/astrom/pmAstrometryObjects.h

    r5674 r6062  
    88*  @author EAM, IfA
    99*
    10 *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    11 *  @date $Date: 2005-12-05 20:49:30 $
     10*  @version $Revision: 1.1.10.1 $ $Name: not supported by cvs2svn $
     11*  @date $Date: 2006-01-20 02:36:41 $
    1212*
    1313*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2121# include <unistd.h>   // for unlink
    2222# include <pslib.h>
    23 # include <pmAstrometry.h>
    24 
    25 /*
    26  * 
     23# include <pmFPA.h>
     24
     25/*
     26 *
    2727 * This structure specifies the coordinate of the detection in each of the
    2828 * four necessary coordinate frames: pix defines the position in the psReadout
     
    3535 * coordinates, while the reference detections will be projected to the other
    3636 * frames from the sky coordinates.
    37  * 
     37 *
    3838 * XXX: There are more members here than in the SDRS.
    39  * 
     39 *
    4040 */
    4141typedef struct
     
    5555
    5656/*
    57  * 
     57 *
    5858 * The pmAstromMatch structure defines the cross-correlation between two
    5959 * arrays. A single such data item specifies that item number pmAstromMatch.idx1
    6060 * in the first list corresponds to pmAstromMatch.idx2 in the second list.
    61  * 
     61 *
    6262 */
    6363typedef struct
     
    7070
    7171/*
    72  * 
     72 *
    7373 * XXX: Not in SDRS.
    74  * 
     74 *
    7575 */
    7676typedef struct
     
    8888
    8989/*
    90  * 
     90 *
    9191 * If the two sets of coordinates are expected to agree very well (ie, the
    9292 * current best-guess astrometric solution is quite close to the radius. The
     
    9797 * ASTROM.MATCH.RADIUS). The output consists an array of pmAstromMatch values,
    9898 * defined below.
    99  * 
     99 *
    100100 */
    101101psArray *pmAstromRadiusMatch(
     
    108108
    109109/*
    110  * 
     110 *
    111111 * This function accepts an array of pmAstromObj objects and rotates them by
    112112 * the given angle about the given center coordinate pCenter,qCenter in the Focal
    113113 * Plane Array coordinates.
    114  * 
     114 *
    115115 * XXX: This differs from the SDRS
    116  * 
     116 *
    117117 */
    118118/* SDRS
     
    132132
    133133/*
    134  * 
     134 *
    135135 * If the two sets of coordinates are not known to agree well, but the
    136136 * relative scale and approximate relative rotation is known, then a much faster
     
    147147 * allowing the procedure to scan over a range of rotations. We define the
    148148 * following function to apply this matching algorithm:
    149  * 
     149 *
    150150 * XXX: In the SDRS, this function is a pointer.
    151  * 
     151 *
    152152 */
    153153pmAstromStats pmAstromGridMatch(
     
    159159
    160160/*
    161  * 
     161 *
    162162 * The result of a pmAstromGridMatch may be used to modify the astrometry
    163163 * transformation information for a pmFPA image hierarchy structure. The result
     
    167167 * the linear terms of the pmFPA.toTangentPlane transformation. These two
    168168 * adjustments are made using the function:
    169  * 
     169 *
    170170 * XXX: This function name is different in the SDRS.
    171  * 
     171 *
    172172 */
    173173psPlaneTransform *pmAstromGridApply(
     
    178178
    179179/*
    180  * 
     180 *
    181181 * This function is identical to pmAstromGridMatch, but is valid for only a
    182182 * single relative rotation. The input config information need not contain any of
    183183 * the GRID.*.ANGLE entries (they will be ignored).
    184  * 
     184 *
    185185 * XXX: This function name is different in the SDRS.
    186  * 
     186 *
    187187 */
    188188/* in pmAstromGrid.c */
     
    195195
    196196/*
    197  * 
     197 *
    198198 * This function accepts the raw and reference source lists and the list of
    199199 * matched entries. It uses the matched list to determine a polynomial
     
    209209 * modifications to pmFPA.toTangentPlane incorporate the rotation component of
    210210 * the linear terms and the higher-order terms of the polynomial fits.
    211  * 
     211 *
    212212 * XXX: No prototype code.
    213  * 
     213 *
    214214 */
    215215bool pmAstromFitFPA(
     
    235235 *ASTROM.ORDER).  The result of this fit is a set of modifications of the
    236236 *components of the pmChip.toFPA transformation.
    237  * 
     237 *
    238238 * XXX: No prototype code.
    239  * 
     239 *
    240240 */
    241241bool pmAstromFitChip(
     
    249249
    250250/*
    251  * 
     251 *
    252252 * The following function determines the position residual, in the tangent
    253253 * plane, as a function of position in the focal plane, for a collection of raw
     
    255255 * the bin size over which the gradient is measured (keyword: ASTROM.GRAD.BOX).
    256256 * The function returns an array of pmAstromGradient structures, defined below.
    257  * 
     257 *
    258258 * XXX: No prototype code.
    259  * 
     259 *
    260260 */
    261261psArray pmAstromMeasureGradients(
     
    269269
    270270/*
    271  * 
     271 *
    272272 * The following data structure carries the information about the residual
    273273 * gradient of source positions in the tangent plane (pmAstromObj.TP) as a
    274274 * function of position in the focal plane (pmAstromObj.FP).
    275  * 
     275 *
    276276 */
    277277typedef struct
     
    285285
    286286/*
    287  * 
     287 *
    288288 * The gradient set measured above can be fitted with a pair of 2D
    289289 * polynomials. The resulting fits can then be related back to the implied
     
    292292 * supplied pmFPA structure. The configuration variable supplies the polynomial
    293293 * order (keyword: ASTROM.DISTORT.ORDER).
    294  * 
     294 *
    295295 * XXX: No prototype code.
    296  * 
     296 *
    297297 */
    298298psArray pmAstromFitDistortion(
     
    310310 ******************************************************************************/
    311311/*
    312  * 
    313  * 
    314  * 
    315  * 
    316  */
    317 
    318 
    319 /*
    320  * 
     312 *
     313 *
     314 *
     315 *
     316 */
     317
     318
     319/*
     320 *
    321321 * Allocates a pmAstromObj struct.
    322  * 
     322 *
    323323 */
    324324pmAstromObj *pmAstromObjAlloc (void);
     
    327327
    328328/*
    329  * 
     329 *
    330330 * Copies a pmAstromObj struct.
    331  * 
     331 *
    332332 */
    333333pmAstromObj *pmAstromObjCopy(
     
    338338
    339339/*
    340  * 
    341  * 
    342  * 
     340 *
     341 *
     342 *
    343343 */
    344344pmAstromMatch *pmAstromMatchAlloc(
     
    351351
    352352/*
    353  * 
    354  * 
    355  * 
     353 *
     354 *
     355 *
    356356 */
    357357psPlaneTransform *pmAstromMatchFit(
     
    366366
    367367/*
    368  * 
    369  * 
    370  * 
     368 *
     369 *
     370 *
    371371 */
    372372int pmAstromObjSortByFPX(
     
    378378
    379379/*
    380  * 
    381  * 
    382  * 
     380 *
     381 *
     382 *
    383383 */
    384384int pmAstromObjSortByMag(
  • branches/eam_rel9_p0/psModules/src/astrom/pmChipMosaic.c

    r5974 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmChipMosaic.h"
    77
     
    3434    // Get the maximum extent of the mosaic image
    3535    int xMin = INT_MAX;
    36     int xMax = 0;
     36    int xMax = - INT_MAX;
    3737    int yMin = INT_MAX;
    38     int yMax = 0;
     38    int yMax = - INT_MAX;
    3939    for (int i = 0; i < source->n; i++) {
    4040        psImage *image = source->data[i]; // The image of interest
     41        if (!image) {
     42            continue;
     43        }
    4144
    4245        assert(image->type.type == PS_TYPE_F32); // Only implemented for F32 images so far.
     
    7477    for (int i = 0; i < source->n; i++) {
    7578        psImage *image = source->data[i]; // The image of interest
     79        if (!image) {
     80            continue;
     81        }
    7682        if (xBinSource->data.S32[i] == xBinTarget && yBinSource->data.S32[i] == yBinTarget &&
    7783                xFlip->data.U8[i] == 0 && yFlip->data.U8[i] == 0) {
     
    107113
    108114// Mosaic a chip together into a single image
    109 static psImage *mosaicChip(pmChip *chip,// Chip to mosaic
    110                            int xBinChip, int yBinChip // Binning of mosaic image in x and y
    111                           )
     115static bool mosaicChip(pmChip *chip,// Chip to mosaic
     116                       int xBinChip, int yBinChip // Binning of mosaic image in x and y
     117                      )
    112118{
    113119
    114120    psArray *cells = chip->cells;       // The array of cells
    115121    psArray *images = psArrayAlloc(cells->n); // Array of images that will be mosaicked
     122    psArray *weights = psArrayAlloc(cells->n); // Array of weight images to be mosaicked
     123    psArray *masks = psArrayAlloc(cells->n); // Array of mask images to be mosaicked
    116124    psVector *x0 = psVectorAlloc(cells->n, PS_TYPE_S32); // Origin x coordinates
    117125    psVector *y0 = psVectorAlloc(cells->n, PS_TYPE_S32); // Origin y coordinates
     
    126134        x0->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0");
    127135        y0->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0");
     136        psTrace(__func__, 9, "Cell %d: x0=%d y0=%d\n", i, x0->data.S32[i], y0->data.S32[i]);
    128137        xBin->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN");
    129138        yBin->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN");
     
    159168        }
    160169        psImage *image = ((pmReadout*)readouts->data[0])->image; // The image to put into the mosaic
     170        psImage *weight = ((pmReadout*)readouts->data[0])->weight;
     171        psImage *mask = ((pmReadout*)readouts->data[0])->weight;
    161172        images->data[i] = psImageSubset(image, *trimsec); // Trimmed image
    162     }
    163 
     173        weights->data[i] = weight ? psImageSubset(weight, *trimsec) : NULL;
     174        masks->data[i] = mask ? psImageSubset(mask, *trimsec) : NULL;
     175    }
    164176    // Mosaic the images together and we're done
    165     psImage *mosaic = p_pmImageMosaic(images, xFlip, yFlip, xBin, yBin, xBinChip, yBinChip, x0, y0);
     177    psImage *image = p_pmImageMosaic(images, xFlip, yFlip, xBin, yBin, xBinChip, yBinChip, x0, y0);
     178    psImage *weight = p_pmImageMosaic(weights, xFlip, yFlip, xBin, yBin, xBinChip, yBinChip, x0, y0);
     179    psImage *mask = p_pmImageMosaic(masks, xFlip, yFlip, xBin, yBin, xBinChip, yBinChip, x0, y0);
    166180
    167181    // Clean up
     
    173187    psFree(yFlip);
    174188    psFree(images);
    175 
    176     return mosaic;
     189    psFree(weights);
     190    psFree(masks);
     191
     192    // Chop off all the component cells, and put in a new one
     193
     194    #if 1
     195    // XXX For the sake of getting something working, I am not going to bother with sorting out where
     196    // the double free is coming from.  I'm going to drop the pointers on the array and create a memory
     197    // leak.  We can clean this up later, when we're not under as much pressure.
     198    chip->cells = psArrayAlloc(0);
     199    #else
     200
     201    psArrayElementsFree(chip->cells);
     202    chip->cells = psArrayRealloc(chip->cells, 0);
     203    chip->cells->n = 0;
     204    #endif
     205
     206    pmCell *cell = pmCellAlloc(chip, NULL, __func__); // New cell
     207    cell->exists = true;
     208    cell->process = true;
     209    pmReadout *readout = pmReadoutAlloc(cell); // New readout
     210    readout->image = image;
     211    readout->weight = weight;
     212    readout->mask = mask;
     213    //psFree(readout);
     214
     215    return true;
    177216}
    178217
     
    193232
    194233        numChips++;
    195         psImage *mosaic = mosaicChip(chip, xBinChip, yBinChip); // Mosaic of cells within the chip
    196 
    197         // Chop off all the component cells, and put in a new one
    198         psArrayElementsFree(chip->cells);
    199         chip->cells = psArrayRealloc(chip->cells, 1);
    200         pmCell *cell = pmCellAlloc(chip, NULL, __func__); // New cell
    201         pmReadout *readout = pmReadoutAlloc(cell); // New readout
    202         readout->image = mosaic;
    203         psFree(readout);
     234        mosaicChip(chip, xBinChip, yBinChip); // Mosaic of cells within the chip
     235
    204236    }
    205237
  • branches/eam_rel9_p0/psModules/src/astrom/pmChipMosaic.h

    r5974 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77// Mosaic multiple images, with flips, binning and offsets
  • branches/eam_rel9_p0/psModules/src/astrom/pmConcepts.c

    r5975 r6062  
    9999
    100100// Set all registered concepts to blank value for the specified level
    101 static bool conceptsBlank(psMetadata *specs,  // One of the concepts specifications
     101static bool conceptsBlank(psMetadata **specs,  // One of the concepts specifications
    102102                          psMetadata *target // Place to install the concepts
    103103                         )
    104104{
    105105    pmConceptsInit();
    106     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator on specs
     106    psMetadataIterator *specsIter = psMetadataIteratorAlloc(*specs, PS_LIST_HEAD, NULL); // Iterator on specs
    107107    psMetadataItem *specItem = NULL;    // Item from the specs metadata
    108108    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     
    117117
    118118// Read all registered concepts for the specified level
    119 static bool conceptsRead(psMetadata *specs, // One of the concepts specifications
     119static bool conceptsRead(psMetadata **specs, // One of the concepts specifications
    120120                         pmFPA *fpa,    // The FPA
    121121                         pmChip *chip,  // The chip
     
    126126{
    127127    pmConceptsInit();
    128     psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator on specs
     128    psMetadataIterator *specsIter = psMetadataIteratorAlloc(*specs, PS_LIST_HEAD, NULL); // Iterator on specs
    129129    psMetadataItem *specItem = NULL;    // Item from the specs metadata
    130130    while ((specItem = psMetadataGetAndIncrement(specsIter))) {
     
    147147
    148148// Write all registered concepts for the specified level
    149 static bool conceptsWrite(psMetadata *specs, // One of the concepts specifications
     149static bool conceptsWrite(psMetadata **specs, // One of the concepts specifications
    150150                          pmFPA *fpa,   // The FPA
    151151                          pmChip *chip, // The chip
     
    160160    while ((item = psMetadataGetAndIncrement(iter))) {
    161161        const char *name = item->name;  // Name of the concept
    162         psMetadataItem *specItem = psMetadataLookup(specs, name); // Specification for the concept
     162        psMetadataItem *specItem = psMetadataLookup(*specs, name); // Specification for the concept
    163163        if (specItem) {
    164164            pmConceptSpec *spec = specItem->data.V; // The specification
     
    182182                       )
    183183{
    184     return conceptsBlank(conceptsFPA, fpa->concepts);
     184    psTrace("psModule.concepts", 5, "Blanking FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     185    return conceptsBlank(&conceptsFPA, fpa->concepts);
    185186}
    186187
     
    190191                      )
    191192{
    192     return conceptsRead(conceptsFPA, fpa, NULL, NULL, db, fpa->concepts);
     193    psTrace("psModule.concepts", 5, "Reading FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     194    return conceptsRead(&conceptsFPA, fpa, NULL, NULL, db, fpa->concepts);
    193195}
    194196
     
    198200                       )
    199201{
    200     return conceptsWrite(conceptsFPA, fpa, NULL, NULL, db, fpa->concepts);
     202    psTrace("psModule.concepts", 5, "Writing FPA concepts: %x %x\n", conceptsFPA, fpa->concepts);
     203    return conceptsWrite(&conceptsFPA, fpa, NULL, NULL, db, fpa->concepts);
    201204}
    202205
     
    205208                        )
    206209{
    207     return conceptsBlank(conceptsChip, chip->concepts);
     210    psTrace("psModule.concepts", 5, "Blanking chip concepts: %x %x\n", conceptsChip, chip->concepts);
     211    return conceptsBlank(&conceptsChip, chip->concepts);
    208212}
    209213
     
    213217                       )
    214218{
     219    psTrace("psModule.concepts", 5, "Reading chip concepts: %x %x\n", conceptsChip, chip->concepts);
    215220    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    216     return conceptsRead(conceptsChip, fpa, chip, NULL, db, chip->concepts);
     221    return conceptsRead(&conceptsChip, fpa, chip, NULL, db, chip->concepts);
    217222}
    218223
     
    222227                        )
    223228{
     229    psTrace("psModule.concepts", 5, "Writing chip concepts: %x %x\n", conceptsChip, chip->concepts);
    224230    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    225     return conceptsWrite(conceptsChip, fpa, chip, NULL, db, chip->concepts);
     231    return conceptsWrite(&conceptsChip, fpa, chip, NULL, db, chip->concepts);
    226232}
    227233
     
    230236                        )
    231237{
    232     return conceptsBlank(conceptsCell, cell->concepts);
     238    psTrace("psModule.concepts", 5, "Blanking cell concepts: %x %x\n", conceptsCell, cell->concepts);
     239    return conceptsBlank(&conceptsCell, cell->concepts);
    233240}
    234241
     
    238245                       )
    239246{
     247    psTrace("psModule.concepts", 5, "Writing cell concepts: %x %x\n", conceptsCell, cell->concepts);
    240248    pmChip *chip = cell->parent;        // Chip to which the cell belongs
    241249    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    242     return conceptsRead(conceptsCell, fpa, chip, cell, db, cell->concepts);
     250    return conceptsRead(&conceptsCell, fpa, chip, cell, db, cell->concepts);
    243251}
    244252
     
    248256                        )
    249257{
     258    psTrace("psModule.concepts", 5, "Writing cell concepts: %x %x\n", conceptsCell, cell->concepts);
    250259    pmChip *chip = cell->parent;        // Chip to which the cell belongs
    251260    pmFPA *fpa = chip->parent;          // FPA to which the chip belongs
    252     return conceptsWrite(conceptsCell, fpa, chip, cell, db, cell->concepts);
     261    return conceptsWrite(&conceptsCell, fpa, chip, cell, db, cell->concepts);
    253262}
    254263
     
    297306        conceptsChip = psMetadataAlloc();
    298307        init = true;
    299         // XXX Insert here the native Chip concepts
     308        // There are no standard concepts at the chip level to be installed
    300309    }
    301310    if (! conceptsCell) {
     
    397406        }
    398407
     408        // CELL.X0
     409        pmConceptRegister(psMetadataItemAllocS32("CELL.X0", "Position of (0,0) on the chip", 0),
     410                          (pmConceptReadFunc)pmConceptRead_CELL_X0,
     411                          (pmConceptWriteFunc)pmConceptWrite_CELL_X0, PM_CONCEPT_LEVEL_CELL);
     412
     413        // CELL.Y0
     414        pmConceptRegister(psMetadataItemAllocS32("CELL.Y0", "Position of (0,0) on the chip", 0),
     415                          (pmConceptReadFunc)pmConceptRead_CELL_Y0,
     416                          (pmConceptWriteFunc)pmConceptWrite_CELL_Y0, PM_CONCEPT_LEVEL_CELL);
     417
    399418    }
    400419
  • branches/eam_rel9_p0/psModules/src/astrom/pmConcepts.h

    r5975 r6062  
    44#include "pslib.h"
    55
    6 #include "pmAstrometry.h"
     6#include "pmFPA.h"
    77
    88// Function to call to read a concept
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsRead.c

    r5975 r6062  
    33#include "pslib.h"
    44
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmConceptsRead.h"
    77#include "psAdditionals.h"
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsRead.h

    r5975 r6062  
    22#define PM_CONCEPTS_READ_H
    33
    4 #include "pmAstrometry.h"
     4#include "pmFPA.h"
    55
    66psMetadataItem *pmConceptReadFromCamera(pmCell *cell, // The cell
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsStandard.c

    r5975 r6062  
    55#include "pmConceptsRead.h"
    66#include "pmConceptsWrite.h"
    7 #include "pmAstrometry.h"
     7#include "pmFPA.h"
    88#include "pmConceptsStandard.h"
    99#include "psAdditionals.h"
     
    987987{
    988988    psMetadataItem *x0item = psMetadataLookup(cell->concepts, "CELL.X0");
    989     x0item->data.S32 -= fortranCorr(fpa, "CELL.X0");
    990     return pmConceptWriteItem(fpa, chip, cell, db, x0item);
     989    psMetadataItem *newItem = psMetadataItemAllocS32("CELL.X0", "Position of (0,0) on the chip",
     990                              x0item->data.S32 - fortranCorr(fpa, "CELL.X0"));
     991    return pmConceptWriteItem(fpa, chip, cell, db, newItem);
    991992}
    992993
     
    994995{
    995996    psMetadataItem *y0item = psMetadataLookup(cell->concepts, "CELL.Y0");
    996     y0item->data.S32 -= fortranCorr(fpa, "CELL.Y0");
    997     return pmConceptWriteItem(fpa, chip, cell, db, y0item);
    998 }
    999 
     997    psMetadataItem *newItem = psMetadataItemAllocS32("CELL.Y0", "Position of (0,0) on the chip",
     998                              y0item->data.S32 - fortranCorr(fpa, "CELL.Y0"));
     999    return pmConceptWriteItem(fpa, chip, cell, db, newItem);
     1000}
     1001
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsStandard.h

    r5975 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77psMetadataItem *pmConceptRead_FPA_RA(pmFPA *fpa, pmChip *chip, pmCell *cell, psDB *db);
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsWrite.c

    r5975 r6062  
    33#include "pslib.h"
    44
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmConceptsRead.h"
    77#include "psAdditionals.h"
  • branches/eam_rel9_p0/psModules/src/astrom/pmConceptsWrite.h

    r5975 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77// Well, not really "write", but check to make sure it's there and matches
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPAConstruct.c

    r5974 r6062  
    33#include "pslib.h"
    44
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmFPAConstruct.h"
    77#include "psAdditionals.h"
    8 #include "pmFPAConceptsGet.h"
    98
    109//////////////////////////////////////////////////////////////////////////////////////////////////////////////
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPAConstruct.h

    r5796 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77// Read the contents of a FITS file (format specified by the camera configuration) into memory
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPARead.c

    r5974 r6062  
    33#include "pslib.h"
    44
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmFPARead.h"
    77#include "pmConcepts.h"
     
    9494    hdu->header = header;
    9595
    96     // XXX: Insert mask and weight reading here
     96    // Mask and weight not set yet
     97    hdu->weights = NULL;
     98    hdu->masks = NULL;
    9799
    98100    return true;
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPARead.h

    r5796 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77bool pmFPARead(pmFPA *fpa,              // FPA to read into
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPAWrite.c

    r5974 r6062  
    33#include "pslib.h"
    44
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66#include "pmFPARead.h"
    77#include "pmConcepts.h"
  • branches/eam_rel9_p0/psModules/src/astrom/pmFPAWrite.h

    r5796 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77bool pmFPAWrite(psFits *fits,           // FITS file to which to write
  • branches/eam_rel9_p0/psModules/src/astrom/pmReadout.c

    r5796 r6062  
    22#include "pslib.h"
    33
    4 #include "pmAstrometry.h"
     4#include "pmFPA.h"
    55
    66// Get the bias images for a readout, using the CELL.BIASSEC
  • branches/eam_rel9_p0/psModules/src/astrom/pmReadout.h

    r5796 r6062  
    33
    44#include "pslib.h"
    5 #include "pmAstrometry.h"
     5#include "pmFPA.h"
    66
    77// Get the bias sections for a specific readout
  • branches/eam_rel9_p0/psModules/src/detrend/pmFlatField.c

    r5795 r6062  
    2424 *  @author Ross Harman, MHPCC
    2525 *
    26  *  @version $Revision: 1.4.8.1 $ $Name: not supported by cvs2svn $
    27  *  @date $Date: 2005-12-17 03:18:39 $
     26 *  @version $Revision: 1.4.8.1.2.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2006-01-20 02:38:28 $
    2828 *
    2929 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    4444
    4545
    46 bool pmFlatField(pmReadout *in, pmReadout *mask, const pmReadout *flat)
     46bool pmFlatField(pmReadout *in, const pmReadout *flat)
    4747{
    48     // XXX: Not sure if this is correct.  Must consult with IfA.
    49     PS_ASSERT_PTR_NON_NULL(mask, false);
    5048    int i = 0;
    5149    int j = 0;
     
    8078        return false;
    8179    }
    82     inMask = mask->image;
     80    inMask = in->mask;
    8381
    8482    // Check input image and its mask are not larger than flat image
     
    9088        return false;
    9189    }
    92     if (inMask->numRows > flatImage->numRows || inMask->numCols > flatImage->numCols) {
     90    if (inMask && (inMask->numRows > flatImage->numRows || inMask->numCols > flatImage->numCols)) {
    9391        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    9492                 PS_ERRORTEXT_pmFlatField_SIZE_MASK_IMAGE,
     
    112110                 totOffRow, totOffCol, inImage->numRows, inImage->numCols);
    113111        return false;
    114     } else if(totOffRow>=inMask->numRows || totOffCol>=inMask->numCols) {
     112    } else if(inMask && (totOffRow>=inMask->numRows || totOffCol>=inMask->numCols)) {
    115113        psError( PS_ERR_BAD_PARAMETER_SIZE, true,
    116114                 PS_ERRORTEXT_pmFlatField_OFFSET_MASK_IMAGE,
     
    122120    inType = inImage->type.type;
    123121    flatType = flatImage->type.type;
    124     maskType = inMask->type.type;
    125122    if(PS_IS_PSELEMTYPE_COMPLEX(inType)) {
    126123        psError( PS_ERR_BAD_PARAMETER_TYPE, true,
     
    133130                 flatType);
    134131        return false;
    135     } else if(maskType != PS_TYPE_MASK) {
     132    } else if(inMask && inMask->type.type != PS_TYPE_MASK) {
    136133        psError( PS_ERR_BAD_PARAMETER_TYPE, true,
    137134                 PS_ERRORTEXT_pmFlatField_TYPE_MASK_IMAGE,
     
    153150            if(flatImage->data.TYPE[j][i] <= 0.0) {                                                          \
    154151                /* Negative or zero flat pixels shall be masked in input image as  PM_MASK_FLAT */           \
    155                 inMask->data.PS_TYPE_MASK_DATA[j][i] |= PM_MASK_FLAT;                                        \
     152                if (inMask) {                                                                                \
     153                    inMask->data.PS_TYPE_MASK_DATA[j][i] |= PM_MASK_FLAT;                                    \
     154                }                                                                                            \
    156155                flatImage->data.TYPE[j][i] = 0.0;                                                            \
    157156            }                                                                                                \
     
    160159    for(j = totOffRow; j < inImage->numRows; j++) {                                                          \
    161160        for(i = totOffCol; i < inImage->numCols; i++) {                                                      \
    162             if(!inMask->data.PS_TYPE_MASK_DATA[j][i]) {                                                      \
     161            if(inMask && !inMask->data.PS_TYPE_MASK_DATA[j][i]) {                                            \
    163162                /* Module shall divide the input image by the flat-fielded image */                          \
    164163                inImage->data.TYPE[j][i] /= flatImage->data.TYPE[j][i];                                      \
  • branches/eam_rel9_p0/psModules/src/detrend/pmFlatField.h

    r5795 r6062  
    2424 *  @author Ross Harman, MHPCC
    2525 *
    26  *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
    27  *  @date $Date: 2005-12-17 03:18:39 $
     26 *  @version $Revision: 1.2.8.1.2.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2006-01-20 02:38:28 $
    2828 *
    2929 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3131
    3232#include "pslib.h"
    33 #include "pmAstrometry.h"
     33#include "pmFPA.h"
    3434
    3535
     
    4343bool pmFlatField(
    4444    pmReadout *in,          ///< Readout with input image
    45     pmReadout *mask,        ///< Input image mask
    4645    const pmReadout *flat   ///< Readout with flat image
    4746);
  • branches/eam_rel9_p0/psModules/src/detrend/pmMaskBadPixels.h

    r5795 r6062  
    2424 *  @author Ross Harman, MHPCC
    2525 *
    26  *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
    27  *  @date $Date: 2005-12-17 03:18:39 $
     26 *  @version $Revision: 1.2.8.1.2.1 $ $Name: not supported by cvs2svn $
     27 *  @date $Date: 2006-01-20 02:38:28 $
    2828 *
    2929 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3131
    3232#include "pslib.h"
    33 #include "pmAstrometry.h"
     33#include "pmFPA.h"
    3434
    3535/** Mask values */
  • branches/eam_rel9_p0/psModules/src/detrend/pmNonLinear.h

    r5795 r6062  
    1010 *  @author GLG, MHPCC
    1111 *
    12  *  @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2005-12-17 03:18:39 $
     12 *  @version $Revision: 1.2.8.1.2.1 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2006-01-20 02:38:28 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2121
    2222#include "pslib.h"
    23 #include "pmAstrometry.h"
     23#include "pmFPA.h"
    2424
    2525pmReadout *pmNonLinearityPolynomial(pmReadout *in,
  • branches/eam_rel9_p0/psModules/src/imcombine/pmReadoutCombine.h

    r5865 r6062  
    55 *  @author GLG, MHPCC
    66 *
    7  *  @version $Revision: 1.2.10.1 $ $Name: not supported by cvs2svn $
    8  *  @date $Date: 2005-12-31 04:34:52 $
     7 *  @version $Revision: 1.2.10.2 $ $Name: not supported by cvs2svn $
     8 *  @date $Date: 2006-01-20 02:38:28 $
    99 *
    1010 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2323#include "pslib.h"
    2424#include "psConstants.h"
    25 #include "pmAstrometry.h"
     25#include "pmFPA.h"
    2626
    2727typedef struct
  • branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractBias.c

    r5867 r6062  
    1111 *  @author GLG, MHPCC
    1212 *
    13  *  @version $Revision: 1.6.8.1.2.1 $ $Name: not supported by cvs2svn $
    14  *  @date $Date: 2005-12-31 04:35:58 $
     13 *  @version $Revision: 1.6.8.1.2.2 $ $Name: not supported by cvs2svn $
     14 *  @date $Date: 2006-01-20 02:38:28 $
    1515 *
    1616 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2222#endif
    2323
     24#include <assert.h>
    2425#include "pmSubtractBias.h"
    2526
    2627#define PM_SUBTRACT_BIAS_POLYNOMIAL_ORDER 2
    2728#define PM_SUBTRACT_BIAS_SPLINE_ORDER 3
     29
     30
     31#define MAX(a,b) ((a) > (b) ? (a) : (b))
     32#define MIN(a,b) ((a) < (b) ? (a) : (b))
     33
    2834
    2935// XXX: put these in psConstants.h
     
    5662}\
    5763
     64
     65void overscanOptionsFree(pmOverscanOptions *options)
     66{
     67    psFree(options->stat);
     68    psFree(options->poly);
     69    psFree(options->spline);
     70}
     71
     72pmOverscanOptions *pmOverscanOptionsAlloc(bool single, pmFit fitType, unsigned int order, psStats *stat)
     73{
     74    pmOverscanOptions *opts = psAlloc(sizeof(pmOverscanOptions));
     75    psMemSetDeallocator(opts, (psFreeFunc)overscanOptionsFree);
     76
     77    // Inputs
     78    opts->single = single;
     79    opts->fitType = fitType;
     80    opts->order = order;
     81    opts->stat = psMemIncrRefCounter(stat);
     82
     83    // Outputs
     84    opts->poly = NULL;
     85    opts->spline = NULL;
     86
     87    return opts;
     88}
     89
     90
    5891/******************************************************************************
    5992psSubtractFrame(): this routine will take as input a readout for the input
     
    6194place from the input image.
    6295*****************************************************************************/
    63 static pmReadout *SubtractFrame(pmReadout *in,
    64                                 const pmReadout *bias)
    65 {
    66     psS32 i;
    67     psS32 j;
    68 
    69     if (bias == NULL) {
    70         psLogMsg(__func__, PS_LOG_NOTE,
    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++) {
    87             in->image->data.F32[i][j]-=
    88                 bias->image->data.F32[i+in->row0-bias->row0][j+in->col0-bias->col0];
    89             if ((in->mask != NULL) && (bias->mask != NULL)) {
    90                 (in->mask->data.U8[i][j])|=
    91                     bias->mask->data.U8[i+in->row0-bias->row0][j+in->col0-bias->col0];
     96static bool SubtractFrame(pmReadout *in,// Input readout
     97                          const pmReadout *sub, // Readout to be subtracted from input
     98                          float scale   // Scale to apply before subtracting
     99                         )
     100{
     101    assert(in);
     102    assert(sub);
     103
     104    // Get the trim sections
     105    psRegion *inTrimsec = psMetadataLookupPtr(NULL, in->parent->concepts, "CELL.TRIMSEC");
     106    psRegion *subTrimsec = psMetadataLookupPtr(NULL, sub->parent->concepts, "CELL.TRIMSEC");
     107    psImage *inImage = psImageSubset(in->image, *inTrimsec); // The input image
     108    psImage *subImage = psImageSubset(sub->image, *subTrimsec); // The image to be subtracted
     109    psImage *inMask = in->mask ? psImageSubset(in->mask, *inTrimsec) : NULL; // The input mask
     110    psImage *subMask = sub->mask ? psImageSubset(sub->mask, *subTrimsec) : NULL; // The input mask
     111
     112    // Offsets of the cells
     113    int x0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.X0");
     114    int y0in = psMetadataLookupS32(NULL, in->parent->concepts, "CELL.Y0");
     115    int x0sub = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.X0");
     116    int y0sub = psMetadataLookupS32(NULL, sub->parent->concepts, "CELL.Y0");
     117
     118    if ((inImage->numCols + x0in - x0sub) > subImage->numCols) {
     119        psError(PS_ERR_UNKNOWN, true, "Image does not have enough columns for subtraction.\n");
     120        return false;
     121    }
     122    if ((inImage->numRows + y0in - y0sub) > subImage->numRows) {
     123        psError(PS_ERR_UNKNOWN, true, "Image does not have enough rows for subtraction.\n");
     124        return false;
     125    }
     126
     127    if (scale == 1.0) {
     128        for (int i = 0; i < inImage->numRows; i++) {
     129            for (int j = 0; j < inImage->numCols; j++) {
     130                inImage->data.F32[i][j] -= subImage->data.F32[i+y0in-y0sub][j+x0in-x0sub];
     131                if (inMask && subMask) {
     132                    inMask->data.U8[i][j] |= subMask->data.U8[i+y0in-y0sub][j+x0in-x0sub];
     133                }
    92134            }
    93135        }
    94     }
    95 
    96     return(in);
    97 }
    98 
     136    } else {
     137        for (int i = 0; i < inImage->numRows; i++) {
     138            for (int j = 0; j < inImage->numCols; j++) {
     139                inImage->data.F32[i][j] -= subImage->data.F32[i+y0in-y0sub][j+x0in-x0sub] * scale;
     140                if (inMask && subMask) {
     141                    inMask->data.U8[i][j] |= subMask->data.U8[i+y0in-y0sub][j+x0in-x0sub];
     142                }
     143            }
     144        }
     145    }
     146
     147    return true;
     148}
     149
     150
     151#if 0
    99152/******************************************************************************
    100153ImageSubtractScalar(): subtract a scalar from the input image.
     
    114167    return(image);
    115168}
     169#endif
    116170
    117171/******************************************************************************
     
    180234
    181235
     236#if 0
    182237/******************************************************************************
    183238ScaleOverscanVector(): this routine takes as input an arbitrary vector,
     
    283338}
    284339
     340#endif
     341
     342// Produce an overscan vector from an array of pixels
     343static psVector *overscanVector(pmOverscanOptions *overscanOpts, // Overscan options
     344                                const psArray *pixels, // Array of vectors containing the pixel values
     345                                psStats *myStats // Statistic to use in reducing the overscan
     346                               )
     347{
     348    // Reduce the overscans
     349    psVector *reduced = psVectorAlloc(pixels->n, PS_TYPE_F32); // Overscan for each row
     350    psVector *ordinate = psVectorAlloc(pixels->n, PS_TYPE_F32); // Ordinate
     351    psVector *mask = psVectorAlloc(pixels->n, PS_TYPE_U8); // Mask for fitting
     352    for (int i = 0; i < pixels->n; i++) {
     353        psVector *values = pixels->data[i]; // Vector with overscan values
     354        if (values->n > 0) {
     355            mask->data.U8[i] = 0;
     356            ordinate->data.F32[i] = 2.0*(float)i/(float)pixels->n - 1.0; // Scale to [-1,1]
     357            psVectorStats(myStats, values, NULL, NULL, 0);
     358            double reducedVal = NAN; // Result of statistics
     359            if (! p_psGetStatValue(myStats, &reducedVal)) {
     360                psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result "
     361                        "of statistics on row %d.\n", i);
     362                return NULL;
     363            }
     364            reduced->data.F32[i] = reducedVal;
     365            //            printf("%f ", reducedVal);
     366        } else if (overscanOpts->fitType == PM_FIT_NONE) {
     367            psError(PS_ERR_UNKNOWN, true, "The overscan is not supplied for all points on the "
     368                    "image, and no fit is requested.\n");
     369            return NULL;
     370        } else {
     371            // We'll fit this one out
     372            mask->data.U8[i] = 1;
     373        }
     374
     375        //        printf("\n");
     376    }
     377
     378    // Fit the overscan, if required
     379    switch (overscanOpts->fitType) {
     380    case PM_FIT_NONE:
     381        // No fitting --- that's easy.
     382        break;
     383    case PM_FIT_POLY_ORD:
     384        overscanOpts->poly = psPolynomial1DAlloc(overscanOpts->order, PS_POLYNOMIAL_ORD);
     385        overscanOpts->poly = psVectorFitPolynomial1D(overscanOpts->poly, mask, 1, reduced, NULL,
     386                             ordinate);
     387        psFree(reduced);
     388        reduced = psPolynomial1DEvalVector(overscanOpts->poly, ordinate);
     389        break;
     390    case PM_FIT_POLY_CHEBY:
     391        overscanOpts->poly = psPolynomial1DAlloc(overscanOpts->order, PS_POLYNOMIAL_CHEB);
     392        overscanOpts->poly = psVectorFitPolynomial1D(overscanOpts->poly, mask, 1, reduced, NULL,
     393                             ordinate);
     394        psFree(reduced);
     395        reduced = psPolynomial1DEvalVector(overscanOpts->poly, ordinate);
     396        break;
     397    case PM_FIT_SPLINE:
     398        // XXX I don't think psSpline1D is up to scratch yet --- it has no mask, and requires an
     399        // input spline
     400        overscanOpts->spline = psVectorFitSpline1D(reduced, ordinate);
     401        psFree(reduced);
     402        reduced = psSpline1DEvalVector(overscanOpts->spline, ordinate);
     403        break;
     404    default:
     405        psError(PS_ERR_UNKNOWN, true, "Unknown value for the fitting type: %d\n", overscanOpts->fitType);
     406        return NULL;
     407        break;
     408    }
     409
     410    psFree(ordinate);
     411    psFree(mask);
     412
     413    return reduced;
     414}
     415
     416
     417
    285418/******************************************************************************
    286419XXX: The SDRS does not specify type support.  F32 is implemented here.
    287420 *****************************************************************************/
    288 pmReadout *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)
     421pmReadout *pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
     422                          const pmReadout *bias, const pmReadout *dark)
    296423{
    297424    psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4,
     
    301428    PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL);
    302429
    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");
     430    pmCell *cell = in->parent;      // The parent cell
     431    psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // The trim region
     432    psImage *image = psImageSubset(in->image, *trimsec); // The image corresponding to the trim region
     433
     434    // Overscan processing
     435    if (overscanOpts) {
     436        // Check for an unallowable pmFit.
     437        if (overscanOpts->fitType != PM_FIT_NONE && overscanOpts->fitType != PM_FIT_POLY_ORD &&
     438                overscanOpts->fitType != PM_FIT_POLY_CHEBY && overscanOpts->fitType != PM_FIT_SPLINE) {
     439            psError(PS_ERR_UNKNOWN, true, "Invalid fit type (%d).  Returning original image.\n", overscanOpts->fitType);
     440            return(in);
     441        }
     442
     443        // Get the list of overscans
     444        psList *overscanRegions = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC");
     445        psList *overscans = psListAlloc(NULL); // List of the overscan images
     446        psListIterator *iter = psListIteratorAlloc(overscanRegions, PS_LIST_HEAD, false); // Iterator
     447        psRegion *biassec = NULL;       // A BIASSEC region from the list
     448        while ((biassec = psListGetAndIncrement(iter))) {
     449            psImage *overscan = psImageSubset(in->image, *biassec);
     450            psListAdd(overscans, PS_LIST_TAIL, overscan);
     451            psFree(overscan);
     452        }
     453        psFree(iter);
     454
     455        psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); // A new psStats, to avoid clobbering original
     456        myStats->options = GenNewStatOptions(overscanOpts->stat);
     457
     458        // Reduce all overscan pixels to a single value
     459        if (overscanOpts->single) {
     460            psVector *pixels = psVectorAlloc(0, PS_TYPE_F32);
     461            pixels->n = 0;
     462            psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
     463            psImage *overscan = NULL;   // Overscan image from iterator
     464            while ((overscan = psListGetAndIncrement(iter))) {
     465                int index = pixels->n;  // Index
     466                pixels = psVectorRealloc(pixels, pixels->n + overscan->numRows * overscan->numCols);
     467                // XXX Reimplement with memcpy
     468                for (int i = 0; i < overscan->numRows; i++) {
     469                    for (int j = 0; j < overscan->numCols; j++) {
     470                        pixels->data.F32[index++] = overscan->data.F32[i][j];
     471                    }
     472                }
     473
     474            }
     475            psFree(iter);
     476
     477            (void)psVectorStats(myStats, pixels, NULL, NULL, 0);
     478            double reduced = NAN;     // Result of statistics
     479            if (! p_psGetStatValue(myStats, &reduced)) {
     480                psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation.  Returning input image.\n");
    398481                return(in);
    399482            }
    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);
     483            (void)psBinaryOp(image, image, "-", psScalarAlloc((float)reduced, PS_TYPE_F32));
     484        } else {
     485
     486            // We do the regular overscan subtraction
     487            bool readRows = psMetadataLookupBool(NULL, cell->concepts, "CELL.READDIR"); // Read direction
     488
     489            if (readRows) {
     490                // The read direction is rows
     491                psArray *pixels = psArrayAlloc(image->numRows); // Array of vectors containing pixels
     492                for (int i = 0; i < pixels->n; i++) {
     493                    psVector *values = psVectorAlloc(0, PS_TYPE_F32);
     494                    values->n = 0;
     495                    pixels->data[i] = values;
     496                }
     497
     498                // Pull the pixels out into the vectors
     499                psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
     500                psImage *overscan = NULL; // Overscan image from iterator
     501                while ((overscan = psListGetAndIncrement(iter))) {
     502                    int diff = image->row0 - overscan->row0; // Offset between the two regions
     503                    for (int i = MAX(0,diff); i < MIN(image->numRows, overscan->numRows + diff); i++) {
     504                        // i is row on overscan
     505                        // XXX Reimplement with memcpy
     506                        psVector *values = pixels->data[i];
     507                        int index = values->n; // Index in the vector
     508                        values = psVectorRealloc(values, values->n + overscan->numCols);
     509                        for (int j = 0; j < overscan->numCols; j++) {
     510                            values->data.F32[index++] = overscan->data.F32[i][j];
     511                        }
     512                        values->n += overscan->numCols;
     513                        pixels->data[i] = values; // Update the pointer in case it's moved
     514                    }
     515                }
     516
     517                // Reduce the overscans
     518                psVector *reduced = overscanVector(overscanOpts, pixels, myStats);
     519                if (! reduced) {
     520                    return in;
     521                }
     522
     523                // Subtract row by row
     524                for (int i = 0; i < image->numRows; i++) {
     525                    for (int j = 0; j < image->numCols; j++) {
     526                        image->data.F32[i][j] -= reduced->data.F32[i];
     527                    }
     528                }
     529                psFree(reduced);
     530
     531            } else {
     532                // The read direction is columns
     533                psArray *pixels = psArrayAlloc(image->numCols); // Array of vectors containing pixels
     534                for (int i = 0; i < pixels->n; i++) {
     535                    psVector *values = psVectorAlloc(0, PS_TYPE_F32);
     536                    values->n = 0;
     537                    pixels->data[i] = values;
     538                }
     539
     540                // Pull the pixels out into the vectors
     541                psListIterator *iter = psListIteratorAlloc(overscans, PS_LIST_HEAD, false); // Iterator
     542                psImage *overscan = NULL; // Overscan image from iterator
     543                while ((overscan = psListGetAndIncrement(iter))) {
     544                    int diff = image->col0 - overscan->col0; // Offset between the two regions
     545                    for (int i = MAX(0,diff); i < MIN(image->numCols, overscan->numCols + diff); i++) {
     546                        // i is column on overscan
     547                        // XXX Reimplement with memcpy
     548                        psVector *values = pixels->data[i];
     549                        int index = values->n; // Index in the vector
     550                        values = psVectorRealloc(values, values->n + overscan->numRows);
     551                        for (int j = 0; j < overscan->numRows; j++) {
     552                            values->data.F32[index++] = overscan->data.F32[i][j];
     553                        }
     554                        values->n += overscan->numRows;
     555                        pixels->data[i] = values; // Update the pointer in case it's moved
     556                    }
     557                }
     558
     559                // Reduce the overscans
     560                psVector *reduced = overscanVector(overscanOpts, pixels, myStats);
     561                if (! reduced) {
     562                    return in;
     563                }
     564
     565                // Subtract column by column
     566                for (int i = 0; i < image->numCols; i++) {
     567                    for (int j = 0; j < image->numRows; j++) {
     568                        image->data.F32[j][i] -= reduced->data.F32[i];
     569                    }
     570                }
     571                psFree(reduced);
    403572            }
    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 
    532         //
    533         // Re-bin the overscan vector (change its length).
    534         //
    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.
    579         //
    580 
    581 
    582         //
    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             }
    646         } else {
    647             //
    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 
    681     psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4,
    682             "---- pmSubtractBias() exit ----\n");
    683 
    684     if (bias != NULL) {
    685         return(SubtractFrame(in, bias));
    686     }
    687     return(in);
    688 }
    689 
    690 
     573        }
     574        psFree(myStats);
     575        psFree(overscans);
     576    } // End of overscan subtraction
     577
     578    // Bias frame subtraction
     579    if (bias) {
     580        SubtractFrame(in, bias, 1.0);
     581    }
     582
     583    if (dark) {
     584        // Get the scaling
     585        float inTime = psMetadataLookupF32(NULL, in->parent->concepts, "CELL.DARKTIME");
     586        float darkTime = psMetadataLookupF32(NULL, dark->parent->concepts, "CELL.DARKTIME");
     587        SubtractFrame(in, dark, inTime/darkTime);
     588    }
     589
     590    return in;
     591}
     592
     593
  • branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractBias.h

    r5866 r6062  
    1111 *  @author GLG, MHPCC
    1212 *
    13  *  @version $Revision: 1.4.8.1.2.1 $ $Name: not supported by cvs2svn $
    14  *  @date $Date: 2005-12-31 04:35:36 $
     13 *  @version $Revision: 1.4.8.1.2.2 $ $Name: not supported by cvs2svn $
     14 *  @date $Date: 2006-01-20 02:38:28 $
    1515 *
    1616 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2929#include "pslib.h"
    3030
    31 #include "pmAstrometry.h"
     31#include "pmFPA.h"
    3232
    3333typedef enum {
     
    4040
    4141typedef enum {
    42     PM_FIT_NONE,                              ///< No fit
    43     PM_FIT_POLYNOMIAL,                        ///< Fit polynomial
    44     PM_FIT_SPLINE                             ///< Fit cubic splines
     42    PM_FIT_NONE,                        ///< No fit
     43    PM_FIT_POLY_ORD,                    ///< Fit ordinary polynomial
     44    PM_FIT_POLY_CHEBY,                  ///< Fit Chebyshev polynomial
     45    PM_FIT_SPLINE                       ///< Fit cubic splines
    4546} pmFit;
    4647
     48typedef struct
     49{
     50    // Inputs
     51    bool single;                // Reduce all overscan regions to a single value?
     52    pmFit fitType;              // Type of fit to overscan
     53    unsigned int order;         // Order of polynomial, or number of spline pieces
     54    psStats *stat;              // Statistic to use when reducing the minor direction
     55    // Outputs
     56    psPolynomial1D *poly;       // Result of polynomial fit
     57    psSpline1D *spline;         // Result of spline fit
     58}
     59pmOverscanOptions;
     60
     61pmOverscanOptions *pmOverscanOptionsAlloc(bool single, pmFit fitType, unsigned int order, psStats *stat);
     62
     63pmReadout *pmSubtractBias(pmReadout *in, pmOverscanOptions *overscanOpts,
     64                          const pmReadout *bias, const pmReadout *dark);
     65
     66#if 0
    4767pmReadout *pmSubtractBias(pmReadout *in,                ///< The input pmReadout image
    4868                          void *fitSpec,                ///< A polynomial or spline, defining the fit type.
     
    5373                          pmFit fit,                    ///< PM_FIT_SPLINE, PM_FIT_POLYNOMIAL, or PM_FIT_NONE
    5474                          const pmReadout *bias);       ///< A possibly NULL bias pmReadout which is to be subtracted
     75#endif
    5576
    5677#endif
  • branches/eam_rel9_p0/psModules/src/imsubtract/pmSubtractSky.h

    r5170 r6062  
    66 *  @author GLG, MHPCC
    77 *
    8  *  @version $Revision: 1.1 $ $Name: not supported by cvs2svn $
    9  *  @date $Date: 2005-09-28 20:43:52 $
     8 *  @version $Revision: 1.1.18.1 $ $Name: not supported by cvs2svn $
     9 *  @date $Date: 2006-01-20 02:38:28 $
    1010 *
    1111 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2323#include<math.h>
    2424#include "pslib.h"
    25 #include "pmAstrometry.h"
     25#include "pmFPA.h"
    2626
    2727// XXX: this is pmFit in pmSubtractBias.c, named psFit here.
  • branches/eam_rel9_p0/psModules/src/objects/pmObjects.h

    r5990 r6062  
    44 * images is one of the critical tasks of the IPP or any astronomical software
    55 * system. This file will define structures and functions related to the task
    6  * of source detection and measurement. The elements defined in this section 
     6 * of source detection and measurement. The elements defined in this section
    77 * are generally low-level components which can be connected together to
    88 * construct a complete object measurement suite.
     
    1010 *  @author GLG, MHPCC
    1111 *
    12  *  @version $Revision: 1.4.4.3 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2006-01-15 18:21:19 $
     12 *  @version $Revision: 1.4.4.4 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2006-01-20 02:38:28 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2727#include <math.h>
    2828#include "pslib.h"
    29 #include "pmAstrometry.h"
     29#include "pmFPA.h"
    3030/**
    3131 * In the object analysis process, we will use specific mask values to mark the
     
    4545
    4646/** pmPeakType
    47  * 
     47 *
    4848 *  A peak pixel may have several features which may be determined when the
    4949 *  peak is found or measured. These are specified by the pmPeakType enum.
     
    5252 *  edge. The PM_PEAK_FLAT represents a peak pixel which has more than a specific
    5353 *  number of neighbors at the same value, within some tolarence:
    54  * 
     54 *
    5555 */
    5656typedef enum {
     
    6363
    6464/** pmPeak data structure
    65  * 
     65 *
    6666 *  A source has the capacity for several types of measurements. The
    6767 *  simplest measurement of a source is the location and flux of the peak pixel
    6868 *  associated with the source:
    69  * 
     69 *
    7070 */
    7171typedef struct
     
    8080
    8181/** pmMoments data structure
    82  * 
     82 *
    8383 * One of the simplest measurements which can be made quickly for an object
    8484 * are the object moments. We specify a structure to carry the moment information
    8585 * for a specific source:
    86  * 
     86 *
    8787 */
    8888typedef struct
     
    103103
    104104/** pmPSFClump data structure
    105  * 
     105 *
    106106 * A collection of object moment measurements can be used to determine
    107107 * approximate object classes. The key to this analysis is the location and
    108108 * statistics (in the second-moment plane,
    109  * 
     109 *
    110110 */
    111111typedef struct
     
    130130
    131131/** pmModel data structure
    132  * 
     132 *
    133133 * Every source may have two types of models: a PSF model and a EXT (extended-source)
    134134 * model. The PSF model represents the best fit of the image PSF to the specific
     
    136136 * object by the PSF, not by the fit. The EXT model represents the best fit of
    137137 * the given model to the object, with all shape parameters floating in the fit.
    138  * 
     138 *
    139139 */
    140140typedef struct
     
    152152
    153153/** pmSourceType enumeration
    154  * 
     154 *
    155155 * A given source may be identified as most-likely to be one of several source
    156156 * types. The pmSource entry pmSourceType defines the current best-guess for this
    157157 * source.
    158  * 
     158 *
    159159 * XXX: The values given below are currently illustrative and will require
    160160 * some modification as the source classification code is developed. (TBD)
    161  * 
     161 *
    162162 */
    163163typedef enum {
     
    186186
    187187/** pmSource data structure
    188  * 
     188 *
    189189 *  This source has the capacity for several types of measurements. The
    190190 *  simplest measurement of a source is the location and flux of the peak pixel
    191191 *  associated with the source:
    192  * 
     192 *
    193193 */
    194194typedef struct
     
    224224
    225225/** pmMomentsAlloc()
    226  * 
     226 *
    227227 */
    228228pmMoments *pmMomentsAlloc();
     
    230230
    231231/** pmModelAlloc()
    232  * 
     232 *
    233233 */
    234234pmModel *pmModelAlloc(pmModelType type);
     
    236236
    237237/** pmSourceAlloc()
    238  * 
     238 *
    239239 */
    240240pmSource  *pmSourceAlloc();
     
    242242
    243243/** pmFindVectorPeaks()
    244  * 
     244 *
    245245 * Find all local peaks in the given vector above the given threshold. A peak
    246246 * is defined as any element with a value greater than its two neighbors and with
     
    256256 * a vector containing the coordinates (element number) of the detected peaks
    257257 * (type psU32).
    258  * 
     258 *
    259259 */
    260260psVector *pmFindVectorPeaks(
     
    265265
    266266/** pmFindImagePeaks()
    267  * 
     267 *
    268268 * Find all local peaks in the given image above the given threshold. This
    269269 * function should find all row peaks using pmFindVectorPeaks, then test each row
     
    276276 * peaks at the (+x,+y) corner. When selecting the peaks, their type must also be
    277277 * set. The result of this function is an array of pmPeak entries.
    278  * 
     278 *
    279279 */
    280280psArray *pmFindImagePeaks(
     
    285285
    286286/** pmCullPeaks()
    287  * 
     287 *
    288288 * Eliminate peaks from the psList that have a peak value above the given
    289289 * maximum, or fall outside the valid region.
    290  * 
     290 *
    291291 */
    292292psList *pmCullPeaks(
     
    298298
    299299/** pmPeaksSubset()
    300  * 
     300 *
    301301 * Create a new peaks array, removing certain types of peaks from the input
    302302 * array of peaks based on the given criteria. Peaks should be eliminated if they
     
    304304 * the valid region.  The result of the function is a new array with a reduced
    305305 * number of peaks.
    306  * 
     306 *
    307307 */
    308308psArray *pmPeaksSubset(
     
    314314
    315315/** pmSourceDefinePixels()
    316  * 
     316 *
    317317 * Define psImage subarrays for the source located at coordinates x,y on the
    318318 * image set defined by readout. The pixels defined by this operation consist of
     
    326326 * example). This function should be used to define a region of interest around a
    327327 * source, including both source and sky pixels.
    328  * 
     328 *
    329329 * XXX: must code this.
    330  * 
     330 *
    331331 */
    332332// XXX: Uncommenting the pmReadout causes compile errors.
     
    341341
    342342/** pmSourceLocalSky()
    343  * 
     343 *
    344344 * Measure the local sky in the vicinity of the given source. The Radius
    345345 * defines the square aperture in which the moments will be measured. This
     
    351351 * This function allocates the pmMoments structure. The resulting sky is used to
    352352 * set the value of the pmMoments.sky element of the provided pmSource structure.
    353  * 
     353 *
    354354 */
    355355bool pmSourceLocalSky(
     
    361361
    362362/** pmSourceMoments()
    363  * 
     363 *
    364364 * Measure source moments for the given source, using the value of
    365365 * source.moments.sky provided as the local background value and the peak
     
    368368 * are measured within the given circular radius of the source.peak coordinates.
    369369 * The return value indicates the success (TRUE) of the operation.
    370  * 
     370 *
    371371 */
    372372bool pmSourceMoments(
     
    377377
    378378/** pmSourcePSFClump()
    379  * 
     379 *
    380380 * We use the source moments to make an initial, approximate source
    381381 * classification, and as part of the information needed to build a PSF model for
     
    386386 * similar. The function returns a pmPSFClump structure, representing the
    387387 * centroid and size of the clump in the sigma_x, sigma_y second-moment plane.
    388  * 
     388 *
    389389 * The goal is to identify and characterize the stellar clump within the
    390390 * sigma_x, sigma_y second-moment plane.  To do this, an image is constructed to
     
    397397 *  * used to calculate the median and standard deviation of the sigma_x, sigma_y
    398398 * values. These resulting values are returned via the pmPSFClump structure.
    399  * 
     399 *
    400400 * The return value indicates the success (TRUE) of the operation.
    401  * 
     401 *
    402402 * XXX: Limit the S/N of the candidate sources (part of Metadata)? (TBD).
    403403 * XXX: Save the clump parameters on the Metadata (TBD)
    404  * 
     404 *
    405405 */
    406406pmPSFClump pmSourcePSFClump(
     
    411411
    412412/** pmSourceRoughClass()
    413  * 
     413 *
    414414 * Based on the specified data values, make a guess at the source
    415415 * classification. The sources are provides as a psArray of pmSource entries.
     
    418418 * can be extracted from the metadata using the given keywords. Except as noted,
    419419 * the data type for these parameters are psF32.
    420  * 
     420 *
    421421 */
    422422bool pmSourceRoughClass(
     
    428428
    429429/** pmSourceModelGuess()
    430  * 
     430 *
    431431 * Convert available data to an initial guess for the given model. This
    432432 * function allocates a pmModel entry for the pmSource structure based on the
     
    434434 * are specified for each model below. The guess values are placed in the model
    435435 * parameters. The function returns TRUE on success or FALSE on failure.
    436  * 
     436 *
    437437 */
    438438pmModel *pmSourceModelGuess(
     
    443443
    444444/** pmContourType
    445  * 
     445 *
    446446 * Only one type is defined at present.
    447  * 
     447 *
    448448 */
    449449typedef enum {
     
    455455
    456456/** pmSourceContour()
    457  * 
     457 *
    458458 * Find points in a contour for the given source at the given level. If type
    459459 * is PM_CONTOUR_CRUDE, the contour is found by starting at the source peak,
     
    465465 * This function may be used as part of the model guess inputs.  Other contour
    466466 * types may be specified in the future for more refined contours (TBD)
    467  * 
     467 *
    468468 */
    469469psArray *pmSourceContour(
     
    476476
    477477/** pmSourceFitModel()
    478  * 
     478 *
    479479 * Fit the requested model to the specified source. The starting guess for the
    480480 * model is given by the input source.model parameter values. The pixels of
     
    482482 * function calls psMinimizeLMChi2() on the image data. The function returns TRUE
    483483 * on success or FALSE on failure.
    484  * 
     484 *
    485485 */
    486486bool pmSourceFitModel(
     
    492492
    493493/** pmModelFitStatus()
    494  * 
     494 *
    495495 * This function wraps the call to the model-specific function returned by
    496496 * pmModelFitStatusFunc_GetFunction.  The model-specific function examines the
    497497 * model parameters, parameter errors, Chisq, S/N, and other parameters available
    498498 * from model to decide if the particular fit was successful or not.
    499  * 
     499 *
    500500 * XXX: Must code this.
    501  * 
     501 *
    502502 */
    503503bool pmModelFitStatus(
     
    507507
    508508/** pmSourceAddModel()
    509  * 
     509 *
    510510 * Add the given source model flux to/from the provided image. The boolean
    511511 * option center selects if the source is re-centered to the image center or if
     
    514514 * is at most the pixel range specified by the source.pixels image. The success
    515515 * status is returned.
    516  * 
     516 *
    517517 */
    518518bool pmSourceAddModel(
     
    526526
    527527/** pmSourceSubModel()
    528  * 
     528 *
    529529 * Subtract the given source model flux to/from the provided image. The
    530530 * boolean option center selects if the source is re-centered to the image center
     
    533533 * image is at most the pixel range specified by the source.pixels image. The
    534534 * success status is returned.
    535  * 
     535 *
    536536 */
    537537bool pmSourceSubModel(
     
    545545
    546546/**
    547  * 
     547 *
    548548 * The function returns both the magnitude of the fit, defined as -2.5log(flux),
    549549 * where the flux is integrated under the model, theoretically from a radius of 0
     
    552552 * not excluded by the aperture mask. The model flux is calculated by calling the
    553553 * model-specific function provided by pmModelFlux_GetFunction.
    554  * 
     554 *
    555555 * XXX: must code this.
    556  * 
     556 *
    557557 */
    558558bool pmSourcePhotometry(
     
    566566
    567567/**
    568  * 
     568 *
    569569 * This function converts the source classification into the closest available
    570570 * approximation to the Dophot classification scheme:
    571571 * XXX EAM : fix this to use current source classification scheme
    572  * 
     572 *
    573573 * PM_SOURCE_DEFECT: 8
    574574 * PM_SOURCE_SATURATED: 8
     
    585585 * PM_SOURCE_POOR_FIT_GAL: 2
    586586 * PM_SOURCE_OTHER: ?
    587  * 
     587 *
    588588 */
    589589int pmSourceDophotType(
     
    593593
    594594/** pmSourceSextractType()
    595  * 
     595 *
    596596 * This function converts the source classification into the closest available
    597597 * approximation to the Sextractor classification scheme. the correspondence is
    598598 * not yet defined (TBD) .
    599  * 
     599 *
    600600 * XXX: Must code this.
    601  * 
     601 *
    602602 */
    603603int pmSourceSextractType(
     
    606606
    607607/** pmSourceFitModel_v5()
    608  * 
     608 *
    609609 * Fit the requested model to the specified source. The starting guess for the
    610610 * model is given by the input source.model parameter values. The pixels of
     
    612612 * function calls psMinimizeLMChi2() on the image data. The function returns TRUE
    613613 * on success or FALSE on failure.
    614  * 
     614 *
    615615 */
    616616bool pmSourceFitModel_v5(
     
    622622
    623623/** pmSourceFitModel_v7()
    624  * 
     624 *
    625625 * Fit the requested model to the specified source. The starting guess for the
    626626 * model is given by the input source.model parameter values. The pixels of
     
    628628 * function calls psMinimizeLMChi2() on the image data. The function returns TRUE
    629629 * on success or FALSE on failure.
    630  * 
     630 *
    631631 */
    632632bool pmSourceFitModel_v7(
     
    638638
    639639/** pmSourcePhotometry()
    640  * 
     640 *
    641641 * XXX: Need descriptions
    642  * 
     642 *
    643643 */
    644644bool pmSourcePhotometry(
Note: See TracChangeset for help on using the changeset viewer.