Changeset 7454 for trunk/psModules/src/camera/pmChipMosaic.c
- Timestamp:
- Jun 9, 2006, 12:23:43 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/camera/pmChipMosaic.c (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/camera/pmChipMosaic.c
r7382 r7454 4 4 #include "pmFPA.h" 5 5 #include "pmHDU.h" 6 6 #include "pmChipMosaic.h" 7 8 #define CELL_LIST_BUFFER 50 // Buffer size for cell lists 7 9 8 10 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 33 35 } 34 36 35 // Are the pixels for the chip contiguous on the HDU? 36 // Work this out by examining all the CELL.TRIMSEC and CELL.BIASSEC regions for the component cells 37 static bool chipContiguous(psRegion *bounds, // The bounds of the image, altered if primary==true 38 pmChip *chip, // The chip to examine for contiguity 39 bool primary // Is this the primary chip of interest? 40 ) 41 { 42 assert(bounds); 37 38 // Get the bounds for an chip's pixels on the HDU 39 static bool chipBounds(psRegion *bounds, // The bounds for the chip 40 const pmChip *chip // The chip to examine for contiguity 41 ) 42 { 43 43 assert(chip); 44 44 45 if (primary) {46 *bounds = psRegionSet(INFINITY, 0, INFINITY, 0);47 }48 45 psArray *cells = chip->cells; // The array of cells 49 46 bool mdok = true; // Status of MD lookup … … 52 49 psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section 53 50 if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) { 54 psError(PS_ERR_ IO, true, "CELL.TRIMSEC hasn't been set for cell %d.\n", i);51 psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC hasn't been set for cell %d.\n", i); 55 52 return false; 56 53 } 57 54 58 if (primary) { 59 if (trimsec->x0 < bounds->x0) { 60 bounds->x0 = trimsec->x0; 61 } 62 if (trimsec->x1 > bounds->x1) { 63 bounds->x1 = trimsec->x1; 64 } 65 if (trimsec->y0 < bounds->y0) { 66 bounds->y0 = trimsec->y0; 67 } 68 if (trimsec->y1 > bounds->y1) { 69 bounds->y1 = trimsec->y1; 70 } 71 } else if (REGIONS_OVERLAP(trimsec, bounds)) { 55 if (trimsec->x0 < bounds->x0) { 56 bounds->x0 = trimsec->x0; 57 } 58 if (trimsec->x1 > bounds->x1) { 59 bounds->x1 = trimsec->x1; 60 } 61 if (trimsec->y0 < bounds->y0) { 62 bounds->y0 = trimsec->y0; 63 } 64 if (trimsec->y1 > bounds->y1) { 65 bounds->y1 = trimsec->y1; 66 } 67 } 68 69 return true; 70 } 71 72 // Make sure the TRIMSEC doesn't overlap with the established image bounds 73 static bool chipContiguousTrimsec(psRegion *bounds, // The bounds of the image, altered if primary==true 74 const pmChip *chip // The chip to examine for contiguity 75 ) 76 { 77 assert(bounds); 78 assert(chip); 79 80 psArray *cells = chip->cells; // The array of cells 81 bool mdok = true; // Status of MD lookup 82 for (int i = 0; i < cells->n; i++) { 83 pmCell *cell = cells->data[i]; // Cell of interest 84 psRegion *trimsec = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.TRIMSEC"); // Trim section 85 if (!mdok || !trimsec || psRegionIsNaN(*trimsec)) { 86 psError(PS_ERR_UNKNOWN, true, "CELL.TRIMSEC hasn't been set for cell %d.\n", i); 72 87 return false; 73 88 } 74 89 90 if (REGIONS_OVERLAP(trimsec, bounds)) { 91 return false; 92 } 93 } 94 95 return true; 96 } 97 98 // Make sure the BIASSEC doesn't overlap with the established image bounds 99 static bool chipContiguousBiassec(psRegion *bounds, // The bounds of the image, altered if primary==true 100 const pmChip *chip // The chip to examine for contiguity 101 ) 102 { 103 assert(bounds); 104 assert(chip); 105 106 // Check that the biases don't get in the way 107 psArray *cells = chip->cells; // The array of cells 108 bool mdok = true; // Status of MD lookup 109 for (int i = 0; i < cells->n; i++) { 110 pmCell *cell = cells->data[i]; // Cell of interest 75 111 psList *biassecs = psMetadataLookupPtr(&mdok, cell->concepts, "CELL.BIASSEC"); // Bias sections 76 112 if (!mdok || !biassecs) { 77 psError(PS_ERR_ IO, true, "CELL.BIASSEC hasn't been set for cell %d.\n", i);113 psError(PS_ERR_UNKNOWN, true, "CELL.BIASSEC hasn't been set for cell %d.\n", i); 78 114 return false; 79 115 } … … 100 136 } 101 137 138 // Are the pixels for the FPA contiguous on the HDU? 139 // Work this out by examining all the CELL.TRIMSEC and CELL.BIASSEC regions for the component cells 140 static bool fpaContiguous(psRegion *bounds, // The bounds of the image, returned 141 const pmFPA *fpa // The FPA to examine for contiguity 142 ) 143 { 144 assert(bounds); 145 assert(fpa); 146 147 *bounds = psRegionSet(INFINITY, 0, INFINITY, 0); 148 149 // Get the size of the pixels on the HDU 150 psArray *chips = fpa->chips; // The array of chips 151 for (int i = 0; i < chips->n; i++) { 152 pmChip *chip = chips->data[i]; // Chip of interest 153 if (!chipBounds(bounds, chip)) { 154 return false; 155 } 156 } 157 158 // Make sure the bias regions don't get in the way of the HDU 159 for (int i = 0; i < chips->n; i++) { 160 pmChip *chip = chips->data[i]; // Chip of interest 161 if (!chipContiguousBiassec(bounds, chip)) { 162 return false; 163 } 164 } 165 166 // If we got through it all, they must all be contiguous 167 return true; 168 } 169 170 171 172 // Check a cell for niceness in the parity and binning 173 static bool niceCellParityBinning(int *xBin, int *yBin, // Binning for cell, to be returned 174 const pmCell *cell // Cell to check for niceness 175 ) 176 { 177 assert(xBin); 178 assert(yBin); 179 assert(cell); 180 181 // A "nice" cell must have only a single readout 182 if (cell->readouts->n != 1) { 183 return false; 184 } 185 186 // A "nice" cell must have parity == 1 187 bool mdok = true; // Status of MD lookup 188 int xParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY"); // Parity in x 189 if (!mdok || xParity == 0) { 190 psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY hasn't been set for cell.\n"); 191 return false; 192 } 193 if (xParity != 1) { 194 return false; 195 } 196 int yParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY"); // Parity in y 197 if (!mdok || yParity == 0) { 198 psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY hasn't been set for cell.\n"); 199 return false; 200 } 201 if (yParity != 1) { 202 return false; 203 } 204 205 // A "nice" cell must have consistent binning 206 int xBinCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN"); // Binning in x 207 if (!mdok || xBin <= 0) { 208 psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY hasn't been set for cell.\n"); 209 return false; 210 } 211 int yBinCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN"); // Binning in y 212 if (!mdok || yBin <= 0) { 213 psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY hasn't been set for cell.\n"); 214 return false; 215 } 216 if (*xBin == 0 || *yBin == 0) { 217 *xBin = xBinCell; 218 *yBin = yBinCell; 219 } else if (xBinCell != *xBin || yBinCell != *yBin) { 220 return false; 221 } 222 223 return true; 224 } 225 226 227 // Check a cell for niceness in the boundaries 228 static bool niceCellBounds(const pmCell *cell, // Cell to check for niceness 229 const psRegion *imageBounds // Bounds of the image on the HDU 230 ) 231 { 232 // A "nice" cell must have the (0,0) pixel at CELL.X0,CELL.Y0 233 bool mdok = true; // Status of MD lookup 234 int x0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); // Position of (0,0) on chip 235 if (!mdok) { 236 psError(PS_ERR_UNKNOWN, true, "CELL.X0 hasn't been set for cell.\n"); 237 return false; 238 } 239 int y0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); // Position of (0,0) on chip 240 if (!mdok) { 241 psError(PS_ERR_UNKNOWN, true, "CELL.Y0 hasn't been set for cell.\n"); 242 return false; 243 } 244 pmReadout *readout = cell->readouts->data[0]; // A representative readout 245 if (!readout) { 246 return false; // Nothing here 247 } 248 if (x0 != readout->col0 + readout->image->col0 - (int)imageBounds->x0 || 249 y0 != readout->row0 + readout->image->row0 - (int)imageBounds->y0) { 250 psTrace(__func__, 5, "CELL.X0,Y0 don't match: %d,%d vs %d,%d\n", x0, y0, 251 readout->col0 + readout->image->col0 - (int)imageBounds->x0, 252 readout->row0 + readout->image->row0 - (int)imageBounds->y0); 253 return false; 254 } 255 256 return true; 257 } 258 102 259 103 260 // Is the chip "nice"? If so, return the region containing the chip pixels 104 261 static psRegion *niceChip(int *xBinChip, int *yBinChip, // Binning for chip, to be returned 105 pmChip *chip// Chip to examine for "niceness".262 const pmChip *chip // Chip to examine for "niceness". 106 263 ) 107 264 { … … 116 273 117 274 // Check parity and binning for component cells 118 bool mdok = true; // Status of MD lookup119 275 *xBinChip = 0; 120 276 *yBinChip = 0; 121 277 for (int i = 0; i < chip->cells->n; i++) { 122 278 pmCell *cell = chip->cells->data[i]; // The cell of interest 123 124 // A "nice" chip must have only a single readout 125 if (cell->readouts->n != 1) { 279 if (!niceCellParityBinning(xBinChip, yBinChip, cell)) { 126 280 return NULL; 127 281 } 128 129 // A "nice" chip must have parity == 1130 int xParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY"); // Parity in x131 if (!mdok || xParity == 0) {132 psError(PS_ERR_IO, true, "CELL.XPARITY hasn't been set for cell %d.\n", i);133 return NULL;134 }135 if (xParity != 1) {136 return NULL;137 }138 int yParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY"); // Parity in y139 if (!mdok || yParity == 0) {140 psError(PS_ERR_IO, true, "CELL.YPARITY hasn't been set for cell %d.\n", i);141 return NULL;142 }143 if (yParity != 1) {144 return NULL;145 }146 147 // A "nice" chip must have consistent binning148 int xBin = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN"); // Binning in x149 if (!mdok || xBin <= 0) {150 psError(PS_ERR_IO, true, "CELL.XPARITY hasn't been set for cell %d.\n", i);151 return NULL;152 }153 int yBin = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN"); // Binning in y154 if (!mdok || yBin <= 0) {155 psError(PS_ERR_IO, true, "CELL.YPARITY hasn't been set for cell %d.\n", i);156 return NULL;157 }158 if (*xBinChip == 0 || *yBinChip == 0) {159 *xBinChip = xBin;160 *yBinChip = yBin;161 } else if (xBin != *xBinChip || yBin != *yBinChip) {162 return NULL;163 }164 282 } 165 283 166 284 // Now check that the pixels are all contiguous 167 psRegion *imageBounds = psRegionAlloc( 0, 0, 0, 0); // Bound of image on HDU168 if (!chip Contiguous(imageBounds, chip, true)) {285 psRegion *imageBounds = psRegionAlloc(INFINITY, 0, INFINITY, 0); // Bound of image on HDU 286 if (!chipBounds(imageBounds, chip) || !chipContiguousBiassec(imageBounds, chip)) { 169 287 psTrace(__func__, 5, "Image isn't contiguous.\n"); 170 288 psFree(imageBounds); … … 178 296 for (int i = 0; i < chip->cells->n; i++) { 179 297 pmCell *cell = chip->cells->data[i]; // The cell of interest 180 181 // A "nice" chip must have the (0,0) pixel at CELL.X0,CELL.Y0 182 int x0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); // Position of (0,0) on chip 183 if (!mdok) { 184 psError(PS_ERR_IO, true, "CELL.X0 hasn't been set for cell %d.\n", i); 185 return NULL; 186 } 187 int y0 = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); // Position of (0,0) on chip 188 if (!mdok) { 189 psError(PS_ERR_IO, true, "CELL.Y0 hasn't been set for cell %d.\n", i); 190 return NULL; 191 } 192 pmReadout *readout = cell->readouts->data[0]; // A representative readout 193 if (!readout) { 194 return NULL; // Nothing here 195 } 196 if (x0 != readout->col0 + readout->image->col0 - (int)imageBounds->x0 || 197 y0 != readout->row0 + readout->image->row0 - (int)imageBounds->y0) { 198 psTrace(__func__, 5, "CELL.X0,Y0 don't match: %d,%d vs %d,%d\n", x0, y0, 199 readout->col0 + readout->image->col0 - (int)imageBounds->x0, 200 readout->row0 + readout->image->row0 - (int)imageBounds->y0); 298 if (!niceCellBounds(cell, imageBounds)) { 201 299 psFree(imageBounds); 202 300 return NULL; … … 214 312 continue; 215 313 } 216 if (!chipContiguous(imageBounds, testChip, false)) { 314 if (!chipContiguousTrimsec(imageBounds, testChip) || 315 !chipContiguousBiassec(imageBounds, testChip)) { 217 316 psTrace(__func__, 5, "Image isn't contiguous.\n"); 317 psFree(imageBounds); 318 return NULL; 319 } 320 } 321 } 322 323 return imageBounds; 324 } 325 326 // Is the FPA "nice"? If so, return the region containing the FPA pixels 327 static psRegion *niceFPA(int *xBinFPA, int *yBinFPA, // Binning for FPA, to be returned 328 const pmFPA *fpa // FPA to examine for "niceness". 329 ) 330 { 331 assert(xBinFPA); 332 assert(yBinFPA); 333 assert(fpa); 334 335 // Check that we've got the HDU in the chip or the FPA 336 if (!fpa->hdu || !fpa->hdu->images) { 337 return NULL; 338 } 339 340 // Check parity and binning for component cells 341 *xBinFPA = 0; 342 *yBinFPA = 0; 343 for (int i = 0; i < fpa->chips->n; i++) { 344 pmChip *chip = fpa->chips->data[i]; // The chip of interest 345 for (int j = 0; i < chip->cells->n; i++) { 346 pmCell *cell = chip->cells->data[j]; // The cell of interest 347 if (!niceCellParityBinning(xBinFPA, yBinFPA, cell)) { 348 return NULL; 349 } 350 } 351 } 352 353 // Now check that the pixels are all contiguous 354 psRegion *imageBounds = psRegionAlloc(0, 0, 0, 0); // Bound of image on HDU 355 if (!fpaContiguous(imageBounds, fpa)) { 356 psTrace(__func__, 5, "Image isn't contiguous.\n"); 357 psFree(imageBounds); 358 return NULL; 359 } 360 361 psString region = psRegionToString(*imageBounds); 362 psTrace(__func__, 7, "Image bounds: %s\n", region); 363 psFree(region); 364 365 for (int i = 0; i < fpa->chips->n; i++) { 366 pmChip *chip = fpa->chips->data[i]; // The chip of interest 367 for (int j = 0; i < chip->cells->n; i++) { 368 pmCell *cell = chip->cells->data[j]; // The cell of interest 369 if (!niceCellBounds(cell, imageBounds)) { 218 370 psFree(imageBounds); 219 371 return NULL; … … 259 411 psElemType type = 0; 260 412 int numImages = 0; // Number of images 413 psTrace(__func__, 3, "Mosaicking %ld cells.\n", source->n); 261 414 for (int i = 0; i < source->n; i++) { 262 415 psImage *image = source->data[i]; // The image of interest … … 315 468 xFlip->data.U8[i] == 0 && yFlip->data.U8[i] == 0) { 316 469 // Let someone else do the hard work; useful to test psImageOverlaySection if no other reason 317 psImageOverlaySection(mosaic, image, x0->data.S32[i] , y0->data.S32[i], "+");470 psImageOverlaySection(mosaic, image, x0->data.S32[i] - xMin, y0->data.S32[i] - yMin, "+"); 318 471 } else { 319 472 // We have to do the hard work ourself 320 473 for (int y = 0; y < image->numRows; y++) { 321 474 int yParity = yFlip->data.U8[i] ? -1 : 1; 322 float yTargetBase = (y0->data.S32[i] + yParity * yBinSource->data.S32[i] * y) / yBinTarget; 475 float yTargetBase = (y0->data.S32[i] + yParity * yBinSource->data.S32[i] * y - yMin) / 476 yBinTarget; 323 477 for (int x = 0; x < image->numCols; x++) { 324 478 int xParity = xFlip->data.U8[i] ? -1 : 1; 325 float xTargetBase = (x0->data.S32[i] + xParity * xBinSource->data.S32[i] * x ) /479 float xTargetBase = (x0->data.S32[i] + xParity * xBinSource->data.S32[i] * x - xMin) / 326 480 xBinTarget; 327 481 … … 359 513 // Set the concepts in the new cell, based on the values in the old one 360 514 static bool cellConcepts(pmCell *target,// Target cell 361 ps Array*sources, // Source cells515 psList *sources, // Source cells 362 516 int xBin, int yBin, // Binning 363 517 psRegion *trimsec // The trim section … … 378 532 double time = 0.0; // Time of observation 379 533 psTimeType timeSys = 0; // Time system 534 int readdir = 0; // Cell read direction 380 535 381 536 int nCells = 0; // Number of cells; 382 for (int i = 0; i < sources->n; i++) { 383 pmCell *cell = sources->data[i];// The cell of interest 537 psListIterator *sourcesIter = psListIteratorAlloc(sources, PS_LIST_HEAD, false); // Iterator for sources 538 pmCell *cell = NULL; // Source cell from iteration 539 while ((cell = psListGetAndIncrement(sourcesIter))) { 384 540 if (!cell) { 385 541 continue; … … 393 549 psTime *cellTime = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TIME"); 394 550 time += psTimeToMJD(cellTime); 395 if ( i == 0) {551 if (nCells == 1) { 396 552 timeSys = psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS"); 397 } else if (timeSys != psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")) { 398 psLogMsg(__func__, PS_LOG_ERROR, "Differing time systems in use: %d vs %d\n", timeSys, 399 psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")); 400 success = false; 553 readdir = psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR"); 554 } else { 555 if (timeSys != psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")) { 556 psLogMsg(__func__, PS_LOG_ERROR, "Differing time systems in use: %d vs %d\n", timeSys, 557 psMetadataLookupS32(NULL, cell->concepts, "CELL.TIMESYS")); 558 success = false; 559 } 560 if (readdir != psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR")) { 561 psLogMsg(__func__, PS_LOG_ERROR, "Differing cell read directions in use: %d vs %d\n", readdir, 562 psMetadataLookupS32(NULL, cell->concepts, "CELL.READDIR")); 563 success = false; 564 } 401 565 } 402 566 … … 410 574 } 411 575 } 576 psFree(sourcesIter); 577 412 578 gain /= (float)nCells; 413 579 readnoise /= (float)nCells; … … 429 595 MD_UPDATE(target->concepts, "CELL.XBIN", S32, xBin); 430 596 MD_UPDATE(target->concepts, "CELL.YBIN", S32, yBin); 597 MD_UPDATE(target->concepts, "CELL.READDIR", S32, readdir); 431 598 432 599 // CELL.TIME needs special care … … 448 615 449 616 617 // Add a cell and its various properties to the arrays 618 static bool addCell(psArray *images, // Array of images 619 psArray *masks, // Array of masks 620 psArray *weights, // Array of weights 621 psVector *x0, // Array of X0 622 psVector *y0, // Array of Y0 623 psVector *xBin, // Array of XBIN 624 psVector *yBin, // Array of YBIN 625 psVector *xFlip, // Array indicating whether x axis should be flipped 626 psVector *yFlip, // Array indicating whether y axis should be flipped 627 const pmCell *cell, // Cell to add 628 int *xBinMin, // The minimum x binning, returned 629 int *yBinMin, // The minimum y binning, returned 630 bool chipStuff // Worry about chip stuff as well? 631 ) 632 { 633 if (!cell) { 634 return false; 635 } 636 637 // Expand the arrays and vectors to handle new data 638 long index = images->n; // The index to use 639 if (images->n == images->nalloc) { 640 images = psArrayRealloc(images, index + CELL_LIST_BUFFER); 641 masks = psArrayRealloc(masks, index + CELL_LIST_BUFFER); 642 weights = psArrayRealloc(weights, index + CELL_LIST_BUFFER); 643 x0 = psVectorRealloc(x0, index+ CELL_LIST_BUFFER); 644 y0 = psVectorRealloc(y0, index+ CELL_LIST_BUFFER); 645 xBin = psVectorRealloc(xBin, index+ CELL_LIST_BUFFER); 646 yBin = psVectorRealloc(yBin, index+ CELL_LIST_BUFFER); 647 xFlip = psVectorRealloc(xFlip, index+ CELL_LIST_BUFFER); 648 yFlip = psVectorRealloc(yFlip, index+ CELL_LIST_BUFFER); 649 } 650 651 images->n = index + 1; 652 masks->n = index + 1; 653 weights->n = index + 1; 654 x0->n = index + 1; 655 y0->n = index + 1; 656 xBin->n = index + 1; 657 yBin->n = index + 1; 658 xFlip->n = index + 1; 659 yFlip->n = index + 1; 660 661 bool mdok = true; // Status of MD lookup 662 bool good = true; // Is everything good? 663 664 // Offset of the cell on the chip 665 int x0Cell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); 666 if (!mdok) { 667 psError(PS_ERR_UNKNOWN, true, "CELL.X0 for cell is not set.\n"); 668 good = false; 669 } 670 int y0Cell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); 671 if (!mdok) { 672 psError(PS_ERR_UNKNOWN, true, "CELL.Y0 for cell is not set.\n"); 673 good = false; 674 } 675 psTrace(__func__, 5, "Cell %d: x0=%d y0=%d\n", index, x0Cell, y0Cell); 676 677 // Offset of the chip on the FPA 678 int x0Chip = 0, y0Chip = 0; 679 if (chipStuff) { 680 pmChip *chip = cell->parent; // The parent chip 681 if (!chip) { 682 psError(PS_ERR_UNKNOWN, true, "Cell has no parent chip --- can't find CHIP.X0 and CHIP.Y0\n"); 683 good = false; 684 } 685 x0Chip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.X0"); 686 if (!mdok) { 687 psError(PS_ERR_UNKNOWN, true, "CHIP.X0 for chip is not set.\n"); 688 good = false; 689 } 690 y0Chip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.Y0"); 691 if (!mdok) { 692 psError(PS_ERR_UNKNOWN, true, "CHIP.Y0 for chip is not set.\n"); 693 good = false; 694 } 695 } 696 697 // Binning 698 xBin->data.S32[index] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN"); 699 if (!mdok || xBin->data.S32[index] == 0) { 700 psError(PS_ERR_UNKNOWN, true, "CELL.XBIN for cell is not set.\n"); 701 good = false; 702 } 703 if (xBin->data.S32[index] < *xBinMin) { 704 *xBinMin = xBin->data.S32[index]; 705 } 706 yBin->data.S32[index] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN"); 707 if (!mdok || yBin->data.S32[index] == 0) { 708 psError(PS_ERR_UNKNOWN, true, "CELL.YBIN for cell is not set.\n"); 709 good = false; 710 } 711 if (yBin->data.S32[index] < *yBinMin) { 712 *yBinMin = yBin->data.S32[index]; 713 } 714 715 // Do we need to flip? 716 int xParityCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY"); 717 if (!mdok || (xParityCell != 1 && xParityCell != -1)) { 718 psError(PS_ERR_UNKNOWN, true, "CELL.XPARITY for cell is not set.\n"); 719 good = false; 720 } 721 int yParityCell = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY"); 722 if (!mdok || (yParityCell != 1 && yParityCell != -1)) { 723 psError(PS_ERR_UNKNOWN, true, "CELL.YPARITY for cell is not set.\n"); 724 good = false; 725 } 726 727 // Parity of the chip on the FPA 728 int xParityChip = 0, yParityChip = 0; 729 if (chipStuff) { 730 pmChip *chip = cell->parent; // The parent chip 731 xParityChip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.XPARITY"); 732 if (!mdok || (xParityChip != 1 && xParityChip != -1)) { 733 psError(PS_ERR_UNKNOWN, true, "CHIP.XPARITY for chip is not set.\n"); 734 good = false; 735 } 736 yParityChip = psMetadataLookupS32(&mdok, chip->concepts, "CHIP.YPARITY"); 737 if (!mdok || (yParityChip != 1 && yParityChip != -1)) { 738 psError(PS_ERR_UNKNOWN, true, "CHIP.YPARITY for chip is not set.\n"); 739 good = false; 740 } 741 } 742 743 // Set the flips on the basis of the parity 744 if (xParityCell * xParityChip == -1) { 745 xFlip->data.U8[index] = 1; 746 } else { 747 xFlip->data.U8[index] = 0; 748 } 749 if (yParityCell * yParityChip == -1) { 750 yFlip->data.U8[index] = 1; 751 } else { 752 yFlip->data.U8[index] = 0; 753 } 754 755 x0->data.S32[index] = x0Chip + x0Cell; 756 y0->data.S32[index] = y0Chip + y0Cell; 757 758 // Add the readout to the array of images to be mosaicked 759 psArray *readouts = cell->readouts; // The array of readouts 760 if (readouts->n > 1) { 761 psLogMsg(__func__, PS_LOG_WARN, "Cell contains more than one readout (%ld) --- only the first will " 762 "be mosaicked.\n", readouts->n); 763 } 764 pmReadout *readout = readouts->data[0]; // The only readout we'll bother with 765 766 // The images to put into the mosaic 767 images->data[index] = psMemIncrRefCounter(readout->image); 768 weights->data[index] = psMemIncrRefCounter(readout->weight); 769 masks->data[index] = psMemIncrRefCounter(readout->mask); 770 771 psTrace(__func__, 9, "Added cell (%x) %ld: %d,%d; %d,%d, %d,%d.\n", cell, index, 772 x0->data.S32[index], y0->data.S32[index], xBin->data.S32[index], yBin->data.S32[index], 773 xFlip->data.U8[index], yFlip->data.U8[index]); 774 775 return true; 776 } 777 778 450 779 // Mosaic together the cells in a chip 451 bool chipMosaic(psImage **mosaicImage,// The mosaic image, to be returned452 psImage **mosaicMask,// The mosaic mask, to be returned453 psImage **mosaicWeights, // The mosaic weights, to be returned454 int *xBinChip, int *yBinChip, // The binning in x and y, to be returned455 pmChip *chip// Chip to mosaic456 )780 static bool chipMosaic(psImage **mosaicImage, // The mosaic image, to be returned 781 psImage **mosaicMask, // The mosaic mask, to be returned 782 psImage **mosaicWeights, // The mosaic weights, to be returned 783 int *xBinChip, int *yBinChip, // The binning in x and y, to be returned 784 const pmChip *chip // Chip to mosaic 785 ) 457 786 { 458 787 assert(mosaicImage); … … 461 790 assert(chip); 462 791 463 psArray *cells = chip->cells; // The array of cells 464 int numCells = cells->n; // Number of cells 465 psArray *images = psArrayAlloc(numCells); // Array of images that will be mosaicked 466 psArray *weights = psArrayAlloc(numCells); // Array of weight images to be mosaicked 467 psArray *masks = psArrayAlloc(numCells); // Array of mask images to be mosaicked 468 psVector *x0 = psVectorAlloc(numCells, PS_TYPE_S32); // Origin x coordinates 469 psVector *y0 = psVectorAlloc(numCells, PS_TYPE_S32); // Origin y coordinates 470 psVector *xBin = psVectorAlloc(numCells, PS_TYPE_S32); // Binning in x 471 psVector *yBin = psVectorAlloc(numCells, PS_TYPE_S32); // Binning in y 472 psVector *xFlip = psVectorAlloc(numCells, PS_TYPE_U8); // Flip in x? 473 psVector *yFlip = psVectorAlloc(numCells, PS_TYPE_U8); // Flip in y? 474 images->n = weights->n = masks->n = numCells; 475 x0->n = y0->n = xBin->n = yBin->n = xFlip->n = yFlip->n = numCells; 792 psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked 793 psArray *weights = psArrayAlloc(0); // Array of weight images to be mosaicked 794 psArray *masks = psArrayAlloc(0); // Array of mask images to be mosaicked 795 psVector *x0 = psVectorAlloc(0, PS_TYPE_S32); // Origin x coordinates 796 psVector *y0 = psVectorAlloc(0, PS_TYPE_S32); // Origin y coordinates 797 psVector *xBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in x 798 psVector *yBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in y 799 psVector *xFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in x? 800 psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y? 476 801 477 802 // Binning for the mosaicked chip is the minimum binning allowed by the cells … … 480 805 481 806 // Set up the required inputs 482 psTrace(__func__, 1, "Mosaicking %d cells...\n", numCells);483 bool good = true; // Is everything good, well-behaved?484 for (int i = 0; i < numCells && good; i++) {807 bool allGood = true; // Is everything good, well-behaved? 808 psArray *cells = chip->cells; // The array of cells 809 for (int i = 0; i < cells->n; i++) { 485 810 pmCell *cell = cells->data[i]; // The cell of interest 486 811 if (!cell) { 487 812 continue; 488 813 } 489 bool mdok = true; // Status of MD lookup 490 x0->data.S32[i] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.X0"); 491 if (!mdok) { 492 psError(PS_ERR_IO, true, "CELL.X0 for cell %d is not set.\n", i); 493 good = false; 494 } 495 y0->data.S32[i] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.Y0"); 496 if (!mdok) { 497 psError(PS_ERR_IO, true, "CELL.Y0 for cell %d is not set.\n", i); 498 good = false; 499 } 500 psTrace(__func__, 5, "Cell %d: x0=%d y0=%d\n", i, x0->data.S32[i], y0->data.S32[i]); 501 xBin->data.S32[i] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XBIN"); 502 if (!mdok || xBin->data.S32[i] == 0) { 503 psError(PS_ERR_IO, true, "CELL.XBIN for cell %d is not set.\n", i); 504 good = false; 505 } 506 if (xBin->data.S32[i] < *xBinChip) { 507 *xBinChip = xBin->data.S32[i]; 508 } 509 yBin->data.S32[i] = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YBIN"); 510 if (!mdok || yBin->data.S32[i] == 0) { 511 psError(PS_ERR_IO, true, "CELL.YBIN for cell %d is not set.\n", i); 512 good = false; 513 } 514 if (yBin->data.S32[i] < *yBinChip) { 515 *yBinChip = yBin->data.S32[i]; 516 } 517 int xParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.XPARITY"); 518 if (!mdok || (xParity != 1 && xParity != -1)) { 519 psError(PS_ERR_IO, true, "CELL.XPARITY for cell %d is not set.\n", i); 520 good = false; 521 } 522 int yParity = psMetadataLookupS32(&mdok, cell->concepts, "CELL.YPARITY"); 523 if (!mdok || (yParity != 1 && yParity != -1)) { 524 psError(PS_ERR_IO, true, "CELL.YPARITY for cell %d is not set.\n", i); 525 good = false; 526 } 527 if (xParity == -1) { 528 xFlip->data.U8[i] = 1; 529 } else { 530 xFlip->data.U8[i] = 0; 531 } 532 if (yParity == -1) { 533 yFlip->data.U8[i] = 1; 534 } else { 535 yFlip->data.U8[i] = 0; 536 } 537 538 psArray *readouts = cell->readouts; // The array of readouts 539 if (readouts->n > 1) { 540 psLogMsg(__func__, PS_LOG_WARN, "Cell %d contains more than one readout --- only the first will " 541 "be mosaicked.\n", i); 542 } 543 pmReadout *readout = readouts->data[0]; // The only readout we'll bother with 544 545 // The images to put into the mosaic 546 images->data[i] = psMemIncrRefCounter(readout->image); 547 weights->data[i] = psMemIncrRefCounter(readout->weight); 548 masks->data[i] = psMemIncrRefCounter(readout->mask); 814 allGood |= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip, 815 cell, xBinChip, yBinChip, false); 549 816 } 550 817 551 818 // Mosaic the images together and we're done 552 if ( good) {819 if (allGood) { 553 820 *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0); 554 821 *mosaicWeights = imageMosaic(weights, xFlip, yFlip, xBin, yBin, *xBinChip, *yBinChip, x0, y0); … … 567 834 psFree(y0); 568 835 569 return good; 836 return allGood; 837 } 838 839 // Mosaic together the cells in a FPA 840 static bool fpaMosaic(psImage **mosaicImage, // The mosaic image, to be returned 841 psImage **mosaicMask, // The mosaic mask, to be returned 842 psImage **mosaicWeights, // The mosaic weights, to be returned 843 int *xBinFPA, int *yBinFPA, // The binning in x and y, to be returned 844 const pmFPA *fpa // FPA to mosaic 845 ) 846 { 847 assert(mosaicImage); 848 assert(mosaicMask); 849 assert(mosaicWeights); 850 assert(fpa); 851 852 psArray *images = psArrayAlloc(0); // Array of images that will be mosaicked 853 psArray *weights = psArrayAlloc(0); // Array of weight images to be mosaicked 854 psArray *masks = psArrayAlloc(0); // Array of mask images to be mosaicked 855 psVector *x0 = psVectorAlloc(0, PS_TYPE_S32); // Origin x coordinates 856 psVector *y0 = psVectorAlloc(0, PS_TYPE_S32); // Origin y coordinates 857 psVector *xBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in x 858 psVector *yBin = psVectorAlloc(0, PS_TYPE_S32); // Binning in y 859 psVector *xFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in x? 860 psVector *yFlip = psVectorAlloc(0, PS_TYPE_U8); // Flip in y? 861 862 // Binning for the mosaicked chip is the minimum binning allowed by the cells 863 *xBinFPA = INT_MAX; 864 *yBinFPA = INT_MAX; 865 866 // Set up the required inputs 867 bool allGood = true; // Is everything good, well-behaved? 868 psArray *chips = fpa->chips; // Array of chips 869 for (int i = 0; i < chips->n; i++) { 870 pmChip *chip = chips->data[i]; // The chip of interest 871 if (!chip) { 872 continue; 873 } 874 psArray *cells = chip->cells; // The array of cells 875 for (int j = 0; j < cells->n; j++) { 876 pmCell *cell = cells->data[j]; // The cell of interest 877 if (!cell) { 878 continue; 879 } 880 allGood |= addCell(images, masks, weights, x0, y0, xBin, yBin, xFlip, yFlip, 881 cell, xBinFPA, yBinFPA, true); 882 } 883 } 884 885 // Mosaic the images together and we're done 886 if (allGood) { 887 *mosaicImage = imageMosaic(images, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0); 888 *mosaicWeights = imageMosaic(weights, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0); 889 *mosaicMask = imageMosaic(masks, xFlip, yFlip, xBin, yBin, *xBinFPA, *yBinFPA, x0, y0); 890 } 891 892 // Clean up 893 psFree(images); 894 psFree(weights); 895 psFree(masks); 896 psFree(xFlip); 897 psFree(yFlip); 898 psFree(xBin); 899 psFree(yBin); 900 psFree(x0); 901 psFree(y0); 902 903 return allGood; 570 904 } 571 905 … … 599 933 // Once the demands of case 1 have been met, or case 2 has been performed, then we can create a cell to hold 600 934 // the mosaic image. 601 bool pmChipMosaic(pmChip *chip // Chip whose cells will be mosaicked 935 bool pmChipMosaic(pmChip *target, // Target chip --- may contain only a single cell 936 const pmChip *source // Source chip whose cells will be mosaicked 602 937 ) 603 938 { 604 PS_ASSERT_PTR_NON_NULL(chip, false); 939 // Target exists, and has only a single cell 940 PS_ASSERT_PTR_NON_NULL(target, false); 941 PS_ASSERT_PTR_NON_NULL(target->cells, false); 942 if (target->cells->n != 1) { 943 psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target chip for mosaicking must contain a single cell.\n"); 944 return false; 945 } 946 pmCell *targetCell = target->cells->data[0]; // The target cell 947 PS_ASSERT_PTR_NON_NULL(targetCell, false); 948 // Source exists 949 PS_ASSERT_PTR_NON_NULL(source, false); 950 605 951 606 952 psImage *mosaicImage = NULL; // The mosaic image … … 611 957 psRegion *chipRegion = NULL; // Region on the HDU that corresponds to the chip 612 958 int xBin = 0, yBin = 0; // Binning for the chip mosaic 613 if ((chipRegion = niceChip(&xBin, &yBin, chip))) {959 if ((chipRegion = niceChip(&xBin, &yBin, source))) { 614 960 // Case 1 --- we need only cut out the region 615 961 psTrace(__func__, 1, "Case 1 mosaicking: simple cut-out.\n"); 616 pmHDU *hdu = chip->hdu;// The HDU that has the pixels962 pmHDU *hdu = source->hdu; // The HDU that has the pixels 617 963 if (!hdu || !hdu->images) { 618 hdu = chip->parent->hdu;619 } 620 mosaicImage = psMemIncrRefCounter(psImageSubset(hdu->images->data[0], *chipRegion));964 hdu = source->parent->hdu; 965 } 966 mosaicImage = psMemIncrRefCounter(psImageSubset(hdu->images->data[0], *chipRegion)); 621 967 if (hdu->masks) { 622 mosaicMask = psMemIncrRefCounter(psImageSubset(hdu->masks->data[0], *chipRegion));968 mosaicMask = psMemIncrRefCounter(psImageSubset(hdu->masks->data[0], *chipRegion)); 623 969 } 624 970 if (hdu->weights) { … … 628 974 // Case 2 --- we need to mosaic by cut and paste 629 975 psTrace(__func__, 1, "Case 2 mosaicking: cut and paste.\n"); 630 if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, chip)) {631 psError(PS_ERR_ IO, false, "Unable to mosaic cells.\n");976 if (!chipMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source)) { 977 psError(PS_ERR_UNKNOWN, false, "Unable to mosaic cells.\n"); 632 978 return false; 633 979 } … … 635 981 } 636 982 637 // Construct a new cell, set the concepts, and add the mosaic in 638 pmCell *newCell = pmCellAlloc(NULL, "MOSAIC"); // New cell 639 cellConcepts(newCell, chip->cells, xBin, yBin, chipRegion); 983 // Set the concepts for the target cell 984 psList *sourceCells = psArrayToList(source->cells); // List of cells 985 cellConcepts(targetCell, sourceCells, xBin, yBin, chipRegion); 986 psFree(sourceCells); 640 987 psFree(chipRegion); 641 chip->mosaic = (struct pmCell*)newCell; 642 643 // Now make a new readout to go in the new cell 644 pmReadout *newReadout = pmReadoutAlloc(newCell); // New readout 988 989 // Now make a new readout to go in the target cell 990 pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout 645 991 newReadout->image = mosaicImage; 646 992 newReadout->mask = mosaicMask; … … 650 996 return true; 651 997 } 998 999 1000 // Same deal with the FPA 1001 bool pmFPAMosaic(pmFPA *target, // Target FPA --- may contain only a single chip with a single cell 1002 const pmFPA *source // FPA whose chips and cells will be mosaicked 1003 ) 1004 { 1005 // Target exists, and has only a single chip with single cell 1006 PS_ASSERT_PTR_NON_NULL(target, false); 1007 PS_ASSERT_PTR_NON_NULL(target->chips, false); 1008 if (target->chips->n != 1) { 1009 psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target FPA for mosaicking must contain a single chip.\n"); 1010 return false; 1011 } 1012 pmChip *targetChip = target->chips->data[0]; // The target chip 1013 PS_ASSERT_PTR_NON_NULL(targetChip, false); 1014 PS_ASSERT_PTR_NON_NULL(targetChip->cells, false); 1015 if (target->chips->n != 1) { 1016 psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Target FPA for mosaicking must contain a single cell.\n"); 1017 return false; 1018 } 1019 pmCell *targetCell = targetChip->cells->data[0]; // The target cell 1020 PS_ASSERT_PTR_NON_NULL(targetCell, false); 1021 // Source exists 1022 PS_ASSERT_PTR_NON_NULL(source, false); 1023 1024 psImage *mosaicImage = NULL; // The mosaic image 1025 psImage *mosaicMask = NULL; // The mosaic mask 1026 psImage *mosaicWeights = NULL; // The mosaic weights 1027 1028 // Find the HDU 1029 psRegion *fpaRegion = NULL; // Region on the HDU that corresponds to the FPA 1030 int xBin = 0, yBin = 0; // Binning for the FPA mosaic 1031 if ((fpaRegion = niceFPA(&xBin, &yBin, source))) { 1032 // Case 1 --- we need only cut out the region 1033 psTrace(__func__, 1, "Case 1 mosaicking: simple cut-out.\n"); 1034 pmHDU *hdu = source->hdu; // The HDU that has the pixels 1035 mosaicImage = psMemIncrRefCounter(psImageSubset(hdu->images->data[0], *fpaRegion)); 1036 if (hdu->masks) { 1037 mosaicMask = psMemIncrRefCounter(psImageSubset(hdu->masks->data[0], *fpaRegion)); 1038 } 1039 if (hdu->weights) { 1040 mosaicWeights = psMemIncrRefCounter(psImageSubset(hdu->weights->data[0], *fpaRegion)); 1041 } 1042 } else { 1043 // Case 2 --- we need to mosaic by cut and paste 1044 psTrace(__func__, 1, "Case 2 mosaicking: cut and paste.\n"); 1045 if (!fpaMosaic(&mosaicImage, &mosaicMask, &mosaicWeights, &xBin, &yBin, source)) { 1046 psError(PS_ERR_UNKNOWN, false, "Unable to mosaic chips.\n"); 1047 return false; 1048 } 1049 fpaRegion = psRegionAlloc(NAN, NAN, NAN, NAN); // We've cut and paste, so there's no valid trimsec 1050 } 1051 1052 // Set the concepts for the target cell, and add the mosaic in 1053 // First we need a list of cells 1054 psList *sourceCells = psListAlloc(NULL); // List of source cells 1055 psArray *chips = source->chips; // Array of chips 1056 for (long i = 0; i < chips->n; i++) { 1057 pmChip *chip = chips->data[i]; // Chip of interest 1058 if (!chip) { 1059 continue; 1060 } 1061 psArray *cells = chip->cells; 1062 for (long j = 0; j < cells->n; j++) { 1063 pmCell *cell = cells->data[j]; // Cell of interest 1064 if (!cell) { 1065 continue; 1066 } 1067 psListAdd(sourceCells, PS_LIST_TAIL, cell); 1068 } 1069 } 1070 cellConcepts(targetCell, sourceCells, xBin, yBin, fpaRegion); 1071 psFree(sourceCells); 1072 psFree(fpaRegion); 1073 1074 // Now make a new readout to go in the new cell 1075 pmReadout *newReadout = pmReadoutAlloc(targetCell); // New readout 1076 newReadout->image = mosaicImage; 1077 newReadout->mask = mosaicMask; 1078 newReadout->weight = mosaicWeights; 1079 psFree(newReadout); // Drop reference 1080 1081 return true; 1082 } 1083
Note:
See TracChangeset
for help on using the changeset viewer.
