Changeset 20816 for trunk/magic/remove/src
- Timestamp:
- Nov 21, 2008, 1:33:36 PM (17 years ago)
- Location:
- trunk/magic/remove/src
- Files:
-
- 5 added
- 7 edited
-
. (modified) (1 prop)
-
.cvsignore (modified) (1 diff)
-
Makefile.simple (modified) (2 diffs)
-
streaksastrom.c (modified) (1 diff)
-
streakscompare.c (added)
-
streaksio.c (added)
-
streaksio.h (added)
-
streaksremove.c (modified) (17 diffs)
-
streaksremove.h (modified) (4 diffs)
-
streaksreplace.c (added)
-
streaksutil.c (added)
-
warpedpixels.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/magic/remove/src
- Property svn:ignore
-
old new 1 1 streaksremove 2 streaksreplace 3 streakscompare
-
- Property svn:ignore
-
trunk/magic/remove/src/.cvsignore
r20574 r20816 1 1 streaksremove 2 streaksreplace 3 streakscompare -
trunk/magic/remove/src/Makefile.simple
r20580 r20816 1 1 # skeleton Makefile for streaksremove 2 # 3 # The intent is that these programs may be built against an 4 # IPP installation outside the IPP build enviornment. 2 5 3 OBJECTS= \ 6 COMMON_OBJECTS = \ 7 streaksio.o \ 8 streaksutil.o 9 10 REMOVE_OBJECTS= \ 11 ${COMMON_OBJECTS} \ 4 12 streaksremove.o \ 5 13 streaksastrom.o \ … … 8 16 Line.o 9 17 10 CFLAGS=`psmodules-config --cflags` -g -std=gnu99 18 REPLACE_OBJECTS= \ 19 ${COMMON_OBJECTS} \ 20 streaksreplace.o 21 22 COMPARE_OBJECTS= \ 23 ${COMMON_OBJECTS} \ 24 streakscompare.o 25 26 OPTFLAGS= -g 27 CFLAGS=`psmodules-config --cflags` -std=gnu99 ${OPTFLAGS} 11 28 LDFLAGS=`psmodules-config --libs` 12 29 13 streaksremove: ${OBJECTS} 30 PROGRAMS= streaksremove streaksreplace streakscompare 14 31 15 install: streaksremove 16 cp streaksremove $(PSCONFDIR)/$(PSCONFIG)/bin 17 chmod 755 $(PSCONFDIR)/$(PSCONFIG)/bin/streaksremove 32 all: ${PROGRAMS} 33 34 streaksremove: ${REMOVE_OBJECTS} 35 36 streaksreplace: ${REPLACE_OBJECTS} 37 38 streakscompare: ${COMPARE_OBJECTS} 39 40 install: ${PROGRAMS} 41 install -t $(PSCONFDIR)/$(PSCONFIG)/bin streaksremove 42 install -t $(PSCONFDIR)/$(PSCONFIG)/bin streaksreplace 43 install -t $(PSCONFDIR)/$(PSCONFIG)/bin streakscompare 18 44 19 45 clean: 20 rm -f *.o streaksremove46 rm -f *.o ${PROGRAMS} 21 47 22 48 -
trunk/magic/remove/src/streaksastrom.c
r20573 r20816 150 150 } 151 151 152 static bool 153 readAstrometry(streakFiles *sf) 154 { 155 pmHDU *phu = pmFPAviewThisPHU(sf->view, sf->inAstrom->fpa); 156 if (phu) { 157 bool status; 158 char *ctype = psMetadataLookupStr(&status, phu->header, "CTYPE1"); 159 if (ctype) { 160 sf->bilevelAstrometry = !strcmp (&ctype[4], "-DIS"); 161 } 162 } 163 164 if (sf->bilevelAstrometry) { 165 // Do we get here for GPC1 ? I don't necessarily have an fpa for the input image 166 if (!pmAstromReadBilevelMosaic(sf->inAstrom->fpa, phu->header)) { 167 psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input FPA."); 168 return false; 169 } 170 } else { 171 pmHDU *hdu = pmFPAviewThisHDU(sf->view, sf->inAstrom->fpa); 172 PS_ASSERT_PTR_NON_NULL(hdu, 1) 173 PS_ASSERT_PTR_NON_NULL(hdu->header, 1) 174 175 // we use a default FPA pixel scale of 1.0 176 if (!pmAstromReadWCS (sf->inAstrom->fpa, sf->chip, hdu->header, 1.0)) { 177 psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for input FPA."); 178 return false; 179 } 180 } 181 182 return true; 183 } 184 185 void 186 setupAstrometry(streakFiles *sf) 187 { 188 bool status; 189 // load astrometry file 190 if (USE_SUPPLIED_ASTROM(sf->stage)) { 191 sf->inAstrom = pmFPAfileDefineFromArgs(&status, sf->config, "PSWARP.ASTROM", "ASTROM"); 192 } else { 193 // otherwise get astrometry from pmfile 194 if (!sf->inImage->pmfile) { 195 streaksExit("unexpected null pmFPAfile", PS_EXIT_CONFIG_ERROR); 196 } 197 sf->inAstrom = sf->inImage->pmfile; 198 } 199 sf->view = pmFPAviewAlloc(0); 200 201 if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) { 202 psError(PS_ERR_UNKNOWN, false, "Failed to load input."); 203 streaksExit("", PS_EXIT_DATA_ERROR); 204 } 205 206 while ((sf->chip = pmFPAviewNextChip(sf->view, sf->inAstrom->fpa, 1))) { 207 if (sf->inAstrom->fpa->chips->n == 1) { 208 // There's only one chip in this FPA and we've got it so break 209 break; 210 } 211 bool status; 212 psString chip_name = psMetadataLookupStr(&status, sf->chip->concepts, "CHIP.NAME"); 213 if (!strcmp(chip_name, sf->class_id)) { 214 break; 215 } 216 } 217 if (!sf->chip) { 218 psError(PS_ERR_UNKNOWN, true, "Failed to find chip with data."); 219 streaksExit("", PS_EXIT_DATA_ERROR); 220 } 221 if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) { 222 psError(PS_ERR_UNKNOWN, false, "failed to load chip"); 223 streaksExit("", PS_EXIT_DATA_ERROR); 224 } 225 if (!readAstrometry(sf)) { 226 psError(PS_ERR_UNKNOWN, false, "failed to read astrometry"); 227 streaksExit("", PS_EXIT_DATA_ERROR); 228 } 229 } -
trunk/magic/remove/src/streaksremove.c
r20810 r20816 1 1 #include "streaksremove.h" 2 #include "libgen.h" 3 #include "unistd.h" 4 5 static nebServer *ourNebServer = NULL; 6 7 // to enhance clarity we don't propagate errors up the stack 8 // we just bail out 9 void streaksremoveExit(psString str, int exitCode) { 10 psErrorStackPrint(stderr, str); 11 exit(exitCode); 12 } 13 14 static void sFileFree(sFile *sfile) 15 { 16 psFree(sfile->resolved_name); 17 psFree(sfile->name); 18 psFree(sfile); 19 } 20 21 22 // getNebServer() 23 // 24 // it gets created the first time a nebulous file is accessed. 25 // if config is passed in we are to create it and exit if not able. 26 // if config is null we return NULL indicating that there are no nebulous files in use 27 // The purpose of this is to avoid passing extra arguments between all of the functions. 28 // but it is probably a bad idea. 29 // 30 static nebServer *getNebServer(pmConfig *config) 31 { 32 if (ourNebServer) { 33 return ourNebServer; 34 } 35 2 3 static pmConfig *parseArguments(int argc, char **argv); 4 static bool readAndCopyToOutput(streakFiles *sf, bool exciseAll); 5 static StreakPixels * getStreakPixels(streakFiles *sfiles, Streaks *streaks); 6 static void exciseNonWarpedPixels(streakFiles *sfiles, double newMaskValue); 7 static bool warpedPixel(streakFiles *sfiles, PixelPos *cellCoord); 8 static void excisePixel(streakFiles *sfiles, unsigned int x, unsigned int y, bool streak, double newMaskValue); 9 static void writeImages(streakFiles *sf, bool exciseImageCube); 10 static bool replicateOutputs(streakFiles *sfiles); 11 12 int 13 main(int argc, char *argv[]) 14 { 15 bool status; 16 17 psLibInit(NULL); 18 19 pmConfig *config = parseArguments(argc, argv); 36 20 if (!config) { 37 return NULL; 38 } 39 40 psString serverURI = getenv("NEB_SERVER"); 41 42 // XXX: Note: all of the flags to psError should be true, but I don't think nebclient 43 // uses psError 44 if (!serverURI) { 45 bool status; 46 serverURI = psMetadataLookupStr(&status, config->site, "NEB_SERVER"); 47 if (!status) { 48 psError(PM_ERR_CONFIG, true, "failed to lookup config value for NEB_SERVER."); 49 streaksremoveExit("", PS_EXIT_CONFIG_ERROR); 50 } 51 } 52 53 if (!serverURI) { 54 psError(PM_ERR_CONFIG, true, "Could not determine nebulous server URI."); 55 56 streaksremoveExit("", PS_EXIT_CONFIG_ERROR); 57 } 58 59 ourNebServer = nebServerAlloc(serverURI); 60 if (!ourNebServer) { 61 psError(PM_ERR_SYS, true, "failed to create a nebServer object from %s.", serverURI); 62 streaksremoveExit("", PS_EXIT_CONFIG_ERROR); 63 } 64 65 return ourNebServer; 66 } 67 68 static psString 69 resolveFilename(pmConfig *config, sFile *sfile, bool create) 70 { 71 sfile->inNebulous = IN_NEBULOUS(sfile->name); 72 73 if (sfile->inNebulous) { 74 // make sure we have our neb server connection 75 nebServer *server = getNebServer(config); 76 if (create) { 77 // delete the existing file, since there may be more than one 78 // instance. It will get created below in pmConfigConvertFilename 79 if (nebFind(server, sfile->name)) { 80 nebDelete(server, sfile->name); 21 psError(PS_ERR_UNKNOWN, false, "failed to parse arguments\n"); 22 return PS_EXIT_CONFIG_ERROR; 23 } 24 25 psMetadata *masks = psMetadataLookupMetadata(&status, config->recipes, "MASKS"); 26 if (!status) { 27 psError(PM_ERR_CONFIG, false, "failed to lookup MASKS in recipes\n"); 28 return PS_EXIT_CONFIG_ERROR; 29 } 30 double maskStreak = (double) psMetadataLookupU8(&status, masks, "STREAK"); 31 if (!status) { 32 psError(PM_ERR_CONFIG, false, "failed to lookup mask value for STREAK in recipes\n"); 33 return PS_EXIT_CONFIG_ERROR; 34 } 35 36 psString streaksFileName = psMetadataLookupStr(NULL, config->arguments, "STREAKS"); 37 38 Streaks *streaks = readStreaksFile(streaksFileName); 39 if (!streaks) { 40 psErrorStackPrint(stderr, "failed to read streaks file: %s", streaksFileName); 41 exit (PS_EXIT_PROG_ERROR); 42 } 43 44 streakFiles *sfiles = openFiles(config, true); 45 setupAstrometry(sfiles); 46 47 bool exciseAll = false; 48 // --keepnonwarped is a test and debug mode 49 bool keepNonWarpedPixels = psMetadataLookupBool(&status, config->arguments, "KEEP_NON_WARPED"); 50 51 // we need to check for non warped pixels unless we've been asked not to or the stage is diff 52 // (By definition pixels in diff images were included in a diff) 53 bool checkNonWarpedPixels = ! (keepNonWarpedPixels || (sfiles->stage == IPP_STAGE_DIFF) ); 54 55 if (checkNonWarpedPixels ) { 56 // From ICD: 57 // In the raw and detrended images, the pixels which were not 58 // included in any of the streak-processed warps must also be masked. 59 // Note that the warp and difference skycells are only generated if more 60 // than a small fraction of the pixels are lit by the input image. 61 // if no skycells are provided sfiles->exciseAll is set to true 62 63 if (! computeWarpedPixels(sfiles) ) { 64 // we have no choice to excise all pixels 65 exciseAll = true; 66 } 67 } 68 69 if (sfiles->stage == IPP_STAGE_RAW) { 70 // copy PHU to output files 71 copyPHU(sfiles, true); 72 73 // advance to the first image extension 74 if (!streakFilesNextExtension(sfiles)) { 75 psErrorStackPrint(stderr, "failed to advance to first extension of input images"); 76 exit (PS_EXIT_PROG_ERROR); 77 } 78 } 79 80 // Iterate through each component of the input (only one except for raw stage) 81 do { 82 bool exciseImageCube = false; 83 84 // read the images and copy the data from the inputs to the outputs 85 // This also sets up the astrometry and initializes the recovery image(s) 86 87 if (!readAndCopyToOutput(sfiles, exciseAll)) { 88 // false return value indicates that this extension is not an image and 89 // the contents has already been copied to the output file. 90 // we don't need to process this extesion for streaks. 91 continue; 92 } 93 94 if (!exciseAll) { 95 // Identify pixels to mask because of streaks 96 97 StreakPixels *pixels = getStreakPixels(sfiles, streaks); 98 99 // XXX: 100 // 101 // PFS: Need to get mask weight for PM_MASK_DETECTOR. Is this stored 102 // in a config somewhere? Not sure how to properly set the maskValue. 103 104 105 if (checkNonWarpedPixels) { 106 exciseNonWarpedPixels(sfiles, maskStreak); 81 107 } 82 } 83 } 84 85 return pmConfigConvertFilename(sfile->name, config, create, create); 86 } 87 88 sFile *sFileOpen(pmConfig *config, ippStage stage, psString fileSelect, 89 psString outputFilename, bool required) 90 { 91 bool status; 92 sFile *sfile = psAlloc(sizeof(sFile)); 93 memset(sfile, 0, sizeof(sFile)); 94 95 // We use psFits directly to read the image unless the stage is warp 96 // or diff. In those cases we use the pmFPAfile functions to read the image file 97 // to make managing the astrometry easy. 98 // The reason we don't use pmFPAfile in all cases is that I was having trouble getting 99 // all of the keywords in the raw image files written to the output destreaked files 100 101 if (!CHIP_LEVEL_INPUT(stage) && !strcmp(fileSelect, "INPUT")) { 102 // stage is warp or diff AND fileSelect eq "INPUT" 103 // get data from pmFPAfile. 104 105 // we need to know what the nebulous and real filenames are so we steal 106 // some code from pmFPAfileDefineFromArgs 107 // XXX: create a pmFPAfile function that does this and use it there 108 psArray *infiles = psMetadataLookupPtr(&status, config->arguments, "INPUT"); 109 if (!status) { 110 psError(PS_ERR_PROGRAMMING, false, "INPUT not found in config->arguments"); 111 streaksremoveExit("", PS_EXIT_PROG_ERROR); 112 } 113 if (infiles->n != 1) { 114 psError(PS_ERR_IO, false, "Found n == %ld files in %s in arguments expencted 1\n", 115 infiles->n, "INPUT"); 116 streaksremoveExit("", PS_EXIT_DATA_ERROR); 117 } 118 // end of file name lookup code adapted from pmFPAfileDefineFromArgs 119 // 120 sfile->name = psStringCopy(infiles->data[0]); 121 sfile->inNebulous = IN_NEBULOUS(sfile->name); 122 123 // XXX: I should probably be using a different file rule for diffs, but I don't 124 // have an input rule that takes a diff image. 125 // Since they're skycells, this should be compatible 126 sfile->pmfile = pmFPAfileDefineFromArgs(&status, config, "PPSUB.INPUT", "INPUT"); 127 if (!sfile->pmfile) { 128 psError(PS_ERR_IO, false, "Failed to define file for %s", fileSelect); 129 streaksremoveExit("", PS_EXIT_DATA_ERROR); 130 } 131 132 pmFPAview *view = pmFPAviewAlloc(0); 133 if (!pmFPAfileIOChecks(config, view, PM_FPA_BEFORE)) { 134 psError(PS_ERR_UNKNOWN, false, "Failed to load input."); 135 streaksremoveExit("", PS_EXIT_DATA_ERROR); 136 } 137 psFree(view); 138 sfile->resolved_name = psStringCopy(sfile->pmfile->filename); 139 140 // copy header from fpu 141 sfile->header = (psMetadata*) psMemIncrRefCounter(sfile->pmfile->fpa->hdu->header); 142 143 return sfile; 144 } 145 146 // For all other files we use using psFits for i/o 147 148 psString name = psMetadataLookupStr(&status, config->arguments, fileSelect); 149 if (!status || !name) { 150 if (required) { 151 psError(PS_ERR_IO, false, "Failed to lookup name for %s", fileSelect); 152 sFileFree(sfile); 153 streaksremoveExit("", 1); 154 } 155 return NULL; 156 } 157 158 // if outputFilename is not null name it contains the "directory" 159 // and outputFilename is the basename name of the file (or nebulous key) 160 // and the file is to be opened for writing 161 if (outputFilename) { 162 psStringAppend(&sfile->name, "%s%s", name, outputFilename); 163 sfile->resolved_name = resolveFilename(config, sfile, true); 164 if (!sfile->resolved_name) { 165 psError(PS_ERR_IO, false, "Failed to resolve filename for %s", sfile->name); 166 sFileFree(sfile); 167 streaksremoveExit("", 1); 168 } 169 sfile->fits = psFitsOpen(sfile->resolved_name, "w"); 170 if (sfile->fits) { 171 sfile->fits->options = psFitsOptionsAlloc(); 172 } 173 } else { 174 sfile->name = psStringCopy(name); 175 sfile->resolved_name = resolveFilename(config, sfile, false); 176 if (!sfile->resolved_name) { 177 psError(PS_ERR_IO, false, "Failed to resolve name for %s", sfile->name); 178 sFileFree(sfile); 179 streaksremoveExit("", 1); 180 } 181 sfile->fits = psFitsOpen(sfile->resolved_name, "r"); 182 if (sfile->fits) { 183 sfile->nHDU = psFitsGetSize(sfile->fits); 184 } 185 } 186 187 if (!sfile->fits) { 188 psError(PS_ERR_IO, false, "failed to open fits file %s for %s", 189 sfile->resolved_name, outputFilename ? "writing" : "reading"); 190 sFileFree(sfile); 191 streaksremoveExit("", 1); 192 } 193 194 return sfile; 195 } 196 197 198 static bool 199 readAstrometry(streakFiles *sf) 200 { 201 pmHDU *phu = pmFPAviewThisPHU(sf->view, sf->inAstrom->fpa); 202 if (phu) { 203 bool status; 204 char *ctype = psMetadataLookupStr(&status, phu->header, "CTYPE1"); 205 if (ctype) { 206 sf->bilevelAstrometry = !strcmp (&ctype[4], "-DIS"); 207 } 208 } 209 210 if (sf->bilevelAstrometry) { 211 // Do we get here for GPC1 ? I don't necessarily have an fpa for the input image 212 if (!pmAstromReadBilevelMosaic(sf->inAstrom->fpa, phu->header)) { 213 psError(PS_ERR_UNKNOWN, false, "Unable to read bilevel mosaic astrometry for input FPA."); 214 return false; 215 } 216 } else { 217 pmHDU *hdu = pmFPAviewThisHDU(sf->view, sf->inAstrom->fpa); 218 PS_ASSERT_PTR_NON_NULL(hdu, 1) 219 PS_ASSERT_PTR_NON_NULL(hdu->header, 1) 220 221 // we use a default FPA pixel scale of 1.0 222 if (!pmAstromReadWCS (sf->inAstrom->fpa, sf->chip, hdu->header, 1.0)) { 223 psError(PS_ERR_UNKNOWN, false, "Unable to read WCS astrometry for input FPA."); 224 return false; 225 } 226 } 227 228 return true; 229 } 230 231 // load the fpa containing the astrometry, find the appropriate chip and process the data 232 static void 233 setupAstromFromFPA(streakFiles *sf) 234 { 235 sf->view = pmFPAviewAlloc(0); 236 237 if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) { 238 psError(PS_ERR_UNKNOWN, false, "Failed to load input."); 239 streaksremoveExit("", PS_EXIT_DATA_ERROR); 240 } 241 242 while ((sf->chip = pmFPAviewNextChip(sf->view, sf->inAstrom->fpa, 1))) { 243 if (sf->inAstrom->fpa->chips->n == 1) { 244 // There's only one chip in this FPA and we've got it so break 245 break; 246 } 247 bool status; 248 psString chip_name = psMetadataLookupStr(&status, sf->chip->concepts, "CHIP.NAME"); 249 if (!strcmp(chip_name, sf->class_id)) { 250 break; 251 } 252 } 253 if (!sf->chip) { 254 psError(PS_ERR_UNKNOWN, true, "Failed to find chip with data."); 255 streaksremoveExit("", PS_EXIT_DATA_ERROR); 256 } 257 if (!pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_BEFORE)) { 258 psError(PS_ERR_UNKNOWN, false, "failed to load chip"); 259 streaksremoveExit("", PS_EXIT_DATA_ERROR); 260 } 261 262 readAstrometry(sf); 263 } 264 265 streakFiles *openFiles(pmConfig *config) 266 { 267 bool status; 268 streakFiles *sf = psAlloc(sizeof(streakFiles)); 269 memset(sf, 0, sizeof(*sf)); 270 271 sf->config = config; 272 273 // error checking is done by sFileOpen. If a file can't be opened we just exit 274 ippStage stage = psMetadataLookupS32(&status, config->arguments, "STAGE"); 275 276 sf->stage = stage; 277 sf->extnum = 0; 278 279 sf->class_id = psMetadataLookupStr(&status, config->arguments, "CLASS_ID"); 280 281 sf->inImage = sFileOpen(config, stage, "INPUT", NULL, true); 282 sf->nHDU = sf->inImage->nHDU; 283 284 // don't need to free inputBasename see basename(3) 285 // The names of the temporary and recovery files are taken from the input 286 char *inputBasename = basename(sf->inImage->name); 287 sf->outImage = sFileOpen(config, stage, "OUTPUT", inputBasename, true); 288 sf->recImage = sFileOpen(config, stage, "RECOVERY", inputBasename, false); 289 290 sf->inMask = sFileOpen(config, stage, "INPUT.MASK", NULL, false); 291 if (sf->inMask) { 292 inputBasename = basename(sf->inMask->name); 293 sf->outMask = sFileOpen(config, stage, "OUTPUT", inputBasename, true); 294 sf->recMask = sFileOpen(config, stage, "RECOVERY", inputBasename, true); 295 } 296 sf->inWeight = sFileOpen(config, stage, "INPUT.WEIGHT", NULL, false); 297 if (sf->inWeight) { 298 inputBasename = basename(sf->inWeight->name); 299 sf->outWeight = sFileOpen(config, stage, "OUTPUT", inputBasename, true); 300 sf->recWeight = sFileOpen(config, stage, "RECOVERY", inputBasename, true); 301 } 302 303 // load astrometry file 304 if (USE_SUPPLIED_ASTROM(sf->stage)) { 305 sf->inAstrom = pmFPAfileDefineFromArgs(&status, config, "PSWARP.ASTROM", "ASTROM"); 306 } else { 307 // otherwise get astrometry from pmfile 308 if (!sf->inImage->pmfile) { 309 streaksremoveExit("unexpected null pmFPAfile", PS_EXIT_CONFIG_ERROR); 310 } 311 sf->inAstrom = sf->inImage->pmfile; 312 } 313 setupAstromFromFPA(sf); 314 315 psElemType tileType; // Type corresponding to "long" 316 if (sizeof(long) == sizeof(psS64)) { 317 tileType = PS_TYPE_S64; 318 } else if (sizeof(long) == sizeof(psS32)) { 319 tileType = PS_TYPE_S32; 320 } else { 321 psAbort("can't map (long) type to a psLib type"); 322 } 323 324 sf->tiles = psVectorAlloc(3, tileType); // Tile sizes 325 if (tileType == PS_TYPE_S64) { 326 sf->tiles->data.S64[0] = 0; 327 sf->tiles->data.S64[1] = 1; 328 sf->tiles->data.S64[2] = 1; 329 } else { 330 sf->tiles->data.S32[0] = 0; 331 sf->tiles->data.S32[1] = 1; 332 sf->tiles->data.S32[2] = 1; 333 } 334 335 sf->transparentStreaks = psMetadataLookupF64(&status, config->arguments, "TRANSPARENT_STREAKS"); 336 337 return sf; 338 } 339 340 static bool 341 moveExt(sFile *sfile, int extnum) 342 { 343 bool status = psFitsMoveExtNum(sfile->fits, extnum, false); 344 if (!status) { 345 psError(PS_ERR_IO, false, 346 "failed to move to extension %d for %s", extnum, sfile->resolved_name); 347 streaksremoveExit("", PS_EXIT_DATA_ERROR); 348 } 349 return true; 350 } 351 352 static bool 353 streakFilesNextExtension(streakFiles *sf) 354 { 355 // unless stage is raw or chip when we get here we're done 356 if (sf->stage != IPP_STAGE_RAW) { 357 sf->view->readout = -1; 358 pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_AFTER); 359 sf->view->cell = -1; 360 pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_AFTER); 361 sf->view->chip = -1; 362 pmFPAfileIOChecks(sf->config, sf->view, PM_FPA_AFTER); 363 return false; 364 } 365 366 ++sf->extnum; 367 if (sf->nHDU == 1) { 368 // return true the first time through 369 return (sf->extnum == 1); 370 } 371 if (sf->extnum < sf->nHDU) { 372 moveExt(sf->inImage, sf->extnum); 373 if (sf->inMask) { 374 moveExt(sf->inMask, sf->extnum); 375 } 376 if (sf->inWeight) { 377 moveExt(sf->inWeight, sf->extnum); 378 } 379 return true; 380 } else { 381 return false; 382 } 383 } 384 385 psString checkdir(char *path) 386 { 387 // insure that path ends in / 388 int len = strlen(path); 389 psString dir = NULL; 390 if (strrchr(path, '/') != (path + len - 1)) { 391 psStringAppend(&dir, "%s/", path); 392 } else { 393 dir = psStringCopy(path); 394 } 395 return dir; 396 } 397 398 ippStage 399 parseStage(psString stageStr) 400 { 401 if (!strcmp("raw", stageStr)) { 402 return IPP_STAGE_RAW; 403 } else if (!strcmp("chip", stageStr)) { 404 return IPP_STAGE_CHIP; 405 } else if (!strcmp("warp", stageStr)) { 406 return IPP_STAGE_WARP; 407 } else if (!strcmp("diff", stageStr)) { 408 return IPP_STAGE_DIFF; 409 } else { 410 psError(PS_ERR_UNKNOWN, true, "unknown stage string: %s\n", stageStr); 411 streaksremoveExit("", PS_EXIT_DATA_ERROR); 412 // notreached 413 return IPP_STAGE_NONE; 414 } 415 } 416 417 418 pmConfig *parseArguments(int argc, char **argv) { 108 109 if (sfiles->inImage->image) { 110 for (int i = 0; i < psArrayLength (pixels); ++i) { 111 PixelPos *pixelPos = psArrayGet (pixels, i); 112 113 if (!checkNonWarpedPixels || warpedPixel(sfiles, pixelPos)) { 114 115 excisePixel(sfiles, pixelPos->x, pixelPos->y, true, maskStreak); 116 117 } else { 118 // This pixel was not included in any warp and has thus already excised 119 // by exciseNonWarpedPixels 120 } 121 } 122 } else { 123 // this component contains an image cube, excise it completely 124 exciseImageCube = true; 125 } 126 psArrayElementsFree (pixels); 127 } 128 129 // write out the destreaked temporary images and the recovery images 130 writeImages(sfiles, exciseImageCube); 131 132 } while (streakFilesNextExtension(sfiles)); 133 134 // close all files 135 closeImages(sfiles); 136 137 // NOTE: from here on we can't just quit if something goes wrong. 138 // especially if we're working at the raw stage 139 140 if (!replicateOutputs(sfiles)) { 141 psError(PS_ERR_UNKNOWN, false, "failed to replicate output files"); 142 psErrorStackPrint(stderr, ""); 143 exit(PS_EXIT_UNKNOWN_ERROR); 144 } 145 146 #ifdef NOTYET 147 if (psMetadataLookupBool(&status, config->arguments, "REPLACE")) { 148 // swap the instances for the input and output 149 // Note this is a database operation. No file I/O is performed 150 if (!swapOutputsToInputs(sfiles)) { 151 psError(PS_ERR_UNKNOWN, false, "failed to swap files"); 152 153 // XXX: Now what? I guess swapOutputsToInputs will need to undo anything that 154 // it has done and give a detailed report of what happened 155 156 psErrorStackPrint(stderr, ""); 157 exit(PS_EXIT_UNKNOWN_ERROR); 158 } 159 160 if (psMetadataLookupBool(&status, config->arguments, "REMOVE")) { 161 // delete the temporary storage objects (which now points to the original image(s) 162 if (!deleteTemps(sfiles)) { 163 psError(PS_ERR_UNKNOWN, false, "failed to delete temporary files"); 164 // XXX: Now what? At this point the output files have been swapped, so we can't 165 // repeat the operation. 166 167 // Returning error status here is problematic. The inputs have been streak removed 168 // but they're still lying around 169 // Maybe just print an error message and 170 // let other system tools clean up 171 psErrorStackPrint(stderr, ""); 172 exit(PS_EXIT_UNKNOWN_ERROR); 173 } 174 } 175 } 176 #endif // REPLACE, REMOVE 177 // nebServerFree(ourNebServer); 178 psFree(config); 179 pmConceptsDone(); 180 pmConfigDone(); 181 psLibFinalize(); 182 183 // PAU 184 fprintf(stderr, "Found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "streaksremove"); 185 186 return 0; 187 } 188 189 static pmConfig *parseArguments(int argc, char **argv) 190 { 419 191 420 192 pmConfig *config = pmConfigRead(&argc, argv, NULL); 421 193 if (!config) { 422 streaks removeExit("failed to parse arguments", PS_EXIT_CONFIG_ERROR);194 streaksExit("failed to parse arguments", PS_EXIT_CONFIG_ERROR); 423 195 } 424 196 … … 550 322 return NULL; 551 323 } 552 psString dir = checkdir(argv[argnum]);324 psString dir = pathToDirectory(argv[argnum]); 553 325 psMetadataAddStr(config->arguments, PS_LIST_TAIL, "OUTPUT", 0, "directory for temporary files", 554 326 dir); … … 561 333 if ((argnum = psArgumentGet(argc, argv, "-recovery"))) { 562 334 psArgumentRemove(argnum, &argc, argv); 563 psString dir = checkdir(argv[argnum]);335 psString dir = pathToDirectory(argv[argnum]); 564 336 psMetadataAddStr(config->arguments, PS_LIST_TAIL, "RECOVERY", 0, "directory for recovery files", 565 337 dir); … … 591 363 592 364 return config; 593 }594 595 static void596 copyPHU(streakFiles *sfiles)597 {598 psAssert(sfiles->stage == IPP_STAGE_RAW, "copyPHU should only be used for raw stage");599 600 psMetadata *imageHeader = psFitsReadHeader(NULL, sfiles->inImage->fits);601 if (!imageHeader) {602 psError(PS_ERR_IO, false, "failed to read primary header from %s\n",603 sfiles->inImage->resolved_name);604 streaksremoveExit("", PS_EXIT_DATA_ERROR);605 }606 607 // TODO: add keyword indicating that streaks have been removed608 if (!psFitsWriteBlank(sfiles->outImage->fits, imageHeader, NULL)) {609 psError(PS_ERR_IO, false, "failed to write primary header to %s",610 sfiles->outImage->resolved_name);611 streaksremoveExit("", PS_EXIT_DATA_ERROR);612 }613 // TODO: add keyword indicating that this is the recovery image614 if (sfiles->recImage && !psFitsWriteBlank(sfiles->recImage->fits, imageHeader, NULL)) {615 psError(PS_ERR_IO, false, "failed to write primary header to %s",616 sfiles->recImage->resolved_name);617 streaksremoveExit("", PS_EXIT_DATA_ERROR);618 }619 psFree(imageHeader);620 621 sFile *inMask = sfiles->inMask;622 if (inMask) {623 psMetadata *maskHeader = psFitsReadHeader(NULL, inMask->fits);624 if (!maskHeader) {625 psError(PS_ERR_IO, false, "failed to read primary header from %s\n",626 sfiles->inMask->resolved_name);627 streaksremoveExit("", 1);628 }629 // TODO: add keyword indicating that streaks have been removed630 if (!psFitsWriteBlank(sfiles->outMask->fits, maskHeader, NULL)) {631 psError(PS_ERR_IO, false, "failed to write primary header to %s",632 sfiles->outMask->resolved_name);633 streaksremoveExit("", PS_EXIT_DATA_ERROR);634 }635 // TODO: add keyword indicating that this is the recovery image636 if (sfiles->recMask && !psFitsWriteBlank(sfiles->recMask->fits, maskHeader, NULL)) {637 psError(PS_ERR_IO, false, "failed to write primary header to %s",638 sfiles->recMask->resolved_name);639 streaksremoveExit("", PS_EXIT_DATA_ERROR);640 }641 psFree(maskHeader);642 }643 sFile *inWeight = sfiles->inWeight;644 if (inWeight) {645 psMetadata *weightHeader = psFitsReadHeader(NULL, inWeight->fits);646 if (!weightHeader) {647 psError(PS_ERR_IO, false, "failed to read primary header from %s\n",648 sfiles->inWeight->resolved_name);649 streaksremoveExit("", 1);650 }651 // TODO: add keyword indicating that streaks have been removed652 if (!psFitsWriteBlank(sfiles->outWeight->fits, weightHeader, NULL)) {653 psError(PS_ERR_IO, false, "failed to write primary header to %s",654 sfiles->outWeight->resolved_name);655 streaksremoveExit("", PS_EXIT_DATA_ERROR);656 }657 // TODO: add keyword indicating that this is a recovery image658 if (sfiles->recWeight && !psFitsWriteBlank(sfiles->recWeight->fits, weightHeader, NULL)) {659 psError(PS_ERR_IO, false, "failed to write primary header to %s",660 sfiles->recWeight->resolved_name);661 streaksremoveExit("", PS_EXIT_DATA_ERROR);662 }663 psFree(weightHeader);664 }665 }666 667 // Determine whether the current header for this file is an image or not668 // Find a cleaner way to do this669 static bool670 isImage(sFile *in)671 {672 bool status;673 psString exttype = psMetadataLookupStr(&status, in->header, "EXTTYPE");674 if (exttype && !strcmp(exttype, "IMAGE")) {675 return true;676 }677 // examine current header and determine if it is an image678 psString xtension = psMetadataLookupStr(&status, in->header, "XTENSION");679 if (xtension) {680 if (!strcmp(xtension, "IMAGE")) {681 return true;682 } else if (!strcmp(xtension, "BINTABLE")) {683 psString ztension = psMetadataLookupStr(&status, in->header, "ZTENSION");684 if (ztension && !strcmp(ztension, "IMAGE")) {685 return true;686 }687 }688 } else if (psMetadataLookupBool(&status, in->header, "ZIMAGE")) {689 return true;690 } else if (in->nHDU == 1) {691 // no extensions in the file, can just return true? For now require692 // at least one dimension693 int naxis = psMetadataLookupS32(&status, in->header, "NAXIS");694 return naxis > 0;695 }696 return false;697 }698 699 static void700 readImageFrom_pmFile(streakFiles *sf)701 {702 // XXX: This function assumes that it is only used for a single703 // chip single cell FPA (i.e. a skycell)704 pmFPAview *view = sf->view;705 assert(view->chip == 0);706 view->cell = 0;707 sf->cell = pmFPAviewThisCell(view, sf->inImage->pmfile->fpa);708 709 if (!sf->cell) {710 streaksremoveExit("no cells found in chip", PS_EXIT_PROG_ERROR);711 }712 if (sf->cell->readouts->n != 1) {713 psError(PS_ERR_PROGRAMMING, true, "unexpected number of readouts found: %ld", sf->cell->readouts->n);714 streaksremoveExit("", PS_EXIT_PROG_ERROR);715 }716 view->readout = 0;717 pmReadout *readout = pmFPAviewThisReadout(view, sf->inImage->pmfile->fpa);718 if (!readout) {719 streaksremoveExit("readout 0 not found", PS_EXIT_PROG_ERROR);720 }721 722 sf->inImage->image = (psImage*) psMemIncrRefCounter(readout->image);723 sf->inImage->numCols = readout->image->numCols;724 sf->inImage->numRows = readout->image->numRows;725 }726 727 void728 setDataExtent(ippStage stage, sFile *in)729 {730 if (stage == IPP_STAGE_RAW) {731 psString datasec = psMetadataLookupStr(NULL, in->header, "DATASEC");732 if (!datasec) {733 psError(PS_ERR_IO, false, "failed to find DATASEC in header");734 streaksremoveExit("", PS_EXIT_DATA_ERROR);735 }736 int xmin, xmax, ymin, ymax;737 sscanf(datasec, "[%d:%d,%d:%d]", &xmin, &xmax, &ymin, &ymax);738 in->numCols = xmax - xmin + 1;739 in->numRows = ymax - ymin + 1;740 } else {741 in->numCols = in->image->numCols;742 in->numRows = in->image->numRows;743 }744 }745 746 static void747 readImage(sFile *in, int extnum, ippStage stage)748 {749 psRegion region = {0, 0, 0, 0};750 751 if (in->header) psFree(in->header);752 if (in->image) {753 psFree(in->image);754 in->image = NULL;755 }756 if (in->imagecube) {757 psFree(in->imagecube);758 in->imagecube = NULL;759 }760 761 in->header = psFitsReadHeader(NULL, in->fits);762 if (!in->header) {763 psError(PS_ERR_IO, false, "failed to read header from %s extnum: %d",764 in->resolved_name, extnum);765 streaksremoveExit("", PS_EXIT_DATA_ERROR);766 }767 768 if (!isImage(in)) {769 return;770 }771 772 in->numZPlanes = psMetadataLookupS32(NULL, in->header, "NAXIS3");773 774 if (in->numZPlanes == 0) {775 in->image = psFitsReadImage(in->fits, region, 0);776 if (!in->image) {777 psError(PS_ERR_IO, false, "failed to read image from %s extnum: %d",778 in->resolved_name, extnum);779 streaksremoveExit("", PS_EXIT_DATA_ERROR);780 }781 } else {782 if (stage != IPP_STAGE_RAW) {783 psError(PS_ERR_PROGRAMMING, true, "unexpected image cube found in non-raw image");784 streaksremoveExit("", PS_EXIT_PROG_ERROR);785 }786 in->imagecube = psFitsReadImageCube(in->fits, region);787 if (!in->imagecube) {788 psError(PS_ERR_IO, false, "failed to read image cube from %s extnum: %d",789 in->resolved_name, extnum);790 streaksremoveExit("", PS_EXIT_DATA_ERROR);791 }792 psImage *image = (psImage *) (in->imagecube->data[0]);793 }794 setDataExtent(stage, in);795 }796 797 static void798 setFitsOptions(sFile *sfile, int bitpix, float bscale, float bzero)799 {800 if (!sfile) {801 return;802 }803 if (sfile->fits->options) {804 psFree(sfile->fits->options);805 }806 sfile->fits->options = psFitsOptionsAlloc();807 sfile->fits->options->scaling = PS_FITS_SCALE_MANUAL;808 sfile->fits->options->bitpix = bitpix;809 sfile->fits->options->bscale = bscale;810 sfile->fits->options->bzero = bzero;811 }812 813 static void814 copyFitsOptions(sFile *out, sFile *rec, sFile *in)815 {816 // Get current BITPIX, BSCALE, BZERO, EXTNAME817 // Probably not necessary to look the numerical values up in this818 // way, but guards against changes to psLib and cfitsio FITS819 // handling.820 psMetadataItem *bitpixItem = psMetadataLookup(in->header, "BITPIX");821 psAssert(bitpixItem, "Every FITS image should have BITPIX");822 int bitpix = psMetadataItemParseS32(bitpixItem);823 psMetadataItem *bscaleItem = psMetadataLookup(in->header, "BSCALE");824 825 float bscale;826 if (!bscaleItem) {827 psWarning("BSCALE isn't set; defaulting to unity");828 bscale = 1.0;829 } else {830 bscale = psMetadataItemParseF32(bscaleItem);831 }832 psMetadataItem *bzeroItem = psMetadataLookup(in->header, "BZERO");833 float bzero;834 if (!bzeroItem) {835 psWarning("BZERO isn't set; defaulting to zero");836 bzero = 0.0;837 } else {838 bzero = psMetadataItemParseF32(bzeroItem);839 }840 841 #ifdef COMPRESS_OUTPUT842 setFitsOptions(out, bitpix, bscale, bzero);843 setFitsOptions(rec, bitpix, bscale, bzero);844 #endif845 }846 847 848 static void849 copyTable(sFile *out, sFile *in, int extnum)850 {851 bool mdok;852 psString xtension = psMetadataLookupStr(&mdok, in->header, "XTENSION");853 psString extname = psMetadataLookupStr(&mdok, in->header, "EXTNAME");854 855 if (!xtension) {856 psWarning("extnum %d has no image and xtension is not defined in %s",857 extnum, in->resolved_name);858 // XXX abort?859 return;860 }861 if (!extname) {862 psWarning("extnum %d has no image and extname not defined in %s",863 extnum, in->resolved_name);864 // XXX abort?865 return;866 }867 psArray *table = psFitsReadTable(in->fits);868 if (!table) {869 psError(PS_ERR_UNKNOWN, false, "failed to read table in extension %d from in->resolved name", extnum);870 streaksremoveExit("", PS_EXIT_DATA_ERROR);871 }872 873 if (!psFitsWriteTable(out->fits, out->header, table, extname)) {874 psError(PS_ERR_UNKNOWN, false, "failed to copy table in extension %d", extnum);875 streaksremoveExit("", PS_EXIT_DATA_ERROR);876 }877 }878 879 static void880 createNewImage(sFile *out, sFile *in, int extnum, double initValue)881 {882 out->image = psImageRecycle(out->image, in->image->numCols, in->image->numRows, in->image->type.type);883 if (!out->image) {884 psError(PS_ERR_UNKNOWN, false, "failed to allocate image for extnsion %d", extnum);885 streaksremoveExit("", PS_EXIT_UNKNOWN_ERROR);886 }887 psImageInit(out->image, initValue);888 }889 890 static void891 setupImageRefs(sFile *out, sFile *recovery, sFile *in, int extnum, bool exciseAll)892 {893 if (!exciseAll) {894 // set output image to be the input image895 out->image = (psImage*) psMemIncrRefCounter(in->image);896 if (recovery) {897 // create a recovery image initialized to NAN898 createNewImage(recovery, in, extnum, NAN);899 }900 } else {901 // Excising all pixels in the input902 // set the output to an image all NANs903 createNewImage(out, in, extnum, NAN);904 if (recovery) {905 // save the whole input as the recovery image906 recovery->image = (psImage*) psMemIncrRefCounter(in->image);907 }908 }909 365 } 910 366 … … 929 385 if (!sf->astrom) { 930 386 psError(PS_ERR_UNKNOWN, false, "failed to set up astrometry for extension %d", sf->extnum); 931 streaks removeExit("", PS_EXIT_UNKNOWN_ERROR);387 streaksExit("", PS_EXIT_UNKNOWN_ERROR); 932 388 } 933 389 if (sf->stage == IPP_STAGE_CHIP) { … … 936 392 if (!pmAstromWriteWCS(sf->inImage->header, sf->inAstrom->fpa, sf->chip, 0.001)) { 937 393 psError(PS_ERR_UNKNOWN, false, "failed to update astrometry for extension %d", sf->extnum); 938 streaks removeExit("", PS_EXIT_UNKNOWN_ERROR);394 streaksExit("", PS_EXIT_UNKNOWN_ERROR); 939 395 } 940 396 } … … 958 414 959 415 // set up the compression parameters 960 #ifdef COMPRESS_OUTPUT416 #ifdef STREAKS_COMPRESS_OUTPUT 961 417 // compression of the image pixels is disabled for now. Some consortium members 962 418 // have problems reading them … … 967 423 // perhaps we should just use the definition of COMP_IMG in the configuration 968 424 psFitsSetCompression(sf->outImage->fits, PS_FITS_COMPRESS_RICE, sf->tiles, 8, 0, 0); 969 #endif970 425 if (sf->recImage) { 971 426 psFitsSetCompression(sf->recImage->fits, PS_FITS_COMPRESS_RICE, sf->tiles, 8, 0, 0); 972 427 } 428 #endif 973 429 974 430 if (sf->inMask) { … … 1010 466 // area (no overscan) 1011 467 1012 1013 468 return true; 1014 469 } 1015 470 1016 static void 1017 writeImage(sFile *sfile, psString extname, int extnum) 1018 { 1019 if (!sfile || !sfile->image) { 1020 return; 1021 } 1022 if (!psFitsWriteImage(sfile->fits, sfile->header, sfile->image, 0, extname)) { 1023 psError(PS_ERR_IO, false, "failed to write image to %s extnum: %d", 1024 sfile->resolved_name, extnum); 1025 streaksremoveExit("", PS_EXIT_DATA_ERROR); 1026 } 1027 psFree(sfile->image); 1028 sfile->image = NULL; 1029 psFree(sfile->header); 1030 sfile->header = NULL; 1031 } 1032 1033 static void 1034 writeImageCube(sFile *sfile, psArray *imagecube, psString extname, int extnum) 1035 { 1036 if (!imagecube) { 1037 return; 1038 } 1039 if (!psFitsWriteImageCube(sfile->fits, sfile->header, imagecube, extname)) { 1040 psError(PS_ERR_IO, false, "failed to write image to %s extnum: %d", 1041 sfile->resolved_name, extnum); 1042 streaksremoveExit("", PS_EXIT_DATA_ERROR); 1043 } 1044 psFree(sfile->header); 1045 sfile->header = NULL; 1046 } 471 1047 472 1048 473 static void … … 1098 523 } 1099 524 1100 static void1101 closeImage(sFile *sfile)1102 {1103 if (!sfile) {1104 return;1105 }1106 if (sfile->fits && !psFitsClose(sfile->fits)) {1107 psError(PS_ERR_IO, false, "failed to close image to %s",1108 sfile->resolved_name);1109 streaksremoveExit("", PS_EXIT_DATA_ERROR);1110 }1111 psFree(sfile->header);1112 psFree(sfile->image);1113 psFree(sfile->imagecube);1114 psFree(sfile->name);1115 psFree(sfile->resolved_name);1116 psFree(sfile);1117 }1118 1119 static void1120 closeImages(streakFiles *sf)1121 {1122 closeImage(sf->inImage);1123 closeImage(sf->outImage);1124 closeImage(sf->recImage);1125 if (sf->inMask) {1126 closeImage(sf->inMask);1127 closeImage(sf->outMask);1128 closeImage(sf->recMask);1129 }1130 if (sf->inWeight) {1131 closeImage(sf->inWeight);1132 closeImage(sf->outWeight);1133 closeImage(sf->recWeight);1134 }1135 }1136 1137 static bool1138 replicate(sFile *sfile, void *xattr)1139 {1140 if (!sfile->inNebulous) {1141 return true;1142 }1143 nebServer *server = getNebServer(NULL);1144 1145 // for now just set "user.copies" to 21146 if (!nebSetXattr(server, sfile->name, "user.copies", "2", NEB_REPLACE)) {1147 psError(PM_ERR_UNKNOWN, true, "nebSetXattr failed for %s\n%s", sfile->name, nebErr(server));1148 return false;1149 }1150 if (!nebReplicate(server, sfile->name, NULL, NULL)) {1151 psError(PM_ERR_UNKNOWN, true, "nebSetXattr failed for %s\n%s", sfile->name, nebErr(server));1152 return false;1153 }1154 return true;1155 }1156 1157 525 // for any of the outputs that are stored in Nebulous set their extended attributes 1158 526 // and replicate the files … … 1200 568 } 1201 569 1202 static bool1203 swapOutputToInput(sFile *in, sFile *out)1204 {1205 1206 if (in->inNebulous) {1207 nebServer *server = getNebServer(NULL);1208 1209 if (!nebSwap(server, in->name, out->name)) {1210 psError(PM_ERR_SYS, true, "failed to swap files for: %s.",1211 in->name, nebErr(server));1212 return false;1213 }1214 } else {1215 psString command = NULL;1216 1217 // regular files. use mv creating a backup1218 // NOTE: -b is a gnu option and may not always be available1219 psStringAppend(&command, "mv -b --suffix=.bak %s %s", out->resolved_name, in->resolved_name);1220 int status = system(command);1221 if (status != 0) {1222 psError(PM_ERR_SYS, true, "%s failed with status %d.",1223 command, status);1224 psFree(command);1225 return false;1226 }1227 psFree(command);1228 // XXX: shouldn't I be doing mv in->resolved_name.bak out->resolved_name1229 // to complete the swap if !remove?1230 }1231 1232 return true;1233 }1234 static bool1235 swapOutputsToInputs(streakFiles *sfiles)1236 {1237 if (sfiles->inMask) {1238 if (!swapOutputToInput(sfiles->inMask, sfiles->outMask)) {1239 psError(PM_ERR_SYS, false, "failed to swap instances for Mask.");1240 return false;1241 }1242 }1243 1244 if (sfiles->inWeight) {1245 if (!swapOutputToInput(sfiles->inWeight, sfiles->outWeight)) {1246 psError(PM_ERR_SYS, false, "failed to swap instances for Weight.");1247 return false;1248 }1249 }1250 1251 if (!swapOutputToInput(sfiles->inImage, sfiles->outImage)) {1252 psError(PM_ERR_SYS, false, "failed to swap instances for Image.");1253 return false;1254 }1255 1256 return true;1257 }1258 1259 static bool1260 deleteFile(sFile *sfile)1261 {1262 1263 if (sfile->inNebulous) {1264 nebServer *server = getNebServer(NULL);1265 if (!nebDelete(server, sfile->name)) {1266 psError(PM_ERR_SYS, false, "failed to delete %s\n%s.", sfile->name,1267 nebErr(server));1268 return false;1269 }1270 } else {1271 if (unlink(sfile->resolved_name)) {1272 psError(PM_ERR_SYS, false, "failed to delete %s\n%s.", sfile->resolved_name,1273 strerror(errno));1274 return false;1275 }1276 }1277 return true;1278 }1279 1280 static bool1281 deleteTemps(streakFiles *sfiles)1282 {1283 if (sfiles->outMask) {1284 if (!deleteFile(sfiles->outMask)) {1285 psError(PM_ERR_SYS, false, "failed to delete Mask.");1286 return false;1287 }1288 }1289 1290 if (sfiles->outWeight) {1291 if (!deleteFile(sfiles->outWeight)) {1292 psError(PM_ERR_SYS, false, "failed to delete Weight.");1293 return false;1294 }1295 }1296 1297 if (!deleteFile(sfiles->outImage)) {1298 psError(PM_ERR_SYS, false, "failed to delete Image.");1299 return false;1300 }1301 1302 return true;1303 }1304 570 1305 571 static void … … 1312 578 1313 579 double imageValue = psImageGet (sfiles->inImage->image, x, y); 1314 if (sfiles->recImage ) {580 if (sfiles->recImage && !isnan(imageValue) ) { 1315 581 psImageSet (sfiles->recImage->image, x, y, imageValue); 1316 582 } … … 1327 593 } 1328 594 1329 // TODO:1330 // Need to get mask weight for PM_MASK_DETECTOR. Is this stored1331 // in a config somewhere? Not sure how to properly set the maskValue.1332 1333 595 if (sfiles->inWeight) { 1334 596 double weightValue = psImageGet (sfiles->inWeight->image, x, y); … … 1385 647 } 1386 648 1387 bool649 static bool 1388 650 warpedPixel(streakFiles *sfiles, PixelPos *cellCoord) 1389 651 { … … 1419 681 } 1420 682 1421 bool683 static bool 1422 684 streakEndOnComponent(streak *streak, double r_min, double r_max, double d_min, double d_max) 1423 685 { … … 1434 696 1435 697 1436 Streaks *698 static Streaks * 1437 699 restrictStreaksToComponent(streakFiles *sfiles, Streaks *streaks) 1438 700 { … … 1494 756 return pixels; 1495 757 } 1496 int 1497 main(int argc, char *argv[]) 1498 { 1499 long i; 1500 bool status; 1501 StreakPixels *pixels; 1502 PixelPos *pixelPos; 1503 1504 psLibInit(NULL); 1505 1506 pmConfig *config = parseArguments(argc, argv); 1507 if (!config) { 1508 psError(PS_ERR_UNKNOWN, false, "failed to parse arguments\n"); 1509 return PS_EXIT_CONFIG_ERROR; 1510 } 1511 1512 psMetadata *masks = psMetadataLookupMetadata(&status, config->recipes, "MASKS"); 1513 if (!status) { 1514 psError(PM_ERR_CONFIG, false, "failed to lookup MASKS in recipes\n"); 1515 return PS_EXIT_CONFIG_ERROR; 1516 } 1517 double maskStreak = (double) psMetadataLookupU8(&status, masks, "STREAK"); 1518 if (!status) { 1519 psError(PM_ERR_CONFIG, false, "failed to lookup mask value for STREAK in recipes\n"); 1520 return PS_EXIT_CONFIG_ERROR; 1521 } 1522 1523 psString streaksFileName = psMetadataLookupStr(NULL, config->arguments, "STREAKS"); 1524 1525 Streaks *streaks = readStreaksFile(streaksFileName); 1526 if (!streaks) { 1527 psErrorStackPrint(stderr, "failed to read streaks file: %s", streaksFileName); 1528 exit (PS_EXIT_PROG_ERROR); 1529 } 1530 1531 streakFiles *sfiles = openFiles(config); 1532 1533 bool exciseAll = false; 1534 // --keepnonwarped is a test and debug mode 1535 bool keepNonWarpedPixels = psMetadataLookupBool(&status, config->arguments, "KEEP_NON_WARPED"); 1536 1537 // we need to check for non warped pixels unless we've been asked not to or the stage is diff 1538 // (By definition pixels in diff images were included in a diff) 1539 bool checkNonWarpedPixels = ! (keepNonWarpedPixels || (sfiles->stage == IPP_STAGE_DIFF) ); 1540 1541 if (checkNonWarpedPixels ) { 1542 // From ICD: 1543 // In the raw and detrended images, the pixels which were not 1544 // included in any of the streak-processed warps must also be masked. 1545 // Note that the warp and difference skycells are only generated if more 1546 // than a small fraction of the pixels are lit by the input image. 1547 // if no skycells are provided sfiles->exciseAll is set to true 1548 1549 if (! computeWarpedPixels(sfiles) ) { 1550 // we have no choice to excise all pixels 1551 exciseAll = true; 1552 } 1553 } 1554 1555 1556 if (sfiles->stage == IPP_STAGE_RAW) { 1557 // copy PHU to output files 1558 copyPHU(sfiles); 1559 1560 // advance to the first image extension 1561 if (!streakFilesNextExtension(sfiles)) { 1562 psErrorStackPrint(stderr, "failed to advance to first extension of input images"); 1563 exit (PS_EXIT_PROG_ERROR); 1564 } 1565 } 1566 1567 // Iterate through components of input files 1568 do { 1569 bool exciseImageCube = false; 1570 1571 // read the images and copy the data from the inputs to the outputs 1572 // This also sets up the astrometry and initializes the recovery image(s) 1573 1574 if (!readAndCopyToOutput(sfiles, exciseAll)) { 1575 // false return value indicates that this extension is not an image and 1576 // the contents has already been copied to the output file. 1577 // we don't need to process this extesion for streaks. 1578 continue; 1579 } 1580 1581 if (!exciseAll) { 1582 // Identify pixels to mask because of streaks 1583 1584 pixels = getStreakPixels(sfiles, streaks); 1585 1586 // XXX: 1587 // 1588 // PFS: Need to get mask weight for PM_MASK_DETECTOR. Is this stored 1589 // in a config somewhere? Not sure how to properly set the maskValue. 1590 1591 1592 if (checkNonWarpedPixels) { 1593 exciseNonWarpedPixels(sfiles, maskStreak); 1594 } 1595 1596 if (sfiles->inImage->image) { 1597 for (i = 0; i < psArrayLength (pixels); ++i) { 1598 pixelPos = psArrayGet (pixels, i); 1599 1600 if (!checkNonWarpedPixels || warpedPixel(sfiles, pixelPos)) { 1601 1602 excisePixel(sfiles, pixelPos->x, pixelPos->y, true, maskStreak); 1603 1604 } else { 1605 // This pixel was not included in any warp and has thus already excised 1606 // by exciseNonWarpedPixels 1607 } 1608 } 1609 } else { 1610 // this component contains an image cube, excise it completely 1611 exciseImageCube = true; 1612 } 1613 psArrayElementsFree (pixels); 1614 } 1615 1616 // write out the destreaked temporary images and the recovery images 1617 writeImages(sfiles, exciseImageCube); 1618 1619 } while (streakFilesNextExtension(sfiles)); 1620 1621 // close all files 1622 closeImages(sfiles); 1623 1624 // NOTE: from here on we can't just quit if something goes wrong. 1625 // especially if we're working at the raw stage 1626 1627 if (!replicateOutputs(sfiles)) { 1628 psError(PS_ERR_UNKNOWN, false, "failed to replicate output files"); 1629 psErrorStackPrint(stderr, ""); 1630 exit(PS_EXIT_UNKNOWN_ERROR); 1631 } 1632 1633 #ifdef NOTYET 1634 if (psMetadataLookupBool(&status, config->arguments, "REPLACE")) { 1635 // swap the instances for the input and output 1636 // Note this is a database operation. No file I/O is performed 1637 if (!swapOutputsToInputs(sfiles)) { 1638 psError(PS_ERR_UNKNOWN, false, "failed to swap files"); 1639 1640 // XXX: Now what? I guess swapOutputsToInputs will need to undo anything that 1641 // it has done and give a detailed report of what happened 1642 1643 psErrorStackPrint(stderr, ""); 1644 exit(PS_EXIT_UNKNOWN_ERROR); 1645 } 1646 1647 if (psMetadataLookupBool(&status, config->arguments, "REMOVE")) { 1648 // delete the temporary storage objects (which now points to the original image(s) 1649 if (!deleteTemps(sfiles)) { 1650 psError(PS_ERR_UNKNOWN, false, "failed to delete temporary files"); 1651 // XXX: Now what? At this point the output files have been swapped, so we can't 1652 // repeat the operation. 1653 1654 // Returning error status here is problematic. The inputs have been streak removed 1655 // but they're still lying around 1656 // Maybe just print an error message and 1657 // let other system tools clean up 1658 psErrorStackPrint(stderr, ""); 1659 exit(PS_EXIT_UNKNOWN_ERROR); 1660 } 1661 } 1662 } 1663 #endif // REPLACE, REMOVE 1664 nebServer(ourNebServer); 1665 psFree(config); 1666 pmConceptsDone(); 1667 pmConfigDone(); 1668 psLibFinalize(); 1669 1670 // PAU 1671 fprintf(stderr, "Found %d leaks at %s\n", psMemCheckLeaks (0, NULL, NULL, false), "streaksremove"); 1672 1673 return 0; 1674 } 758 -
trunk/magic/remove/src/streaksremove.h
r20807 r20816 10 10 #include "psmodules.h" 11 11 #include "nebclient.h" 12 13 typedef struct {14 int dummy;15 } Warps;16 12 17 13 #include "streaksextern.h" … … 70 66 } streakFiles; 71 67 68 #include "streaksio.h" 69 70 extern void setupAstrometry(streakFiles *); 72 71 extern strkAstrom *streakSetAstrometry(strkAstrom *, ippStage stage, pmFPA *, pmChip *, bool fromCell, psMetadata *md, 73 72 int numCols, int numRows); … … 75 74 extern void cellToChip(PixelPos *chip, strkAstrom *astrom, PixelPos *cell); 76 75 77 78 76 extern bool computeWarpedPixels(streakFiles *sf); 79 extern void streaksremoveExit(psString, int); 77 extern void streaksExit(psString, int); 78 extern ippStage parseStage(psString); 79 extern psString pathToDirectory(char *path); 80 80 81 81 #define CHIP_LEVEL_INPUT(_stage) ((_stage == IPP_STAGE_RAW) || (_stage == IPP_STAGE_CHIP)) … … 85 85 #define IN_NEBULOUS(_filename) (!strncasecmp(_filename, "neb://", strlen("neb://"))) 86 86 87 88 87 #endif // STREAKS_H -
trunk/magic/remove/src/warpedpixels.c
r20778 r20816 57 57 if (!fits) { 58 58 psError(PS_ERR_IO, false, "failed to open skycell file: %s", fileName); 59 streaks removeExit("", PS_EXIT_DATA_ERROR);59 streaksExit("", PS_EXIT_DATA_ERROR); 60 60 } 61 61 psMetadata *header = psFitsReadHeader(NULL, fits); 62 62 if (!header) { 63 63 psError(PS_ERR_IO, false, "failed to read fixts header from skycell file: %s", fileName); 64 streaks removeExit("", PS_EXIT_DATA_ERROR);64 streaksExit("", PS_EXIT_DATA_ERROR); 65 65 } 66 66 // set up astrometry for conversion from skycell image to sky … … 68 68 if (!wcs) { 69 69 psError(PS_ERR_IO, false, "failed to read astrometry from skycell file: %s", fileName); 70 streaks removeExit("", PS_EXIT_DATA_ERROR);70 streaksExit("", PS_EXIT_DATA_ERROR); 71 71 } 72 72 int naxis1 = psMetadataLookupS32(NULL, header, "NAXIS1"); … … 99 99 if (!pmAstromWCStoSky(&sky, wcs, &pt[i])) { 100 100 psError(PS_ERR_IO, false, "failed to convert pt %d of %s to sky coords: %s", fileName); 101 streaks removeExit("", PS_EXIT_DATA_ERROR);101 streaksExit("", PS_EXIT_DATA_ERROR); 102 102 } 103 103 strkPt p; … … 105 105 if (!skyToCell(&p, sf->astrom, sky.r, sky.d)) { 106 106 psError(PS_ERR_IO, false, "failed to convert pt %d of %s to sky coords: %s", fileName); 107 streaks removeExit("", PS_EXIT_DATA_ERROR);107 streaksExit("", PS_EXIT_DATA_ERROR); 108 108 } 109 109 pt[i].x = p.x;
Note:
See TracChangeset
for help on using the changeset viewer.
