Changeset 5795
- Timestamp:
- Dec 16, 2005, 5:18:39 PM (21 years ago)
- Location:
- branches/pap_branch_051214/psModules/src
- Files:
-
- 14 edited
-
astrom/Makefile.am (modified) (1 diff)
-
astrom/pmAstrometry.c (modified) (16 diffs)
-
astrom/pmAstrometry.h (modified) (15 diffs)
-
camera/Makefile.am (modified) (1 diff)
-
detrend/pmFlatField.c (modified) (10 diffs)
-
detrend/pmFlatField.h (modified) (3 diffs)
-
detrend/pmMaskBadPixels.c (modified) (5 diffs)
-
detrend/pmMaskBadPixels.h (modified) (4 diffs)
-
detrend/pmMaskBadPixelsErrors.h (modified) (3 diffs)
-
detrend/pmNonLinear.c (modified) (5 diffs)
-
detrend/pmNonLinear.h (modified) (3 diffs)
-
imsubtract/Makefile.am (modified) (1 diff)
-
imsubtract/pmSubtractBias.c (modified) (11 diffs)
-
imsubtract/pmSubtractBias.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/pap_branch_051214/psModules/src/astrom/Makefile.am
r5674 r5795 4 4 libpsmoduleastrom_la_LDFLAGS = -release $(PACKAGE_VERSION) 5 5 libpsmoduleastrom_la_SOURCES = \ 6 pmAstrometry.c \ 7 pmAstrometryObjects.c 6 pmAstrometry.c \ 7 pmAstrometryObjects.c \ 8 pmChipMosaic.c \ 9 pmFPAConceptsGet.c \ 10 pmFPAConceptsSet.c \ 11 pmFPAConstruct.c \ 12 pmFPARead.c \ 13 pmFPAWrite.c \ 14 pmReadout.c \ 15 psAdditionals.c 8 16 9 17 psmoduleincludedir = $(includedir) 10 18 psmoduleinclude_HEADERS = \ 11 pmAstrometry.h \ 12 pmAstrometryObjects.h 19 pmAstrometry.h \ 20 pmAstrometryObjects.h \ 21 pmChipMosaic.h \ 22 pmFPAConceptsGet.h \ 23 pmFPAConceptsSet.h \ 24 pmFPAConstruct.h \ 25 pmFPARead.h \ 26 pmFPAWrite.h \ 27 pmReadout.h \ 28 psAdditionals.h -
branches/pap_branch_051214/psModules/src/astrom/pmAstrometry.c
r5739 r5795 10 10 * XXX: We should review the extent of the warning messages on these functions 11 11 * when the transformations are not successful. 12 * 12 * 13 13 * XXX: Should we implement non-linear cell->chip transforms? 14 * 15 * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $16 * @date $Date: 2005-12- 08 00:00:57$14 * 15 * @version $Revision: 1.11.2.1 $ $Name: not supported by cvs2svn $ 16 * @date $Date: 2005-12-17 03:18:38 $ 17 17 * 18 18 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 60 60 psFree(readout->mask); 61 61 psFree(readout->weight); 62 //63 // XXX: Not sure if this is the right way to do things. Currently the psListAdd()64 // increase the memory reference counter to the list data. So, we65 // iterate through the list, and decrement the reference counters.66 //67 if (1) {68 if ((readout->bias != NULL) && (readout->bias->head != NULL)) {69 psListElem *tmpElem = (psListElem *) readout->bias->head;70 while (NULL != tmpElem) {71 psMemDecrRefCounter((psImage *) tmpElem->data);72 tmpElem = tmpElem->next;73 }74 }75 }76 psFree(readout->bias);77 62 psFree(readout->analysis); 78 63 psFree(readout->parent); … … 88 73 psFree(cell->concepts); 89 74 psFree(cell->analysis); 75 psFree(cell->camera); 90 76 // 91 77 // Set the parent to NULL in all cell->readouts before psFree(cell->readouts) … … 101 87 psFree(cell->readouts); 102 88 psFree(cell->parent); 103 psFree(cell-> private);89 psFree(cell->hdu); 104 90 } 105 91 } … … 125 111 psFree(chip->cells); 126 112 psFree(chip->parent); 127 psFree(chip-> private);113 psFree(chip->hdu); 128 114 } 129 115 } … … 151 137 } 152 138 psFree(fpa->chips); 153 psFree(fpa-> private);139 psFree(fpa->hdu); 154 140 psFree(fpa->phu); 155 141 } 156 142 } 157 143 144 void p_pmHDUFree(p_pmHDU *hdu) 145 { 146 if (hdu) { 147 psFree(hdu->extname); 148 psFree(hdu->header); 149 psFree(hdu->images); 150 psFree(hdu->masks); 151 psFree(hdu->weights); 152 } 153 } 154 158 155 // XXX: Verify these default values for row0, col0, rowBins, colBins 156 // PAP: These values may disappear in the future in favour of values in parent->concepts? 159 157 pmReadout *pmReadoutAlloc(pmCell *cell) 160 158 { 161 159 pmReadout *tmpReadout = (pmReadout *) psAlloc(sizeof(pmReadout)); 162 160 163 tmpReadout->col0 = -1;164 tmpReadout->row0 = -1;165 tmpReadout->colBins = -1;166 tmpReadout->rowBins = -1;161 tmpReadout->col0 = 0; 162 tmpReadout->row0 = 0; 163 tmpReadout->colBins = 0; 164 tmpReadout->rowBins = 0; 167 165 tmpReadout->image = NULL; 168 166 tmpReadout->mask = NULL; 169 167 tmpReadout->weight = NULL; 170 tmpReadout->bias = NULL;171 168 tmpReadout->analysis = psMetadataAlloc(); 172 169 tmpReadout->parent = cell; … … 179 176 180 177 // XXX: Verify these default values for row0, col0. 178 // PAP: These values may disappear in the future in favour of values in the "concepts"? 181 179 pmCell *pmCellAlloc( 182 180 pmChip *chip, 183 psMetadata *camera data,184 psStringname)181 psMetadata *cameraData, 182 const char *name) 185 183 { 186 184 pmCell *tmpCell = (pmCell *) psAlloc(sizeof(pmCell)); 187 185 188 tmpCell->col0 = -1;189 tmpCell->row0 = -1;186 tmpCell->col0 = 0; 187 tmpCell->row0 = 0; 190 188 tmpCell->toChip = NULL; 191 189 tmpCell->toFPA = NULL; … … 196 194 psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not add CELL.NAME to metadata.\n"); 197 195 } 198 tmpCell->camera = cameradata;199 tmpCell->analysis = NULL;196 tmpCell->camera = psMemIncrRefCounter(cameraData); 197 tmpCell->analysis = psMetadataAlloc(); 200 198 tmpCell->readouts = psArrayAlloc(0); 201 tmpCell->parent = chip;199 tmpCell->parent = psMemIncrRefCounter(chip); 202 200 if (chip != NULL) { 203 201 chip->cells = psArrayAdd(chip->cells, 1, (psPtr) tmpCell); 204 202 } 205 tmpCell->valid = false;206 tmpCell-> private= NULL;203 tmpCell->valid = true; // All cells are valid by default 204 tmpCell->hdu = NULL; 207 205 208 206 psMemSetDeallocator(tmpCell, (psFreeFunc) cellFree); … … 211 209 212 210 // XXX: Verify these default values for row0, col0. 211 // PAP: row0, col0 may disappear in the future in favour of storing values in the "concepts". 213 212 pmChip *pmChipAlloc( 214 213 pmFPA *fpa, 215 psStringname)214 const char *name) 216 215 { 217 216 pmChip *tmpChip = (pmChip *) psAlloc(sizeof(pmChip)); 218 217 219 tmpChip->col0 = -1;220 tmpChip->row0 = -1;218 tmpChip->col0 = 0; 219 tmpChip->row0 = 0; 221 220 tmpChip->toFPA = NULL; 222 221 tmpChip->fromFPA = NULL; … … 226 225 psLogMsg(__func__, PS_LOG_WARN, "WARNING: Could not add CHIP.NAME to metadata.\n"); 227 226 } 228 tmpChip->analysis = NULL;227 tmpChip->analysis = psMetadataAlloc(); 229 228 tmpChip->cells = psArrayAlloc(0); 230 tmpChip->parent = fpa;229 tmpChip->parent = psMemIncrRefCounter(fpa); 231 230 if (fpa != NULL) { 232 231 fpa->chips = psArrayAdd(fpa->chips, 1, (psPtr) tmpChip); 233 232 } 234 tmpChip->valid = false;235 tmpChip-> private= NULL;233 tmpChip->valid = true; // Work on all chips, by default 234 tmpChip->hdu = NULL; 236 235 237 236 psMemSetDeallocator(tmpChip, (psFreeFunc) chipFree); … … 248 247 tmpFPA->concepts = psMetadataAlloc(); 249 248 tmpFPA->analysis = NULL; 250 tmpFPA->camera = camera;249 tmpFPA->camera = psMemIncrRefCounter((psPtr)camera); 251 250 tmpFPA->chips = psArrayAlloc(0); 252 tmpFPA-> private= NULL;251 tmpFPA->hdu = NULL; 253 252 tmpFPA->phu = NULL; 254 253 255 254 psMemSetDeallocator(tmpFPA, (psFreeFunc) FPAFree); 256 255 return(tmpFPA); 256 } 257 258 p_pmHDU *p_pmHDUAlloc(const char *extname) 259 { 260 p_pmHDU *hdu = psAlloc(sizeof(p_pmHDU)); 261 psMemSetDeallocator(hdu, (psFreeFunc)p_pmHDUFree); 262 263 hdu->extname = psStringCopy(extname); 264 hdu->header = NULL; 265 hdu->images = NULL; 266 hdu->masks = NULL; 267 hdu->weights = NULL; 268 269 return hdu; 257 270 } 258 271 … … 800 813 } 801 814 815 816 /***************************************************************************** 817 *****************************************************************************/ 818 819 // Set cells within a chip to a specified validity 820 static bool setCellsValid(const pmChip *chip, // Chip of interest 821 bool valid // Valid? 822 ) 823 { 824 PS_ASSERT_PTR_NON_NULL(chip, false); 825 826 psArray *cells = chip->cells; // Component cells 827 if (! cells) { 828 return false; 829 } 830 for (int i = 0; i < cells->n; i++) { 831 pmCell *tmpCell = cells->data[i]; // Cell of interest 832 if (tmpCell) { 833 tmpCell->valid = valid; 834 } 835 } 836 837 return true; 838 } 839 802 840 /***************************************************************************** 803 841 *****************************************************************************/ … … 807 845 { 808 846 PS_ASSERT_PTR_NON_NULL(fpa, false); 809 if ((fpa->chips == NULL) || (chipNum >= fpa->chips->n)) { 847 848 psArray *chips = fpa->chips; // Component chips 849 if ((chips == NULL) || (chipNum >= chips->n)) { 810 850 return(false); 811 851 } 812 psBool rc = true; 813 814 for (psS32 i = 0 ; i < fpa->chips->n ; i++) { 815 pmChip *tmpChip = (pmChip *) fpa->chips->data[i]; 852 853 for (int i = 0 ; i < chips->n ; i++) { 854 pmChip *tmpChip = (pmChip *) chips->data[i]; 816 855 if (tmpChip == NULL) { 817 rc = false; 856 continue; 857 } 858 if (i == chipNum) { 859 tmpChip->valid = true; 860 setCellsValid(tmpChip, true); 818 861 } else { 819 if (i == chipNum) { 820 tmpChip->valid = true; 821 } else { 822 tmpChip->valid = false; 823 } 824 } 825 } 826 827 return(rc); 862 tmpChip->valid = false; 863 setCellsValid(tmpChip, false); 864 } 865 866 } 867 868 return true; 828 869 } 829 870 … … 831 872 /***************************************************************************** 832 873 XXX: The SDRS is ambiguous on a few things: 833 Whether or not the other chips should be set valid=true. 834 Should we return the number of chip valid=true before or after they're set, 874 Whether or not the other chips should be set valid=true. [PAP: No] 875 Should we return the number of chip valid=true before or after they're set, [PAP: After] 835 876 *****************************************************************************/ 836 877 /** 837 * 878 * 838 879 * pmFPAExcludeChip shall set valid to false only for the specified chip 839 880 * number (chipNum). In the event that the specified chip number does not exist … … 841 882 * The function shall return the number of chips within the fpa that have valid 842 883 * set to true. 843 * 884 * 844 885 */ 845 886 int pmFPAExcludeChip( … … 849 890 PS_ASSERT_PTR_NON_NULL(fpa, false); 850 891 851 if (fpa->chips == NULL) { 892 psArray *chips = fpa->chips; // Component chips 893 if (chips == NULL) { 852 894 psLogMsg(__func__, PS_LOG_WARN, "WARNING: fpa->chips == NULL\n"); 853 895 return(0); 854 896 } 855 if ((chipNum >= fpa->chips->n) || (NULL == (pmChip *) fpa->chips->data[chipNum])) {897 if ((chipNum >= chips->n) || (NULL == (pmChip *) chips->data[chipNum])) { 856 898 psLogMsg(__func__, PS_LOG_WARN, "WARNING: the specified chip (%d) does not exist.\n", chipNum); 857 899 return(0); 858 900 } 859 901 860 psS32 numChips = 0;861 for ( psS32 i = 0 ; i < fpa->chips->n ; i++) {862 pmChip *tmpChip = (pmChip *) fpa->chips->data[i];902 int numChips = 0; // Number of valid chips 903 for (int i = 0 ; i < chips->n ; i++) { 904 pmChip *tmpChip = (pmChip *) chips->data[i]; // Chip of interest 863 905 if (tmpChip != NULL) { 864 906 if (i == chipNum) { 865 907 tmpChip->valid = false; 866 } else {867 tmpChip->valid = true;908 setCellsValid(tmpChip, false); // Wipe out the cell as well 909 } else if (tmpChip->valid) { 868 910 numChips++; 869 911 } -
branches/pap_branch_051214/psModules/src/astrom/pmAstrometry.h
r5739 r5795 8 8 * @author GLG, MHPCC 9 9 * 10 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $11 * @date $Date: 2005-12- 08 00:00:57$10 * @version $Revision: 1.5.2.1 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2005-12-17 03:18:38 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 30 30 { 31 31 const char *extname; // Extension name, if it corresponds to this level 32 psArray *pixels; // The pixel data, if it corresponds to this level33 32 psMetadata *header; // The FITS header, if it corresponds to this level 33 psArray *images; // The pixel data, if it corresponds to this level 34 psArray *masks; // The mask data, if it corresponds to this level 35 psArray *weights; // The weight data, if it corresponds to this level 34 36 } 35 37 p_pmHDU; 36 38 37 39 /** Focal plane data structure 38 * 40 * 39 41 * A focal plane consists of one or more chips (according to the number of 40 42 * pieces of contiguous silicon). It contains metadata containers for the … … 49 51 * transformation which will be derived from numerically inverting the forward 50 52 * transformation. 51 * 53 * 52 54 */ 53 55 typedef struct … … 62 64 const psMetadata *camera; ///< Camera configuration 63 65 psArray *chips; ///< The chips 64 p_pmHDU * private;///< FITS data66 p_pmHDU *hdu; ///< FITS data 65 67 psMetadata *phu; ///< Primary Header 66 68 } … … 68 70 69 71 /** Chip data structure 70 * 72 * 71 73 * A chip consists of one or more cells (according to the number of amplifiers 72 74 * on the device). The chip contains metadata containers for the concepts and … … 79 81 * inverting the forward transformation. A boolean indicates whether the chip is 80 82 * of interest, allowing it to be excluded from analysis. 81 * 83 * 82 84 */ 83 85 typedef struct … … 95 97 pmFPA *parent; ///< Parent FPA 96 98 bool valid; ///< Do we bother about reading and working with this chip? 97 p_pmHDU * private;///< FITS data99 p_pmHDU *hdu; ///< FITS data 98 100 } 99 101 pmChip; … … 124 126 pmChip *parent; ///< Parent chip 125 127 bool valid; ///< Do we bother about reading and working with this cell? 126 p_pmHDU * private;///< FITS data128 p_pmHDU *hdu; ///< FITS data 127 129 } 128 130 pmCell; … … 141 143 { 142 144 // Position on the cell 145 // XXX: These may be removed in the future; use parent->concepts instead? 143 146 int col0; ///< Offset from the left of chip. 144 147 int row0; ///< Offset from the bottom of chip. … … 149 152 psImage *mask; ///< Mask of input image 150 153 psImage *weight; ///< Weight of input image 151 psList *bias; ///< List of bias section (sub-)images152 154 psMetadata *analysis; ///< Readout-level analysis metadata 153 155 pmCell *parent; ///< Parent cell … … 180 182 */ 181 183 pmCell *pmCellAlloc( 182 pmChip *chip, ///< Parent chip183 psMetadata *camera data,184 psString name184 pmChip *chip, ///< Parent chip 185 psMetadata *cameraData, ///< Camera data 186 const char *name ///< Name of cell 185 187 ); 186 188 187 189 /** Allocates a pmChip 188 * 190 * 189 191 * The constructor shall make an empty pmChip. If the parent fpa is not NULL, 190 192 * the parent link is made and the chip shall be placed in the parent's array … … 196 198 */ 197 199 pmChip *pmChipAlloc( 198 pmFPA *fpa, 199 psString name 200 200 pmFPA *fpa, ///< FPA to which the chip belongs 201 const char *name ///< Name of chip 201 202 ); 202 203 203 204 /** Allocates a pmFPA 204 * 205 * 205 206 * The constructor shall make an empty pmFPA. The chips array shall be 206 207 * allocated with a zero size, the camera and db pointers set to the values 207 208 * provided, and the concepts metadata constructed. All other pointers in the 208 209 * structure shall be initialized to NULL. 209 * 210 * 210 211 */ 211 212 pmFPA *pmFPAAlloc( … … 213 214 ); 214 215 216 /** Allocates a p_pmHDU 217 * 218 * XXX: More detailed description 219 * 220 * @return p_pmHDU* newly allocated p_pmHDU 221 */ 222 p_pmHDU *p_pmHDUAlloc(const char *extname // Extension name 223 ); 224 215 225 216 226 /** Verify parent links. 217 * 227 * 218 228 * This function checks the validity of the parent links in the FPA hierarchy. 219 229 * If a parent link is not set (or not set correctly), it is corrected, and the 220 230 * function shall return false. If all the parent pointers were correct, the 221 231 * function shall return true. 222 * 232 * 223 233 */ 224 234 bool pmFPACheckParents( … … 229 239 230 240 /** FUNC DESC 231 * 232 * 233 * 234 * 235 */ 236 241 * 242 * 243 * 244 * 245 */ 246 247 248 249 /** 250 * 251 * pmFPASelectChip shall set valid to true for the specified chip number 252 * (chipNum), and all other chips shall have valid set to false. In the event 253 * that the specified chip number does not exist within the fpa, the function 254 * shall return false. 255 * 256 */ 257 bool pmFPASelectChip( 258 pmFPA *fpa, 259 int chipNum 260 ); 261 262 /** 263 * 264 * pmFPAExcludeChip shall set valid to false only for the specified chip 265 * number (chipNum). In the event that the specified chip number does not exist 266 * within the fpa, the function shall generate a warning, and perform no action. 267 * The function shall return the number of chips within the fpa that have valid 268 * set to true. 269 * 270 */ 271 int pmFPAExcludeChip( 272 pmFPA *fpa, 273 int chipNum 274 ); 237 275 238 276 … … 423 461 ); 424 462 425 /**426 *427 * pmFPASelectChip shall set valid to true for the specified chip number428 * (chipNum), and all other chips shall have valid set to false. In the event429 * that the specified chip number does not exist within the fpa, the function430 * shall return false.431 *432 */433 bool pmFPASelectChip(434 pmFPA *fpa,435 int chipNum436 );437 438 /**439 *440 * pmFPAExcludeChip shall set valid to false only for the specified chip441 * number (chipNum). In the event that the specified chip number does not exist442 * within the fpa, the function shall generate a warning, and perform no action.443 * The function shall return the number of chips within the fpa that have valid444 * set to true.445 *446 */447 int pmFPAExcludeChip(448 pmFPA *fpa,449 int chipNum450 );451 452 463 453 464 #endif // #ifndef PS_ASTROMETRY_H -
branches/pap_branch_051214/psModules/src/camera/Makefile.am
r5170 r5795 3 3 libpsmodulecamera_la_CPPFLAGS = $(SRCINC) $(PSMODULE_CFLAGS) 4 4 libpsmodulecamera_la_LDFLAGS = -release $(PACKAGE_VERSION) 5 libpsmodulecamera_la_SOURCES = 5 libpsmodulecamera_la_SOURCES = \ 6 pmChipMosaic.c \ 7 pmFPAConceptsGet.c \ 8 pmFPAConceptsSet.c \ 9 pmFPAConstruct.c \ 10 pmFPAMorph.c \ 11 pmFPARead.c \ 12 pmFPAWrite.c 6 13 7 14 psmoduleincludedir = $(includedir) 8 psmoduleinclude_HEADERS = 9 15 psmoduleinclude_HEADERS = \ 16 pmChipMosaic.h \ 17 pmFPAConceptsGet.h \ 18 pmFPAConceptsSet.h \ 19 pmFPAConstruct.h \ 20 pmFPAMorph.h \ 21 pmFPARead.h \ 22 pmFPAWrite.h -
branches/pap_branch_051214/psModules/src/detrend/pmFlatField.c
r5543 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 6 1 7 /** @file pmFlatField.c 2 8 * … … 18 24 * @author Ross Harman, MHPCC 19 25 * 20 * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $21 * @date $Date: 2005-1 1-18 19:43:14$26 * @version $Revision: 1.4.8.1 $ $Name: not supported by cvs2svn $ 27 * @date $Date: 2005-12-17 03:18:39 $ 22 28 * 23 29 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 30 36 #include<stdio.h> 31 37 #include<math.h> 32 #include <string .h>38 #include <strings.h> 33 39 34 40 #include "pslib.h" … … 36 42 #include "pmMaskBadPixels.h" 37 43 #include "pmFlatFieldErrors.h" 38 #include "pmSubtractBias.h"39 44 40 // XXX: This should be removed when the autoconf stuff handles psConstants.h correctly.41 #define PS_WARN_PTR_NON_NULL(NAME) \42 if ((NAME) == NULL) { \43 psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \44 } \45 45 46 bool pmFlatField( 47 pmReadout *in, 48 const pmReadout *flat) 46 bool pmFlatField(pmReadout *in, pmReadout *mask, const pmReadout *flat) 49 47 { 50 // XXX: Use the proper image and readout asserts.51 PS_ASSERT_PTR_NON_NULL(in, true);52 PS_ASSERT_PTR_NON_NULL(in->image, false);53 PS_ASSERT_PTR_NON_NULL(in->mask, false);54 PS_ASSERT_PTR_NON_NULL(flat, false);55 PS_ASSERT_PTR_NON_NULL(flat->image, false);56 if (in == NULL)57 printf("XXX: NULL\n");58 59 48 // XXX: Not sure if this is correct. Must consult with IfA. 60 PS_ASSERT_PTR_NON_NULL(in->mask, false); 61 62 PS_WARN_PTR_NON_NULL(in->parent); 63 if (in->parent != NULL) { 64 PS_WARN_PTR_NON_NULL(in->parent->concepts); 65 } 49 PS_ASSERT_PTR_NON_NULL(mask, false); 66 50 int i = 0; 67 51 int j = 0; … … 71 55 psElemType flatType; 72 56 psElemType maskType; 57 psImage *inImage = NULL; 73 58 psImage *inMask = NULL; 74 59 psImage *flatImage = NULL; 75 60 76 // 77 // Determine trimmed image from metadata. 78 // 79 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 61 62 // Check for nulls 63 if (in == NULL) { 64 return true; // Readout may not have data in it 65 } else if(flat==NULL) { 66 psError( PS_ERR_BAD_PARAMETER_NULL, true, 67 PS_ERRORTEXT_pmFlatField_NULL_FLAT_READOUT); 68 return false; 69 } 70 71 inImage = in->image; 80 72 flatImage = flat->image; 81 inMask = in->mask; 73 if (inImage == NULL) { 74 psError( PS_ERR_BAD_PARAMETER_NULL, true, 75 PS_ERRORTEXT_pmFlatField_NULL_INPUT_IMAGE); 76 return false; 77 } else if(flatImage == NULL) { 78 psError( PS_ERR_BAD_PARAMETER_NULL, true, 79 PS_ERRORTEXT_pmFlatField_NULL_FLAT_IMAGE); 80 return false; 81 } 82 inMask = mask->image; 82 83 83 84 // Check input image and its mask are not larger than flat image 84 85 85 if (trimmedImg == NULL) 86 printf("XXX: 00\n"); 87 if (flatImage == NULL) 88 printf("XXX 01\n"); 89 90 if (trimmedImg->numRows>flatImage->numRows || trimmedImg->numCols>flatImage->numCols) { 86 if (inImage->numRows>flatImage->numRows || inImage->numCols>flatImage->numCols) { 91 87 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 92 88 PS_ERRORTEXT_pmFlatField_SIZE_INPUT_IMAGE, 93 trimmedImg->numRows, trimmedImg->numCols, flatImage->numRows, flatImage->numCols);89 inImage->numRows, inImage->numCols, flatImage->numRows, flatImage->numCols); 94 90 return false; 95 91 } … … 102 98 103 99 // Determine total offset based on image offset with chip offset 104 totOffCol = trimmedImg->col0 + in->col0;105 totOffRow = trimmedImg->row0 + in->row0;100 totOffCol = inImage->col0 + in->col0; 101 totOffRow = inImage->row0 + in->row0; 106 102 107 103 // Check that offsets are within image limits … … 111 107 totOffRow, totOffCol, flatImage->numRows, flatImage->numCols); 112 108 return false; 113 } else if(totOffRow>= trimmedImg->numRows || totOffCol>=trimmedImg->numCols) {109 } else if(totOffRow>=inImage->numRows || totOffCol>=inImage->numCols) { 114 110 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 115 111 PS_ERRORTEXT_pmFlatField_OFFSET_INPUT_IMAGE, 116 totOffRow, totOffCol, trimmedImg->numRows, trimmedImg->numCols);112 totOffRow, totOffCol, inImage->numRows, inImage->numCols); 117 113 return false; 118 114 } else if(totOffRow>=inMask->numRows || totOffCol>=inMask->numCols) { … … 124 120 125 121 // Check for incorrect types 126 inType = trimmedImg->type.type;122 inType = inImage->type.type; 127 123 flatType = flatImage->type.type; 128 124 maskType = inMask->type.type; … … 153 149 case PS_TYPE_##TYPE: \ 154 150 /* Per Eugene's request, use two sets of loops: first to fill mask, second to avoid div with bad pix */ \ 155 for(j = totOffRow; j < trimmedImg->numRows; j++) { \156 for(i = totOffCol; i < trimmedImg->numCols; i++) { \151 for(j = totOffRow; j < inImage->numRows; j++) { \ 152 for(i = totOffCol; i < inImage->numCols; i++) { \ 157 153 if(flatImage->data.TYPE[j][i] <= 0.0) { \ 158 154 /* Negative or zero flat pixels shall be masked in input image as PM_MASK_FLAT */ \ … … 162 158 } \ 163 159 } \ 164 for(j = totOffRow; j < trimmedImg->numRows; j++) { \165 for(i = totOffCol; i < trimmedImg->numCols; i++) { \160 for(j = totOffRow; j < inImage->numRows; j++) { \ 161 for(i = totOffCol; i < inImage->numCols; i++) { \ 166 162 if(!inMask->data.PS_TYPE_MASK_DATA[j][i]) { \ 167 163 /* Module shall divide the input image by the flat-fielded image */ \ 168 trimmedImg->data.TYPE[j][i] /= flatImage->data.TYPE[j][i]; \164 inImage->data.TYPE[j][i] /= flatImage->data.TYPE[j][i]; \ 169 165 } \ 170 166 } \ -
branches/pap_branch_051214/psModules/src/detrend/pmFlatField.h
r5435 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 6 1 7 /** @file pmFlatField.h 2 8 * … … 18 24 * @author Ross Harman, MHPCC 19 25 * 20 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $21 * @date $Date: 2005-1 0-20 23:06:24$26 * @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $ 27 * @date $Date: 2005-12-17 03:18:39 $ 22 28 * 23 29 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 37 43 bool pmFlatField( 38 44 pmReadout *in, ///< Readout with input image 45 pmReadout *mask, ///< Input image mask 39 46 const pmReadout *flat ///< Readout with flat image 40 47 ); -
branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixels.c
r5543 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmMaskBadPixels.c 2 7 * … … 19 24 * @author Ross Harman, MHPCC 20 25 * 21 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $22 * @date $Date: 2005-1 1-18 19:43:14$26 * @version $Revision: 1.3.8.1 $ $Name: not supported by cvs2svn $ 27 * @date $Date: 2005-12-17 03:18:39 $ 23 28 * 24 29 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 31 36 #include<stdio.h> 32 37 #include<math.h> 33 #include<string .h>38 #include<strings.h> 34 39 35 40 #include "pmMaskBadPixels.h" 36 41 #include "pmMaskBadPixelsErrors.h" 37 #include "pmSubtractBias.h"38 42 39 //XXX: REmove, autoconf is broken. 40 #define PS_WARN_PTR_NON_NULL(NAME) \ 41 if ((NAME) == NULL) { \ 42 psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \ 43 } \ 43 bool pmMaskBadPixels(pmReadout *in, const psImage *mask, unsigned int maskVal, float sat, 44 unsigned int growVal, int grow) 45 { 46 int i = 0; 47 int j = 0; 48 int jj = 0; 49 int ii = 0; 50 int rRound = 0; 51 int rowMin = 0; 52 int rowMax = 0; 53 int colMin = 0; 54 int colMax = 0; 55 int totOffCol = 0; 56 int totOffRow = 0; 57 float r = 0.0f; 58 psElemType inType; 59 psElemType maskType; 60 psImage *inImage = NULL; 61 psImage *inMask = NULL; 44 62 45 63 46 /****************************************************************************** 47 GrowPixel(inMask, row, col, radius, maskVal): This private routine takes an 48 input image mask and a pixel location, then sets (logical or) all pixels with 49 parameter radius if that pixel to maskVal parameter. 50 *****************************************************************************/ 51 psBool GrowPixel( 52 psImage *inMask, 53 psS32 col, 54 psS32 row, 55 psS32 radius, 56 psU32 maskVal) 57 { 58 psS32 rowMin = PS_MAX(row-radius, 0); 59 psS32 rowMax = PS_MIN(row+radius+1, inMask->numRows); 60 psS32 colMin = PS_MAX(col-radius, 0); 61 psS32 colMax = PS_MIN(col+radius+1, inMask->numCols); 62 psF32 squareRadius = PS_SQR(radius); 64 // Check for nulls 65 if (in == NULL) { 66 return true; // Readout may not have data in it 67 } else if(mask==NULL) { 68 psError( PS_ERR_BAD_PARAMETER_NULL, true, 69 PS_ERRORTEXT_pmMaskBadPixels_NULL_MASK_IMAGE); 70 return false; 71 } 63 72 64 65 for(psS32 i=rowMin; i<rowMax; i++) { 66 for(psS32 j=colMin; j<colMax; j++) { 67 // Old code: 68 // psF32 rRound = 0.5 + sqrtf((psF32) (((col-j)*(col-j)) + ((row-i)*(row-i)))); 69 // if(rRound <= radius) { 70 psF32 squareDis = (psF32) (((col-j)*(col-j)) + ((row-i)*(row-i))); 71 if (squareDis <= squareRadius) { 72 inMask->data.U8[i][j] |= maskVal; 73 } 74 } 75 } 76 return(true); 77 } 78 79 /****************************************************************************** 80 GetRadius(inImg, col, row, sat, growVal, grow): This private routine takes an 81 input image and pixel location and determines what radius that pixel must grow 82 by. 83 84 //XXX: Inline this or macro it for speed. 85 *****************************************************************************/ 86 static psS32 GetRadius( 87 psImage *inImg, 88 psS32 col, 89 psS32 row, 90 psF32 sat, 91 psU32 growVal, 92 psS32 grow) 93 { 94 psS32 growRadius = 0; 95 if (inImg->type.type == PS_TYPE_F32) { 96 if(inImg->data.F32[row][col] == growVal) { 97 growRadius = grow; 98 } 99 if (inImg->data.F32[row][col] > sat) { 100 growRadius = PS_MAX(growRadius+1, 2); 101 } 102 } else if (inImg->type.type == PS_TYPE_S32) { 103 if(inImg->data.S32[row][col] == growVal) { 104 growRadius = grow; 105 } 106 if (inImg->data.S32[row][col] > sat) { 107 growRadius = PS_MAX(growRadius+1, 2); 108 } 109 } else if (inImg->type.type == PS_TYPE_U16) { 110 if(inImg->data.U16[row][col] == growVal) { 111 growRadius = grow; 112 } 113 if (inImg->data.U16[row][col] > sat) { 114 growRadius = PS_MAX(growRadius+1, 2); 115 } 116 } else { 117 psError( PS_ERR_BAD_PARAMETER_TYPE, true, 118 PS_ERRORTEXT_pmMaskBadPixels_TYPE_MASK_IMAGE, 119 inImg->type.type); 120 } 121 return(growRadius); 122 } 123 124 125 bool pmMaskBadPixels( 126 pmReadout *in, 127 const pmReadout *mask, 128 unsigned int maskVal, 129 float sat, 130 unsigned int growVal, 131 int grow) 132 { 133 // XXX: Review this code then put all asserts at the top. 134 PS_ASSERT_PTR_NON_NULL(in, true); 135 PS_ASSERT_PTR_NON_NULL(in->image, false); 136 PS_WARN_PTR_NON_NULL(in->parent); 137 if (in->parent != NULL) { 138 PS_WARN_PTR_NON_NULL(in->parent->concepts); 139 } 140 PS_ASSERT_PTR_NON_NULL(mask, false); 141 int i = 0; 142 int j = 0; 143 int totOffCol = 0; 144 int totOffRow = 0; 145 psElemType inType; 146 psElemType maskType; 147 psImage *inMask = NULL; 148 149 // 150 // Determine trimmed image from metadata. 151 // 152 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 153 if(in->mask == NULL) { 154 in->mask = psImageAlloc(trimmedImg->numCols, trimmedImg->numRows, PS_TYPE_MASK); 155 PS_IMAGE_SET_U8(in->mask, 0); 73 inImage = in->image; 74 if (inImage == NULL) { 75 psError( PS_ERR_BAD_PARAMETER_NULL, true, 76 PS_ERRORTEXT_pmMaskBadPixels_NULL_INPUT_IMAGE); 77 return false; 78 } else if(in->mask == NULL) { 79 in->mask = psImageAlloc(inImage->numCols, inImage->numRows, PS_TYPE_MASK); 80 memset(in->mask->data.V[0], 0, inImage->numCols*inImage->numRows*PSELEMTYPE_SIZEOF(PS_TYPE_MASK)); 156 81 } 157 82 inMask = in->mask; 158 83 159 84 // Check input image and its mask are not larger than mask 160 if( trimmedImg->numRows > mask->image->numRows || trimmedImg->numCols > mask->image->numCols) {85 if(inImage->numRows > mask->numRows || inImage->numCols > mask->numCols) { 161 86 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 162 87 PS_ERRORTEXT_pmMaskBadPixels_SIZE_INPUT_IMAGE, 163 trimmedImg->numRows, trimmedImg->numCols, mask->image->numRows, mask->image->numCols);88 inImage->numRows, inImage->numCols, mask->numRows, mask->numCols); 164 89 return false; 165 } else if(inMask->numRows > mask->image->numRows || inMask->numCols > mask->image->numCols) {90 } else if(inMask->numRows>mask->numRows || inMask->numCols>mask->numCols) { 166 91 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 167 92 PS_ERRORTEXT_pmMaskBadPixels_SIZE_MASK_IMAGE, 168 inMask->numRows, inMask->numCols, mask-> image->numRows, mask->image->numCols);93 inMask->numRows, inMask->numCols, mask->numRows, mask->numCols); 169 94 return false; 170 95 } 171 96 172 97 // Determine total offset based on image offset with chip offset 173 totOffCol = trimmedImg->col0 + in->col0;174 totOffRow = trimmedImg->row0 + in->row0;98 totOffCol = inImage->col0 + in->col0; 99 totOffRow = inImage->row0 + in->row0; 175 100 176 101 // Check that offsets are within image limits 177 if(totOffRow>=mask-> image->numRows || totOffCol>=mask->image->numCols) {102 if(totOffRow>=mask->numRows || totOffCol>=mask->numCols) { 178 103 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 179 104 PS_ERRORTEXT_pmMaskBadPixels_OFFSET_MASK_IMAGE, 180 totOffRow, totOffCol, mask-> image->numRows, mask->image->numCols);105 totOffRow, totOffCol, mask->numRows, mask->numCols); 181 106 return false; 182 } else if(totOffRow>= trimmedImg->numRows || totOffCol>=trimmedImg->numCols) {107 } else if(totOffRow>=inImage->numRows || totOffCol>=inImage->numCols) { 183 108 psError( PS_ERR_BAD_PARAMETER_SIZE, true, 184 109 PS_ERRORTEXT_pmMaskBadPixels_OFFSET_INPUT_IMAGE, 185 totOffRow, totOffCol, trimmedImg->numRows, trimmedImg->numCols);110 totOffRow, totOffCol, inImage->numRows, inImage->numCols); 186 111 return false; 187 112 } else if(totOffRow>=inMask->numRows || totOffCol>=inMask->numCols) { … … 193 118 194 119 // Check for incorrect types 195 inType = trimmedImg->type.type;196 maskType = mask-> image->type.type;120 inType = inImage->type.type; 121 maskType = mask->type.type; 197 122 if(PS_IS_PSELEMTYPE_COMPLEX(inType)) { 198 123 psError( PS_ERR_BAD_PARAMETER_TYPE, true, … … 207 132 } 208 133 209 // 210 // This is the main loop which examines each pixel and masks pixels if 211 // A: The mask matches the maskValue 212 // B: The pixel is larger than the saturation value 213 // C: The pixel equals the grow value (in which case a circle is masked) 214 // 215 for(i=totOffRow; i<trimmedImg->numRows; i++) { 216 for(j=totOffCol; j<trimmedImg->numCols; j++) { 217 // 218 // A: Pixels which satisfy maskVal shall be masked 219 // 220 if (mask->image->data.U8[i][j] == maskVal) { 221 in->mask->data.U8[i][j] |= maskVal; 222 } 134 // Macro for all PS types 135 #define PM_BAD_PIXELS(TYPE) \ 136 case PS_TYPE_##TYPE: \ 137 for(j=totOffRow; j<inImage->numRows; j++) { \ 138 for(i=totOffCol; i<inImage->numCols; i++) { \ 139 \ 140 /* Pixels with flux greater than sat shall be masked */ \ 141 if(inImage->data.TYPE[j][i] > sat) { \ 142 inMask->data.PS_TYPE_MASK_DATA[j][i] |= PM_MASK_SAT; \ 143 } \ 144 \ 145 /* Pixels which satisfy maskVal shall be masked */ \ 146 inMask->data.PS_TYPE_MASK_DATA[j][i] |= (mask->data.PS_TYPE_MASK_DATA[j][i]&maskVal); \ 147 \ 148 /* Pixels which satisfy growVal and within the grow radius shall be masked */ \ 149 if(mask->data.PS_TYPE_MASK_DATA[j][i] & growVal) { \ 150 rowMin = MAX(j-grow, 0); \ 151 rowMax = MIN(j+grow+1, inImage->numRows); \ 152 colMin = MAX(i-grow, 0); \ 153 colMax = MIN(i+grow+1, inImage->numCols); \ 154 for(jj=rowMin; jj<rowMax; jj++) { \ 155 for(ii=colMin; ii<colMax; ii++) { \ 156 r = sqrtf((ii-i)*(ii-i)+(jj-j)*(jj-j)); \ 157 rRound = r + 0.5; \ 158 if(rRound <= grow) { \ 159 inMask->data.PS_TYPE_MASK_DATA[jj][ii] |= \ 160 (mask->data.PS_TYPE_MASK_DATA[j][i]&growVal); \ 161 } \ 162 } \ 163 } \ 164 } \ 165 } \ 166 } \ 167 break; 223 168 224 // 225 // We first determine how much we need to grow by and store this in 226 // growRadius. 227 // 228 psS32 growRadius = GetRadius(trimmedImg, j, i, sat, growVal, grow); 229 230 // 231 // Grow the pixel mask if necessary. 232 // 233 if (growRadius != 0) { 234 GrowPixel(in->mask, j, i, growRadius, maskVal); 235 } 236 } 169 // Switch to call bad pixel masking macro defined above 170 switch(inType) { 171 PM_BAD_PIXELS(U8); 172 PM_BAD_PIXELS(U16); 173 PM_BAD_PIXELS(U32); 174 PM_BAD_PIXELS(U64); 175 PM_BAD_PIXELS(S8); 176 PM_BAD_PIXELS(S16); 177 PM_BAD_PIXELS(S32); 178 PM_BAD_PIXELS(S64); 179 PM_BAD_PIXELS(F32); 180 PM_BAD_PIXELS(F64); 181 default: 182 psError( PS_ERR_BAD_PARAMETER_TYPE, true, 183 PS_ERRORTEXT_pmMaskBadPixels_TYPE_UNSUPPORTED, 184 inType); 237 185 } 238 186 239 return true;187 return false; 240 188 } -
branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixels.h
r5516 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmMaskBadPixels.h 2 7 * … … 19 24 * @author Ross Harman, MHPCC 20 25 * 21 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $22 * @date $Date: 2005-1 1-15 20:09:03$26 * @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $ 27 * @date $Date: 2005-12-17 03:18:39 $ 23 28 * 24 29 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 36 41 } pmMaskValue; 37 42 38 // XXX: Use PS_MIN, PS_MAX39 43 /** Macro to find maximum of two numbers */ 40 44 #define MAX(A,B)((A)>=(B)?(A):(B)) … … 54 58 bool pmMaskBadPixels( 55 59 pmReadout *in, ///< Readout containing input image data. 56 const p mReadout *mask,///< Mask data to be added to readout mask data.60 const psImage *mask, ///< Mask data to be added to readout mask data. 57 61 unsigned int maskVal, ///< Mask value to determine what to add to input mask. 58 62 float sat, ///< Saturation limit to mask bad pixels. -
branches/pap_branch_051214/psModules/src/detrend/pmMaskBadPixelsErrors.h
r5170 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmMaskBadPixelsErrors.h 2 7 * … … 7 12 * @author Ross Harman, MHPCC 8 13 * 9 * @version $Revision: 1.1 $ $Name: not supported by cvs2svn $10 * @date $Date: 2005- 09-28 20:43:52$14 * @version $Revision: 1.1.16.1 $ $Name: not supported by cvs2svn $ 15 * @date $Date: 2005-12-17 03:18:39 $ 11 16 * 12 17 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 23 28 * $2 The error text (rest of the line in pmMaskBadPixelsErrors.h) 24 29 * $n The order of the source line in pmMaskBadPixelsErrors.h (comments excluded) 25 * 30 * 26 31 * DO NOT EDIT THE LINES BETWEEN //~Start and //~End! ANY CHANGES WILL BE OVERWRITTEN. 27 32 */ -
branches/pap_branch_051214/psModules/src/detrend/pmNonLinear.c
r5675 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmNonLinear.c 2 7 * … … 5 10 * @author GLG, MHPCC 6 11 * 7 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $8 * @date $Date: 2005-12- 05 20:49:40$12 * @version $Revision: 1.5.8.1 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-12-17 03:18:39 $ 9 14 * 10 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 22 27 23 28 #include "pmNonLinear.h" 24 #include "pmSubtractBias.h"25 29 26 // XXX: Remove, autoconf must be27 #define PS_WARN_PTR_NON_NULL(NAME) \28 if ((NAME) == NULL) { \29 psLogMsg(__func__, PS_LOG_WARN, "WARNING: %s is NULL.", #NAME); \30 } \31 30 /****************************************************************************** 32 31 pmNonLinearityLookup(): This routine will take an pmReadout image as input 33 32 and a 1-D polynomial. For each pixel in the input image, the polynomial will 34 be evaluated at that pixels value, and the image pixel will then be set 35 to 33 be evaluated at that pixels value, and the image pixel will then be set to 36 34 that value. 37 *****************************************************************************/35 *****************************************************************************/ 38 36 39 pmReadout *pmNonLinearityPolynomial( 40 pmReadout *inputReadout, 41 const psPolynomial1D *input1DPoly) 37 pmReadout *pmNonLinearityPolynomial(pmReadout *inputReadout, 38 const psPolynomial1D *input1DPoly) 42 39 { 43 40 PS_ASSERT_PTR_NON_NULL(inputReadout, NULL); … … 45 42 PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL); 46 43 PS_ASSERT_PTR_NON_NULL(input1DPoly, NULL); 47 PS_WARN_PTR_NON_NULL(inputReadout->parent);48 if (inputReadout->parent != NULL) {49 PS_WARN_PTR_NON_NULL(inputReadout->parent->concepts);50 }51 44 52 // 53 // Determine trimmed image from metadata. 54 // 55 psImage *trimmedImg = p_psDetermineTrimmedImage(inputReadout); 45 psS32 i; 46 psS32 j; 56 47 57 for (psS32 i=0;i<trimmedImg->numRows;i++) { 58 for (psS32 j=0;j<trimmedImg->numCols;j++) { 59 trimmedImg->data.F32[i][j] = psPolynomial1DEval(input1DPoly, 60 trimmedImg->data.F32[i][j]); 48 for (i=0;i<inputReadout->image->numRows;i++) { 49 for (j=0;j<inputReadout->image->numCols;j++) { 50 inputReadout->image->data.F32[i][j] = psPolynomial1DEval(input1DPoly, inputReadout->image->data.F32[i][j]); 61 51 } 62 52 } … … 71 61 inFluxe, and the corresponding value in outFlux. The image pixel will then 72 62 be set to the value from outFlux. 73 74 XXX: Must assert that filename exists. This should probably happen in75 the lookup files.76 63 *****************************************************************************/ 77 pmReadout *pmNonLinearityLookup( 78 pmReadout *inputReadout, 79 const char *filename 80 ) 64 pmReadout *pmNonLinearityLookup(pmReadout *inputReadout, 65 const psVector *inFlux, 66 const psVector *outFlux) 81 67 { 82 68 PS_ASSERT_PTR_NON_NULL(inputReadout,NULL); 83 69 PS_ASSERT_PTR_NON_NULL(inputReadout->image,NULL); 84 70 PS_ASSERT_IMAGE_TYPE(inputReadout->image, PS_TYPE_F32, NULL); 85 PS_WARN_PTR_NON_NULL(inputReadout->parent); 86 if (inputReadout->parent != NULL) { 87 PS_WARN_PTR_NON_NULL(inputReadout->parent->concepts); 71 PS_ASSERT_PTR_NON_NULL(inFlux,NULL); 72 if (inFlux->n < 2) { 73 psError(PS_ERR_UNKNOWN,true, "pmNonLinearityLookup(): input vector less than 2 elements. Returning inputReadout image."); 74 return(inputReadout); 88 75 } 89 // 90 // Determine trimmed image from metadata. 91 // 92 psImage *trimmedImg = p_psDetermineTrimmedImage(inputReadout); 76 PS_ASSERT_PTR_NON_NULL(outFlux,NULL); 77 psS32 tableSize = inFlux->n; 78 if (inFlux->n != outFlux->n) { 79 tableSize = PS_MIN(inFlux->n, outFlux->n); 80 psLogMsg(__func__, PS_LOG_WARN, 81 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): input vectors have different sizes (%d, %d)\n", inFlux->n, outFlux->n); 82 } 83 PS_ASSERT_VECTOR_TYPE(inFlux, PS_TYPE_F32, NULL); 84 PS_ASSERT_VECTOR_TYPE(outFlux, PS_TYPE_F32, NULL); 93 85 94 psLookupTable *tmpLT = psLookupTableAlloc(filename, "%f %f", 0); 95 psS32 numLines = psLookupTableRead(tmpLT); 86 psS32 i; 87 psS32 j; 88 psS32 binNum; 89 psScalar x; 96 90 psS32 numPixels = 0; 97 if (numLines < 2) { 98 psLogMsg(__func__, PS_LOG_WARN, 99 "WARNING: Lookup Table is too small. Returning original pmReadout.\n"); 100 } else { 101 for (psS32 i=0;i<trimmedImg->numRows;i++) { 102 for (psS32 j=0;j<trimmedImg->numCols;j++) { 103 psF64 tmpD = psLookupTableInterpolate(tmpLT, trimmedImg->data.F32[i][j], 1); 104 if (!isnan(tmpD)) { 105 trimmedImg->data.F32[i][j] = tmpD; 106 } else { 107 numPixels++; 108 } 91 psF32 slope; 92 93 x.type.type = PS_TYPE_F32; 94 for (i=0;i<inputReadout->image->numRows;i++) { 95 for (j=0;j<inputReadout->image->numCols;j++) { 96 x.data.F32 = inputReadout->image->data.F32[i][j]; 97 binNum = p_psVectorBinDisect((psVector *)inFlux, &x); 98 99 if (binNum == -2) { 100 // We get here if x is below the table lookup range. 101 inputReadout->image->data.F32[i][j] = outFlux->data.F32[0]; 102 numPixels++; 103 104 } else if (binNum == -1) { 105 // We get here if x is above the table lookup range. 106 inputReadout->image->data.F32[i][j] = outFlux->data.F32[tableSize-1]; 107 numPixels++; 108 109 } else if (binNum < -2) { 110 // We get here if there was some other problem. 111 psError(PS_ERR_UNKNOWN,true, "pmNonLinearityLookup(): Could not perform p_psVectorBinDisect(). Returning inputReadout image."); 112 return(inputReadout); 113 numPixels++; 114 } else { 115 // Perform linear interpolation. 116 slope = (outFlux->data.F32[binNum+1] - outFlux->data.F32[binNum]) / 117 (inFlux->data.F32[binNum+1] - inFlux->data.F32[binNum]); 118 inputReadout->image->data.F32[i][j] = outFlux->data.F32[binNum] + 119 ((x.data.F32 - inFlux->data.F32[binNum]) * slope); 109 120 } 110 121 } 111 if (numPixels > 0) {112 psLogMsg(__func__, PS_LOG_WARN,113 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): %d pixels outside table.", numPixels);114 }115 122 } 116 123 if (numPixels > 0) { 124 psLogMsg(__func__, PS_LOG_WARN, 125 "WARNING: pmNonLinear.c: pmNonLinearityLookup(): %d pixels outside table.", numPixels); 126 } 117 127 return(inputReadout); 118 128 } -
branches/pap_branch_051214/psModules/src/detrend/pmNonLinear.h
r5435 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmNonLinear.h 2 7 * … … 5 10 * @author GLG, MHPCC 6 11 * 7 * @version $Revision: 1.2 $ $Name: not supported by cvs2svn $8 * @date $Date: 2005-1 0-20 23:06:24$12 * @version $Revision: 1.2.8.1 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2005-12-17 03:18:39 $ 9 14 * 10 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 18 23 #include "pmAstrometry.h" 19 24 20 pmReadout *pmNonLinearityPolynomial( 21 pmReadout *in, 22 const psPolynomial1D *coeff 23 ); 25 pmReadout *pmNonLinearityPolynomial(pmReadout *in, 26 const psPolynomial1D *coeff); 24 27 25 pmReadout *pmNonLinearityLookup( 26 pmReadout *in, 27 const char *filename 28 ); 28 pmReadout *pmNonLinearityLookup(pmReadout *in, 29 const psVector *inFlux, 30 const psVector *outFlux); 29 31 30 32 #endif -
branches/pap_branch_051214/psModules/src/imsubtract/Makefile.am
r5170 r5795 4 4 libpsmoduleimsubtract_la_LDFLAGS = -release $(PACKAGE_VERSION) 5 5 libpsmoduleimsubtract_la_SOURCES = pmImageSubtract.c \ 6 pmSubtractBias.c \7 pmSubtractSky.c6 pmSubtractBias.c 7 # pmSubtractSky.c 8 8 9 9 psmoduleincludedir = $(includedir) 10 10 psmoduleinclude_HEADERS = \ 11 11 pmImageSubtract.h \ 12 pmSubtractBias.h \13 pmSubtractSky.h12 pmSubtractBias.h 13 # pmSubtractSky.h -
branches/pap_branch_051214/psModules/src/imsubtract/pmSubtractBias.c
r5552 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmSubtractBias.c 2 7 * … … 6 11 * @author GLG, MHPCC 7 12 * 8 * @version $Revision: 1.6 $ $Name: not supported by cvs2svn $9 * @date $Date: 2005-1 1-19 00:55:18$13 * @version $Revision: 1.6.8.1 $ $Name: not supported by cvs2svn $ 14 * @date $Date: 2005-12-17 03:18:39 $ 10 15 * 11 16 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 12 17 * 13 18 */ 14 /*****************************************************************************/ 15 /* INCLUDE FILES */ 16 /*****************************************************************************/ 17 #include <stdio.h> 18 #include <math.h> 19 #include <string.h> 20 #include "pslib.h" 19 21 20 #if HAVE_CONFIG_H 22 21 #include <config.h> 23 22 #endif 23 24 24 #include "pmSubtractBias.h" 25 25 26 /*****************************************************************************/ 27 /* DEFINE STATEMENTS */ 28 /*****************************************************************************/ 26 #define PM_SUBTRACT_BIAS_POLYNOMIAL_ORDER 2 27 #define PM_SUBTRACT_BIAS_SPLINE_ORDER 3 28 29 29 // XXX: put these in psConstants.h 30 void PS_POLY1D_PRINT( 31 psPolynomial1D *poly) 30 void PS_POLY1D_PRINT(psPolynomial1D *poly) 32 31 { 33 32 printf("-------------- PS_POLY1D_PRINT() --------------\n"); … … 57 56 }\ 58 57 59 /*****************************************************************************/60 /* TYPE DEFINITIONS */61 /*****************************************************************************/62 63 /*****************************************************************************/64 /* GLOBAL VARIABLES */65 /*****************************************************************************/66 psS32 currentId = 0; // XXX: remove67 psS32 memLeaks = 0; // XXX: remove68 //PRINT_MEMLEAKS(8); XXX69 /*****************************************************************************/70 /* FILE STATIC VARIABLES */71 /*****************************************************************************/72 73 /*****************************************************************************/74 /* FUNCTION IMPLEMENTATION - LOCAL */75 /*****************************************************************************/76 77 58 /****************************************************************************** 78 psSubtractFrame(): this routine will take as input the pmReadout for the input 79 image and a pmReadout for the bias image. The bias image is subtracted in 80 place from the input image. We assume that sizes and types are checked 81 elsewhere. 82 83 XXX: Verify that the image and readout offsets are being used the right way. 84 85 XXX: Ensure that it does the correct thing with image size. 59 psSubtractFrame(): this routine will take as input a readout for the input 60 image and a readout for the bias image. The bias image is subtracted in 61 place from the input image. 86 62 *****************************************************************************/ 87 static pmReadout *SubtractFrame( 88 pmReadout *in, 89 const pmReadout *bias) 63 static pmReadout *SubtractFrame(pmReadout *in, 64 const pmReadout *bias) 90 65 { 91 // XXX: When did the ->row0 and ->col0 offsets get coded? 92 for (psS32 i=0;i<in->image->numRows;i++) { 93 for (psS32 j=0;j<in->image->numCols;j++) { 66 psS32 i; 67 psS32 j; 68 69 if (bias == NULL) { 70 psLogMsg(__func__, PS_LOG_WARN, 71 "WARNING: pmSubtractBias.c: SubtractFrame(): bias frame is NULL. Returning original image.\n"); 72 return(in); 73 } 74 75 76 if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) { 77 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows. Returning in image\n"); 78 return(in); 79 } 80 if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) { 81 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns. Returning in image\n"); 82 return(in); 83 } 84 85 for (i=0;i<in->image->numRows;i++) { 86 for (j=0;j<in->image->numCols;j++) { 94 87 in->image->data.F32[i][j]-= 95 88 bias->image->data.F32[i+in->row0-bias->row0][j+in->col0-bias->col0]; 96 97 89 if ((in->mask != NULL) && (bias->mask != NULL)) { 98 90 (in->mask->data.U8[i][j])|= … … 105 97 } 106 98 107 108 /******************************************************************************109 psSubtractDarkFrame(): this routine will take as input the pmReadout for the110 input image and a pmReadout for the dark image. The dark image is scaled and111 subtracted in place from the input image.112 113 XXX: Verify that the image and readout offsets are being used the right way.114 115 XXX: Ensure that it does the correct thing with image size.116 *****************************************************************************/117 static pmReadout *SubtractDarkFrame(118 pmReadout *in,119 const pmReadout *dark,120 psF32 scale)121 {122 // XXX: When did the ->row0 and ->col0 offsets get coded?123 if (fabs(scale) > FLT_EPSILON) {124 for (psS32 i=0;i<in->image->numRows;i++) {125 for (psS32 j=0;j<in->image->numCols;j++) {126 in->image->data.F32[i][j]-=127 (scale * dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0]);128 129 if ((in->mask != NULL) && (dark->mask != NULL)) {130 (in->mask->data.U8[i][j])|=131 dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0];132 }133 }134 }135 } else {136 for (psS32 i=0;i<in->image->numRows;i++) {137 for (psS32 j=0;j<in->image->numCols;j++) {138 in->image->data.F32[i][j]-=139 dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0];140 141 if ((in->mask != NULL) && (dark->mask != NULL)) {142 (in->mask->data.U8[i][j])|=143 dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0];144 }145 }146 }147 }148 149 return(in);150 }151 152 99 /****************************************************************************** 153 100 ImageSubtractScalar(): subtract a scalar from the input image. 154 101 155 XXX: Is there a psLib function for this? 102 XXX: Use a psLib function for this. 103 104 XXX: This should 156 105 *****************************************************************************/ 157 static psImage *ImageSubtractScalar( 158 psImage *image, 159 psF32 scalar) 106 static psImage *ImageSubtractScalar(psImage *image, 107 psF32 scalar) 160 108 { 161 109 for (psS32 i=0;i<image->numRows;i++) { … … 221 169 222 170 if (numOptions == 0) { 223 psError(PS_ERR_UNKNOWN,true, "No allowablestatistics options have been specified.\n");171 psError(PS_ERR_UNKNOWN,true, "No statistics options have been specified.\n"); 224 172 } 225 173 if (numOptions != 1) { … … 230 178 } 231 179 232 /****************************************************************************** 233 Polynomial1DCopy(): This private function copies the members of the existing 234 psPolynomial1D "in" into the existing psPolynomial1D "out". The previous 235 members of the existing psPolynomial1D "out" are psFree'ed. 236 *****************************************************************************/ 237 static psBool Polynomial1DCopy( 238 psPolynomial1D *out, 239 psPolynomial1D *in) 240 { 241 psFree(out->coeff); 242 psFree(out->coeffErr); 243 psFree(out->mask); 244 245 out->type = in->type; 246 out->nX = in->nX; 247 248 out->coeff = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64)); 249 // XXX: use memcpy 250 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 251 out->coeff[i] = in->coeff[i]; 252 } 253 254 out->coeffErr = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64)); 255 // XXX: use memcpy 256 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 257 out->coeffErr[i] = in->coeffErr[i]; 258 } 259 260 out->mask = (psMaskType *) psAlloc((in->nX + 1) * sizeof(psMaskType)); 261 // XXX: use memcpy 262 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 263 out->mask[i] = in->mask[i]; 264 } 265 266 return(true); 267 } 268 269 /****************************************************************************** 270 Polynomial1DDup(): This private function duplicates and then returns the input 271 psPolynomial1D "in". 272 *****************************************************************************/ 273 static psPolynomial1D *Polynomial1DDup( 274 psPolynomial1D *in) 275 { 276 psPolynomial1D *out = psPolynomial1DAlloc(in->nX, in->type); 277 Polynomial1DCopy(out, in); 278 return(out); 279 } 280 281 282 /****************************************************************************** 283 SplineCopy(): This private function copies the members of the existing 284 psSpline in into the existing psSpline out. 285 *****************************************************************************/ 286 static psBool SplineCopy( 287 psSpline1D *out, 288 psSpline1D *in) 289 { 290 PS_ASSERT_PTR_NON_NULL(out, false); 291 PS_ASSERT_PTR_NON_NULL(in, false); 292 293 for (psS32 i = 0 ; i < out->n ; i++) { 294 psFree(out->spline[i]); 295 } 296 psFree(out->spline); 297 psFree(out->knots); 298 psFree(out->p_psDeriv2); 299 300 out->n = in->n; 301 out->spline = (psPolynomial1D **) psAlloc(in->n * sizeof(psPolynomial1D *)); 302 for (psS32 i = 0 ; i < in->n ; i++) { 303 out->spline[i] = Polynomial1DDup(in->spline[i]); 304 } 305 306 // XXX: use psVectorCopy if they get it working. 307 out->knots = psVectorAlloc(in->knots->n, in->knots->type.type); 308 for (psS32 i = 0 ; i < in->knots->n ; i++) { 309 out->knots->data.F32[i] = in->knots->data.F32[i]; 310 } 311 /* 312 out->knots = psVectorCopy(out->knots, in->knots, in->knots->type.type); 313 */ 314 315 out->p_psDeriv2 = (psF32 *) psAlloc((in->n + 1) * sizeof(psF32)); 316 // XXX: use memcpy 317 for (psS32 i = 0 ; i < (in->n + 1) ; i++) { 318 out->p_psDeriv2[i] = in->p_psDeriv2[i]; 319 } 320 321 return(true); 322 } 180 323 181 324 182 /****************************************************************************** … … 328 186 PM_FIT_POLYNOMIAL: fit a polynomial to the entire input vector data. 329 187 PM_FIT_SPLINE: fit splines to the input vector data. 330 The resulting spline or polynomial is set in the fitSpec argument. 188 XXX: Doesn't it make more sense to do polynomial interpolation on a few 189 elements of the input vector, rather than fit a polynomial to the entire 190 vector? 331 191 *****************************************************************************/ 332 static psVector *ScaleOverscanVector( 333 psVector *overscanVector, 334 psS32 n, 335 void *fitSpec, 336 pmFit fit) 192 static psVector *ScaleOverscanVector(psVector *overscanVector, 193 psS32 n, 194 void *fitSpec, 195 pmFit fit) 337 196 { 338 197 psTrace(".psModule.pmSubtracBias.ScaleOverscanVector", 4, 339 198 "---- ScaleOverscanVector() begin (%d -> %d) ----\n", overscanVector->n, n); 199 // PS_VECTOR_PRINT_F32(overscanVector); 340 200 341 201 if (NULL == overscanVector) { … … 350 210 // 351 211 if (n == overscanVector->n) { 352 return(psVectorCopy(newVec, overscanVector, PS_TYPE_F32)); 353 } 212 for (psS32 i = 0 ; i < n ; i++) { 213 newVec->data.F32[i] = overscanVector->data.F32[i]; 214 } 215 return(newVec); 216 } 217 psPolynomial1D *myPoly; 218 psSpline1D *mySpline; 354 219 psF32 x; 355 220 psS32 i; 356 221 if (fit == PM_FIT_POLYNOMIAL) { 357 222 // Fit a polynomial to the old overscan vector. 358 psPolynomial1D *myPoly = (psPolynomial1D *) fitSpec;223 myPoly = (psPolynomial1D *) fitSpec; 359 224 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 360 PS_ASSERT_POLY1D(myPoly, NULL);361 225 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 362 226 if (myPoly == NULL) { 363 psError(PS_ERR_UNKNOWN, false, " Could not fit a polynomial to the psVector.\n");227 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector()(1): Could not fit a polynomial to the psVector.\n"); 364 228 return(NULL); 365 229 } … … 368 232 // of the old vector, use the fitted polynomial to determine the 369 233 // interpolated value at that point, and set the new vector. 370 for ( psS32i=0;i<n;i++) {234 for (i=0;i<n;i++) { 371 235 x = ((psF32) i) * ((psF32) overscanVector->n) / ((psF32) n); 372 236 newVec->data.F32[i] = psPolynomial1DEval(myPoly, x); 373 237 } 374 238 } else if (fit == PM_FIT_SPLINE) { 239 psS32 mustFreeSpline = 0; 240 // Fit a spline to the old overscan vector. 241 mySpline = (psSpline1D *) fitSpec; 242 // XXX: Does it make any sense to have a psSpline argument? 243 if (mySpline == NULL) { 244 mustFreeSpline = 1; 245 } 246 375 247 // 376 248 // NOTE: Since the X arg in the psVectorFitSpline1D() function is NULL, … … 378 250 // properly when doing the spline eval. 379 251 // 380 psSpline1D *mySpline = psVectorFitSpline1D(NULL, overscanVector); 252 // mySpline = psVectorFitSpline1D(mySpline, NULL, overscanVector, NULL); 253 mySpline = psVectorFitSpline1D(NULL, overscanVector); 381 254 if (mySpline == NULL) { 382 psError(PS_ERR_UNKNOWN, false, " Could not fit a spline to the psVector.\n");255 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector()(2): Could not fit a spline to the psVector.\n"); 383 256 return(NULL); 384 257 } 258 // PS_PRINT_SPLINE(mySpline); 385 259 386 260 // For each element of the new vector, convert the x-ordinate to that 387 // of the old vector, use the fitted splineto determine the261 // of the old vector, use the fitted polynomial to determine the 388 262 // interpolated value at that point, and set the new vector. 389 for ( psS32i=0;i<n;i++) {263 for (i=0;i<n;i++) { 390 264 // Scale to [0 : overscanVector->n - 1] 391 265 x = ((psF32) i) * ((psF32) (overscanVector->n-1)) / ((psF32) n); 392 266 newVec->data.F32[i] = psSpline1DEval(mySpline, x); 393 267 } 394 395 psSpline1D *ptrSpline = (psSpline1D *) fitSpec; 396 if (ptrSpline != NULL) { 397 // Copy the resulting spline fit into ptrSpline. 398 PS_ASSERT_SPLINE(ptrSpline, NULL); 399 SplineCopy(ptrSpline, mySpline); 400 } 401 psFree(mySpline); 268 if (mustFreeSpline ==1) { 269 psFree(mySpline); 270 } 271 // PS_VECTOR_PRINT_F32(newVec); 272 273 402 274 } else { 403 275 psError(PS_ERR_UNKNOWN, true, "unknown fit type. Returning NULL.\n"); … … 412 284 413 285 /****************************************************************************** 286 XXX: The SDRS does not specify type support. F32 is implemented here. 414 287 *****************************************************************************/ 415 static psS32 GetOverscanSize( 416 psImage *inImg, 417 pmOverscanAxis overScanAxis) 418 { 419 if (overScanAxis == PM_OVERSCAN_ROWS) { 420 return(inImg->numCols); 421 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 422 return(inImg->numRows); 423 } else if (overScanAxis == PM_OVERSCAN_ALL) { 424 return(1); 425 } 426 return(0); 427 } 428 429 /****************************************************************************** 430 GetOverscanAxis(in) this private routine determines the appropiate overscan 431 axis from the parent cell metadata. 432 433 XXX: Verify the READDIR corresponds with my overscan axis. 434 *****************************************************************************/ 435 static pmOverscanAxis GetOverscanAxis(pmReadout *in) 436 { 437 psBool rc; 438 if ((in->parent != NULL) && (in->parent->concepts)) { 439 psS32 dir = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.READDIR"); 440 if (rc == true) { 441 if (dir == 1) { 442 return(PM_OVERSCAN_ROWS); 443 } else if (dir == 2) { 444 return(PM_OVERSCAN_COLUMNS); 445 } else if (dir == 3) { 446 return(PM_OVERSCAN_ALL); 447 } 448 } 449 } 450 451 psLogMsg(__func__, PS_LOG_WARN, 452 "WARNING: pmSubtractBias.(): could not determine CELL.READDIR from in->parent metadata. Setting overscan axis to PM_OVERSCAN_NONE.\n"); 453 return(PM_OVERSCAN_NONE); 454 } 455 456 /****************************************************************************** 457 psListLength(list): determine the length of a psList. 458 459 XXX: Put this elsewhere. 460 *****************************************************************************/ 461 static psS32 psListLength( 462 psList *list) 463 { 464 psS32 length = 0; 465 psListElem *tmpElem = (psListElem *) list->head; 466 while (NULL != tmpElem) { 467 tmpElem = tmpElem->next; 468 length++; 469 } 470 return(length); 471 } 472 473 /****************************************************************************** 474 Note: this isn't needed anymore as of psModule SDRS 12-09. 475 *****************************************************************************/ 476 static psBool OverscanReducePixel( 477 psImage *in, 478 psList *bias, 479 psStats *myStats) 480 { 481 PS_ASSERT_PTR_NON_NULL(in, NULL); 482 PS_ASSERT_PTR_NON_NULL(bias, NULL); 483 PS_ASSERT_PTR_NON_NULL(bias->head, NULL); 484 PS_ASSERT_PTR_NON_NULL(myStats, NULL); 485 486 // Allocate a psVector with one element per overscan image. 487 psS32 numOverscanImages = psListLength(bias); 488 psVector *statsAll = psVectorAlloc(numOverscanImages, PS_TYPE_F32); 489 psListElem *tmpOverscan = (psListElem *) bias->head; 490 psS32 i = 0; 491 psF64 statValue; 492 // 493 // We loop through each overscan image, calculating the specified 494 // statistic on that image. 495 // 496 while (NULL != tmpOverscan) { 497 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 498 499 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 500 myStats = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff); 501 if (myStats == NULL) { 502 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 503 psFree(statsAll); 504 return(false); 505 } 506 if (false == p_psGetStatValue(myStats, &statValue)) { 507 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 508 psFree(statsAll); 509 return(false); 510 } 511 statsAll->data.F32[i] = statValue; 512 i++; 513 tmpOverscan = tmpOverscan->next; 514 } 515 516 // 517 // We reduce the individual stats for each overscan image to 518 // a single psF32. 519 // 520 myStats = psVectorStats(myStats, statsAll, NULL, NULL, 0); 521 if (myStats == NULL) { 522 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 523 psFree(statsAll); 524 return(false); 525 } 526 if (false == p_psGetStatValue(myStats, &statValue)) { 527 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 528 psFree(statsAll); 529 return(false); 530 } 531 532 // 533 // Subtract the result and return. 534 // 535 ImageSubtractScalar(in, statValue); 536 psFree(statsAll); 537 return(in); 538 } 539 540 /****************************************************************************** 541 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces 542 a single psImage to a column by combining all pixels from each row into a 543 single pixel via requested statistic in myStats. 544 *****************************************************************************/ 545 static psVector *ReduceOverscanImageToCol( 546 psImage *overscanImage, 547 psStats *myStats) 548 { 549 psF64 statValue; 550 psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32); 551 psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32); 552 553 // 554 // For each row, we store all pixels in that row into a temporary psVector, 555 // then we run psVectorStats() on that vector. 556 // 557 for (psS32 i=0;i<overscanImage->numRows;i++) { 558 for (psS32 j=0;j<overscanImage->numCols;j++) { 559 tmpRow->data.F32[j] = overscanImage->data.F32[i][j]; 560 } 561 562 psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0); 563 if (rc == NULL) { 564 psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation. Returning in image.\n"); 565 return(NULL); 566 } 567 568 if (false == p_psGetStatValue(rc, &statValue)) { 569 psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation. Returning in image.\n"); 570 return(NULL); 571 } 572 573 tmpCol->data.F32[i] = (psF32) statValue; 574 } 575 psFree(tmpRow); 576 577 return(tmpCol); 578 } 579 580 /****************************************************************************** 581 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces 582 a single psImage to a row by combining all pixels from each column into a 583 single pixel via requested statistic in myStats. 584 *****************************************************************************/ 585 static psVector *ReduceOverscanImageToRow( 586 psImage *overscanImage, 587 psStats *myStats) 588 { 589 psF64 statValue; 590 psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32); 591 psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32); 592 593 // 594 // For each column, we store all pixels in that column into a temporary psVector, 595 // then we run psVectorStats() on that vector. 596 // 597 for (psS32 i=0;i<overscanImage->numCols;i++) { 598 for (psS32 j=0;j<overscanImage->numRows;j++) { 599 tmpCol->data.F32[j] = overscanImage->data.F32[j][i]; 600 } 601 602 psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0); 603 if (rc == NULL) { 604 psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation. Returning in image.\n"); 605 return(NULL); 606 } 607 608 if (false == p_psGetStatValue(rc, &statValue)) { 609 psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation. Returning in image.\n"); 610 return(NULL); 611 } 612 613 tmpRow->data.F32[i] = (psF32) statValue; 614 } 615 psFree(tmpCol); 616 617 return(tmpRow); 618 } 619 620 /****************************************************************************** 621 OverscanReduce(vecSize, bias, myStats): This private routine takes a psList of 622 overscan images (in bias) and reduces them to a single psVector via the 623 specified psStats struct. The vector is then scaled to the length or the 624 row/column in inImg. 625 *****************************************************************************/ 626 static psVector* OverscanReduce( 627 psImage *inImg, 628 pmOverscanAxis overScanAxis, 629 psList *bias, 630 void *fitSpec, 631 pmFit fit, 632 psStats *myStats) 633 { 634 if ((overScanAxis != PM_OVERSCAN_ROWS) && (overScanAxis != PM_OVERSCAN_COLUMNS)) { 635 psError(PS_ERR_UNKNOWN, true, "overScanAxis must be PM_OVERSCAN_ROWS or PM_OVERSCAN_COLUMNS\n"); 636 return(NULL); 637 } 638 PS_ASSERT_PTR_NON_NULL(inImg, NULL); 639 PS_ASSERT_PTR_NON_NULL(bias, NULL); 640 PS_ASSERT_PTR_NON_NULL(bias->head, NULL); 641 PS_ASSERT_PTR_NON_NULL(myStats, NULL); 642 // 643 // Allocate a psVector for the output of this routine. 644 // 645 psS32 vecSize = GetOverscanSize(inImg, overScanAxis); 646 psVector *overscanVector = psVectorAlloc(vecSize, PS_TYPE_F32); 647 648 // 649 // Allocate an array of psVectors with one psVector per element of the 650 // final oversan column vector. These psVectors will be used with 651 // psStats to reduce the multiple elements from each overscan column 652 // vector to a single final column vector. 653 // 654 psS32 numOverscanImages = psListLength(bias); 655 psVector **overscanVectors = (psVector **) psAlloc(numOverscanImages * sizeof(psVector *)); 656 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 657 overscanVectors[i] = NULL; 658 } 659 660 // 661 // We iterate through the list of overscan images. For each image, 662 // we reduce it to a single column or row. Save the overscan vector 663 // in overscanVectors[]. 664 // 665 psListElem *tmpOverscan = (psListElem *) bias->head; 666 psS32 overscanID = 0; 667 while (tmpOverscan != NULL) { 668 psImage *tmpOverscanImage = (psImage *) tmpOverscan->data; 669 if (overScanAxis == PM_OVERSCAN_ROWS) { 670 overscanVectors[overscanID] = ReduceOverscanImageToRow(tmpOverscanImage, myStats); 671 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 672 overscanVectors[overscanID] = ReduceOverscanImageToCol(tmpOverscanImage, myStats); 673 } 674 675 tmpOverscan = tmpOverscan->next; 676 overscanID++; 677 } 678 679 // 680 // For each overscan vector, if necessary, we scale that column or 681 // row to vecSize. Note: we should have already ensured that the 682 // fit is poly or spline. 683 // 684 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 685 psVector *tmpOverscanVector = overscanVectors[i]; 686 687 if (tmpOverscanVector->n != vecSize) { 688 overscanVectors[i] = ScaleOverscanVector(tmpOverscanVector, vecSize, fitSpec, fit); 689 if (overscanVectors[i] == NULL) { 690 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector.\n"); 691 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 692 psFree(overscanVectors[i]); 693 } 694 psFree(overscanVectors); 695 psFree(tmpOverscanVector); 696 return(NULL); 697 } 698 psFree(tmpOverscanVector); 699 } 700 } 701 702 // 703 // We collect all elements in the overscan vectors for the various 704 // overscan images into a single psVector (tmpVec). Then we call 705 // psStats on that vector to determine the final values for the 706 // overscan vector. 707 // 708 psVector *tmpVec = psVectorAlloc(numOverscanImages, PS_TYPE_F32); 709 psF64 statValue; 710 for (psS32 i = 0 ; i < vecSize ; i++) { 711 // Collect the i-th elements from each overscan vector into a single vector. 712 for (psS32 j = 0 ; j < numOverscanImages ; j++) { 713 tmpVec->data.F32[j] = overscanVectors[j]->data.F32[i]; 714 } 715 716 if (NULL == psVectorStats(myStats, tmpVec, NULL, NULL, 0)) { 717 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 718 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 719 psFree(overscanVectors[i]); 720 } 721 psFree(overscanVectors); 722 psFree(tmpVec); 723 return(NULL); 724 } 725 if (false == p_psGetStatValue(myStats, &statValue)) { 726 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 727 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 728 psFree(overscanVectors[i]); 729 } 730 psFree(overscanVectors); 731 psFree(tmpVec); 732 return(NULL); 733 } 734 735 overscanVector->data.F32[i] = (psF32) statValue; 736 } 737 738 // 739 // We're done. Free the intermediate overscan vectors. 740 // 741 psFree(tmpVec); 742 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 743 psFree(overscanVectors[i]); 744 } 745 psFree(overscanVectors); 746 747 // 748 // Return the computed overscanVector 749 // 750 return(overscanVector); 751 } 752 753 /****************************************************************************** 754 RebinOverscanVector(overscanVector, nBinOrig, myStats): this private routine 755 takes groups of nBinOrig elements in the input vector, combines them into a 756 single pixel via myStats and psVectorStats(), and then outputs a vector of 757 those pixels. 758 *****************************************************************************/ 759 static psS32 RebinOverscanVector( 760 psVector *overscanVector, 761 psS32 nBinOrig, 762 psStats *myStats) 763 { 764 psF64 statValue; 765 psS32 nBin; 766 if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) { 767 psS32 numBins = 1+((overscanVector->n)/nBinOrig); 768 psVector *myBin = psVectorAlloc(numBins, PS_TYPE_F32); 769 psVector *binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32); 770 771 for (psS32 i=0;i<numBins;i++) { 772 for(psS32 j=0;j<nBinOrig;j++) { 773 if (overscanVector->n > ((i*nBinOrig)+j)) { 774 binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j]; 775 } else { 776 // XXX: we get here if nBinOrig does not evenly divide 777 // the overscanVector vector. This is the last bin. Should 778 // we change the binVec->n to acknowledge that? 779 binVec->n = j; 780 } 781 } 782 psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0); 783 if (rc == NULL) { 784 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 785 return(-1); 786 } 787 if (false == p_psGetStatValue(rc, &statValue)) { 788 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 789 return(-1); 790 } 791 myBin->data.F32[i] = statValue; 792 } 793 794 // Change the effective size of overscanVector. 795 overscanVector->n = numBins; 796 for (psS32 i=0;i<numBins;i++) { 797 overscanVector->data.F32[i] = myBin->data.F32[i]; 798 } 799 psFree(binVec); 800 psFree(myBin); 801 nBin = nBinOrig; 802 } else { 803 nBin = 1; 804 } 805 806 return(nBin); 807 } 808 809 /****************************************************************************** 810 FitOverscanVectorAndUnbin(inImg, overscanVector, overScanAxis, fitSpec, fit, 811 nBin): this private routine fits a psPolynomial or psSpline to the overscan 812 vector. It then creates a new vector, with a size determined by the input 813 image, evaluates the psPolynomial or psSpline at each element in that vector, 814 then returns that vector. 815 *****************************************************************************/ 816 static psVector *FitOverscanVectorAndUnbin( 817 psImage *inImg, 818 psVector *overscanVector, 819 pmOverscanAxis overScanAxis, 820 void *fitSpec, 821 pmFit fit, 822 psS32 nBin) 823 { 824 psPolynomial1D* myPoly = NULL; 825 psSpline1D *mySpline = NULL; 826 // 827 // Fit a polynomial or spline to the overscan vector. 828 // 829 if (fit == PM_FIT_POLYNOMIAL) { 830 myPoly = (psPolynomial1D *) fitSpec; 831 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 832 PS_ASSERT_POLY1D(myPoly, NULL); 833 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 834 if (myPoly == NULL) { 835 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to overscan vector. Returning NULL.\n"); 836 return(NULL); 837 } 838 } else if (fit == PM_FIT_SPLINE) { 839 mySpline = psVectorFitSpline1D(NULL, overscanVector); 840 if (mySpline == NULL) { 841 psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector. Returning NULL.\n"); 842 return(NULL); 843 } 844 if (fitSpec != NULL) { 845 // Copy the resulting spline fit into fitSpec. 846 psSpline1D *ptrSpline = (psSpline1D *) fitSpec; 847 PS_ASSERT_SPLINE(ptrSpline, NULL); 848 SplineCopy(ptrSpline, mySpline); 849 } 850 } 851 852 // 853 // Evaluate the poly/spline at each pixel in the overscan row/column. 854 // 855 psS32 vecSize = GetOverscanSize(inImg, overScanAxis); 856 psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32); 857 if ((nBin > 1) && (nBin < overscanVector->n)) { 858 for (psS32 i = 0 ; i < vecSize ; i++) { 859 if (fit == PM_FIT_POLYNOMIAL) { 860 newVec->data.F32[i] = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 861 } else if (fit == PM_FIT_SPLINE) { 862 newVec->data.F32[i] = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 863 } 864 } 865 } else { 866 for (psS32 i = 0 ; i < vecSize ; i++) { 867 if (fit == PM_FIT_POLYNOMIAL) { 868 newVec->data.F32[i] = psPolynomial1DEval(myPoly, (psF32) i); 869 } else if (fit == PM_FIT_SPLINE) { 870 newVec->data.F32[i] = psSpline1DEval(mySpline, (psF32) i); 871 } 872 } 873 } 874 875 psFree(mySpline); 876 psFree(overscanVector); 877 return(newVec); 878 } 879 880 881 882 /****************************************************************************** 883 UnbinOverscanVector(inImg, overscanVector, overScanAxis, nBin): this private 884 routine takes a psVector overscanVector that was previously binned by a factor 885 of nBin, and then expands it to its original size, duplicated elements nBin 886 times for each element in the input vector overscanVector. 887 *****************************************************************************/ 888 static psVector *UnbinOverscanVector( 889 psImage *inImg, 890 psVector *overscanVector, 891 pmOverscanAxis overScanAxis, 892 psS32 nBin) 893 { 894 psS32 vecSize; 895 896 if (overScanAxis == PM_OVERSCAN_ROWS) { 897 vecSize = inImg->numCols; 898 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 899 vecSize = inImg->numRows; 900 } 901 902 psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32); 903 for (psS32 i = 0 ; i < vecSize ; i++) { 904 newVec->data.F32[i] = overscanVector->data.F32[i/nBin]; 905 } 906 907 psFree(overscanVector); 908 return(newVec); 909 } 910 911 912 /****************************************************************************** 913 SubtractVectorFromImage(inImg, overscanVector, overScanAxis): this private 914 routine subtracts the overscanVector column-wise or row-wise from inImg. 915 *****************************************************************************/ 916 static psImage *SubtractVectorFromImage( 917 psImage *inImg, 918 psVector *overscanVector, 919 pmOverscanAxis overScanAxis) 920 { 921 // 922 // Subtract overscan vector row-wise from the image. 923 // 924 if (overScanAxis == PM_OVERSCAN_ROWS) { 925 for (psS32 i=0;i<inImg->numCols;i++) { 926 for (psS32 j=0;j<inImg->numRows;j++) { 927 inImg->data.F32[j][i]-= overscanVector->data.F32[i]; 928 } 929 } 930 } 931 932 // 933 // Subtract overscan vector column-wise from the image. 934 // 935 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 936 for (psS32 i=0;i<inImg->numRows;i++) { 937 for (psS32 j=0;j<inImg->numCols;j++) { 938 inImg->data.F32[i][j]-= overscanVector->data.F32[i]; 939 } 940 } 941 } 942 943 return(inImg); 944 } 945 946 947 948 typedef enum { 949 PM_ERROR_NO_SUBTRACTION, 950 PM_WARNING_NO_SUBTRACTION, 951 PM_ERROR_NO_BIAS_SUBTRACT, 952 PM_WARNING_NO_BIAS_SUBTRACT, 953 PM_ERROR_NO_DARK_SUBTRACT, 954 PM_WARNING_NO_DARK_SUBTRACT, 955 PM_OKAY 956 } pmSubtractBiasAssertStatus; 957 /****************************************************************************** 958 AssertCodeOverscan(....) this private routine verifies that the various input 959 parameters to pmSubtractBias() are correct for overscan subtraction. 960 *****************************************************************************/ 961 pmSubtractBiasAssertStatus AssertCodeOverscan( 962 pmReadout *in, 963 void *fitSpec, 964 pmFit fit, 965 bool overscan, 966 psStats *stat, 967 int nBinOrig, 968 const pmReadout *bias, 969 const pmReadout *dark) 970 { 971 972 PS_ASSERT_READOUT_NON_NULL(in, PM_ERROR_NO_SUBTRACTION); 973 PS_ASSERT_READOUT_NON_EMPTY(in, PM_ERROR_NO_SUBTRACTION); 974 PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION); 975 PS_WARN_PTR_NON_NULL(in->parent); 976 if (in->parent != NULL) { 977 PS_WARN_PTR_NON_NULL(in->parent->concepts); 978 } 979 980 if (overscan == true) { 981 pmOverscanAxis overScanAxis = GetOverscanAxis(in); 982 PS_ASSERT_PTR_NON_NULL(stat, PM_ERROR_NO_SUBTRACTION); 983 PS_ASSERT_PTR_NON_NULL(in->bias, PM_ERROR_NO_SUBTRACTION); 984 PS_ASSERT_PTR_NON_NULL(in->bias->head, PM_ERROR_NO_SUBTRACTION); 985 // 986 // Check the type, size of each bias image. 987 // 988 psListElem *tmpOverscan = (psListElem *) in->bias->head; 989 psS32 numOverscans = 0; 990 while (NULL != tmpOverscan) { 991 numOverscans++; 992 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 993 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION); 994 // XXX: Get this right with the rows and columns. 995 if (overScanAxis == PM_OVERSCAN_ROWS) { 996 if (myOverscanImage->numRows != in->image->numRows) { 997 psLogMsg(__func__, PS_LOG_WARN, 998 "WARNING: pmSubtractBias.(): overscan image (# %d) has %d rows, input image has %d rows\n", 999 numOverscans, myOverscanImage->numCols, in->image->numRows); 1000 if (fit == PM_FIT_NONE) { 1001 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors. Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n"); 1002 return(PM_ERROR_NO_SUBTRACTION); 1003 } 1004 } 1005 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 1006 if (myOverscanImage->numCols != in->image->numCols) { 1007 psLogMsg(__func__, PS_LOG_WARN, 1008 "WARNING: pmSubtractBias.(): overscan image (# %d) has %d columns, input image has %d columns\n", 1009 numOverscans, myOverscanImage->numCols, in->image->numCols); 1010 if (fit == PM_FIT_NONE) { 1011 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors. Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n"); 1012 return(PM_ERROR_NO_SUBTRACTION); 1013 } 1014 } 1015 } else if (overScanAxis != PM_OVERSCAN_ALL) { 1016 psError(PS_ERR_UNKNOWN, true, "Must specify and overscan axis.\n"); 1017 return(PM_ERROR_NO_SUBTRACTION); 1018 } 1019 tmpOverscan = tmpOverscan->next; 1020 } 1021 } else { 1022 if (fit != PM_FIT_NONE) { 1023 psLogMsg(__func__, PS_LOG_WARN, 1024 "WARNING: pmSubtractBias.(): overscan is FALSE and fit is not PM_FIT_NONE.\n"); 1025 return(PM_WARNING_NO_SUBTRACTION); 1026 } 1027 } 1028 1029 // XXX: I do not like the following spec since it's useless to specify 1030 // a psSpline as the fitSpec. 1031 if (0) { 1032 if ((fitSpec == NULL) && 1033 ((fit != PM_FIT_NONE) || (overscan == true))) { 1034 psError(PS_ERR_UNKNOWN, true, "fitSpec is NULL and fit is not PM_FIT_NONE or overscan is TRUE.\n"); 1035 return(PM_ERROR_NO_SUBTRACTION); 1036 } 1037 } 1038 1039 return(PM_OKAY); 1040 } 1041 1042 /****************************************************************************** 1043 AssertCodeBias(....) this private routine verifies that the various input 1044 parameters to pmSubtractBias() are correct for bias subtraction. 1045 *****************************************************************************/ 1046 static pmSubtractBiasAssertStatus AssertCodeBias( 1047 pmReadout *in, 1048 void *fitSpec, 1049 pmFit fit, 1050 bool overscan, 1051 psStats *stat, 1052 int nBinOrig, 1053 const pmReadout *bias, 1054 const pmReadout *dark) 1055 { 1056 if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) { 1057 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows. Returning in image\n"); 1058 return(PM_ERROR_NO_BIAS_SUBTRACT); 1059 } 1060 if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) { 1061 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns. Returning in image\n"); 1062 return(PM_ERROR_NO_BIAS_SUBTRACT); 1063 } 1064 1065 if (bias != NULL) { 1066 PS_ASSERT_READOUT_NON_EMPTY(bias, PM_ERROR_NO_BIAS_SUBTRACT); 1067 PS_ASSERT_READOUT_TYPE(bias, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT); 1068 } 1069 return(PM_OKAY); 1070 } 1071 1072 /****************************************************************************** 1073 AssertCodeDark(....) this private routine verifies that the various input 1074 parameters to pmSubtractBias() are correct for dark subtraction. 1075 *****************************************************************************/ 1076 pmSubtractBiasAssertStatus AssertCodeDark( 1077 pmReadout *in, 1078 void *fitSpec, 1079 pmFit fit, 1080 bool overscan, 1081 psStats *stat, 1082 int nBinOrig, 1083 const pmReadout *bias, 1084 const pmReadout *dark) 1085 { 1086 if ((in->image->numRows + in->row0 - dark->row0) > dark->image->numRows) { 1087 psError(PS_ERR_UNKNOWN, true, "dark image does not have enough rows. Returning in image\n"); 1088 return(PM_ERROR_NO_DARK_SUBTRACT); 1089 } 1090 if ((in->image->numCols + in->col0 - dark->col0) > dark->image->numCols) { 1091 psError(PS_ERR_UNKNOWN, true, "dark image does not have enough columns. Returning in image\n"); 1092 return(PM_ERROR_NO_DARK_SUBTRACT); 1093 } 1094 1095 if (dark != NULL) { 1096 PS_ASSERT_READOUT_NON_EMPTY(dark, PM_ERROR_NO_DARK_SUBTRACT); 1097 PS_ASSERT_READOUT_TYPE(dark, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT); 1098 } 1099 return(PM_OKAY); 1100 } 1101 1102 /****************************************************************************** 1103 p_psDetermineTrimmedImage(): global routine: determines the region of the 1104 input pmReadout which will be operated on by the various detrend modules. It 1105 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout. 1106 1107 Use it this way: 1108 PS_WARN_PTR_NON_NULL(in->parent); 1109 if (in->parent != NULL) { 1110 PS_WARN_PTR_NON_NULL(in->parent->concepts); 1111 } 1112 // 1113 // Determine trimmed image from metadata. 1114 // 1115 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 1116 1117 XXX: Create a pmUtils.c file and put this routine there. 1118 *****************************************************************************/ 1119 psImage *p_psDetermineTrimmedImage(pmReadout *in) 1120 { 1121 if ((in->parent == NULL) || (in->parent->concepts == NULL)) { 1122 psLogMsg(__func__, PS_LOG_WARN, 1123 "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata (NULL).\n"); 1124 return(in->image); 1125 } 1126 1127 psBool rc = false; 1128 psImage *trimmedImg = NULL; 1129 psRegion *trimRegion = psMetadataLookupPtr(&rc, in->parent->concepts, 1130 "CELL.TRIMSEC"); 1131 if (rc == false) { 1132 psLogMsg(__func__, PS_LOG_WARN, 1133 "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata.\n"); 1134 trimmedImg = in->image; 1135 } else { 1136 trimmedImg = psImageSubset(in->image, *trimRegion); 1137 } 1138 1139 return(trimmedImg); 1140 } 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 /****************************************************************************** 1160 pmSubtractBias(....): see SDRS for complete specification. 1161 1162 XXX: Code and assert type support: U16, S32, F32. 1163 XXX: Add trace messages. 1164 *****************************************************************************/ 1165 pmReadout *pmSubtractBias( 1166 pmReadout *in, 1167 void *fitSpec, 1168 pmFit fit, 1169 bool overscan, 1170 psStats *stat, 1171 int nBin, 1172 const pmReadout *bias, 1173 const pmReadout *dark) 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) 1174 296 { 1175 297 psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4, 1176 298 "---- pmSubtractBias() begin ----\n"); 1177 // 1178 // Check input parameters, generate warnings and errors. 1179 // 1180 if (PM_OKAY != AssertCodeOverscan(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 1181 return(in); 1182 } 1183 // 1184 // Determine trimmed image from metadata. 1185 // 1186 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 1187 1188 // 1189 // Subtract overscan frames if necessary. 1190 // 1191 if (overscan == true) { 1192 pmOverscanAxis overScanAxis = GetOverscanAxis(in); 299 PS_ASSERT_READOUT_NON_NULL(in, NULL); 300 PS_ASSERT_READOUT_NON_EMPTY(in, NULL); 301 PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL); 302 303 // 304 // If the overscans != NULL, then check the type of each image. 305 // 306 if (overscans != NULL) { 307 psListElem *tmpOverscan = (psListElem *) overscans->head; 308 while (NULL != tmpOverscan) { 309 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 310 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 311 tmpOverscan = tmpOverscan->next; 312 } 313 } 314 315 if ((overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE)) { 316 psError(PS_ERR_UNKNOWN,true, "(overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE). Returning in image\n"); 317 return(in); 318 } 319 320 // Check for an unallowable pmFit. 321 if ((fit != PM_OVERSCAN_NONE) && 322 (fit != PM_OVERSCAN_ROWS) && 323 (fit != PM_OVERSCAN_COLUMNS) && 324 (fit != PM_OVERSCAN_ALL)) { 325 psError(PS_ERR_UNKNOWN, true, "fit is unallowable (%d). Returning in image.\n", fit); 326 return(in); 327 } 328 // Check for an unallowable pmOverscanAxis. 329 if ((overScanAxis != PM_OVERSCAN_NONE) && 330 (overScanAxis != PM_OVERSCAN_ROWS) && 331 (overScanAxis != PM_OVERSCAN_COLUMNS) && 332 (overScanAxis != PM_OVERSCAN_ALL)) { 333 psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d). Returning in image.\n", overScanAxis); 334 return(in); 335 } 336 psS32 i; 337 psS32 j; 338 psS32 numBins = 0; 339 static psVector *overscanVector = NULL; 340 psVector *tmpRow = NULL; 341 psVector *tmpCol = NULL; 342 psVector *myBin = NULL; 343 psVector *binVec = NULL; 344 psListElem *tmpOverscan = NULL; 345 double statValue; 346 psImage *myOverscanImage = NULL; 347 psPolynomial1D *myPoly = NULL; 348 psSpline1D *mySpline = NULL; 349 psS32 nBin; 350 351 // 352 // Create a static stats data structure and determine the highest 353 // priority stats option. 354 // 355 static psStats *myStats = NULL; 356 if (myStats == NULL) { 357 myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); 358 p_psMemSetPersistent(myStats, true); 359 } 360 if (stat != NULL) { 361 myStats->options = GenNewStatOptions(stat); 362 } 363 364 365 if (overScanAxis == PM_OVERSCAN_NONE) { 366 if (fit != PM_FIT_NONE) { 367 psLogMsg(__func__, PS_LOG_WARN, 368 "WARNING: pmSubtractBias.(): overScanAxis equals NONE, and fit does not equal NONE. Proceeding to full fram subtraction.\n"); 369 } 370 371 if (overscans != NULL) { 372 psLogMsg(__func__, PS_LOG_WARN, 373 "WARNING: pmSubtractBias.(): overScanAxis equals NONE and overscans does not equal NULL. Proceeding to full fram subtraction.\n"); 374 } 375 return(SubtractFrame(in, bias)); 376 } 377 378 if ((overScanAxis == PM_OVERSCAN_ALL) && (fit != PM_FIT_NONE)) { 379 psLogMsg(__func__, PS_LOG_WARN, 380 "WARNING: pmSubtractBias.(): overScanAxis equals ALL, and fit does not equal NONE. Proceeding with the rest of the module.\n"); 381 } 382 383 384 // 385 // We subtract each overscan region from the image data. 386 // If we get here we know that overscans != NULL. 387 // 388 389 if (overScanAxis == PM_OVERSCAN_ALL) { 390 tmpOverscan = (psListElem *) overscans->head; 391 while (NULL != tmpOverscan) { 392 myOverscanImage = (psImage *) tmpOverscan->data; 393 394 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 395 psStats *rc = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff); 396 if (rc == NULL) { 397 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 398 return(in); 399 } 400 if (false == p_psGetStatValue(myStats, &statValue)) { 401 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 402 return(in); 403 } 404 ImageSubtractScalar(in->image, statValue); 405 406 tmpOverscan = tmpOverscan->next; 407 } 408 return(in); 409 } 410 411 // This check is redundant with above code. 412 if (!((overScanAxis == PM_OVERSCAN_ROWS) || (overScanAxis == PM_OVERSCAN_COLUMNS))) { 413 psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d).\nReturning in image.\n", overScanAxis); 414 return(in); 415 } 416 417 tmpOverscan = (psListElem *) overscans->head; 418 while (NULL != tmpOverscan) { 419 // PS_IMAGE_PRINT_F32_HIDEF(in->image); 420 myOverscanImage = (psImage *) tmpOverscan->data; 421 422 if (overScanAxis == PM_OVERSCAN_ROWS) { 423 if (myOverscanImage->numCols != (in->image)->numCols) { 424 psLogMsg(__func__, PS_LOG_WARN, 425 "WARNING: pmSubtractBias.(): overscan image has %d columns, input image has %d columns\n", 426 myOverscanImage->numCols, in->image->numCols); 427 } 428 429 // We create a row vector and subtract this vector from image. 430 // XXX: Is there a better way to extract a psVector from a psImage without 431 // having to copy every element in that vector? 432 overscanVector = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32); 433 for (i=0;i<overscanVector->n;i++) { 434 overscanVector->data.F32[i] = 0.0; 435 } 436 tmpRow = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32); 437 438 // For each column of the input image, loop through every row, 439 // collect the pixel in that row, then performed the specified 440 // statistical op on those pixels. Store this in overscanVector. 441 for (i=0;i<myOverscanImage->numCols;i++) { 442 for (j=0;j<myOverscanImage->numRows;j++) { 443 tmpRow->data.F32[j] = myOverscanImage->data.F32[j][i]; 444 } 445 psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0); 446 if (rc == NULL) { 447 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 448 return(in); 449 } 450 if (false == p_psGetStatValue(rc, &statValue)) { 451 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 452 return(in); 453 } 454 overscanVector->data.F32[i] = statValue; 455 } 456 psFree(tmpRow); 457 458 // Scale the overscan vector to the size of the input image. 459 if (overscanVector->n != in->image->numCols) { 460 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 461 psVector *newVec = ScaleOverscanVector(overscanVector, 462 in->image->numCols, 463 fitSpec, fit); 464 if (newVec == NULL) { 465 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector. Returning in image.\n"); 466 return(in); 467 } 468 psFree(overscanVector); 469 overscanVector = newVec; 470 } else { 471 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector. Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL. Returning in image.\n"); 472 psFree(overscanVector); 473 return(in); 474 } 475 } 476 } 477 478 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 479 if (myOverscanImage->numRows != (in->image)->numRows) { 480 psLogMsg(__func__, PS_LOG_WARN, 481 "WARNING: pmSubtractBias.(): overscan image has %d rows, input image has %d rows\n", 482 myOverscanImage->numRows, in->image->numRows); 483 } 484 485 // We create a column vector and subtract this vector from image. 486 overscanVector = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32); 487 for (i=0;i<overscanVector->n;i++) { 488 overscanVector->data.F32[i] = 0.0; 489 } 490 tmpCol = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32); 491 492 // For each row of the input image, loop through every column, 493 // collect the pixel in that row, then performed the specified 494 // statistical op on those pixels. Store this in overscanVector. 495 for (i=0;i<myOverscanImage->numRows;i++) { 496 for (j=0;j<myOverscanImage->numCols;j++) { 497 tmpCol->data.F32[j] = myOverscanImage->data.F32[i][j]; 498 } 499 psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0); 500 if (rc == NULL) { 501 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 502 return(in); 503 } 504 if (false == p_psGetStatValue(rc, &statValue)) { 505 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 506 return(in); 507 } 508 overscanVector->data.F32[i] = statValue; 509 } 510 psFree(tmpCol); 511 512 // Scale the overscan vector to the size of the input image. 513 if (overscanVector->n != in->image->numRows) { 514 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 515 psVector *newVec = ScaleOverscanVector(overscanVector, 516 in->image->numRows, 517 fitSpec, fit); 518 if (newVec == NULL) { 519 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector. Returning in image.\n"); 520 return(in); 521 } 522 psFree(overscanVector); 523 overscanVector = newVec; 524 } else { 525 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector. Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL. Returning in image.\n"); 526 psFree(overscanVector); 527 return(in); 528 } 529 } 530 } 531 1193 532 // 1194 // Create a psStats data structure and determine the highest 1195 // priority stats option. 533 // Re-bin the overscan vector (change its length). 1196 534 // 1197 psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); 1198 if (stat != NULL) { 1199 myStats->options = GenNewStatOptions(stat); 1200 } 1201 535 // Only if nBinOrig > 1. 536 if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) { 537 numBins = 1+((overscanVector->n)/nBinOrig); 538 myBin = psVectorAlloc(numBins, PS_TYPE_F32); 539 binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32); 540 541 for (i=0;i<numBins;i++) { 542 for(j=0;j<nBinOrig;j++) { 543 if (overscanVector->n > ((i*nBinOrig)+j)) { 544 binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j]; 545 } else { 546 // XXX: we get here if nBinOrig does not evenly divide 547 // the overscanVector vector. This is the last bin. Should 548 // we change the binVec->n to acknowledge that? 549 binVec->n = j; 550 } 551 } 552 psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0); 553 if (rc == NULL) { 554 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 555 return(in); 556 } 557 if (false == p_psGetStatValue(rc, &statValue)) { 558 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 559 return(in); 560 } 561 myBin->data.F32[i] = statValue; 562 } 563 564 // Change the effective size of overscanVector. 565 overscanVector->n = numBins; 566 for (i=0;i<numBins;i++) { 567 overscanVector->data.F32[i] = myBin->data.F32[i]; 568 } 569 psFree(binVec); 570 psFree(myBin); 571 nBin = nBinOrig; 572 } else { 573 nBin = 1; 574 } 575 576 // At this point the number of data points in overscanVector should be 577 // equal to the number of rows/columns (whatever is appropriate) in the 578 // image divided by numBins. 1202 579 // 1203 // Reduce overscan images to a single pixel, then subtract. 1204 // This code is no longer required as of SDRS 12-09. 580 581 1205 582 // 1206 if (overScanAxis == PM_OVERSCAN_ALL) { 1207 if (false == OverscanReducePixel(trimmedImg, in->bias, myStats)) { 1208 return(in); 1209 } 1210 psFree(myStats); 583 // This doesn't seem right. The only way to do a spline fit is if, 584 // by SDRS requirements, fitSpec is not-NULL> But in order for it 585 // to be non-NULL, someone must have called psSpline1DAlloc() with 586 // the min, max, and number of splines. 587 // 588 if (!((fitSpec == NULL) || (fit == PM_FIT_NONE))) { 589 // 590 // Fit a polynomial or spline to the overscan vector. 591 // 592 if (fit == PM_FIT_POLYNOMIAL) { 593 myPoly = (psPolynomial1D *) fitSpec; 594 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 595 if (myPoly == NULL) { 596 psError(PS_ERR_UNKNOWN, false, "(3) Could not fit a polynomial to overscan vector. Returning in image.\n"); 597 psFree(overscanVector); 598 return(in); 599 } 600 } else if (fit == PM_FIT_SPLINE) { 601 // XXX: This makes no sense 602 // XXX: must free mySpline? 603 mySpline = (psSpline1D *) fitSpec; 604 mySpline = psVectorFitSpline1D(NULL, overscanVector); 605 if (mySpline == NULL) { 606 psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector. Returning in image.\n"); 607 psFree(overscanVector); 608 return(in); 609 } 610 } 611 612 // 613 // Subtract fitted overscan vector row-wise from the image. 614 // 615 if (overScanAxis == PM_OVERSCAN_ROWS) { 616 for (i=0;i<(in->image)->numCols;i++) { 617 psF32 tmpF32 = 0.0; 618 if (fit == PM_FIT_POLYNOMIAL) { 619 tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 620 } else if (fit == PM_FIT_SPLINE) { 621 tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 622 } 623 for (j=0;j<(in->image)->numRows;j++) { 624 (in->image)->data.F32[j][i]-= tmpF32; 625 } 626 } 627 } 628 629 // 630 // Subtract fitted overscan vector column-wise from the image. 631 // 632 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 633 for (i=0;i<(in->image)->numRows;i++) { 634 psF32 tmpF32 = 0.0; 635 if (fit == PM_FIT_POLYNOMIAL) { 636 tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 637 } else if (fit == PM_FIT_SPLINE) { 638 tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 639 } 640 641 for (j=0;j<(in->image)->numCols;j++) { 642 (in->image)->data.F32[i][j]-= tmpF32; 643 } 644 } 645 } 1211 646 } else { 1212 647 // 1213 // Reduce the overscan images to a single overscan vector. 1214 // 1215 psVector *overscanVector = OverscanReduce(in->image, overScanAxis, 1216 in->bias, fitSpec, 1217 fit, myStats); 1218 if (overscanVector == NULL) { 1219 psError(PS_ERR_UNKNOWN, false, "Could not reduce overscan images to a single overscan vector. Returning in image\n"); 1220 psFree(myStats); 1221 return(in); 1222 } 1223 1224 // 1225 // Rebin the overscan vector if necessary. 1226 // 1227 psS32 newBin = RebinOverscanVector(overscanVector, nBin, myStats); 1228 if (newBin < 0) { 1229 psError(PS_ERR_UNKNOWN, false, "Could rebin the overscan vector. Returning in image\n"); 1230 psFree(myStats); 1231 return(in); 1232 } 1233 1234 // 1235 // If necessary, fit a psPolynomial or psSpline to the overscan vector. 1236 // Then, unbin the overscan vector to appropriate length for the in image. 1237 // 1238 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 1239 overscanVector = FitOverscanVectorAndUnbin(trimmedImg, overscanVector, overScanAxis, fitSpec, fit, newBin); 1240 if (overscanVector == NULL) { 1241 psError(PS_ERR_UNKNOWN, false, "Could not fit the polynomial or spline to the overscan vector. Returning in image\n"); 1242 psFree(myStats); 1243 return(in); 1244 } 1245 } else { 1246 overscanVector = UnbinOverscanVector(trimmedImg, overscanVector, overScanAxis, newBin); 1247 } 1248 1249 // 1250 // Subtract the overscan vector from the input image. 1251 // 1252 SubtractVectorFromImage(trimmedImg, overscanVector, overScanAxis); 1253 psFree(myStats); 1254 psFree(overscanVector); 1255 } 1256 } 1257 1258 // 1259 // Perform bias subtraction if necessary. 1260 // 1261 if (bias != NULL) { 1262 if (PM_OKAY == AssertCodeBias(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 1263 SubtractFrame(in, bias); 1264 } 1265 } 1266 1267 // 1268 // Perform dark subtraction if necessary. 1269 // 1270 if (dark != NULL) { 1271 if (PM_OKAY == AssertCodeDark(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 1272 psBool rc; 1273 psF32 scale = 0.0; 1274 if (in->parent != NULL) { 1275 scale = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.DARKTIME"); 1276 if (rc == false) { 1277 psLogMsg(__func__, PS_LOG_WARN, 1278 "WARNING: pmSubtractBias.(): could not determine CELL.FARKTIME from in->parent metadata.\n"); 1279 } 1280 } 1281 SubtractDarkFrame(in, dark, scale); 1282 } 1283 } 1284 1285 // 1286 // All done. 1287 // 648 // If we get here, then no polynomials were fit to the overscan 649 // vector. We simply subtract it, taking into account binning, 650 // from the image. 651 // 652 653 // 654 // Subtract overscan vector row-wise from the image. 655 // 656 if (overScanAxis == PM_OVERSCAN_ROWS) { 657 for (i=0;i<(in->image)->numCols;i++) { 658 for (j=0;j<(in->image)->numRows;j++) { 659 (in->image)->data.F32[j][i]-= overscanVector->data.F32[i/nBin]; 660 } 661 } 662 } 663 664 // 665 // Subtract overscan vector column-wise from the image. 666 // 667 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 668 for (i=0;i<(in->image)->numRows;i++) { 669 for (j=0;j<(in->image)->numCols;j++) { 670 (in->image)->data.F32[i][j]-= overscanVector->data.F32[i/nBin]; 671 } 672 } 673 } 674 } 675 676 psFree(overscanVector); 677 678 tmpOverscan = tmpOverscan->next; 679 } 680 1288 681 psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4, 1289 682 "---- pmSubtractBias() exit ----\n"); 683 684 if (bias != NULL) { 685 return(SubtractFrame(in, bias)); 686 } 1290 687 return(in); 1291 688 } -
branches/pap_branch_051214/psModules/src/imsubtract/pmSubtractBias.h
r5587 r5795 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 // XXX WARNING: I have completely replaced this file with an OLD VERSION (that works) instead of the 3 // one that was being worked on. 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 1 6 /** @file pmSubtractBias.h 2 7 * … … 6 11 * @author GLG, MHPCC 7 12 * 8 * @version $Revision: 1.4 $ $Name: not supported by cvs2svn $9 * @date $Date: 2005-1 1-23 23:54:30$13 * @version $Revision: 1.4.8.1 $ $Name: not supported by cvs2svn $ 14 * @date $Date: 2005-12-17 03:18:39 $ 10 15 * 11 16 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 23 28 #include<math.h> 24 29 #include "pslib.h" 30 25 31 #include "pmAstrometry.h" 26 32 … … 38 44 } pmFit; 39 45 40 pmReadout *pmSubtractBias( 41 pmReadout *in, ///< The input pmReadout image 42 void *fitSpec, ///< A polynomial or spline, defining the fit type. 43 pmFit fit, ///< PM_FIT_SPLINE, PM_FIT_POLYNOMIAL, or PM_FIT_NONE 44 bool overscan, 45 psStats *stat, ///< The statistic to be used in combining overscan data 46 int nBin, ///< The amount of binning to be done image pixels. 47 const pmReadout *bias, ///< A possibly NULL bias pmReadout which is to be subtracted 48 const pmReadout *dark ///< A possibly NULL bias pmReadout which is to be subtracted 49 ); 50 51 /****************************************************************************** 52 DetermineTrimmedImageg() This private routine determines the region of the 53 input pmReadout which will be operated on by the various detrend modules. It 54 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout. 55 56 XXX: Consider making a pmUtils.c file and put this routine there. 57 *****************************************************************************/ 58 psImage *p_psDetermineTrimmedImage( 59 pmReadout *in 60 ); 46 pmReadout *pmSubtractBias(pmReadout *in, ///< The input pmReadout image 47 void *fitSpec, ///< A polynomial or spline, defining the fit type. 48 const psList *overscans, ///< A psList of overscan images 49 pmOverscanAxis overScanAxis, ///< Defines how overscans are applied 50 psStats *stat, ///< The statistic to be used in combining overscan data 51 int nBin, ///< The amount of binning to be done image pixels. 52 pmFit fit, ///< PM_FIT_SPLINE, PM_FIT_POLYNOMIAL, or PM_FIT_NONE 53 const pmReadout *bias); ///< A possibly NULL bias pmReadout which is to be subtracted 61 54 62 55 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
