Changeset 34281
- Timestamp:
- Aug 2, 2012, 2:47:03 PM (14 years ago)
- Location:
- tags/ipp-20120802/ppTranslate
- Files:
-
- 8 edited
-
. (modified) (1 prop)
-
src/ppMops.c (modified) (2 diffs)
-
src/ppMops.h (modified) (3 diffs)
-
src/ppMopsArguments.c (modified) (1 diff)
-
src/ppMopsGetSkyChipPsfVersion.c (modified) (1 diff)
-
src/ppMopsMerge.c (modified) (1 diff)
-
src/ppMopsRead.c (modified) (1 diff)
-
src/ppMopsWrite.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
tags/ipp-20120802/ppTranslate
- Property svn:mergeinfo deleted
-
tags/ipp-20120802/ppTranslate/src/ppMops.c
r34280 r34281 67 67 } 68 68 69 69 70 psArray *detections = ppMopsRead(args); // Detections from each input 70 71 if (!detections) { … … 91 92 psLibFinalize(); 92 93 93 /* fprintf (stderr, "found %d leaks at %s\n", */ 94 /* psMemCheckLeaks2 (0, */ 95 /* NULL, stdout, false, 500), "ppMops"); */ 94 fprintf (stderr, "found %d leaks at %s\n", 95 psMemCheckLeaks2 (0, 96 NULL, stdout, false, 500), "ppMops"); 96 97 97 98 return PS_EXIT_SUCCESS; 98 99 } 99 100 101 102 #if 0 103 ps 104 105 106 psArray *detections = NULL; // Detections 107 psMetadata *header = NULL; // Header for detections 108 { 109 psFits *fits = psFitsOpen(data->detections, "r"); // FITS file 110 header = psFitsReadHeader(NULL, fits); 111 if (!header) { 112 psErrorStackPrint(stderr, "Unable to read header"); 113 psFitsClose(fits); 114 psFree(data); 115 exit(PS_EXIT_DATA_ERROR); 116 } 117 if (!psFitsMoveExtName(fits, IN_EXTNAME)) { 118 psErrorStackPrint(stderr, "Unable to move to extension %s", IN_EXTNAME); 119 psFitsClose(fits); 120 psFree(header); 121 psFree(data); 122 exit(PS_EXIT_DATA_ERROR); 123 } 124 detections = psFitsReadTable(fits); 125 psFitsClose(fits); 126 if (!detections) { 127 psErrorStackPrint(stderr, "Unable to read detections"); 128 psFree(data); 129 psFree(header); 130 exit(PS_EXIT_DATA_ERROR); 131 } 132 } 133 134 // Translate the columns 135 int numIn = detections->n; // Number of rows in input 136 int numOut = 0; // Number of rows in output 137 psArray *output = psArrayAllocEmpty(numIn); // Output table 138 double plateScale = 0.0; // Average plate scale 139 for (int i = 0; i < numIn; i++) { 140 psMetadata *inRow = detections->data[i]; // Input row 141 142 double ra = psMetadataLookupF64(NULL, inRow, "RA_PSF"); 143 double dec = psMetadataLookupF64(NULL, inRow, "DEC_PSF"); 144 double mag = psMetadataLookupF64(NULL, inRow, "PSF_INST_MAG") + data->zp; 145 double magErr = psMetadataLookupF64(NULL, inRow, "PSF_INST_MAG_SIG"); 146 float ext = psMetadataLookupF32(NULL, inRow, "EXT_NSIGMA"); 147 double xErr = psMetadataLookupF64(NULL, inRow, "X_PSF_SIG"); 148 double yErr = psMetadataLookupF64(NULL, inRow, "Y_PSF_SIG"); 149 double scale = psMetadataLookupF64(NULL, inRow, "PLTSCALE"); 150 double angle = psMetadataLookupF64(NULL, inRow, "POSANGLE"); 151 psU32 flags = psMetadataLookupU32(NULL, inRow, "FLAGS"); 152 153 if (!isfinite(mag) || !isfinite(magErr) || (flags & SOURCE_MASK) || 154 ((flags & PM_SOURCE_MODE_DEFECT) && !(flags & PM_SOURCE_MODE_MOMENTS_FAILURE)) 155 ) { 156 // DEFECT can be due to bad moments 157 continue; 158 } 159 160 psMetadata *outRow = output->data[numOut] = psMetadataAlloc(); // Output row 161 162 numOut++; 163 plateScale += scale; 164 165 // XXX Not at all sure I've got the angles around the right way here... 166 double cosAngle = cos(angle), sinAngle = sin(angle); 167 double cosAngle2 = PS_SQR(cosAngle), sinAngle2 = PS_SQR(sinAngle); 168 double xErr2 = PS_SQR(xErr), yErr2 = PS_SQR(yErr); 169 double errScale = scale / 3600.0; 170 double raErr = errScale * sqrt(cosAngle2 * xErr2 + sinAngle2 * yErr2); 171 double decErr = errScale * sqrt(sinAngle2 * xErr2 + cosAngle2 * yErr2); 172 173 psMetadataAddF64(outRow, PS_LIST_TAIL, "RA_DEG", 0, "Right ascension (degrees)", ra); 174 psMetadataAddF64(outRow, PS_LIST_TAIL, "DEC_DEG", 0, "Declination (degrees)", dec); 175 psMetadataAddF64(outRow, PS_LIST_TAIL, "RA_SIG", 0, "Right ascension error (degrees)", raErr); 176 psMetadataAddF64(outRow, PS_LIST_TAIL, "DEC_SIG", 0, "Declination error (degrees)", decErr); 177 psMetadataAddF64(outRow, PS_LIST_TAIL, "MAG", 0, "Magnitude", mag); 178 psMetadataAddF64(outRow, PS_LIST_TAIL, "MAG_SIG", 0, "Magnitude error", magErr); 179 psMetadataAddU32(outRow, PS_LIST_TAIL, "FLAGS", 0, "Detection bit flags", flags); 180 181 // The below need fixing 182 psMetadataAddF64(outRow, PS_LIST_TAIL, "STARPSF", 0, "EXT_NSIGMA", ext); 183 psMetadataAddF64(outRow, PS_LIST_TAIL, "ANG", 0, "Position angle of trail (degrees)", 0.0); 184 psMetadataAddF64(outRow, PS_LIST_TAIL, "ANG_SIG", 0, "Position angle error (degrees)", 0.0); 185 psMetadataAddF64(outRow, PS_LIST_TAIL, "LEN", 0, "Length of trail (arcsec)", 0.0); 186 psMetadataAddF64(outRow, PS_LIST_TAIL, "LEN_SIG", 0, "Length error (arcsec)", 0.0); 187 } 188 output->n = numOut; 189 plateScale /= numOut; 190 psFree(detections); 191 192 // Translate the header 193 psMetadata *outHeader = psMetadataAlloc(); // Output header 194 ppMopsVersionHeader(outHeader); 195 { 196 const char *ra = psMetadataLookupStr(NULL, header, "FPA.RA"); 197 const char *dec = psMetadataLookupStr(NULL, header, "FPA.DEC"); 198 const char *filter = psMetadataLookupStr(NULL, header, "FPA.FILTER"); 199 float airmass = psMetadataLookupF32(NULL, header, "FPA.AIRMASS"); 200 float exptime = psMetadataLookupF32(NULL, header, "EXPTIME"); 201 double angle = psMetadataLookupF64(NULL, header, "FPA.POSANGLE"); 202 double alt = psMetadataLookupF64(NULL, header, "FPA.ALT"); 203 double az = psMetadataLookupF64(NULL, header, "FPA.AZ"); 204 psS64 imageid = psMetadataLookupS64(NULL, header, "IMAGEID"); 205 double mjd = psMetadataLookupF64(NULL, header, "MJD-OBS") + exptime / 2.0 / 3600 / 24; 206 207 float psf = plateScale * 0.5 * (psMetadataLookupF32(NULL, header, "FWHM_MAJ") + 208 psMetadataLookupF32(NULL, header, "FWHM_MIN")); 209 210 psMetadataAddStr(outHeader, PS_LIST_TAIL, "RA", 0, "Right ascension of boresight", ra); 211 psMetadataAddStr(outHeader, PS_LIST_TAIL, "DEC", 0, "Declination of boresight", dec); 212 psMetadataAddF32(outHeader, PS_LIST_TAIL, "AIRMASS", 0, "Airmass of exposure", airmass); 213 psMetadataAddF64(outHeader, PS_LIST_TAIL, "MJD-OBS", 0, "MJD of exposure midpoint", mjd); 214 psMetadataAddStr(outHeader, PS_LIST_TAIL, "FILTER", 0, "Filter name", filter); 215 psMetadataAddF64(outHeader, PS_LIST_TAIL, "EXPTIME", 0, "Exposure time (sec)", exptime); 216 psMetadataAddF64(outHeader, PS_LIST_TAIL, "ROTANGLE", 0, "Rotator position angle", angle); 217 psMetadataAddF64(outHeader, PS_LIST_TAIL, "TEL_ALT", 0, "Telescope altitude", alt); 218 psMetadataAddF64(outHeader, PS_LIST_TAIL, "TEL_AZ", 0, "Telescope azimuth", az); 219 psMetadataAddS64(outHeader, PS_LIST_TAIL, "DIFFIMID", 0, "Difference image identifier", imageid); 220 psMetadataAddStr(outHeader, PS_LIST_TAIL, "FPA_ID", 0, "Exposure name", data->exp_name); 221 psMetadataAddS64(outHeader, PS_LIST_TAIL, "EXP_ID", 0, "Exposure identifier", data->exp_id); 222 psMetadataAddBool(outHeader, PS_LIST_TAIL, "POSITIVE", 0, "Positive subtraction?", data->direction); 223 psMetadataAddStr(outHeader, PS_LIST_TAIL, "OBSCODE", 0, "IAU Observatory code", OBSERVATORY_CODE); 224 psMetadataAddF32(outHeader, PS_LIST_TAIL, "STARPSF", 0, "Stellar PSF (arcsec)", psf); 225 226 // These are completely fake 227 psMetadataAddF32(outHeader, PS_LIST_TAIL, "LIMITMAG", 0, "Limiting magnitude (FAKE)", 99.0); 228 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE1", 0, "Detection efficiency (FAKE)", 0.0); 229 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE2", 0, "Detection efficiency (FAKE)", 0.0); 230 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE3", 0, "Detection efficiency (FAKE)", 0.0); 231 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE4", 0, "Detection efficiency (FAKE)", 0.0); 232 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE5", 0, "Detection efficiency (FAKE)", 0.0); 233 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE6", 0, "Detection efficiency (FAKE)", 0.0); 234 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE7", 0, "Detection efficiency (FAKE)", 0.0); 235 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE8", 0, "Detection efficiency (FAKE)", 0.0); 236 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE9", 0, "Detection efficiency (FAKE)", 0.0); 237 psMetadataAddF32(outHeader, PS_LIST_TAIL, "DE10", 0, "Detection efficiency (FAKE)", 0.0); 238 } 239 psFree(header); 240 241 // Write the new table 242 { 243 psFits *fits = psFitsOpen(data->output, "w"); // FITS file 244 if (!fits) { 245 psErrorStackPrint(stderr, "Unable to open %s for writing", data->output); 246 psFree(outHeader); 247 psFree(output); 248 psFree(data); 249 exit(PS_EXIT_SYS_ERROR); 250 } 251 252 if (numOut == 0) { 253 // Write dummy table 254 psMetadata *outRow = psMetadataAlloc(); // Dummy output row 255 psMetadataAddF64(outRow, PS_LIST_TAIL, "RA_DEG", 0, "Right ascension (degrees)", NAN); 256 psMetadataAddF64(outRow, PS_LIST_TAIL, "DEC_DEG", 0, "Declination (degrees)", NAN); 257 psMetadataAddF64(outRow, PS_LIST_TAIL, "RA_SIG", 0, "Right ascension error (degrees)", NAN); 258 psMetadataAddF64(outRow, PS_LIST_TAIL, "DEC_SIG", 0, "Declination error (degrees)", NAN); 259 psMetadataAddF64(outRow, PS_LIST_TAIL, "MAG", 0, "Magnitude", NAN); 260 psMetadataAddF64(outRow, PS_LIST_TAIL, "MAG_SIG", 0, "Magnitude error", NAN); 261 psMetadataAddU32(outRow, PS_LIST_TAIL, "FLAGS", 0, "Detection bit flags", 0); 262 263 // The below need fixing 264 psMetadataAddF64(outRow, PS_LIST_TAIL, "STARPSF", 0, "EXT_NSIGMA", NAN); 265 psMetadataAddF64(outRow, PS_LIST_TAIL, "ANG", 0, "Position angle of trail (degrees)", NAN); 266 psMetadataAddF64(outRow, PS_LIST_TAIL, "ANG_SIG", 0, "Position angle error (degrees)", NAN); 267 psMetadataAddF64(outRow, PS_LIST_TAIL, "LEN", 0, "Length of trail (arcsec)", NAN); 268 psMetadataAddF64(outRow, PS_LIST_TAIL, "LEN_SIG", 0, "Length error (arcsec)", NAN); 269 if (!psFitsWriteTableEmpty(fits, outHeader, outRow, OUT_EXTNAME)) { 270 psErrorStackPrint(stderr, "Unable to write table."); 271 psFree(outHeader); 272 psFree(output); 273 psFree(outRow); 274 psFree(data); 275 exit(PS_EXIT_SYS_ERROR); 276 } 277 psFree(outRow); 278 } else if (!psFitsWriteTable(fits, outHeader, output, OUT_EXTNAME)) { 279 psErrorStackPrint(stderr, "Unable to write table."); 280 psFree(outHeader); 281 psFree(output); 282 psFree(data); 283 exit(PS_EXIT_SYS_ERROR); 284 } 285 psFitsClose(fits); 286 } 287 288 psFree(outHeader); 289 psFree(output); 290 psFree(data); 291 292 #endif 293 -
tags/ipp-20120802/ppTranslate/src/ppMops.h
r34280 r34281 30 30 } ppMopsArguments; 31 31 32 #if 0 33 #warning "IS THERE ANYTHING TO BE MODIFIED HERE?" 34 TTYPE19 = 'PSF_CHISQ' / label for field 19 35 TFORM19 = '1E ' / data format of field: 4-byte REAL 36 TTYPE20 = 'CR_NSIGMA' / label for field 20 37 TFORM20 = '1E ' / data format of field: 4-byte REAL 38 TTYPE21 = 'EXT_NSIGMA' / label for field 21 39 TFORM21 = '1E ' / data format of field: 4-byte REAL 40 TTYPE22 = 'PSF_MAJOR' / label for field 22 41 TFORM22 = '1E ' / data format of field: 4-byte REAL 42 TTYPE23 = 'PSF_MINOR' / label for field 23 43 TFORM23 = '1E ' / data format of field: 4-byte REAL 44 TTYPE24 = 'PSF_THETA' / label for field 24 45 TFORM24 = '1E ' / data format of field: 4-byte REAL 46 TTYPE25 = 'PSF_QF ' / label for field 25 47 TFORM25 = '1E ' / data format of field: 4-byte REAL 48 TTYPE26 = 'PSF_NDOF' / label for field 26 49 TFORM26 = '1J ' / data format of field: 4-byte INTEGER 50 TTYPE27 = 'PSF_NPIX' / label for field 27 51 TFORM27 = '1J ' / data format of field: 4-byte INTEGER 52 TTYPE28 = 'MOMENTS_XX' / label for field 28 53 TFORM28 = '1E ' / data format of field: 4-byte REAL 54 TTYPE29 = 'MOMENTS_XY' / label for field 29 55 TFORM29 = '1E ' / data format of field: 4-byte REAL 56 TTYPE30 = 'MOMENTS_YY' / label for field 30 57 TFORM30 = '1E ' / data format of field: 4-byte REAL 58 #endif 59 32 60 /// Parse arguments 33 61 ppMopsArguments *ppMopsArgumentsParse(int argc, char *argv[]); … … 47 75 long numGood; // Number of "good" detections 48 76 psS64 diffSkyfileId; // unique id for input skyfile 49 psMetadata *table; // Columns from the input file (SkyChip.psf extension) 50 psMetadata *fittedTrails; // Columns from the fitted trails (SkyChip.xfit extension) 51 long fittedTrailsSize; // Size of the fitted trails (SkyChip.xfit extension) 77 psMetadata *table; // Columns from the input file 52 78 psVector *x, *y; // Image coordinates 53 79 psVector *ra, *dec; // Sky coordinates … … 77 103 /// @returns 1 if EXTTYPE of "SkyChip.psf" is PS1_DV1 78 104 /// @returns 2 if EXTTYPE of "SkyChip.psf" is PS1_DV2 79 /// @returns 3 if EXTTYPE of "SkyChip.psf" is PS1_DV380 105 /// @returns 0 otherwise 81 106 int ppMopsGetSkyChipPsfVersion(const psFits* fits); -
tags/ipp-20120802/ppTranslate/src/ppMopsArguments.c
r34280 r34281 34 34 fprintf(stderr, "\n"); 35 35 psArgumentHelp(arguments); 36 fprintf(stderr, "\t\tCMF file version can be set to either 1 for PS1_DV1 , 2 for PS1_DV2, or 3 for PS1_DV3\n");36 fprintf(stderr, "\t\tCMF file version can be set to either 1 for PS1_DV1 or 2 for PS1_DV1\n"); 37 37 fprintf(stderr, "\t\tSee IPP-MOPS ICD for details\n"); 38 38 psLibFinalize(); -
tags/ipp-20120802/ppTranslate/src/ppMopsGetSkyChipPsfVersion.c
r34280 r34281 14 14 psFree(headerSkyChip); 15 15 return 2; 16 } else if (strcmp(version, "PS1_DV3") == 0) {17 psFree(headerSkyChip);18 return 2;19 16 } 20 17 psWarning("Unsupported EXTTYPE in SkyChip.psf table: [%s]", version); -
tags/ipp-20120802/ppTranslate/src/ppMopsMerge.c
r34280 r34281 71 71 72 72 for (int i = 0; i < numInputs; i++) { 73 psTrace("ppMops.merge", 1, "Processing batch %d\n", i);74 73 ppMopsDetections *det = detections->data[i]; // Detections of interest 75 74 if (!det) { -
tags/ipp-20120802/ppTranslate/src/ppMopsRead.c
r34280 r34281 8 8 #include "ppMops.h" 9 9 10 static psMetadata* sort_by_increasing_idet(psMetadata *fittedTrail, long length, long fillLength);11 12 10 /* 13 11 ppMopsRead possibly modifies the args->version if the user did not 14 12 set it explicitely. 15 */13 */ 16 14 psArray *ppMopsRead(ppMopsArguments *args) 17 15 { 18 psTrace("ppMops.read", 1, "Reading input detections\n"); 19 20 psArray *inNames = args->input; // Input names 21 long num = inNames->n; // Number of inputs 22 psArray *detections = psArrayAlloc(num); // Array of detections, to return 23 for (int i = 0; i < num; i++) { 24 const char *name = inNames->data[i]; 25 26 psFits *fits = psFitsOpen(name, "r"); // FITS file 27 if (!fits) { 28 psError(PS_ERR_IO, false, "Unable to open input %d", i); 29 return false; 16 psTrace("ppMops.read", 1, "Reading input detections\n"); 17 18 psArray *inNames = args->input; // Input names 19 long num = inNames->n; // Number of inputs 20 psArray *detections = psArrayAlloc(num); // Array of detections, to return 21 for (int i = 0; i < num; i++) { 22 const char *name = inNames->data[i]; 23 24 psFits *fits = psFitsOpen(name, "r"); // FITS file 25 if (!fits) { 26 psError(PS_ERR_IO, false, "Unable to open input %d", i); 27 return false; 28 } 29 30 psMetadata *header = psFitsReadHeader(NULL, fits); // Primary header 31 if (!header) { 32 psError(PS_ERR_IO, false, "Unable to read header %d", i); 33 return false; 34 } 35 36 psS64 diffSkyfileId = psMetadataLookupS64(NULL, header, "IMAGEID"); // Identifier for image 37 if (diffSkyfileId == 0) { 38 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find identifier for image %d", i); 39 return false; 40 } 41 42 if (!psFitsMoveExtName(fits, "SkyChip.psf")) { 43 psError(PS_ERR_IO, false, "Unable to move to HDU with detections"); 44 return false; 45 } 46 int skyChipPsfVersion = ppMopsGetSkyChipPsfVersion(fits); 47 if (args->version == 0) { 48 psTrace("ppMops.read", 1, "Changing args->version to %d\n", skyChipPsfVersion); 49 args->version = (unsigned short) skyChipPsfVersion; 50 } 51 if (skyChipPsfVersion == 0) { 52 // Try to read with the user specified version? 53 skyChipPsfVersion = args->version; 54 } 55 /* Display a warning message if there are version 56 inconsistencies between the file and the flag (note that 57 those inconsistencies might be wanted) */ 58 if (skyChipPsfVersion != args->version) { 59 if (skyChipPsfVersion > args->version) { 60 psWarning("The FITS data will be downgraded from PS1_DV%d to PS1_DV%d\n", 61 skyChipPsfVersion, args->version); 62 } else { // Necessarily: skyChipPsfVersion > args->version 63 psWarning("The FITS data will be upgraded from PS1_DV%d to PS1_DV%d (new values set to default 0, NaN...)\n", 64 skyChipPsfVersion, args->version); 65 } 66 } 67 68 long size = psFitsTableSize(fits); // Size of table 69 if (size <= 0) { 70 psErrorStackPrint(stderr, "Unable to determine size of table %d", i); 71 psErrorClear(); 72 psWarning("Ignoring input %d", i); 73 psFree(header); 74 psFitsClose(fits); 75 continue; 76 } 77 ppMopsDetections *det = ppMopsDetectionsAlloc(size); 78 detections->data[i] = det; 79 det->component = psStringNCopy(name, strrchr(name, '.') - name); // Strip off extension 80 det->num = size; 81 det->diffSkyfileId = diffSkyfileId; 82 83 psTrace("ppMops.read", 3, "Reading %ld rows from %s\n", size, (const char*)inNames->data[i]); 84 85 det->raBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.RA")); 86 det->decBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.DEC")); 87 det->filter = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.FILTER")); 88 det->airmass = psMetadataLookupF32(NULL, header, "AIRMASS"); 89 det->exptime = psMetadataLookupF32(NULL, header, "EXPTIME"); 90 det->posangle = psMetadataLookupF64(NULL, header, "FPA.POSANGLE"); 91 det->alt = psMetadataLookupF64(NULL, header, "FPA.ALT"); 92 det->az = psMetadataLookupF64(NULL, header, "FPA.AZ"); 93 det->mjd = psMetadataLookupF64(NULL, header, "MJD-OBS") + det->exptime / 2.0 / 3600 / 24; 94 95 det->seeing = (float) 0.5 * (psMetadataLookupF32(NULL, header, "FWHM_MAJ") + 96 psMetadataLookupF32(NULL, header, "FWHM_MIN")); 97 98 det->naxis1 = psMetadataLookupS32(NULL, header, "IMNAXIS1"); // Number of columns 99 det->naxis2 = psMetadataLookupS32(NULL, header, "IMNAXIS2"); // Number of rows 100 101 psFree(header); 102 103 psMetadata *table = psFitsReadTableAllColumns(fits); // Table of interest 104 if (!table) { 105 psError(PS_ERR_IO, false, "Unable to read table %d", i); 106 return NULL; 107 } 108 det->table = table; 109 psFitsClose(fits); 110 if (args->version == 0) { 111 if (skyChipPsfVersion < 2) { 112 // XXX: TODO: Do we need to add dummy vectors for the missing columns? 113 } 114 } 115 116 psVector *ra = psMetadataLookupVector(NULL, table, "RA_PSF"); 117 psVector *dec = psMetadataLookupVector(NULL, table, "DEC_PSF"); 118 119 det->raErr = psVectorAlloc(size, PS_TYPE_F64); 120 det->decErr = psVectorAlloc(size, PS_TYPE_F64); 121 det->mask = psVectorAlloc(size, PS_TYPE_U8); 122 123 // convert ra and dec to radians for use in the purge duplicates function 124 det->ra = (psVector*)psBinaryOp(NULL, ra, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 125 det->dec = (psVector*)psBinaryOp(NULL, dec, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 126 det->x = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "X_PSF")); 127 det->y = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "Y_PSF")); 128 if (!det->ra || !det->dec || !det->x || !det->y) { 129 psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find all of RA, Dec, X and Y columns"); 130 return NULL; 131 } 132 133 // Add our new vectors to the table so that duplicates and masked items may be purged 134 psMetadataAddVector(table, PS_LIST_HEAD, "DEC_ERR", 0, NULL, det->decErr); 135 psMetadataAddVector(table, PS_LIST_HEAD, "RA_ERR", 0, NULL, det->raErr); 136 137 psTrace("ppMops.read", 2, "Read %ld rows from %s\n", det->num, det->component); 138 139 psVector *mag = psMetadataLookupVector(NULL, table, "PSF_INST_MAG"); 140 psVector *magErr = psMetadataLookupVector(NULL, table, "PSF_INST_MAG_SIG"); 141 psVector *xErrV = psMetadataLookupVector(NULL, table, "X_PSF_SIG"); 142 psVector *yErrV = psMetadataLookupVector(NULL, table, "Y_PSF_SIG"); 143 psVector *scaleV = psMetadataLookupVector(NULL, table, "PLTSCALE"); 144 psVector *angleV = psMetadataLookupVector(NULL, table, "POSANGLE"); 145 psVector *flagsV = psMetadataLookupVector(NULL, table, "FLAGS"); 146 147 double plateScale = 0.0; // Plate scale 148 long numGood = 0; // Number of good rows 149 for (long row = 0; row < size; row++) { 150 151 psU32 flags = flagsV->data.U32[row]; // psFitsTableGetU32(NULL, table, row, "FLAGS"); 152 if (flags & SOURCE_MASK) { 153 psTrace("ppMops.read", 10, "Discarding row %ld from input %d because of flags: %ud", row, i, flags); 154 det->mask->data.U8[row] = 0xFF; 155 continue; 156 } 157 158 // Calculate error in RA, Dec 159 160 double xErr = xErrV->data.F32[row]; 161 double yErr = yErrV->data.F32[row]; 162 double scale = scaleV->data.F32[row]; 163 double angle = angleV->data.F32[row]; 164 165 if (!isfinite(det->x->data.F32[row]) || !isfinite(det->y->data.F32[row]) || 166 !isfinite(det->ra->data.F64[row]) || !isfinite(det->dec->data.F64[row]) || 167 !isfinite(mag->data.F32[row]) || !isfinite(magErr->data.F32[row]) || 168 !isfinite(xErr) || !isfinite(yErr) || !isfinite(scale) || !isfinite(angle)) { 169 psTrace("ppMops.read", 10, 170 "Discarding row %ld from input %d because of non-finite values: " 171 "%f %f %lf %lf %f %f %f %f %f %f", 172 row, i, 173 det->x->data.F32[row], det->y->data.F32[row], 174 det->ra->data.F64[row], det->dec->data.F64[row], 175 mag->data.F32[row], magErr->data.F32[row], 176 xErr, yErr, scale, angle); 177 det->mask->data.U8[row] = 0xFF; 178 continue; 179 } 180 181 // XXX Not at all sure I've got the angles around the right way here... 182 double cosAngle = cos(angle), sinAngle = sin(angle); 183 double cosAngle2 = PS_SQR(cosAngle), sinAngle2 = PS_SQR(sinAngle); 184 double xErr2 = PS_SQR(xErr), yErr2 = PS_SQR(yErr); 185 double errScale = scale / 3600.0; 186 det->raErr->data.F64[row] = errScale * sqrt(cosAngle2 * xErr2 + sinAngle2 * yErr2); 187 det->decErr->data.F64[row] = errScale * sqrt(sinAngle2 * xErr2 + cosAngle2 * yErr2); 188 189 det->mask->data.U8[row] = 0; 190 plateScale += scale; 191 numGood++; 192 } 193 det->seeing *= ((float) plateScale) / ((float) numGood); 194 195 // Are we using numGood for anything outside of this function? 196 det->numGood = numGood; 197 198 if (isfinite(args->zp) && numGood > 0) { 199 psBinaryOp(mag, mag, "+", psScalarAlloc(args->zp, PS_TYPE_F32)); 200 } 201 202 psTrace("ppMops.read", 2, "Read %ld good rows from %s\n", numGood, (const char*)name); 30 203 } 31 204 32 psMetadata *header = psFitsReadHeader(NULL, fits); // Primary header 33 if (!header) { 34 psError(PS_ERR_IO, false, "Unable to read header %d", i); 35 return false; 36 } 37 38 psS64 diffSkyfileId = psMetadataLookupS64(NULL, header, "IMAGEID"); // Identifier for image 39 if (diffSkyfileId == 0) { 40 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find identifier for image %d", i); 41 return false; 42 } 43 44 if (!psFitsMoveExtName(fits, "SkyChip.psf")) { 45 psError(PS_ERR_IO, false, "Unable to move to HDU with detections"); 46 return false; 47 } 48 int skyChipPsfVersion = ppMopsGetSkyChipPsfVersion(fits); 49 if (args->version == 0) { 50 psTrace("ppMops.read", 1, "Changing args->version to %d\n", skyChipPsfVersion); 51 args->version = (unsigned short) skyChipPsfVersion; 52 } 53 if (skyChipPsfVersion == 0) { 54 // Try to read with the user specified version? 55 skyChipPsfVersion = args->version; 56 } 57 /* Display a warning message if there are version 58 inconsistencies between the file and the flag (note that 59 those inconsistencies might be wanted) */ 60 if (skyChipPsfVersion != args->version) { 61 if (skyChipPsfVersion > args->version) { 62 psWarning("The FITS data will be downgraded from PS1_DV%d to PS1_DV%d\n", 63 skyChipPsfVersion, args->version); 64 } else { // Necessarily: skyChipPsfVersion > args->version 65 psWarning("The FITS data will be upgraded from PS1_DV%d to PS1_DV%d (new values set to default 0, NaN...)\n", 66 skyChipPsfVersion, args->version); 67 } 68 } 69 70 long size = psFitsTableSize(fits); // Size of table 71 if (size <= 0) { 72 psErrorStackPrint(stderr, "Unable to determine size of table %d", i); 73 psErrorClear(); 74 psWarning("Ignoring input %d", i); 75 psFree(header); 76 psFitsClose(fits); 77 continue; 78 } 79 ppMopsDetections *det = ppMopsDetectionsAlloc(size); 80 detections->data[i] = det; 81 det->component = psStringNCopy(name, strrchr(name, '.') - name); // Strip off extension 82 det->num = size; 83 det->diffSkyfileId = diffSkyfileId; 84 85 psTrace("ppMops.read", 3, "Reading %ld rows from %s\n", size, (const char*)inNames->data[i]); 86 87 det->raBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.RA")); 88 det->decBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.DEC")); 89 det->filter = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.FILTER")); 90 det->airmass = psMetadataLookupF32(NULL, header, "AIRMASS"); 91 det->exptime = psMetadataLookupF32(NULL, header, "EXPTIME"); 92 det->posangle = psMetadataLookupF64(NULL, header, "FPA.POSANGLE"); 93 det->alt = psMetadataLookupF64(NULL, header, "FPA.ALT"); 94 det->az = psMetadataLookupF64(NULL, header, "FPA.AZ"); 95 det->mjd = psMetadataLookupF64(NULL, header, "MJD-OBS") + det->exptime / 2.0 / 3600 / 24; 96 97 det->seeing = (float) 0.5 * (psMetadataLookupF32(NULL, header, "FWHM_MAJ") + 98 psMetadataLookupF32(NULL, header, "FWHM_MIN")); 99 100 det->naxis1 = psMetadataLookupS32(NULL, header, "IMNAXIS1"); // Number of columns 101 det->naxis2 = psMetadataLookupS32(NULL, header, "IMNAXIS2"); // Number of rows 102 103 psFree(header); 104 105 psMetadata *table = psFitsReadTableAllColumns(fits); // Table of interest 106 if (!table) { 107 psError(PS_ERR_IO, false, "Unable to read table %d", i); 108 return NULL; 109 } 110 //Sort table by idet if necessary 111 psMetadata* sortedTable = sort_by_increasing_idet(table, det->num, det->num); 112 if (sortedTable != table) { 113 psFree(table); 114 table = sortedTable; 115 } // else det->table is sorted 116 det->table = table; 117 psTrace("ppMops.read", 9, "PSF table:\n%s\n", psMetadataConfigFormat(det->table)); 118 psTrace("ppMops.read", 9, "End of PSF table\n"); 119 120 //fittedTrail extension (Supported for releases 2 and above) 121 if (skyChipPsfVersion >= 2) { 122 if (!psFitsMoveExtName(fits, "SkyChip.xfit")) { 123 psTrace("ppMops.read", 3, "No fitted trails extension"); 124 } else { 125 psTrace("ppMops.read", 3, "Fitted trails extension found\n"); 126 det->fittedTrailsSize = psFitsTableSize(fits); 127 if (det->fittedTrailsSize <= 0) { 128 psErrorStackPrint(stderr, "Unable to determine size of fitted trails extension table %d", i); 129 psTrace("ppMops.read", 3, "No entry in fitted trails extension!!!!\n"); 130 psErrorClear(); 131 det->fittedTrails = NULL; 132 } else { 133 det->fittedTrails = psFitsReadTableAllColumns(fits); // Table of interest 134 if (!det->fittedTrails) { 135 psError(PS_ERR_IO, false, "Unable to read fittedTrails table %d", i); 136 return NULL; 137 } 138 psMetadata* sortedFittedTrails = sort_by_increasing_idet(det->fittedTrails, det->fittedTrailsSize, det->num); 139 if (sortedFittedTrails != det->fittedTrails) { 140 psFree(det->fittedTrails); 141 det->fittedTrails = sortedFittedTrails; 142 } // else det->fittedTrails is sorted 143 psTrace("ppMops.read", 9, "Fitted trail:\n%s\n", psMetadataConfigFormat(det->fittedTrails)); 144 psTrace("ppMops.read", 9, "End of Fitted trail\n"); 145 } 146 } 147 } 148 149 psFitsClose(fits); 150 151 if (args->version == 0) { 152 if (skyChipPsfVersion < 2) { 153 // XXX: TODO: Do we need to add dummy vectors for the missing columns? 154 } 155 } 156 157 psVector *ra = psMetadataLookupVector(NULL, table, "RA_PSF"); 158 psVector *dec = psMetadataLookupVector(NULL, table, "DEC_PSF"); 159 160 det->raErr = psVectorAlloc(size, PS_TYPE_F64); 161 det->decErr = psVectorAlloc(size, PS_TYPE_F64); 162 det->mask = psVectorAlloc(size, PS_TYPE_U8); 163 164 // convert ra and dec to radians for use in the purge duplicates function 165 det->ra = (psVector*)psBinaryOp(NULL, ra, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 166 det->dec = (psVector*)psBinaryOp(NULL, dec, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 167 det->x = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "X_PSF")); 168 det->y = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "Y_PSF")); 169 if (!det->ra || !det->dec || !det->x || !det->y) { 170 psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find all of RA, Dec, X and Y columns"); 171 return NULL; 172 } 173 174 // Add our new vectors to the table so that duplicates and masked items may be purged 175 psMetadataAddVector(table, PS_LIST_HEAD, "DEC_ERR", 0, NULL, det->decErr); 176 psMetadataAddVector(table, PS_LIST_HEAD, "RA_ERR", 0, NULL, det->raErr); 177 178 psTrace("ppMops.read", 2, "Read %ld rows from %s\n", det->num, det->component); 179 180 psVector *mag = psMetadataLookupVector(NULL, table, "PSF_INST_MAG"); 181 psVector *magErr = psMetadataLookupVector(NULL, table, "PSF_INST_MAG_SIG"); 182 psVector *xErrV = psMetadataLookupVector(NULL, table, "X_PSF_SIG"); 183 psVector *yErrV = psMetadataLookupVector(NULL, table, "Y_PSF_SIG"); 184 psVector *scaleV = psMetadataLookupVector(NULL, table, "PLTSCALE"); 185 psVector *angleV = psMetadataLookupVector(NULL, table, "POSANGLE"); 186 psVector *flagsV = psMetadataLookupVector(NULL, table, "FLAGS"); 187 188 double plateScale = 0.0; // Plate scale 189 long numGood = 0; // Number of good rows 190 for (long row = 0; row < size; row++) { 191 192 psU32 flags = flagsV->data.U32[row]; // psFitsTableGetU32(NULL, table, row, "FLAGS"); 193 if (flags & SOURCE_MASK) { 194 psTrace("ppMops.read", 10, "Discarding row %ld from input %d because of flags: %ud", row, i, flags); 195 det->mask->data.U8[row] = 0xFF; 196 continue; 197 } 198 199 // Calculate error in RA, Dec 200 201 double xErr = xErrV->data.F32[row]; 202 double yErr = yErrV->data.F32[row]; 203 double scale = scaleV->data.F32[row]; 204 double angle = angleV->data.F32[row]; 205 206 if (!isfinite(det->x->data.F32[row]) || !isfinite(det->y->data.F32[row]) || 207 !isfinite(det->ra->data.F64[row]) || !isfinite(det->dec->data.F64[row]) || 208 !isfinite(mag->data.F32[row]) || !isfinite(magErr->data.F32[row]) || 209 !isfinite(xErr) || !isfinite(yErr) || !isfinite(scale) || !isfinite(angle)) { 210 psTrace("ppMops.read", 10, 211 "Discarding row %ld from input %d because of non-finite values: " 212 "%f %f %lf %lf %f %f %f %f %f %f", 213 row, i, 214 det->x->data.F32[row], det->y->data.F32[row], 215 det->ra->data.F64[row], det->dec->data.F64[row], 216 mag->data.F32[row], magErr->data.F32[row], 217 xErr, yErr, scale, angle); 218 det->mask->data.U8[row] = 0xFF; 219 continue; 220 } 221 222 // XXX Not at all sure I've got the angles around the right way here... 223 double cosAngle = cos(angle), sinAngle = sin(angle); 224 double cosAngle2 = PS_SQR(cosAngle), sinAngle2 = PS_SQR(sinAngle); 225 double xErr2 = PS_SQR(xErr), yErr2 = PS_SQR(yErr); 226 double errScale = scale / 3600.0; 227 det->raErr->data.F64[row] = errScale * sqrt(cosAngle2 * xErr2 + sinAngle2 * yErr2); 228 det->decErr->data.F64[row] = errScale * sqrt(sinAngle2 * xErr2 + cosAngle2 * yErr2); 229 det->mask->data.U8[row] = 0; 230 plateScale += scale; 231 numGood++; 232 } 233 det->seeing *= ((float) plateScale) / ((float) numGood); 234 235 // Are we using numGood for anything outside of this function? 236 det->numGood = numGood; 237 238 if (isfinite(args->zp) && numGood > 0) { 239 psBinaryOp(mag, mag, "+", psScalarAlloc(args->zp, PS_TYPE_F32)); 240 } 241 242 psTrace("ppMops.read", 2, "Read %ld good rows from %s\n", numGood, (const char*)name); 243 } 244 245 psTrace("ppMops.read", 1, "Done reading input detections\n"); 246 247 return detections; 205 psTrace("ppMops.read", 1, "Done reading input detections\n"); 206 207 return detections; 248 208 } 249 250 static long* sorted_idets_indexes(psVector *idets);251 static int compare (const void *a, const void *b);252 static psVector* fill_F32_vector(psVector* in, int size, long* indexes, int indexes_length);253 254 // We want the entries in table/fittedTrails to be sorted by increasing idet255 static psMetadata* sort_by_increasing_idet(psMetadata *aTable, long length, long fillLength) {256 if (aTable == NULL) {257 return aTable;258 }259 psVector *idets = psMetadataLookupVector(NULL, aTable, "IPP_IDET");260 if (!idets) {261 psError(PS_ERR_PROGRAMMING, true, "Failed to find IPP_IDET column");262 return NULL;263 }264 bool is_sorted = true;265 int count = 0;266 long previous_value = -1;267 while (is_sorted && (count<length) ){268 is_sorted = (previous_value < idets->data.S64[count]);269 previous_value = idets->data.S64[count];270 count += 1;271 }272 if (is_sorted && (length==fillLength)) {273 psTrace("ppMops.read", 5, "Values are already sorted by idet and the table is complete\n");274 return aTable;275 }276 //otherwise sort (even if it should not happen) and fill277 long* sortedIndexVector = sorted_idets_indexes(idets);278 psMetadata* sortedTable = psMetadataAlloc();279 char* column_name = "X_EXT";280 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,281 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );282 column_name = "Y_EXT";283 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,284 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );285 column_name = "X_EXT_SIG";286 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,287 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );288 column_name = "Y_EXT_SIG";289 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,290 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );291 column_name = "EXT_INST_MAG";292 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,293 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );294 column_name = "EXT_INST_MAG_SIG";295 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,296 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );297 column_name = "NPARAMS";298 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,299 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );300 column_name = "EXT_WIDTH_MAJ";301 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,302 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );303 column_name = "EXT_WIDTH_MIN";304 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,305 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );306 column_name = "EXT_THETA";307 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,308 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );309 column_name = "EXT_WIDTH_MAJ_ERR";310 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,311 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );312 column_name = "EXT_WIDTH_MIN_ERR";313 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,314 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );315 column_name = "EXT_THETA_ERR";316 psMetadataAddVector( sortedTable, PS_LIST_TAIL, column_name, 0, NULL,317 fill_F32_vector(psMetadataLookupVector(NULL, aTable, column_name), fillLength, sortedIndexVector, idets->n) );318 return sortedTable;319 }320 321 static psVector* fill_F32_vector(psVector* in, int length, long* indexes, int indexes_length) {322 if (in == NULL) {323 return NULL;324 }325 psVector* out = psVectorAlloc(length, in->type.type);326 int current_index = 0;327 for (int i = 0; i < indexes_length; i++) {328 while ( (current_index < indexes[i]) && (current_index < length) ) {329 out->data.F32[current_index] = NAN;330 current_index += 1;331 }332 out->data.F32[current_index] = in->data.F32[i];333 current_index += 1;334 }335 while ( current_index < length ) {336 out->data.F32[current_index] = NAN;337 current_index += 1;338 }339 return out;340 }341 342 static int compare (const void *a, const void *b) {343 return ( *((long*) a)-*((long*) b));344 }345 346 static long* sorted_idets_indexes(psVector *idets) {347 long* sortedIndexes = (long*) malloc(idets->n * sizeof(long));348 for (int i=0;i<idets->n;i++) {349 sortedIndexes[i] = idets->data.S64[i];350 }351 qsort(sortedIndexes, idets->n, sizeof(long), (void *) compare);352 return sortedIndexes;353 } -
tags/ipp-20120802/ppTranslate/src/ppMopsWrite.c
r34280 r34281 9 9 #include "ppTranslateVersion.h" 10 10 11 static bool addOutputColumn(psMetadata *table, const psArray *detections, long total, int extension,char *outColName, char *inColName, bool convertTo32);11 static bool addOutputColumn(psMetadata *table, const psArray *detections, long total, char *outColName, char *inColName, bool convertTo32); 12 12 static bool addSkyfileIDColumn(psMetadata *table, const psArray *detections, long total, char *colName); 13 13 14 14 bool ppMopsWrite(const psArray *detections, const ppMopsArguments *args) 15 15 { 16 psFits *fits = psFitsOpen(args->output, "w"); // FITS file 17 if (!fits) { 18 psError(PS_ERR_IO, false, "Unable to open output file."); 19 return false; 20 } 21 22 psMetadata *header = psMetadataAlloc(); // Header to write 23 psString source = ppTranslateSource(), version = ppTranslateVersion(); 24 psMetadataAddStr(header, PS_LIST_TAIL, "SWSOURCE", 0, "Software source", source); 25 psMetadataAddStr(header, PS_LIST_TAIL, "SWVERSN", 0, "Software version", version); 26 ppTranslateVersionHeader(header); 27 psFree(source); 28 psFree(version); 29 30 psMetadataAddStr(header, PS_LIST_TAIL, "EXP_NAME", 0, "Exposure name", args->exp_name); 31 psMetadataAddS64(header, PS_LIST_TAIL, "EXP_ID", 0, "Exposure identifier", args->exp_id); 32 psMetadataAddS64(header, PS_LIST_TAIL, "CHIP_ID", 0, "Chip stage identifier", args->chip_id); 33 psMetadataAddS64(header, PS_LIST_TAIL, "CAM_ID", 0, "Cam stage identifier", args->cam_id); 34 psMetadataAddS64(header, PS_LIST_TAIL, "FAKE_ID", 0, "Fake stage identifier", args->fake_id); 35 psMetadataAddS64(header, PS_LIST_TAIL, "WARP_ID", 0, "Warp stage identifier", args->warp_id); 36 psMetadataAddS64(header, PS_LIST_TAIL, "DIFF_ID", 0, "Diff stage identifier", args->diff_id); 37 psMetadataAddBool(header, PS_LIST_TAIL, "DIFF_POS", 0, "Positive subtraction?", args->positive); 38 39 // Get these header words from the first input non null input 40 ppMopsDetections *det = NULL; 41 for (int d = 0; d < detections->n && det == NULL; d++) { 42 det = detections->data[d]; 43 } 44 if (det != NULL) { 45 psMetadataAddF64(header, PS_LIST_TAIL, "MJD-OBS", 0, "MJD of exposure midpoint", det->mjd); 46 psMetadataAddStr(header, PS_LIST_TAIL, "RA", 0, "Right Ascension of boresight", det->raBoresight); 47 psMetadataAddStr(header, PS_LIST_TAIL, "DEC", 0, "Declination of boresight", det->decBoresight); 48 psMetadataAddF64(header, PS_LIST_TAIL, "TEL_ALT", 0, "Telescope altitude", det->alt); 49 psMetadataAddF64(header, PS_LIST_TAIL, "TEL_AZ", 0, "Telescope azimuth", det->az); 50 psMetadataAddF64(header, PS_LIST_TAIL, "EXPTIME", 0, "Exposure time (sec)", det->exptime); 51 psMetadataAddF64(header, PS_LIST_TAIL, "ROTANGLE", 0, "Rotator position angle", det->posangle); 52 psMetadataAddStr(header, PS_LIST_TAIL, "FILTER", 0, "Filter name", det->filter); 53 psMetadataAddF32(header, PS_LIST_TAIL, "AIRMASS", 0, "Airmass of exposure", det->airmass); 54 psMetadataAddF32(header, PS_LIST_TAIL, "SEEING", 0, "Mean seeing", det->seeing); 55 } else { 56 psWarning("no inputs with surviving detections. output header will be incomplete"); 57 } 58 psMetadataAddStr(header, PS_LIST_TAIL, "OBSCODE", 0, "IAU Observatory code", OBSERVATORY_CODE); 59 psMetadataAddF32(header, PS_LIST_TAIL, "MAGZP", 0, "Magnitude zero point", args->zp); 60 psMetadataAddF32(header, PS_LIST_TAIL, "MAGZPERR", 0, "Error in magnitude zero point", args->zpErr); 61 psMetadataAddF32(header, PS_LIST_TAIL, "ASTRORMS", 0, "RMS of astrometric fit", args->rmsAstrom); 62 63 //field in header that tells about the CMF version 64 char cmfVersion[8]; 65 sprintf(cmfVersion, PS1_DV_FORMAT, args->version); 66 psMetadataAddStr(header, PS_LIST_TAIL, "CMFVERSION", 0, "CMF version", cmfVersion); 67 68 // Find the total number of detections 69 70 long total = 0; 71 for (long i=0; i<detections->n; i++) { 72 ppMopsDetections *det = detections->data[i]; 73 if (!det) { 74 continue; 75 } 76 total += det->num; 77 } 78 79 psTrace("ppMops.write", 1, "Writing %ld rows to %s", total, args->output); 80 81 if (total == 0) { 82 // Write dummy table 83 psMetadata *row = psMetadataAlloc(); // Output row 84 psMetadataAddF64(row, PS_LIST_TAIL, "RA", 0, "Right ascension (degrees)", NAN); 85 psMetadataAddF64(row, PS_LIST_TAIL, "RA_ERR", 0, "Right ascension error (degrees)", NAN); 86 psMetadataAddF64(row, PS_LIST_TAIL, "DEC", 0, "Declination (degrees)", NAN); 87 psMetadataAddF64(row, PS_LIST_TAIL, "DEC_ERR", 0, "Declination error (degrees)", NAN); 88 psMetadataAddF32(row, PS_LIST_TAIL, "MAG", 0, "Magnitude", NAN); 89 psMetadataAddF32(row, PS_LIST_TAIL, "MAG_ERR", 0, "Magnitude error", NAN); 90 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_CHI2", 0, "chi^2 of PSF fit", NAN); 91 psMetadataAddS32(row, PS_LIST_TAIL, "PSF_DOF", 0, "Degrees of freedom of PSF fit", 0); 92 psMetadataAddF32(row, PS_LIST_TAIL, "CR_SIGNIFICANCE", 0, "Significance of CR", NAN); 93 psMetadataAddF32(row, PS_LIST_TAIL, "EXT_SIGNIFICANCE", 0, "Significance of extendedness", NAN); 94 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_MAJOR", 0, "PSF major axis (pixels)", NAN); 95 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_MINOR", 0, "PSF minor axis (pixels)", NAN); 96 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_THETA", 0, "PSF position angle (deg on chip)", NAN); 97 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_QUALITY", 0, "PSF quality factor", NAN); 98 psMetadataAddS32(row, PS_LIST_TAIL, "PSF_NPIX", 0, "Number of pixels in PSF", 0); 99 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_XX", 0, "xx moment", NAN); 100 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_XY", 0, "xy moment", NAN); 101 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_YY", 0, "yy moment", NAN); 102 psMetadataAddU32(row, PS_LIST_TAIL, "FLAGS", 0, "Detection bit flags", 0); 103 psMetadataAddS64(row, PS_LIST_TAIL, "DIFF_SKYFILE_ID", 0, "Identifier for diff skyfile", 0); 104 105 psMetadataAddS32(row, PS_LIST_TAIL, "N_POS", 0, "Number of positive pixels", 0); 106 psMetadataAddF32(row, PS_LIST_TAIL, "F_POS", 0, "Fraction of positive pixels", NAN); 107 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_BAD", 0, "Ratio of positive pixels to negative", NAN); 108 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_MASK", 0, "Ratio of positive pixels to masked", NAN); 109 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_ALL", 0, "Ratio of positive pixels to all", NAN); 110 111 if (args->version == 2) { 112 // Write data of version 2 (see ICD) 113 psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET", PS_DATA_U32, "IPP detection identifier index", 114 NAN); 115 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX", PS_DATA_F32, "PSF fit instrumental magnitude", 116 NAN); 117 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX_SIG",PS_DATA_F32, "Sigma of PSF instrumental magnitude", 118 NAN); 119 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG", PS_DATA_F32, "magnitude in standard aperture", 120 NAN); 121 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW", PS_DATA_F32, "magnitude in real aperture", 122 NAN); 123 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS", PS_DATA_F32, "radius used for aperture mags", 124 NAN); 125 psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX", PS_DATA_F32, "instrumental flux in standard aperture", 126 NAN); 127 psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX_SIG", PS_DATA_F32, "aperture flux error", 128 NAN); 129 psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude", 130 NAN); 131 psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG", PS_DATA_F32, "PSF Magnitude using supplied calibration", 132 NAN); 133 psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG", PS_DATA_F32, "measured scatter of zero point calibration", 134 NAN); 135 psMetadataAdd (row, PS_LIST_TAIL, "SKY", PS_DATA_F32, "Sky level", 136 NAN); 137 psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA", PS_DATA_F32, "Sigma of sky level", 138 NAN); 139 psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT", PS_DATA_F32, "PSF coverage/quality factor (poor)", 140 NAN); 141 psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1", PS_DATA_F32, "first radial moment", 142 NAN); 143 psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH", PS_DATA_F32, "half radial moment", 144 NAN); 145 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX", PS_DATA_F32, "Kron Flux (in 2.5 R1)", 146 NAN); 147 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR", PS_DATA_F32, "Kron Flux Error", 148 NAN); 149 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER", PS_DATA_F32, "Kron Flux (in 1.0 R1)", 150 NAN); 151 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER", PS_DATA_F32, "Kron Flux (in 4.0 R1)", 152 NAN); 153 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_R_P", PS_DATA_F32, "distance to positive match source", 154 NAN); 155 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_SN_P", PS_DATA_F32, "signal-to-noise of pos match src", 156 NAN); 157 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_R_M", PS_DATA_F32, "distance to negative match source", 158 NAN); 159 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_SN_M", PS_DATA_F32, "signal-to-noise of neg match src", 160 NAN); 161 psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2", PS_DATA_U32, "psphot analysis flags (group 2)", 162 0); 163 psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES", PS_DATA_U16, "Number of frames overlapping source center", 164 0); 165 psMetadataAdd (row, PS_LIST_TAIL, "PADDING", PS_DATA_S16, "padding", 166 0); 167 if (args->version == 3) { 168 // TODO: Write data of version 3 (see ICD) 169 } 170 } 171 172 if (!psFitsWriteTableEmpty(fits, header, row, OUT_EXTNAME)) { 173 psErrorStackPrint(stderr, "Unable to write empty table."); 174 psFree(header); 175 psFree(row); 176 return false; 177 } 178 psFree(row); 179 } else { 180 181 #define addColumn(_outName, _inName, _convertTo32) \ 182 if (!addOutputColumn(table, detections, total, 0, _outName, _inName, _convertTo32)) { \ 183 psError(PS_ERR_UNKNOWN, false, "Failed to add column %s", _outName); \ 184 return false; \ 185 } 186 187 // Allocate the output table 188 psMetadata *table = psMetadataAlloc(); 189 addColumn("RA", "RA_PSF", 0); 190 addColumn("RA_ERR", NULL, 0); // calculated from various parameters including X_PSF_SIG Y_PSF_SIG and POSANG 191 addColumn("DEC", "DEC_PSF", 0); 192 addColumn("DEC_ERR", NULL, 0); // calculated from various parameters including X_PSF_SIG Y_PSF_SIG and POSANG 193 addColumn("MAG", "PSF_INST_MAG", 0); 194 addColumn("MAG_ERR", "PSF_INST_MAG_SIG", 0); 195 addColumn("PSF_CHI2", "PSF_CHISQ", 0); 196 addColumn("PSF_DOF", "PSF_NDOF", 1); 197 addColumn("CR_SIGNIFICANCE", "CR_NSIGMA", 0); 198 addColumn("EXT_SIGNIFICANCE", "EXT_NSIGMA", 0); 199 addColumn("PSF_MAJOR", NULL, 0); 200 addColumn("PSF_MINOR", NULL, 0); 201 addColumn("PSF_THETA", NULL, 0); 202 addColumn("PSF_QUALITY", "PSF_QF", 0); 203 addColumn("PSF_NPIX", NULL, 1); 204 addColumn("MOMENTS_XX", NULL, 0); 205 addColumn("MOMENTS_XY", NULL, 0); 206 addColumn("MOMENTS_YY", NULL, 0); 207 addColumn("N_POS", "DIFF_NPOS", 1); 208 addColumn("F_POS", "DIFF_FRATIO", 0); 209 addColumn("RATIO_BAD", "DIFF_NRATIO_BAD", 0); 210 addColumn("RATIO_MASK", "DIFF_NRATIO_MASK", 0); 211 addColumn("RATIO_ALL", "DIFF_NRATIO_ALL", 0); 212 addColumn("FLAGS", "FLAGS", 1); 213 addSkyfileIDColumn(table, detections, total, "DIFF_SKYFILE_ID"); 214 if (args->version >= 2) { 215 addColumn("IPP_IDET", NULL, 1); 216 addColumn("PSF_INST_FLUX", NULL, 0); 217 addColumn("PSF_INST_FLUX_SIG", NULL, 0); 218 addColumn("AP_MAG", NULL, 0); 219 addColumn("AP_MAG_RAW", NULL, 0); 220 addColumn("AP_MAG_RADIUS", NULL, 0); 221 addColumn("AP_FLUX", NULL, 0); 222 addColumn("AP_FLUX_SIG", NULL, 0); 223 addColumn("PEAK_FLUX_AS_MAG", NULL, 0); 224 addColumn("CAL_PSF_MAG", NULL, 0); 225 addColumn("CAL_PSF_MAG_SIG", NULL, 0); 226 addColumn("SKY", NULL, 0); 227 addColumn("SKY_SIGMA", NULL, 0); 228 addColumn("PSF_QF_PERFECT", NULL, 0); 229 addColumn("MOMENTS_R1", NULL, 0); 230 addColumn("MOMENTS_RH", NULL, 0); 231 addColumn("KRON_FLUX", NULL, 0); 232 addColumn("KRON_FLUX_ERR", NULL, 0); 233 addColumn("KRON_FLUX_INNER", NULL, 0); 234 addColumn("KRON_FLUX_OUTER", NULL, 0); 235 addColumn("DIFF_R_P", NULL, 0); 236 addColumn("DIFF_SN_P", NULL, 0); 237 addColumn("DIFF_R_M", NULL, 0); 238 addColumn("DIFF_SN_M", NULL, 0); 239 addColumn("FLAGS2", NULL, 1); 240 addColumn("IPP_IDET", NULL, 0); 241 addColumn("N_FRAMES", NULL, 0); 242 addColumn("PADDING", NULL, 0); 243 if (det->fittedTrails != NULL) { 244 #define addFittedTrailColumn(_outName, _inName, _convertTo32) \ 245 if (!addOutputColumn(table, detections, total, 1, _outName, _inName, _convertTo32)) { \ 246 psTrace("ppMops.write", 1, "Failed to add column %s -> Replaced with NAN", _outName); \ 16 17 psFits *fits = psFitsOpen(args->output, "w"); // FITS file 18 if (!fits) { 19 psError(PS_ERR_IO, false, "Unable to open output file."); 20 return false; 21 } 22 23 psMetadata *header = psMetadataAlloc(); // Header to write 24 psString source = ppTranslateSource(), version = ppTranslateVersion(); 25 psMetadataAddStr(header, PS_LIST_TAIL, "SWSOURCE", 0, "Software source", source); 26 psMetadataAddStr(header, PS_LIST_TAIL, "SWVERSN", 0, "Software version", version); 27 ppTranslateVersionHeader(header); 28 psFree(source); 29 psFree(version); 30 31 psMetadataAddStr(header, PS_LIST_TAIL, "EXP_NAME", 0, "Exposure name", args->exp_name); 32 psMetadataAddS64(header, PS_LIST_TAIL, "EXP_ID", 0, "Exposure identifier", args->exp_id); 33 psMetadataAddS64(header, PS_LIST_TAIL, "CHIP_ID", 0, "Chip stage identifier", args->chip_id); 34 psMetadataAddS64(header, PS_LIST_TAIL, "CAM_ID", 0, "Cam stage identifier", args->cam_id); 35 psMetadataAddS64(header, PS_LIST_TAIL, "FAKE_ID", 0, "Fake stage identifier", args->fake_id); 36 psMetadataAddS64(header, PS_LIST_TAIL, "WARP_ID", 0, "Warp stage identifier", args->warp_id); 37 psMetadataAddS64(header, PS_LIST_TAIL, "DIFF_ID", 0, "Diff stage identifier", args->diff_id); 38 psMetadataAddBool(header, PS_LIST_TAIL, "DIFF_POS", 0, "Positive subtraction?", args->positive); 39 40 // Get these header words from the first input non null input 41 ppMopsDetections *det = NULL; 42 for (int d = 0; d < detections->n && det == NULL; d++) { 43 det = detections->data[d]; 44 } 45 if (det != NULL) { 46 psMetadataAddF64(header, PS_LIST_TAIL, "MJD-OBS", 0, "MJD of exposure midpoint", det->mjd); 47 psMetadataAddStr(header, PS_LIST_TAIL, "RA", 0, "Right Ascension of boresight", det->raBoresight); 48 psMetadataAddStr(header, PS_LIST_TAIL, "DEC", 0, "Declination of boresight", det->decBoresight); 49 psMetadataAddF64(header, PS_LIST_TAIL, "TEL_ALT", 0, "Telescope altitude", det->alt); 50 psMetadataAddF64(header, PS_LIST_TAIL, "TEL_AZ", 0, "Telescope azimuth", det->az); 51 psMetadataAddF64(header, PS_LIST_TAIL, "EXPTIME", 0, "Exposure time (sec)", det->exptime); 52 psMetadataAddF64(header, PS_LIST_TAIL, "ROTANGLE", 0, "Rotator position angle", det->posangle); 53 psMetadataAddStr(header, PS_LIST_TAIL, "FILTER", 0, "Filter name", det->filter); 54 psMetadataAddF32(header, PS_LIST_TAIL, "AIRMASS", 0, "Airmass of exposure", det->airmass); 55 psMetadataAddF32(header, PS_LIST_TAIL, "SEEING", 0, "Mean seeing", det->seeing); 56 } else { 57 psWarning("no inputs with surviving detections. output header will be incomplete"); 58 } 59 psMetadataAddStr(header, PS_LIST_TAIL, "OBSCODE", 0, "IAU Observatory code", OBSERVATORY_CODE); 60 psMetadataAddF32(header, PS_LIST_TAIL, "MAGZP", 0, "Magnitude zero point", args->zp); 61 psMetadataAddF32(header, PS_LIST_TAIL, "MAGZPERR", 0, "Error in magnitude zero point", args->zpErr); 62 psMetadataAddF32(header, PS_LIST_TAIL, "ASTRORMS", 0, "RMS of astrometric fit", args->rmsAstrom); 63 64 //field in header that tells about the CMF version 65 char cmfVersion[8]; 66 sprintf(cmfVersion, PS1_DV_FORMAT, args->version); 67 psMetadataAddStr(header, PS_LIST_TAIL, "CMFVERSION", 0, "CMF version", cmfVersion); 68 69 // Find the total number of detections 70 71 long total = 0; 72 for (long i=0; i<detections->n; i++) { 73 ppMopsDetections *det = detections->data[i]; 74 if (!det) { 75 continue; 247 76 } 248 addFittedTrailColumn("X_EXT", NULL, 0); 249 addFittedTrailColumn("Y_EXT", NULL, 0); 250 addFittedTrailColumn("X_EXT_SIG", NULL, 0); 251 addFittedTrailColumn("Y_EXT_SIG", NULL, 0); 252 addFittedTrailColumn("EXT_INST_MAG", NULL, 0); 253 addFittedTrailColumn("EXT_INST_MAG_SIG", NULL, 0); 254 addFittedTrailColumn("NPARAMS", NULL, 0); 255 addFittedTrailColumn("EXT_WIDTH_MAJ", NULL, 0); 256 addFittedTrailColumn("EXT_WIDTH_MIN", NULL, 0); 257 addFittedTrailColumn("EXT_THETA", NULL, 0); 258 addFittedTrailColumn("EXT_WIDTH_MAJ_ERR", NULL, 0); 259 addFittedTrailColumn("EXT_WIDTH_MIN_ERR", NULL, 0); 260 addFittedTrailColumn("EXT_THETA_ERR", NULL, 0); 261 } 262 } 263 if (!psFitsWriteTableAllColumns(fits, header, table, OUT_EXTNAME)) { 264 psError(psErrorCodeLast(), false, "Unable to write table"); 265 return false; 266 } 267 psFree(table); 268 } 269 270 psFree(header); 271 psFitsClose(fits); 272 273 psTrace("ppMops.write", 1, "Done writing %ld rows to %s", det->num, args->output); 274 275 return true; 77 total += det->num; 78 } 79 80 psTrace("ppMops.write", 1, "Writing %ld rows to %s", total, args->output); 81 82 if (total == 0) { 83 // Write dummy table 84 psMetadata *row = psMetadataAlloc(); // Output row 85 psMetadataAddF64(row, PS_LIST_TAIL, "RA", 0, "Right ascension (degrees)", NAN); 86 psMetadataAddF64(row, PS_LIST_TAIL, "RA_ERR", 0, "Right ascension error (degrees)", NAN); 87 psMetadataAddF64(row, PS_LIST_TAIL, "DEC", 0, "Declination (degrees)", NAN); 88 psMetadataAddF64(row, PS_LIST_TAIL, "DEC_ERR", 0, "Declination error (degrees)", NAN); 89 psMetadataAddF32(row, PS_LIST_TAIL, "MAG", 0, "Magnitude", NAN); 90 psMetadataAddF32(row, PS_LIST_TAIL, "MAG_ERR", 0, "Magnitude error", NAN); 91 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_CHI2", 0, "chi^2 of PSF fit", NAN); 92 psMetadataAddS32(row, PS_LIST_TAIL, "PSF_DOF", 0, "Degrees of freedom of PSF fit", 0); 93 psMetadataAddF32(row, PS_LIST_TAIL, "CR_SIGNIFICANCE", 0, "Significance of CR", NAN); 94 psMetadataAddF32(row, PS_LIST_TAIL, "EXT_SIGNIFICANCE", 0, "Significance of extendedness", NAN); 95 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_MAJOR", 0, "PSF major axis (pixels)", NAN); 96 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_MINOR", 0, "PSF minor axis (pixels)", NAN); 97 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_THETA", 0, "PSF position angle (deg on chip)", NAN); 98 psMetadataAddF32(row, PS_LIST_TAIL, "PSF_QUALITY", 0, "PSF quality factor", NAN); 99 psMetadataAddS32(row, PS_LIST_TAIL, "PSF_NPIX", 0, "Number of pixels in PSF", 0); 100 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_XX", 0, "xx moment", NAN); 101 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_XY", 0, "xy moment", NAN); 102 psMetadataAddF32(row, PS_LIST_TAIL, "MOMENTS_YY", 0, "yy moment", NAN); 103 psMetadataAddU32(row, PS_LIST_TAIL, "FLAGS", 0, "Detection bit flags", 0); 104 psMetadataAddS64(row, PS_LIST_TAIL, "DIFF_SKYFILE_ID", 0, "Identifier for diff skyfile", 0); 105 106 psMetadataAddS32(row, PS_LIST_TAIL, "N_POS", 0, "Number of positive pixels", 0); 107 psMetadataAddF32(row, PS_LIST_TAIL, "F_POS", 0, "Fraction of positive pixels", NAN); 108 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_BAD", 0, "Ratio of positive pixels to negative", NAN); 109 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_MASK", 0, "Ratio of positive pixels to masked", NAN); 110 psMetadataAddF32(row, PS_LIST_TAIL, "RATIO_ALL", 0, "Ratio of positive pixels to all", NAN); 111 112 if (args->version == 2) { 113 // Write data of version 2 (see ICD) 114 psMetadataAdd (row, PS_LIST_TAIL, "IPP_IDET", PS_DATA_U32, "IPP detection identifier index", 115 NAN); 116 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX", PS_DATA_F32, "PSF fit instrumental magnitude", 117 NAN); 118 psMetadataAdd (row, PS_LIST_TAIL, "PSF_INST_FLUX_SIG",PS_DATA_F32, "Sigma of PSF instrumental magnitude", 119 NAN); 120 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG", PS_DATA_F32, "magnitude in standard aperture", 121 NAN); 122 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RAW", PS_DATA_F32, "magnitude in real aperture", 123 NAN); 124 psMetadataAdd (row, PS_LIST_TAIL, "AP_MAG_RADIUS", PS_DATA_F32, "radius used for aperture mags", 125 NAN); 126 psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX", PS_DATA_F32, "instrumental flux in standard aperture", 127 NAN); 128 psMetadataAdd (row, PS_LIST_TAIL, "AP_FLUX_SIG", PS_DATA_F32, "aperture flux error", 129 NAN); 130 psMetadataAdd (row, PS_LIST_TAIL, "PEAK_FLUX_AS_MAG", PS_DATA_F32, "Peak flux expressed as magnitude", 131 NAN); 132 psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG", PS_DATA_F32, "PSF Magnitude using supplied calibration", 133 NAN); 134 psMetadataAdd (row, PS_LIST_TAIL, "CAL_PSF_MAG_SIG", PS_DATA_F32, "measured scatter of zero point calibration", 135 NAN); 136 psMetadataAdd (row, PS_LIST_TAIL, "SKY", PS_DATA_F32, "Sky level", 137 NAN); 138 psMetadataAdd (row, PS_LIST_TAIL, "SKY_SIGMA", PS_DATA_F32, "Sigma of sky level", 139 NAN); 140 psMetadataAdd (row, PS_LIST_TAIL, "PSF_QF_PERFECT", PS_DATA_F32, "PSF coverage/quality factor (poor)", 141 NAN); 142 psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_R1", PS_DATA_F32, "first radial moment", 143 NAN); 144 psMetadataAdd (row, PS_LIST_TAIL, "MOMENTS_RH", PS_DATA_F32, "half radial moment", 145 NAN); 146 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX", PS_DATA_F32, "Kron Flux (in 2.5 R1)", 147 NAN); 148 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_ERR", PS_DATA_F32, "Kron Flux Error", 149 NAN); 150 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_INNER", PS_DATA_F32, "Kron Flux (in 1.0 R1)", 151 NAN); 152 psMetadataAdd (row, PS_LIST_TAIL, "KRON_FLUX_OUTER", PS_DATA_F32, "Kron Flux (in 4.0 R1)", 153 NAN); 154 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_R_P", PS_DATA_F32, "distance to positive match source", 155 NAN); 156 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_SN_P", PS_DATA_F32, "signal-to-noise of pos match src", 157 NAN); 158 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_R_M", PS_DATA_F32, "distance to negative match source", 159 NAN); 160 psMetadataAdd (row, PS_LIST_TAIL, "DIFF_SN_M", PS_DATA_F32, "signal-to-noise of neg match src", 161 NAN); 162 psMetadataAdd (row, PS_LIST_TAIL, "FLAGS2", PS_DATA_U32, "psphot analysis flags (group 2)", 163 0); 164 psMetadataAdd (row, PS_LIST_TAIL, "N_FRAMES", PS_DATA_U16, "Number of frames overlapping source center", 165 0); 166 psMetadataAdd (row, PS_LIST_TAIL, "PADDING", PS_DATA_S16, "padding", 167 0); 168 } 169 170 if (!psFitsWriteTableEmpty(fits, header, row, OUT_EXTNAME)) { 171 psErrorStackPrint(stderr, "Unable to write empty table."); 172 psFree(header); 173 psFree(row); 174 return false; 175 } 176 psFree(row); 177 } else { 178 179 #define addColumn(_outName, _inName, _convertTo32) \ 180 if (!addOutputColumn(table, detections, total, _outName, _inName, _convertTo32)) { \ 181 psError(PS_ERR_UNKNOWN, false, "Failed to add column %s", _outName); \ 182 return false; \ 183 } 184 185 // Allocate the output table 186 psMetadata *table = psMetadataAlloc(); 187 addColumn("RA", "RA_PSF", 0); 188 addColumn("RA_ERR", NULL, 0); // calculated from various parameters including X_PSF_SIG Y_PSF_SIG and POSANG 189 addColumn("DEC", "DEC_PSF", 0); 190 addColumn("DEC_ERR", NULL, 0); // calculated from various parameters including X_PSF_SIG Y_PSF_SIG and POSANG 191 addColumn("MAG", "PSF_INST_MAG", 0); 192 addColumn("MAG_ERR", "PSF_INST_MAG_SIG", 0); 193 addColumn("PSF_CHI2", "PSF_CHISQ", 0); 194 addColumn("PSF_DOF", "PSF_NDOF", 1); 195 addColumn("CR_SIGNIFICANCE", "CR_NSIGMA", 0); 196 addColumn("EXT_SIGNIFICANCE", "EXT_NSIGMA", 0); 197 addColumn("PSF_MAJOR", NULL, 0); 198 addColumn("PSF_MINOR", NULL, 0); 199 addColumn("PSF_THETA", NULL, 0); 200 addColumn("PSF_QUALITY", "PSF_QF", 0); 201 addColumn("PSF_NPIX", NULL, 1); 202 addColumn("MOMENTS_XX", NULL, 0); 203 addColumn("MOMENTS_XY", NULL, 0); 204 addColumn("MOMENTS_YY", NULL, 0); 205 addColumn("N_POS", "DIFF_NPOS", 1); 206 addColumn("F_POS", "DIFF_FRATIO", 0); 207 addColumn("RATIO_BAD", "DIFF_NRATIO_BAD", 0); 208 addColumn("RATIO_MASK", "DIFF_NRATIO_MASK", 0); 209 addColumn("RATIO_ALL", "DIFF_NRATIO_ALL", 0); 210 addColumn("FLAGS", "FLAGS", 1); 211 addSkyfileIDColumn(table, detections, total, "DIFF_SKYFILE_ID"); 212 if (args->version == 2) { 213 addColumn("IPP_IDET", NULL, 1); 214 addColumn("PSF_INST_FLUX", NULL, 0); 215 addColumn("PSF_INST_FLUX_SIG", NULL, 0); 216 addColumn("AP_MAG", NULL, 0); 217 addColumn("AP_MAG_RAW", NULL, 0); 218 addColumn("AP_MAG_RADIUS", NULL, 0); 219 addColumn("AP_FLUX", NULL, 0); 220 addColumn("AP_FLUX_SIG", NULL, 0); 221 addColumn("PEAK_FLUX_AS_MAG", NULL, 0); 222 addColumn("CAL_PSF_MAG", NULL, 0); 223 addColumn("CAL_PSF_MAG_SIG", NULL, 0); 224 addColumn("SKY", NULL, 0); 225 addColumn("SKY_SIGMA", NULL, 0); 226 addColumn("PSF_QF_PERFECT", NULL, 0); 227 addColumn("MOMENTS_R1", NULL, 0); 228 addColumn("MOMENTS_RH", NULL, 0); 229 addColumn("KRON_FLUX", NULL, 0); 230 addColumn("KRON_FLUX_ERR", NULL, 0); 231 addColumn("KRON_FLUX_INNER", NULL, 0); 232 addColumn("KRON_FLUX_OUTER", NULL, 0); 233 addColumn("DIFF_R_P", NULL, 0); 234 addColumn("DIFF_SN_P", NULL, 0); 235 addColumn("DIFF_R_M", NULL, 0); 236 addColumn("DIFF_SN_M", NULL, 0); 237 addColumn("FLAGS2", NULL, 1); 238 addColumn("IPP_IDET", NULL, 0); 239 addColumn("N_FRAMES", NULL, 0); 240 addColumn("PADDING", NULL, 0); 241 } 242 if (!psFitsWriteTableAllColumns(fits, header, table, OUT_EXTNAME)) { 243 psError(psErrorCodeLast(), false, "Unable to write table"); 244 return false; 245 } 246 psFree(table); 247 } 248 249 psFree(header); 250 psFitsClose(fits); 251 252 psTrace("ppMops.write", 1, "Done writing %ld rows to %s", det->num, args->output); 253 254 return true; 276 255 } 277 256 278 // extension parameter values: 279 // 0: SkyChip.psf 280 // 1: SkyChip.xfit 281 // Any other value is ignored 282 static bool addOutputColumn(psMetadata *table, const psArray *detections, long outputSize, int extension, char *outColumnName, char *inColumnName, bool convertTo32) 257 static bool addOutputColumn(psMetadata *table, const psArray *detections, long outputSize, char *outColumnName, char *inColumnName, bool convertTo32) 283 258 { 284 if (inColumnName == NULL) { 285 inColumnName = outColumnName; 286 } 287 psVector *out = NULL; 288 if (convertTo32) { 289 // psFitsReadTableAllColumns reads columns of cfitsio type LONG and ULONG into a 64 bit integers 290 // We want to write 32 bits to the output. 291 int next = 0; 292 for (long i=0; i<detections->n; i++) { 293 ppMopsDetections *det = detections->data[i]; 294 if (!det || det->num == 0) { 295 // no detections survived for this input 296 continue; 297 } 298 psVector *in = NULL; 299 if (extension == 0) { 300 in = psMetadataLookupVector(NULL, det->table, inColumnName); 301 } else if (extension == 1) { 302 in = psMetadataLookupVector(NULL, det->fittedTrails, inColumnName); 303 } else { 304 //Error? 305 } 306 if (!in) { 307 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s (convertTo32 is true)", inColumnName); 308 return false; 309 } 310 if (in->type.type != PS_TYPE_S64 && in->type.type != PS_TYPE_U64) { 311 psError(PS_ERR_PROGRAMMING, true, "input column to convert is not S64 or U64: %s %d", 312 inColumnName, in->type.type); 313 return false; 314 } 315 if (out == NULL) { 316 // First time through set up the output vector and the copy parameters 317 if (in->type.type == PS_TYPE_S64) { 318 out = psVectorAlloc(outputSize, PS_TYPE_S32); 319 } else { 320 out = psVectorAlloc(outputSize, PS_TYPE_U32); 321 } 322 } 323 for (long d=0; d < det->num; d++) { 324 if (in->type.type == PS_TYPE_S64) { 325 out->data.S32[next++] = in->data.S64[d]; 326 } else { 327 out->data.U32[next++] = in->data.U64[d]; 328 } 329 } 330 } 331 } else { 332 void *next = NULL; 333 int elementSize = 0; // size of elements in vector... We are making assumptions here about the organization of primitives in memory so we can use memcopy 334 for (long i=0; i<detections->n; i++) { 335 ppMopsDetections *det = detections->data[i]; 336 if (!det || det->num == 0) { 337 // no detections survived for this input 338 continue; 339 } 340 psVector *in = NULL; 341 if (extension == 0) { 342 psTrace("ppMops.write", 1, "Using det->table for %s", inColumnName); 343 in = psMetadataLookupVector(NULL, det->table, inColumnName); 344 } else if (extension == 1) { 345 psTrace("ppMops.write", 1, "Using det->fittedTrails for %s", inColumnName); 346 in = psMetadataLookupVector(NULL, det->fittedTrails, inColumnName); 347 } else { 348 //Error? 349 } 350 if (!in) { 351 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s (convertTo32 is false)", inColumnName); 352 out = psVectorAlloc(outputSize, PS_TYPE_F32); 353 psVectorInit(out, NAN); 354 psMetadataAddVector(table, PS_LIST_TAIL, outColumnName, 0, NULL, out); 355 return false; 356 } 357 if (out == NULL) { 358 // First time through set up the output vector and the copy parameters 359 out = psVectorAlloc(outputSize, in->type.type); 360 next = (void *) out->data.U8; 361 switch (in->type.type) { 362 case PS_TYPE_S8: 363 elementSize = sizeof(psS8); 364 break; 365 case PS_TYPE_U8: 366 elementSize = sizeof(psU8); 367 break; 368 case PS_TYPE_S16: 369 elementSize = sizeof(psS16); 370 break; 371 case PS_TYPE_U16: 372 elementSize = sizeof(psU16); 373 break; 374 case PS_TYPE_S32: 375 elementSize = sizeof(psS32); 376 break; 377 case PS_TYPE_U32: 378 elementSize = sizeof(psU32); 379 break; 380 case PS_TYPE_S64: 381 elementSize = sizeof(psS64); 382 break; 383 case PS_TYPE_U64: 384 elementSize = sizeof(psU64); 385 break; 386 case PS_TYPE_F32: 387 elementSize = sizeof(psF32); 388 break; 389 case PS_TYPE_F64: 390 elementSize = sizeof(psF64); 391 break; 392 default: 393 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unknown vector type %d", in->type.type); 394 return false; 395 } 396 } 397 // We are doing nasty things here so we can use memcpy. 398 // It would be safer to do a proper loop over the elements. 399 long toCopy = det->num * elementSize; 400 memcpy(next, in->data.U8, toCopy); 401 next += toCopy; 402 } 403 } 404 // Finally add the new column to the output table 405 psMetadataAddVector(table, PS_LIST_TAIL, outColumnName, 0, NULL, out); 406 psFree(out); // drop reference 407 return true; 259 if (inColumnName == NULL) { 260 inColumnName = outColumnName; 261 } 262 263 psVector *out = NULL; 264 if (convertTo32) { 265 // psFitsReadTableAllColumns reads columns of cfitsio type LONG and ULONG into a 64 bit integers 266 // We want to write 32 bits to the output. 267 int next = 0; 268 for (long i=0; i<detections->n; i++) { 269 ppMopsDetections *det = detections->data[i]; 270 if (!det || det->num == 0) { 271 // no detections survived for this input 272 continue; 273 } 274 psVector *in = psMetadataLookupVector(NULL, det->table, inColumnName); 275 if (!in) { 276 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s", inColumnName); 277 return false; 278 } 279 if (in->type.type != PS_TYPE_S64 && in->type.type != PS_TYPE_U64) { 280 psError(PS_ERR_PROGRAMMING, true, "input column to convert is not S64 or U64: %s %d", 281 inColumnName, in->type.type); 282 return false; 283 } 284 if (out == NULL) { 285 // First time through set up the output vector and the copy parameters 286 if (in->type.type == PS_TYPE_S64) { 287 out = psVectorAlloc(outputSize, PS_TYPE_S32); 288 } else { 289 out = psVectorAlloc(outputSize, PS_TYPE_U32); 290 } 291 } 292 for (long d=0; d < det->num; d++) { 293 if (in->type.type == PS_TYPE_S64) { 294 out->data.S32[next++] = in->data.S64[d]; 295 } else { 296 out->data.U32[next++] = in->data.U64[d]; 297 } 298 } 299 } 300 } else { 301 void *next = NULL; 302 int elementSize = 0; // size of elements in vector... We are making assumptions here about the organization of primitives in memory so we can use memcopy 303 for (long i=0; i<detections->n; i++) { 304 ppMopsDetections *det = detections->data[i]; 305 if (!det || det->num == 0) { 306 // no detections survived for this input 307 continue; 308 } 309 psVector *in = psMetadataLookupVector(NULL, det->table, inColumnName); 310 if (!in) { 311 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s", inColumnName); 312 return false; 313 } 314 if (out == NULL) { 315 // First time through set up the output vector and the copy parameters 316 out = psVectorAlloc(outputSize, in->type.type); 317 next = (void *) out->data.U8; 318 switch (in->type.type) { 319 case PS_TYPE_S8: 320 elementSize = sizeof(psS8); 321 break; 322 case PS_TYPE_U8: 323 elementSize = sizeof(psU8); 324 break; 325 case PS_TYPE_S16: 326 elementSize = sizeof(psS16); 327 break; 328 case PS_TYPE_U16: 329 elementSize = sizeof(psU16); 330 break; 331 case PS_TYPE_S32: 332 elementSize = sizeof(psS32); 333 break; 334 case PS_TYPE_U32: 335 elementSize = sizeof(psU32); 336 break; 337 case PS_TYPE_S64: 338 elementSize = sizeof(psS64); 339 break; 340 case PS_TYPE_U64: 341 elementSize = sizeof(psU64); 342 break; 343 case PS_TYPE_F32: 344 elementSize = sizeof(psF32); 345 break; 346 case PS_TYPE_F64: 347 elementSize = sizeof(psF64); 348 break; 349 default: 350 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unknown vector type %d", in->type.type); 351 return false; 352 353 } 354 } 355 // We are doing nasty things here so we can use memcpy. 356 // It would be safer to do a proper loop over the elements. 357 long toCopy = det->num * elementSize; 358 memcpy(next, in->data.U8, toCopy); 359 next += toCopy; 360 } 361 } 362 363 // Finally add the new column to the output table 364 psMetadataAddVector(table, PS_LIST_TAIL, outColumnName, 0, NULL, out); 365 psFree(out); // drop reference 366 367 return true; 408 368 } 409 410 369 static bool addSkyfileIDColumn(psMetadata *table, const psArray *detections, long total, char *colName) 411 370 { 412 psVector *out = psVectorAlloc(total, PS_TYPE_S64);413 long next = 0;414 for (long i = 0; i<detections->n; i++) {415 ppMopsDetections *det = detections->data[i];416 if (!det) {417 continue;418 }419 psS64 diffSkyfileId = det->diffSkyfileId;420 for (long j = 0; j < det->num; j++) {421 out->data.S64[next++] = diffSkyfileId;422 }423 }424 psMetadataAddVector(table, PS_LIST_TAIL, colName, 0, NULL, out);425 psFree(out);426 return true;371 psVector *out = psVectorAlloc(total, PS_TYPE_S64); 372 long next = 0; 373 for (long i = 0; i<detections->n; i++) { 374 ppMopsDetections *det = detections->data[i]; 375 if (!det) { 376 continue; 377 } 378 psS64 diffSkyfileId = det->diffSkyfileId; 379 for (long j = 0; j < det->num; j++) { 380 out->data.S64[next++] = diffSkyfileId; 381 } 382 } 383 psMetadataAddVector(table, PS_LIST_TAIL, colName, 0, NULL, out); 384 psFree(out); 385 return true; 427 386 }
Note:
See TracChangeset
for help on using the changeset viewer.
