Changeset 6570 for branches/rel10_ifa/psModules/src/astrom/pmConceptsRead.c
- Timestamp:
- Mar 10, 2006, 5:20:10 PM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/rel10_ifa/psModules/src/astrom/pmConceptsRead.c
r6552 r6570 5 5 #include "pmFPA.h" 6 6 #include "pmConceptsRead.h" 7 #include "psAdditionals.h" 8 7 8 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 9 // File-static functions 10 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 12 13 static float parseF32(psMetadataItem *item 14 ) 15 { 16 switch (item->type) { 17 case PS_DATA_F32: 18 return item->data.F32; 19 case PS_DATA_F64: 20 // Assume it's OK to truncate to floating point from double 21 return (float)item->data.F64; 22 case PS_DATA_S32: 23 // Promote to float 24 return (float)item->data.S32; 25 default: 26 psError(PS_ERR_IO, true, "Concept %s (%s) is not of floating point type (%x) --- treating as NaN.\n", 27 item->name, item->comment, item->type); 28 return NAN; 29 } 30 } 31 32 static double parseF64(psMetadataItem *item 33 ) 34 { 35 switch (item->type) { 36 case PS_TYPE_F64: 37 return item->data.F64; 38 case PS_TYPE_F32: 39 // Promote to double 40 return (double)item->data.F32; 41 case PS_TYPE_S32: 42 // Promote to double 43 return (double)item->data.S32; 44 default: 45 psError(PS_ERR_IO, true, "Concept %s (%s) is not of double-precision floating point type (%x) " 46 "--- treating as NaN.\n", item->name, item->comment, item->type); 47 return NAN; 48 } 49 } 50 51 static int parseS32(psMetadataItem *item 52 ) 53 { 54 switch (item->type) { 55 case PS_TYPE_S32: 56 return item->data.S32; 57 case PS_TYPE_F32: 58 psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F32 --- converting.\n", 59 item->name, comment); 60 return (int)item->data.F32; 61 case PS_TYPE_F64: 62 psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F64 --- converting.\n", 63 item->name, comment); 64 return (int)item->data.F64; 65 default: 66 psError(PS_ERR_IO, true, "Concept %s (%s) is not of integer type (%x) --- treating as zero.\n", 67 item->name, item->comment, item->type); 68 return 0; 69 } 70 } 71 72 static psString parseString(psMetadataItem *item 73 ) 74 { 75 switch (item->type) { 76 case PS_DATA_STRING: 77 return psMemIncrRefCounter(item->data.V); 78 case PS_DATA_F32: { 79 psString value = NULL; // String to return 80 psStringAppend(&value, "%f", item->data.F32); 81 return value; 82 } 83 case PS_DATA_S32: { 84 psString value = NULL; // String to return 85 psStringAppend(&value, "%d", item->data.S32); 86 return value; 87 } 88 default: 89 psError(PS_ERR_IO, true, "Concept %s (%s) is not of string type (%x) --- treating as " 90 "undefined.\n", name, item->comment, item->type); 91 return psStringCopy(""); 92 } 93 } 94 95 96 // This function gets called for the really boring concepts --- where all you have to do is parse from a 97 // header or database and you don't need to muck around with conversions. There is no similar "formatPlain", 98 // since the type is already known. 99 static psMetadataItem *parsePlain(psMetadataItem *concept, // The concept to parse 100 pmConceptSpec *spec // The concept specification 101 ) 102 { 103 psMetadataItem *blank = spec->blank;// The blank specification, which carries the name, comment, type 104 switch (blank->type) { 105 case PS_DATA_STRING: { 106 psString string = parseString(concept); // Get the string, so I can free it after it goes on the MDI 107 psMetadataItem *item = psMetadataItemAllocStr(blank->name, blank->comment, string); 108 psFree(string); 109 return item; 110 } 111 case PS_DATA_S32: 112 return psMetadataItemAllocS32(blank->name, blank->comment, parseS32(concept)); 113 case PS_DATA_F32: 114 return psMetadataItemAllocF32(blank->name, blank->comment, parseF32(concept)); 115 case PS_DATA_F64: 116 return psMetadataItemAllocF64(blank->name, blank->comment, parseF64(concept)); 117 default: 118 psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) is not of a standard type (%x)\n", 119 blank->name, blank->comment, blank->type); 120 return NULL; 121 } 122 } 123 124 // Get the lowest HDU 125 static pmHDU *getLowestHDU(pmFPA *fpa, // The FPA 126 pmChip *chip, // The chip, or NULL 127 pmCell *cell // The cell, or NULL 128 ) 129 { 130 pmHDU *hdu = NULL; // The HDU that's at the lowest level 131 if (cell) { 132 hdu = pmHDUFromCell(cell); 133 } else if (chip) { 134 hdu = pmHDUFromChip(chip); 135 } else if (fpa) { 136 hdu = pmHDUFromFPA(fpa); 137 } 138 139 return hdu; 140 } 141 142 143 // Parse a single concept 144 static bool conceptParse(pmConceptSpec *spec, // The concept specification 145 psMetadataItem *concept, // The concept to parse 146 psMetadata *cameraFormat, // The camera format 147 psMetadata *target, // The target 148 pmFPA *fpa, // The FPA 149 pmChip *chip, // The chip 150 pmCell *cell // The cell 151 ) 152 { 153 if (concept) { 154 psMetadataItem *parsed = NULL; // The parsed concept 155 if (spec->parse) { 156 parsed = spec->parse(concept, spec, cameraFormat, fpa, chip, cell); 157 } else { 158 parsed = parsePlain(concept, spec->blank); 159 } 160 161 // Reformat so that everything's clean 162 if (strcmp(spec->blank->name, parsedItem->name) != 0 || 163 strcmp(spec->blank->comment, parsedItem->comment) != 0) { 164 psMetadataItem *cleaned = NULL; // Item that's been cleaned up --- correct name and comment 165 switch (spec->type) { 166 case PS_DATA_STRING: 167 cleaned = psMetadataItemAllocStr(spec->blank->name, spec->blank->comment, concept->data.V); 168 break; 169 case PS_DATA_S32: 170 cleaned = psMetadataItemAllocS32(spec->blank->name, spec->blank->comment, concept->data.S32); 171 break; 172 case PS_DATA_F32: 173 cleaned = psMetadataItemAllocF32(spec->blank->name, spec->blank->comment, concept->data.F32); 174 break; 175 case PS_DATA_F64: 176 cleaned = psMetadataItemAllocF64(spec->blank->name, spec->blank->comment, concept->data.F64); 177 break; 178 default: 179 cleaned = psMetadataItemAlloc(spec->blank->name, concept->type, spec->blank->comment, 180 concept->data.V); 181 } 182 psFree(parsed); 183 parsed = cleaned; 184 } 185 psMetadataAddItem(target, parsed, PS_LIST_TAIL, PS_META_REPLACE); 186 psFree(parsed); // Drop reference 187 return true; 188 } 189 190 return false; 191 } 192 193 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 194 // Public functions 195 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 196 197 bool pmConceptsReadFromCamera(psMetadata *specs, // The concept specifications 198 pmCell *cell, // The cell 199 psMetadata *target // Place into which to read the concepts 200 ) 201 { 202 if (cell) { 203 pmHDU *hdu = getLowestHDU(NULL, NULL, cell); // The HDU at the lowest level 204 psMetadata *cameraFormat = hdu->format; // The camera format 205 psMetadata *cellConfig = cell->config; // The camera configuration for this cell 206 psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator 207 psMetadataItem *specItem = NULL; // Item from the specs metadata 208 while ((specItem = psMetadataGetAndIncrement(specsIter))) { 209 pmConceptSpec *spec = specItem->data.V; // The specification 210 psString name = specItem->name; // The concept name 211 psMetadataItem *conceptItem = psMetadataLookup(cellConfig, name); // The concept, or NULL 212 psMetadataItem *value = NULL; // The value of the concept 213 if (conceptItem) { 214 // Check the SOURCE 215 psString nameSource = NULL; // String with the concept name and ".SOURCE" added 216 psStringAppend(nameSource, "%s.SOURCE", name); 217 bool mdok = true; // Status of MD lookup 218 psString source = psMetadataLookupStr(&mdok, cell->config, nameSource); // The source 219 if (mdok && strlen(source)) { 220 if (strcasecmp(source, "HEADER") == 0 && conceptItem->type == PS_DATA_STRING) { 221 value = psMetadataLookup(hdu->header, conceptItem->data.V); 222 } else if (strcasecmp(source, "VALUE") == 0) { 223 value = psMemIncrRefCounter(conceptItem); 224 } else { 225 psError(PS_ERR_IO, true, "%s isn't HEADER or VALUE --- can't read %s\n", source, 226 name); 227 continue; 228 } 229 } else { 230 // Assume it's specified by value 231 value = psMemIncrRefCounter(conceptItem); 232 } 233 conceptParse(spec, value, cameraFormat, target, NULL, NULL, cell); 234 } 235 } 236 psFree(specsIter); 237 return true; 238 } 239 return false; 240 } 241 242 243 bool pmConceptsReadFromDefaults(psMetadata *specs, // The concept specifications 244 pmFPA *fpa, // The FPA 245 pmChip *chip, // The chip 246 pmCell *cell, // The cell 247 psMetadata *target // Place into which to read the concepts 248 ) 249 { 250 bool mdok = true; // Status of MD lookup 251 psMetadata *defaults = psMetadataLookupMD(&mdok, cameraFormat, "DEFAULTS"); // The DEFAULTS spec 252 if (mdok && defaults) { 253 pmHDU *hdu = getLowestHDU(fpa, chip, cell); // The HDU at the lowest level 254 psMetadata *cameraFormat = hdu->format; // The camera format 255 psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator 256 psMetadataItem *specItem = NULL; // Item from the specs metadata 257 while ((specItem = psMetadataGetAndIncrement(specsIter))) { 258 pmConceptSpec *spec = specItem->data.V; // The specification 259 psString name = specItem->name; // The concept name 260 psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL 261 conceptParse(spec, conceptItem, cameraFormat, target, fpa, chip, cell); 262 } 263 psFree(specsIter); 264 return true; 265 } 266 return false; 267 } 268 269 bool pmConceptsReadFromHeader(psMetadata *specs, // The concept specifications 270 pmFPA *fpa, // The FPA 271 pmChip *chip, // The chip 272 pmCell *cell, // The cell 273 psMetadata *target // Place into which to read the concepts 274 ) 275 { 276 bool mdok = true; // Status of MD lookup 277 psMetadata *transSpec = psMetadataLookupMD(&mdok, cameraFormat, "TRANSLATION"); // The TRANSLATION spec 278 if (mdok && transSpec) { 279 pmHDU *hdu = getLowestHDU(fpa, chip, cell); // The HDU at the lowest level 280 psMetadata *cameraFormat = hdu->format; // The camera format 281 psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator 282 psMetadataItem *specItem = NULL; // Item from the specs metadata 283 while ((specItem = psMetadataGetAndIncrement(specsIter))) { 284 pmConceptSpec *spec = specItem->data.V; // The specification 285 psString name = specItem->name; // The concept name 286 psString keywords = psMetadataLookupStr(&mdok, transSpec, name); // The FITS keywords 287 if (mdok && strlen(keyword) > 0) { 288 // In case there are multiple headers 289 psList *keys = psStringSplit(keywords, " ,;"); // List of keywords 290 psMetadataItem *headerItem = NULL; // The item, to be returned 291 if (keys->n == 1) { 292 // Only one key --- proceed as usual 293 headerItem = psMetadataLookup(hdu->header, keywords); 294 } else { 295 psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator 296 psMetadataItem *key = NULL; // Item from iteration 297 psList *values = psListAlloc(void); // List containing the values 298 while ((key = psListGetAndIncrement(keysIter))) { 299 psMetadataItem *value = psMetadataLookup(hdu->header, key); 300 psListAdd(values, PS_LIST_TAIL, value); 301 } 302 psFree(keysIter); 303 headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values); 304 psFree(values); 305 } 306 psFree(keys); 307 308 // This will also clean up the name 309 conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell); 310 } 311 } 312 psFree(specsIter); 313 return true; 314 } 315 return false; 316 } 317 318 // XXX --- the below code has NOT been tested! 319 bool pmConceptsReadFromDatabase(psMetadata *specs, // The concept specifications 320 pmFPA *fpa, // The FPA 321 pmChip *chip, // The chip 322 pmCell *cell, // The cell 323 psDB *db, // The database handle 324 psMetadata *target // Place into which to read the concepts 325 ) 326 { 327 bool mdok = true; // Status of MD lookup 328 psMetadata *dbSpec = psMetadataLookupMD(&mdok, cameraFormat, "DATABSE"); // The DATABASE spec 329 if (mdok && dbSpec) { 330 pmHDU *hdu = getLowestHDU(fpa, chip, cell); // The HDU at the lowest level 331 psMetadata *cameraFormat = hdu->format; // The camera format 332 psMetadataIterator *specsIter = psMetadataIteratorAlloc(specs, PS_LIST_HEAD, NULL); // Iterator 333 psMetadataItem *specItem = NULL; // Item from the specs metadata 334 while ((specItem = psMetadataGetAndIncrement(specsIter))) { 335 pmConceptSpec *spec = specItem->data.V; // The specification 336 psString name = specItem->name; // The concept name 337 338 psMetadata *dbLookup = psMetadataLookupMD(&mdok, dbSpec, name); 339 if (mdok && dbLookup) { 340 const char *tableName = psMetadataLookupStr(&mdStatus, dbLookup, "TABLE"); // Table name 341 // Names of the "where" columns 342 const char *givenCols = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENDBCOL"); 343 // Values of the "where" columns 344 const char *givenPS = psMetadataLookupStr(&mdStatus, dbLookup, "GIVENPS"); 345 346 // Now, need to get the "given"s 347 if (strlen(givenCols) > 0 || strlen(givenPS) > 0) { 348 psList *cols = psStringSplit(givenCols, ",;"); // List of column names 349 psList *values = psStringSplit(givenPS, ",;"); // List of value names for the columns 350 psMetadata *selection = psMetadataAlloc(); // The stuff to select in the DB 351 if (cols->n != values->n) { 352 psLogMsg(__func__, PS_LOG_WARN, 353 "The GIVENDBCOL and GIVENPS entries for %s do not have " 354 "the same number of entries --- ignored.\n", concept); 355 } else { 356 // Iterators for the lists 357 psListIterator *colsIter = psListIteratorAlloc(cols, PS_LIST_HEAD, false); 358 psListIterator *valuesIter = psListIteratorAlloc(values, PS_LIST_HEAD, false); 359 char *column = NULL; // Name of the column 360 while ((column = psListGetAndIncrement(colsIter))) { 361 char *name = psListGetAndIncrement(valuesIter); // Name for the value 362 if (!strlen(column) || !strlen(name)) { 363 psLogMsg(__func__, PS_LOG_WARN, "One of the columns or value names for %s is " 364 " empty --- ignored.\n", concept); 365 } else { 366 // Search for the value name 367 psMetadataItem *item = pmConceptReadFromHeader(fpa, chip, cell, name); 368 if (! item) { 369 item = pmConceptReadFromDefault(fpa, chip, cell, name); 370 } 371 if (! item) { 372 psLogMsg(__func__, PS_LOG_ERROR, "Unable to find the value name %s for DB" 373 " lookup on %s --- ignored.\n", name, concept); 374 } else { 375 // We need to create a new psMetadataItem. I don't think we can't 376 // simply hack the existing one, since that could conceivably cause 377 // memory leaks 378 psMetadataItem *newItem = psMetadataItemAlloc(concept, item->type, 379 item->comment, 380 item->data.V); 381 psMetadataAddItem(selection, newItem, PS_LIST_TAIL, PS_META_REPLACE); 382 psFree(newItem); 383 } 384 } 385 psFree(name); 386 psFree(column); 387 } // Iterating through the columns 388 psFree(colsIter); 389 psFree(valuesIter); 390 391 psArray *dbResult = psDBSelectRows(db, tableName, selection, 2); // Lookup result 392 // Note that we use limit=2 in order to test if there are multiple rows returned 393 394 psMetadataItem *conceptItem = NULL; // The final result of the DB lookup 395 if (dbResult->n == 0) { 396 psLogMsg(__func__, PS_LOG_WARN, 397 "Unable to find any rows in DB for %s --- ignored\n", concept); 398 } else { 399 if (dbResult-> n > 1) { 400 psLogMsg(__func__, PS_LOG_WARN, 401 "Multiple rows returned in DB lookup for %s --- " 402 " using the first one only.\n", concept); 403 } 404 conceptItem = (psMetadataItem*)dbResult->data[0]; 405 } 406 407 // Now we have the result 408 conceptParse(spec, headerItem, cameraFormat, target, fpa, chip, cell); 409 410 } 411 psFree(cols); 412 psFree(values); 413 } 414 } // Doing the "given"s. 415 416 } // Iterating through the concept specifications 417 psFree(specsIter); 418 419 return true; 420 } 421 return false; 422 } 423 424 425 426 427 #if 0 9 428 10 429 psMetadataItem *pmConceptReadFromCamera(pmCell *cell, // The cell … … 241 660 242 661 243 float pmConceptReadF32(pmFPA *fpa, // The FPA 244 pmChip *chip, // The chip 245 pmCell *cell, // The cell 246 psDB *db, // DB handle 247 const char *name // Name of the concept 248 ) 249 { 250 psMetadataItem *item = pmConceptRead(fpa, chip, cell, db, name); 251 float value = NAN; 252 if (item) { 253 switch (item->type) { 254 case PS_DATA_F32: 255 value = item->data.F32; 256 break; 257 case PS_DATA_F64: 258 // Assume it's OK to truncate to floating point from double 259 value = (float)item->data.F64; 260 break; 261 case PS_DATA_S32: 262 // Promote to float 263 value = (float)item->data.S32; 264 break; 265 default: 266 psError(PS_ERR_IO, true, "Concept %s (%s) is not of floating point type (%x) --- treating as " 267 "undefined.\n", name, item->comment, item->type); 268 } 269 psTrace(__func__, 7, "Adding %s (%s): %f\n", name, item->comment, value); 270 } else { 271 psError(PS_ERR_IO, true, "Concept %s is not defined.\n", name); 272 } 273 274 return value; 275 } 276 277 double pmConceptReadF64(pmFPA *fpa, // The FPA 278 pmChip *chip, // The chip 279 pmCell *cell, // The cell 280 psDB *db, // DB handle 281 const char *name // Name of the concept 282 ) 283 { 284 psMetadataItem *item = pmConceptRead(fpa, chip, cell, db, name); 285 double value = NAN; 286 if (item) { 287 switch (item->type) { 288 case PS_TYPE_F64: 289 value = item->data.F64; 290 break; 291 case PS_TYPE_F32: 292 // Promote to double 293 value = (double)item->data.F32; 294 break; 295 case PS_TYPE_S32: 296 // Promote to double 297 value = (double)item->data.S32; 298 break; 299 default: 300 psError(PS_ERR_IO, true, "Concept %s (%s) is not of double-precision floating point type (%x) " 301 "--- treating as undefined.\n", name, item->comment, item->type); 302 } 303 psTrace(__func__, 7, "Adding %s (%s): %f\n", name, item->comment, value); 304 } else { 305 psError(PS_ERR_IO, true, "Concept %s is not defined.\n", name); 306 } 307 308 return value; 309 } 310 311 int pmConceptReadS32(pmFPA *fpa, // The FPA 312 pmChip *chip, // The chip 313 pmCell *cell, // The cell 314 psDB *db, // DB handle 315 const char *name // Name of the concept 316 ) 317 { 318 psMetadataItem *item = pmConceptRead(fpa, chip, cell, db, name); 319 int value = 0; 320 if (item) { 321 switch (item->type) { 322 case PS_TYPE_S32: 323 value = item->data.S32; 324 break; 325 case PS_TYPE_F32: 326 psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F32 --- converting.\n", 327 name, comment); 328 value = (int)item->data.F32; 329 break; 330 case PS_TYPE_F64: 331 psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F64 --- converting.\n", 332 name, comment); 333 value = (int)item->data.F64; 334 break; 335 default: 336 psError(PS_ERR_IO, true, "Concept %s (%s) is not of integer type (%x) --- treating as " 337 "undefined.\n", name, item->comment, item->type); 338 } 339 psTrace(__func__, 7, "Read concept %s (%s): %d\n", name, item->comment, value); 340 } else { 341 psError(PS_ERR_IO, true, "Concept %s is not defined.\n", name); 342 } 343 344 return value; 345 } 346 347 psString pmConceptReadString(pmFPA *fpa, // The FPA 348 pmChip *chip, // The chip 349 pmCell *cell, // The cell 350 psDB *db, // DB handle 351 const char *name // Name of the concept 352 ) 353 { 354 psMetadataItem *item = pmConceptRead(fpa, chip, cell, db, name); 355 psString value = NULL; 356 if (item) { 357 switch (item->type) { 358 case PS_DATA_STRING: 359 value = psMemIncrRefCounter(item->data.V); 360 break; 361 case PS_DATA_F32: 362 psStringAppend(&value, "%f", item->data.F32); 363 break; 364 case PS_DATA_S32: 365 psStringAppend(&value, "%d", item->data.S32); 366 break; 367 default: 368 psError(PS_ERR_IO, true, "Concept %s (%s) is not of string type (%x) --- treating as " 369 "undefined.\n", name, item->comment, item->type); 370 } 371 psTrace(__func__, 7, "Read concept %s (%s): %s\n", name, item->comment, value); 372 } else { 373 psError(PS_ERR_IO, true, "Concept %s is not defined.\n", name); 374 value = psStringCopy(""); 375 } 376 377 return value; 378 } 379 662 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
