Changeset 34289
- Timestamp:
- Aug 3, 2012, 5:28:50 PM (14 years ago)
- Location:
- tags/ipp-20120802/ppTranslate/src
- Files:
-
- 7 edited
-
ppMops.c (modified) (2 diffs)
-
ppMops.h (modified) (3 diffs)
-
ppMopsArguments.c (modified) (1 diff)
-
ppMopsGetSkyChipPsfVersion.c (modified) (1 diff)
-
ppMopsMerge.c (modified) (1 diff)
-
ppMopsRead.c (modified) (1 diff)
-
ppMopsWrite.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
tags/ipp-20120802/ppTranslate/src/ppMops.c
r34281 r34289 67 67 } 68 68 69 70 69 psArray *detections = ppMopsRead(args); // Detections from each input 71 70 if (!detections) { … … 92 91 psLibFinalize(); 93 92 94 fprintf (stderr, "found %d leaks at %s\n", 95 psMemCheckLeaks2 (0, 96 NULL, stdout, false, 500), "ppMops"); 93 /* fprintf (stderr, "found %d leaks at %s\n", */ 94 /* psMemCheckLeaks2 (0, */ 95 /* NULL, stdout, false, 500), "ppMops"); */ 97 96 98 97 return PS_EXIT_SUCCESS; 99 98 } 100 99 101 102 #if 0103 ps104 105 106 psArray *detections = NULL; // Detections107 psMetadata *header = NULL; // Header for detections108 {109 psFits *fits = psFitsOpen(data->detections, "r"); // FITS file110 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 columns135 int numIn = detections->n; // Number of rows in input136 int numOut = 0; // Number of rows in output137 psArray *output = psArrayAllocEmpty(numIn); // Output table138 double plateScale = 0.0; // Average plate scale139 for (int i = 0; i < numIn; i++) {140 psMetadata *inRow = detections->data[i]; // Input row141 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 moments157 continue;158 }159 160 psMetadata *outRow = output->data[numOut] = psMetadataAlloc(); // Output row161 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 fixing182 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 header193 psMetadata *outHeader = psMetadataAlloc(); // Output header194 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 fake227 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 table242 {243 psFits *fits = psFitsOpen(data->output, "w"); // FITS file244 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 table254 psMetadata *outRow = psMetadataAlloc(); // Dummy output row255 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 fixing264 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 #endif293 -
tags/ipp-20120802/ppTranslate/src/ppMops.h
r34281 r34289 30 30 } ppMopsArguments; 31 31 32 #if 033 #warning "IS THERE ANYTHING TO BE MODIFIED HERE?"34 TTYPE19 = 'PSF_CHISQ' / label for field 1935 TFORM19 = '1E ' / data format of field: 4-byte REAL36 TTYPE20 = 'CR_NSIGMA' / label for field 2037 TFORM20 = '1E ' / data format of field: 4-byte REAL38 TTYPE21 = 'EXT_NSIGMA' / label for field 2139 TFORM21 = '1E ' / data format of field: 4-byte REAL40 TTYPE22 = 'PSF_MAJOR' / label for field 2241 TFORM22 = '1E ' / data format of field: 4-byte REAL42 TTYPE23 = 'PSF_MINOR' / label for field 2343 TFORM23 = '1E ' / data format of field: 4-byte REAL44 TTYPE24 = 'PSF_THETA' / label for field 2445 TFORM24 = '1E ' / data format of field: 4-byte REAL46 TTYPE25 = 'PSF_QF ' / label for field 2547 TFORM25 = '1E ' / data format of field: 4-byte REAL48 TTYPE26 = 'PSF_NDOF' / label for field 2649 TFORM26 = '1J ' / data format of field: 4-byte INTEGER50 TTYPE27 = 'PSF_NPIX' / label for field 2751 TFORM27 = '1J ' / data format of field: 4-byte INTEGER52 TTYPE28 = 'MOMENTS_XX' / label for field 2853 TFORM28 = '1E ' / data format of field: 4-byte REAL54 TTYPE29 = 'MOMENTS_XY' / label for field 2955 TFORM29 = '1E ' / data format of field: 4-byte REAL56 TTYPE30 = 'MOMENTS_YY' / label for field 3057 TFORM30 = '1E ' / data format of field: 4-byte REAL58 #endif59 60 32 /// Parse arguments 61 33 ppMopsArguments *ppMopsArgumentsParse(int argc, char *argv[]); … … 75 47 long numGood; // Number of "good" detections 76 48 psS64 diffSkyfileId; // unique id for input skyfile 77 psMetadata *table; // Columns from the input file 49 psMetadata *table; // Columns from the input file (SkyChip.psf extension) 78 50 psVector *x, *y; // Image coordinates 79 51 psVector *ra, *dec; // Sky coordinates … … 103 75 /// @returns 1 if EXTTYPE of "SkyChip.psf" is PS1_DV1 104 76 /// @returns 2 if EXTTYPE of "SkyChip.psf" is PS1_DV2 77 /// @returns 3 if EXTTYPE of "SkyChip.psf" is PS1_DV3 105 78 /// @returns 0 otherwise 106 79 int ppMopsGetSkyChipPsfVersion(const psFits* fits); -
tags/ipp-20120802/ppTranslate/src/ppMopsArguments.c
r34281 r34289 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 or 2 for PS1_DV1\n");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"); 37 37 fprintf(stderr, "\t\tSee IPP-MOPS ICD for details\n"); 38 38 psLibFinalize(); -
tags/ipp-20120802/ppTranslate/src/ppMopsGetSkyChipPsfVersion.c
r34281 r34289 14 14 psFree(headerSkyChip); 15 15 return 2; 16 } else if (strcmp(version, "PS1_DV3") == 0) { 17 psFree(headerSkyChip); 18 return 2; 16 19 } 17 20 psWarning("Unsupported EXTTYPE in SkyChip.psf table: [%s]", version); -
tags/ipp-20120802/ppTranslate/src/ppMopsMerge.c
r34281 r34289 71 71 72 72 for (int i = 0; i < numInputs; i++) { 73 psTrace("ppMops.merge", 1, "Processing batch %d\n", i); 73 74 ppMopsDetections *det = detections->data[i]; // Detections of interest 74 75 if (!det) { -
tags/ipp-20120802/ppTranslate/src/ppMopsRead.c
r34281 r34289 8 8 #include "ppMops.h" 9 9 10 static void addDummyValues(psMetadata* md, long size); 11 static void replaceDummyValuesF32(const char* colName, psMetadata* source, psMetadata* target, psVector* indexes); 12 10 13 /* 11 14 ppMopsRead possibly modifies the args->version if the user did not 12 15 set it explicitely. 13 */16 */ 14 17 psArray *ppMopsRead(ppMopsArguments *args) 15 18 { 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; 19 psTrace("ppMops.read", 1, "Reading input detections\n"); 20 21 psArray *inNames = args->input; // Input names 22 long num = inNames->n; // Number of inputs 23 psArray *detections = psArrayAlloc(num); // Array of detections, to return 24 for (int i = 0; i < num; i++) { 25 const char *name = inNames->data[i]; 26 27 psFits *fits = psFitsOpen(name, "r"); // FITS file 28 if (!fits) { 29 psError(PS_ERR_IO, false, "Unable to open input %d", i); 30 return false; 31 } 32 33 psMetadata *header = psFitsReadHeader(NULL, fits); // Primary header 34 if (!header) { 35 psError(PS_ERR_IO, false, "Unable to read header %d", i); 36 return false; 37 } 38 39 psS64 diffSkyfileId = psMetadataLookupS64(NULL, header, "IMAGEID"); // Identifier for image 40 if (diffSkyfileId == 0) { 41 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to find identifier for image %d", i); 42 return false; 43 } 44 45 if (!psFitsMoveExtName(fits, "SkyChip.psf")) { 46 psError(PS_ERR_IO, false, "Unable to move to HDU with detections"); 47 return false; 48 } 49 int skyChipPsfVersion = ppMopsGetSkyChipPsfVersion(fits); 50 if (args->version == 0) { 51 psTrace("ppMops.read", 1, "Changing args->version to %d\n", skyChipPsfVersion); 52 args->version = (unsigned short) skyChipPsfVersion; 53 } 54 if (skyChipPsfVersion == 0) { 55 // Try to read with the user specified version? 56 skyChipPsfVersion = args->version; 57 } 58 /* Display a warning message if there are version 59 inconsistencies between the file and the flag (note that 60 those inconsistencies might be wanted) */ 61 if (skyChipPsfVersion != args->version) { 62 if (skyChipPsfVersion > args->version) { 63 psWarning("The FITS data will be downgraded from PS1_DV%d to PS1_DV%d\n", 64 skyChipPsfVersion, args->version); 65 } else { // Necessarily: skyChipPsfVersion > args->version 66 psWarning("The FITS data will be upgraded from PS1_DV%d to PS1_DV%d (new values set to default 0, NaN...)\n", 67 skyChipPsfVersion, args->version); 68 } 69 } 70 71 long size = psFitsTableSize(fits); // Size of table 72 if (size <= 0) { 73 psErrorStackPrint(stderr, "Unable to determine size of table %d", i); 74 psErrorClear(); 75 psWarning("Ignoring input %d", i); 76 psFree(header); 77 psFitsClose(fits); 78 continue; 79 } 80 ppMopsDetections *det = ppMopsDetectionsAlloc(size); 81 detections->data[i] = det; 82 det->component = psStringNCopy(name, strrchr(name, '.') - name); // Strip off extension 83 det->num = size; 84 det->diffSkyfileId = diffSkyfileId; 85 86 psTrace("ppMops.read", 3, "Reading %ld rows from %s\n", size, (const char*)inNames->data[i]); 87 88 det->raBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.RA")); 89 det->decBoresight = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.DEC")); 90 det->filter = psMemIncrRefCounter(psMetadataLookupStr(NULL, header, "FPA.FILTER")); 91 det->airmass = psMetadataLookupF32(NULL, header, "AIRMASS"); 92 det->exptime = psMetadataLookupF32(NULL, header, "EXPTIME"); 93 det->posangle = psMetadataLookupF64(NULL, header, "FPA.POSANGLE"); 94 det->alt = psMetadataLookupF64(NULL, header, "FPA.ALT"); 95 det->az = psMetadataLookupF64(NULL, header, "FPA.AZ"); 96 det->mjd = psMetadataLookupF64(NULL, header, "MJD-OBS") + det->exptime / 2.0 / 3600 / 24; 97 98 det->seeing = (float) 0.5 * (psMetadataLookupF32(NULL, header, "FWHM_MAJ") + 99 psMetadataLookupF32(NULL, header, "FWHM_MIN")); 100 101 det->naxis1 = psMetadataLookupS32(NULL, header, "IMNAXIS1"); // Number of columns 102 det->naxis2 = psMetadataLookupS32(NULL, header, "IMNAXIS2"); // Number of rows 103 104 psFree(header); 105 106 psMetadata *table = psFitsReadTableAllColumns(fits); // Table of interest 107 if (!table) { 108 psError(PS_ERR_IO, false, "Unable to read table %d", i); 109 return NULL; 110 } 111 det->table = table; 112 psTrace("ppMops.read", 19, "PSF table:\n%s\n", psMetadataConfigFormat(det->table)); 113 psTrace("ppMops.read", 19, "End of PSF table\n"); 114 115 //fittedTrail extension (Supported for releases 2 and above) 116 if (skyChipPsfVersion >= 2) { 117 //First: append all the new columns that we want to the existing table 118 addDummyValues(det->table, size); 119 if (!psFitsMoveExtName(fits, "SkyChip.xfit")) { 120 psTrace("ppMops.read", 3, "No fitted trails extension"); 121 } else { 122 psTrace("ppMops.read", 3, "Fitted trails extension found\n"); 123 int fittedTrailsSize = psFitsTableSize(fits); 124 if (fittedTrailsSize <= 0) { 125 psErrorStackPrint(stderr, "Unable to determine size of fitted trails extension table %d", i); 126 psTrace("ppMops.read", 3, "No entry in fitted trails extension!!!!\n"); 127 psErrorClear(); 128 } else { 129 psMetadata* fittedTrails = psFitsReadTableAllColumns(fits); // Table of interest 130 if (!fittedTrails) { 131 psError(PS_ERR_IO, false, "Unable to read fittedTrails table in file %d", i); 132 return NULL; 133 } 134 //Iterate on the different names and types expected in the fittedTrails parameters 135 psVector* idet = psMetadataLookupVector(NULL, fittedTrails, "IPP_IDET"); 136 replaceDummyValuesF32("X_EXT", fittedTrails, det->table, idet); 137 replaceDummyValuesF32("Y_EXT", fittedTrails, det->table, idet); 138 replaceDummyValuesF32("X_EXT_SIG", fittedTrails, det->table, idet); 139 replaceDummyValuesF32("Y_EXT_SIG", fittedTrails, det->table, idet); 140 replaceDummyValuesF32("EXT_INST_MAG", fittedTrails, det->table, idet); 141 replaceDummyValuesF32("EXT_INST_MAG_SIG", fittedTrails, det->table, idet); 142 replaceDummyValuesF32("NPARAMS", fittedTrails, det->table, idet); 143 replaceDummyValuesF32("EXT_WIDTH_MAJ", fittedTrails, det->table, idet); 144 replaceDummyValuesF32("EXT_WIDTH_MIN", fittedTrails, det->table, idet); 145 replaceDummyValuesF32("EXT_THETA", fittedTrails, det->table, idet); 146 replaceDummyValuesF32("EXT_WIDTH_MAJ_ERR", fittedTrails, det->table, idet); 147 replaceDummyValuesF32("EXT_WIDTH_MIN_ERR", fittedTrails, det->table, idet); 148 replaceDummyValuesF32("EXT_THETA_ERR", fittedTrails, det->table, idet); 50 149 } 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); 203 } 204 205 psTrace("ppMops.read", 1, "Done reading input detections\n"); 206 207 return detections; 208 } 150 } 151 } 152 153 psFitsClose(fits); 154 155 if (args->version == 0) { 156 if (skyChipPsfVersion < 2) { 157 // XXX: TODO: Do we need to add dummy vectors for the missing columns? 158 } 159 } 160 161 psVector *ra = psMetadataLookupVector(NULL, table, "RA_PSF"); 162 psVector *dec = psMetadataLookupVector(NULL, table, "DEC_PSF"); 163 164 det->raErr = psVectorAlloc(size, PS_TYPE_F64); 165 det->decErr = psVectorAlloc(size, PS_TYPE_F64); 166 det->mask = psVectorAlloc(size, PS_TYPE_U8); 167 168 // convert ra and dec to radians for use in the purge duplicates function 169 det->ra = (psVector*)psBinaryOp(NULL, ra, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 170 det->dec = (psVector*)psBinaryOp(NULL, dec, "*", psScalarAlloc(DEG_TO_RAD(1.0), PS_TYPE_F64)); 171 det->x = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "X_PSF")); 172 det->y = psMemIncrRefCounter(psMetadataLookupVector(NULL, table, "Y_PSF")); 173 if (!det->ra || !det->dec || !det->x || !det->y) { 174 psError(PS_ERR_UNEXPECTED_NULL, true, "Unable to find all of RA, Dec, X and Y columns"); 175 return NULL; 176 } 177 178 // Add our new vectors to the table so that duplicates and masked items may be purged 179 psMetadataAddVector(table, PS_LIST_HEAD, "DEC_ERR", 0, NULL, det->decErr); 180 psMetadataAddVector(table, PS_LIST_HEAD, "RA_ERR", 0, NULL, det->raErr); 181 182 psTrace("ppMops.read", 2, "Read %ld rows from %s\n", det->num, det->component); 183 184 psVector *mag = psMetadataLookupVector(NULL, table, "PSF_INST_MAG"); 185 psVector *magErr = psMetadataLookupVector(NULL, table, "PSF_INST_MAG_SIG"); 186 psVector *xErrV = psMetadataLookupVector(NULL, table, "X_PSF_SIG"); 187 psVector *yErrV = psMetadataLookupVector(NULL, table, "Y_PSF_SIG"); 188 psVector *scaleV = psMetadataLookupVector(NULL, table, "PLTSCALE"); 189 psVector *angleV = psMetadataLookupVector(NULL, table, "POSANGLE"); 190 psVector *flagsV = psMetadataLookupVector(NULL, table, "FLAGS"); 191 192 double plateScale = 0.0; // Plate scale 193 long numGood = 0; // Number of good rows 194 for (long row = 0; row < size; row++) { 195 196 psU32 flags = flagsV->data.U32[row]; // psFitsTableGetU32(NULL, table, row, "FLAGS"); 197 if (flags & SOURCE_MASK) { 198 psTrace("ppMops.read", 10, "Discarding row %ld from input %d because of flags: %ud", row, i, flags); 199 det->mask->data.U8[row] = 0xFF; 200 continue; 201 } 202 203 // Calculate error in RA, Dec 204 double xErr = xErrV->data.F32[row]; 205 double yErr = yErrV->data.F32[row]; 206 double scale = scaleV->data.F32[row]; 207 double angle = angleV->data.F32[row]; 208 209 if (!isfinite(det->x->data.F32[row]) || !isfinite(det->y->data.F32[row]) || 210 !isfinite(det->ra->data.F64[row]) || !isfinite(det->dec->data.F64[row]) || 211 !isfinite(mag->data.F32[row]) || !isfinite(magErr->data.F32[row]) || 212 !isfinite(xErr) || !isfinite(yErr) || !isfinite(scale) || !isfinite(angle)) { 213 psTrace("ppMops.read", 10, 214 "Discarding row %ld from input %d because of non-finite values: " 215 "%f %f %lf %lf %f %f %f %f %f %f", 216 row, i, 217 det->x->data.F32[row], det->y->data.F32[row], 218 det->ra->data.F64[row], det->dec->data.F64[row], 219 mag->data.F32[row], magErr->data.F32[row], 220 xErr, yErr, scale, angle); 221 det->mask->data.U8[row] = 0xFF; 222 continue; 223 } 224 225 // XXX Not at all sure I've got the angles around the right way here... 226 double cosAngle = cos(angle), sinAngle = sin(angle); 227 double cosAngle2 = PS_SQR(cosAngle), sinAngle2 = PS_SQR(sinAngle); 228 double xErr2 = PS_SQR(xErr), yErr2 = PS_SQR(yErr); 229 double errScale = scale / 3600.0; 230 det->raErr->data.F64[row] = errScale * sqrt(cosAngle2 * xErr2 + sinAngle2 * yErr2); 231 det->decErr->data.F64[row] = errScale * sqrt(sinAngle2 * xErr2 + cosAngle2 * yErr2); 232 det->mask->data.U8[row] = 0; 233 plateScale += scale; 234 numGood++; 235 } 236 det->seeing *= ((float) plateScale) / ((float) numGood); 237 238 // Are we using numGood for anything outside of this function? 239 det->numGood = numGood; 240 241 if (isfinite(args->zp) && numGood > 0) { 242 psBinaryOp(mag, mag, "+", psScalarAlloc(args->zp, PS_TYPE_F32)); 243 } 244 245 psTrace("ppMops.read", 2, "Read %ld good rows from %s\n", numGood, (const char*)name); 246 } 247 248 psTrace("ppMops.read", 1, "Done reading input detections\n"); 249 250 return detections; 251 } 252 253 static psVector* createDummyF32(long size) { 254 psVector* dummy = psVectorAlloc(size, PS_TYPE_F32); 255 psVectorInit(dummy, NAN); 256 return dummy; 257 } 258 259 static void addDummyValues(psMetadata* md, long size) { 260 psMetadataAdd(md, PS_LIST_TAIL, "X_EXT", PS_DATA_VECTOR, "EXT model x coordinate", createDummyF32(size)); 261 psMetadataAdd(md, PS_LIST_TAIL, "Y_EXT", PS_DATA_VECTOR, "EXT model y coordinate", createDummyF32(size)); 262 psMetadataAdd(md, PS_LIST_TAIL, "X_EXT_SIG", PS_DATA_VECTOR, "Sigma in EXT x coordinate", createDummyF32(size)); 263 psMetadataAdd(md, PS_LIST_TAIL, "Y_EXT_SIG", PS_DATA_VECTOR, "Sigma in EXT y coordinate", createDummyF32(size)); 264 psMetadataAdd(md, PS_LIST_TAIL, "EXT_INST_MAG", PS_DATA_VECTOR, "EXT fit instrumental magnitude", createDummyF32(size)); 265 psMetadataAdd(md, PS_LIST_TAIL, "EXT_INST_MAG_SIG", PS_DATA_VECTOR, "Sigma of PSF instrumental magnitude", createDummyF32(size)); 266 psMetadataAdd(md, PS_LIST_TAIL, "NPARAMS", PS_DATA_VECTOR, "Number of model parameters", createDummyF32(size)); 267 psMetadataAdd(md, PS_LIST_TAIL, "EXT_WIDTH_MAJ", PS_DATA_VECTOR, "EXT width (major axis), length for trail", createDummyF32(size)); 268 psMetadataAdd(md, PS_LIST_TAIL, "EXT_WIDTH_MIN", PS_DATA_VECTOR, "EXT width (minor axis), sigma for trail", createDummyF32(size)); 269 psMetadataAdd(md, PS_LIST_TAIL, "EXT_THETA", PS_DATA_VECTOR, "EXT orientation angle", createDummyF32(size)); 270 psMetadataAdd(md, PS_LIST_TAIL, "EXT_WIDTH_MAJ_ERR", PS_DATA_VECTOR, "EXT width error (major axis)", createDummyF32(size)); 271 psMetadataAdd(md, PS_LIST_TAIL, "EXT_WIDTH_MIN_ERR", PS_DATA_VECTOR, "EXT width error (minor axis)", createDummyF32(size)); 272 psMetadataAdd(md, PS_LIST_TAIL, "EXT_THETA_ERR", PS_DATA_VECTOR, "EXT orientation angle (error)", createDummyF32(size)); 273 } 274 275 static void replaceDummyValuesF32(const char* colName, psMetadata* source, psMetadata* target, psVector* indexes) { 276 psVector* source_vector = psMetadataLookupVector(NULL, source, colName); 277 psVector* target_vector = psMetadataLookupVector(NULL, target, colName); 278 for (long index = 0; index<indexes->n; ++index) { 279 target_vector->data.F32[indexes->data.S64[index]] = source_vector->data.F32[index]; 280 } 281 } -
tags/ipp-20120802/ppTranslate/src/ppMopsWrite.c
r34281 r34289 14 14 bool ppMopsWrite(const psArray *detections, const ppMopsArguments *args) 15 15 { 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; 76 } 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; 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, _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 addColumn("X_EXT", NULL, 0); 244 addColumn("Y_EXT", NULL, 0); 245 addColumn("X_EXT_SIG", NULL, 0); 246 addColumn("Y_EXT_SIG", NULL, 0); 247 addColumn("EXT_INST_MAG", NULL, 0); 248 addColumn("EXT_INST_MAG_SIG", NULL, 0); 249 addColumn("NPARAMS", NULL, 0); 250 addColumn("EXT_WIDTH_MAJ", NULL, 0); 251 addColumn("EXT_WIDTH_MIN", NULL, 0); 252 addColumn("EXT_THETA", NULL, 0); 253 addColumn("EXT_WIDTH_MAJ_ERR", NULL, 0); 254 addColumn("EXT_WIDTH_MIN_ERR", NULL, 0); 255 addColumn("EXT_THETA_ERR", NULL, 0); 256 } 257 if (!psFitsWriteTableAllColumns(fits, header, table, OUT_EXTNAME)) { 258 psError(psErrorCodeLast(), false, "Unable to write table"); 259 return false; 260 } 261 psFree(table); 262 } 263 264 psFree(header); 265 psFitsClose(fits); 266 267 psTrace("ppMops.write", 1, "Done writing %ld rows to %s", det->num, args->output); 268 269 return true; 255 270 } 256 271 272 // extension parameter values: 273 // 0: SkyChip.psf 274 // 1: SkyChip.xfit 275 // Any other value is ignored 257 276 static bool addOutputColumn(psMetadata *table, const psArray *detections, long outputSize, char *outColumnName, char *inColumnName, bool convertTo32) 258 277 { 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; 278 if (inColumnName == NULL) { 279 inColumnName = outColumnName; 280 } 281 psVector *out = NULL; 282 if (convertTo32) { 283 // psFitsReadTableAllColumns reads columns of cfitsio type LONG and ULONG into a 64 bit integers 284 // We want to write 32 bits to the output. 285 int next = 0; 286 for (long i=0; i<detections->n; i++) { 287 ppMopsDetections *det = detections->data[i]; 288 if (!det || det->num == 0) { 289 // no detections survived for this input 290 continue; 291 } 292 psVector *in = NULL; 293 in = psMetadataLookupVector(NULL, det->table, inColumnName); 294 if (!in) { 295 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s (convertTo32 is true)", inColumnName); 296 return false; 297 } 298 if (in->type.type != PS_TYPE_S64 && in->type.type != PS_TYPE_U64) { 299 psError(PS_ERR_PROGRAMMING, true, "input column to convert is not S64 or U64: %s %d", 300 inColumnName, in->type.type); 301 return false; 302 } 303 if (out == NULL) { 304 // First time through set up the output vector and the copy parameters 305 if (in->type.type == PS_TYPE_S64) { 306 out = psVectorAlloc(outputSize, PS_TYPE_S32); 307 } else { 308 out = psVectorAlloc(outputSize, PS_TYPE_U32); 309 } 310 } 311 for (long d=0; d < det->num; d++) { 312 if (in->type.type == PS_TYPE_S64) { 313 out->data.S32[next++] = in->data.S64[d]; 314 } else { 315 out->data.U32[next++] = in->data.U64[d]; 316 } 317 } 318 } 319 } else { 320 void *next = NULL; 321 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 322 for (long i=0; i<detections->n; i++) { 323 ppMopsDetections *det = detections->data[i]; 324 if (!det || det->num == 0) { 325 // no detections survived for this input 326 continue; 327 } 328 psVector *in = NULL; 329 in = psMetadataLookupVector(NULL, det->table, inColumnName); 330 if (!in) { 331 psError(PS_ERR_PROGRAMMING, true, "failed to find input column: %s (convertTo32 is false)", inColumnName); 332 out = psVectorAlloc(outputSize, PS_TYPE_F32); 333 psVectorInit(out, NAN); 334 psMetadataAddVector(table, PS_LIST_TAIL, outColumnName, 0, NULL, out); 335 return false; 336 } 337 if (out == NULL) { 338 // First time through set up the output vector and the copy parameters 339 out = psVectorAlloc(outputSize, in->type.type); 340 next = (void *) out->data.U8; 341 switch (in->type.type) { 342 case PS_TYPE_S8: 343 elementSize = sizeof(psS8); 344 break; 345 case PS_TYPE_U8: 346 elementSize = sizeof(psU8); 347 break; 348 case PS_TYPE_S16: 349 elementSize = sizeof(psS16); 350 break; 351 case PS_TYPE_U16: 352 elementSize = sizeof(psU16); 353 break; 354 case PS_TYPE_S32: 355 elementSize = sizeof(psS32); 356 break; 357 case PS_TYPE_U32: 358 elementSize = sizeof(psU32); 359 break; 360 case PS_TYPE_S64: 361 elementSize = sizeof(psS64); 362 break; 363 case PS_TYPE_U64: 364 elementSize = sizeof(psU64); 365 break; 366 case PS_TYPE_F32: 367 elementSize = sizeof(psF32); 368 break; 369 case PS_TYPE_F64: 370 elementSize = sizeof(psF64); 371 break; 372 default: 373 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Unknown vector type %d", in->type.type); 374 return false; 375 } 376 } 377 // We are doing nasty things here so we can use memcpy. 378 // It would be safer to do a proper loop over the elements. 379 long toCopy = det->num * elementSize; 380 memcpy(next, in->data.U8, toCopy); 381 next += toCopy; 382 } 383 } 384 // Finally add the new column to the output table 385 psMetadataAddVector(table, PS_LIST_TAIL, outColumnName, 0, NULL, out); 386 psFree(out); // drop reference 387 return true; 368 388 } 389 369 390 static bool addSkyfileIDColumn(psMetadata *table, const psArray *detections, long total, char *colName) 370 391 { 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;392 psVector *out = psVectorAlloc(total, PS_TYPE_S64); 393 long next = 0; 394 for (long i = 0; i<detections->n; i++) { 395 ppMopsDetections *det = detections->data[i]; 396 if (!det) { 397 continue; 398 } 399 psS64 diffSkyfileId = det->diffSkyfileId; 400 for (long j = 0; j < det->num; j++) { 401 out->data.S64[next++] = diffSkyfileId; 402 } 403 } 404 psMetadataAddVector(table, PS_LIST_TAIL, colName, 0, NULL, out); 405 psFree(out); 406 return true; 386 407 }
Note:
See TracChangeset
for help on using the changeset viewer.
