IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 4, 2008, 3:32:28 PM (18 years ago)
Author:
Paul Price
Message:

I've implemented the chip-dependent concepts. It uses a generalised version of the dependent DEFAULT concepts, which can, unfortunately, make the camera format configuration a bit longer, but it consolidates code and keeps things simple both for the code and the configuration.

In the process, I took care of a couple of other concept bugs that have been sitting in my inbox for nearly a year:

  • FPA.NAME has been replaced with FPA.OBS, which is intended to be an observation identifier (bug 885). You're welcome to change the name, so long as you also volunteer to fix all the camera formats.
  • FPA.CAMERA is automatically set (on construction of the FPA) to the camera name as used by the configuration files (bug 931). I've changed the ppStats REGISTER recipe to use FPA.CAMERA instead of FPA.INSTRUMENT (which is retained in the concepts as the instrument's name according to the instrument, whereas FPA.CAMERA is the instrument's name according to our configuration).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/concepts/pmConceptsRead.c

    r17874 r17911  
    181181}
    182182
     183psMetadataItem *p_pmConceptsReadSingleFromDefaults(const char *name, const psMetadata *defaults,
     184                                                  const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
     185{
     186    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
     187    PS_ASSERT_METADATA_NON_NULL(defaults, NULL);
     188
     189    psMetadataItem *item = psMetadataLookup(defaults, name); // The concept, or NULL
     190    psTrace("psModules.concepts", 10, "%s: %p\n", name, item);
     191    if (item && item->type == PS_DATA_METADATA) {
     192        // This is a menu
     193        psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
     194        item = p_pmConceptsDepend(name, item->data.md, defaults, fpa, chip, cell);
     195    }
     196    return item;
     197}
    183198
    184199bool p_pmConceptsReadFromDefaults(psMetadata *target, const psMetadata *specs,
     
    209224        pmConceptSpec *spec = specItem->data.V; // The specification
    210225        psString name = specItem->name; // The concept name
    211         psMetadataItem *conceptItem = psMetadataLookup(defaults, name); // The concept, or NULL
    212         psTrace("psModules.concepts", 10, "%s: %p\n", name, conceptItem);
    213         if (conceptItem && conceptItem->type == PS_DATA_METADATA) {
    214             psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
    215             // Check for DEPEND
    216             psMetadata *dependMenu = conceptItem->data.V; // The DEPEND menu
    217             psString depend = NULL; // The CONCEPT.DEPEND
    218             psStringAppend(&depend, "%s.DEPEND", name);
    219             const char *dependConcept = psMetadataLookupStr(&mdok, defaults, depend); // The concept name
    220             if (!mdok || !dependConcept || strlen(dependConcept) == 0) {
    221                 psError(PS_ERR_IO, true, "Unable to parse %s: couldn't find %s in DEFAULTS.\n", name,
    222                         depend);
    223                 psFree(depend);
    224                 continue;
    225             }
    226             psFree(depend);
    227             // Now look up the depend value
    228             psMetadataItem *dependValue = NULL; // The value of the concept we're looking up
    229             if (cell) {
    230                 dependValue = psMetadataLookup(cell->concepts, dependConcept);
    231             }
    232             if (chip && !dependValue) {
    233                 dependValue = psMetadataLookup(chip->concepts, dependConcept);
    234             }
    235             if (fpa && !dependValue) {
    236                 dependValue = psMetadataLookup(chip->concepts, dependConcept);
    237             }
    238             if (!dependValue) {
    239                 psError(PS_ERR_IO, true, "Unable to find %s to resolve %s in DEFAULTS.\n",
    240                         dependConcept, name);
    241                 continue;
    242             }
    243             if (dependValue->type != PS_DATA_STRING) {
    244                 psError(PS_ERR_BAD_PARAMETER_TYPE, true, "%s is required to resolve %s in DEFAULTS, "
    245                         "but it is not of type STRING.\n", dependConcept, name);
    246                 continue;
    247             }
    248             const char *dependKey = dependValue->data.V; // The key to the DEPEND menu
    249             psTrace("psModules.concepts", 7, "%s.DEPEND resolves to %s....\n", name, dependKey);
    250 
    251             conceptItem = psMetadataLookup(dependMenu, dependKey);
    252             // Now we can parse this as we would ordinarily
    253         }
     226        psMetadataItem *conceptItem = p_pmConceptsReadSingleFromDefaults(name, defaults, fpa, chip, cell);
    254227        if (conceptItem && !conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_DEFAULTS,
    255228                                         cameraFormat, target, fpa, chip, cell)) {
     
    282255    psMetadata *cameraFormat = hduLow->format; // The camera format
    283256    bool mdok = true;                   // Status of MD lookup
    284     psMetadata *transSpec = psMetadataLookupMetadata(&mdok, cameraFormat, "TRANSLATION"); // The TRANSLATION spec
     257    psMetadata *transSpec = psMetadataLookupMetadata(&mdok, cameraFormat, "TRANSLATION"); // TRANSLATION spec
    285258    if (!mdok || !transSpec) {
    286259        psError(PS_ERR_IO, true, "Failed to find \"TRANSLATION\"");
     
    318291        }
    319292
    320         if (! headerItem) {
    321             psString keywords = psMetadataLookupStr(&mdok, transSpec, name); // The FITS keywords
    322             if (mdok && strlen(keywords) > 0) {
    323                 // In case there are multiple headers
    324                 psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
    325                 if (keys->n == 1) {
    326                     // Only one key --- proceed as usual
     293        if (!headerItem) {
     294            psMetadataItem *formatItem = psMetadataLookup(transSpec, name); // Item with keyword
     295            if (!formatItem) {
     296                continue;
     297            }
     298            if (formatItem->type == PS_DATA_METADATA) {
     299                // This is a menu
     300                psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
     301                formatItem = p_pmConceptsDepend(name, formatItem->data.md, transSpec, fpa, chip, cell);
     302                if (!formatItem) {
     303                    continue;
     304                }
     305            }
     306            if (formatItem->type != PS_DATA_STRING) {
     307                psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Type for concept %s in TRANSLATION is not STR",
     308                        name);
     309                psFree(specsIter);
     310                return false;
     311            }
     312            psString keywords = formatItem->data.str; // The FITS keywords
     313
     314            // In case there are multiple headers
     315            psList *keys = psStringSplit(keywords, " ,;", true); // List of keywords
     316            if (keys->n == 1) {
     317                // Only one key --- proceed as usual
     318                if (hduLow->header) {
     319                    headerItem = psMetadataLookup(hduLow->header, keywords);
     320                }
     321                if (!headerItem && hduHigh != hduLow && hduHigh->header) {
     322                    headerItem = psMetadataLookup(hduHigh->header, keywords);
     323                }
     324                psMemIncrRefCounter(headerItem);
     325            } else {
     326                psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator
     327                psString key = NULL; // Item from iteration
     328                psList *values = psListAlloc(NULL); // List containing the values
     329                while ((key = psListGetAndIncrement(keysIter))) {
     330                    psMetadataItem *value = NULL;
    327331                    if (hduLow->header) {
    328                         headerItem = psMetadataLookup(hduLow->header, keywords);
    329                     }
    330                     if (!headerItem && hduHigh != hduLow && hduHigh->header) {
    331                         headerItem = psMetadataLookup(hduHigh->header, keywords);
    332                     }
    333                     psMemIncrRefCounter(headerItem);
    334                 } else {
    335                     psListIterator *keysIter = psListIteratorAlloc(keys, PS_LIST_HEAD, false); // Iterator
    336                     psString key = NULL; // Item from iteration
    337                     psList *values = psListAlloc(NULL); // List containing the values
    338                     while ((key = psListGetAndIncrement(keysIter))) {
    339                         psMetadataItem *value = NULL;
    340                         if (hduLow->header) {
    341                             value = psMetadataLookup(hduLow->header, key);
    342                         }
    343                         if (!value && hduHigh != hduLow && hduHigh->header) {
    344                             value = psMetadataLookup(hduHigh->header, key);
    345                         }
    346                         if (value) {
    347                             psListAdd(values, PS_LIST_TAIL, value);
    348                         } else {
    349                             psWarning("Unable to find header %s --- assuming value is NULL", key);
    350                         }
    351                     }
    352                     psFree(keysIter);
    353                     headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values);
    354                     psFree(values);
    355                 }
    356                 psFree(keys);
    357             }
     332                        value = psMetadataLookup(hduLow->header, key);
     333                    }
     334                    if (!value && hduHigh != hduLow && hduHigh->header) {
     335                        value = psMetadataLookup(hduHigh->header, key);
     336                    }
     337                    if (value) {
     338                        psListAdd(values, PS_LIST_TAIL, value);
     339                    } else {
     340                        psWarning("Unable to find header %s --- assuming value is NULL", key);
     341                    }
     342                }
     343                psFree(keysIter);
     344                headerItem = psMetadataItemAlloc(name, PS_DATA_LIST, specItem->comment, values);
     345                psFree(values);
     346            }
     347            psFree(keys);
    358348        }
    359349
     
    371361    psFree(specsIter);
    372362    return status;
     363}
     364
     365psMetadataItem *p_pmConceptsReadSingleFromDatabase(const char *name, const psMetadata *database, psDB *db,
     366                                                   const pmFPA *fpa, const pmChip *chip, const pmCell *cell)
     367{
     368    PS_ASSERT_STRING_NON_EMPTY(name, NULL);
     369    PS_ASSERT_METADATA_NON_NULL(database, NULL);
     370
     371    psMetadataItem *item = psMetadataLookup(database, name); // Item to return
     372    if (item && item->type == PS_DATA_METADATA) {
     373        // This is a menu
     374        psTrace("psModules.concepts", 5, "%s is of type METADATA.\n", name);
     375        item = p_pmConceptsDepend(name, item->data.md, database, fpa, chip, cell);
     376    }
     377    if (!item) {
     378        return NULL;
     379    }
     380    if (item->type != PS_DATA_STRING) {
     381        psWarning("%s in DATABASE in camera format is not of type STR --- ignored.", name);
     382        return NULL;
     383    }
     384
     385    psString sql = pmConceptsInterpolate(item->data.str, fpa, chip, cell);
     386    if (!p_psDBRunQuery(db, sql)) {
     387        psWarning("Unable to query database for concept %s --- ignored.", name);
     388        psFree(sql);
     389        return NULL;
     390    }
     391    psFree(sql);
     392
     393    psArray *rows = p_psDBFetchResult(db); // Rows returned from the query
     394    if (rows->n == 0) {
     395        psWarning("No rows returned from database query for concept %s --- ignored.", name);
     396        return NULL;
     397    }
     398    if (rows->n > 1) {
     399        psWarning("Multiple rows returned from database query for concept %s --- using the first", name);
     400    }
     401    psMetadata *row = rows->data[0]; // First (and only) row
     402    if (row->list->n > 1) {
     403        psWarning("Multiple columns returned from database query for concept %s --- using the first", name);
     404    }
     405
     406    return psMetadataGet(row, PS_LIST_HEAD); // Item of interest
    373407}
    374408
     
    400434        pmConceptSpec *spec = specItem->data.V; // The specification
    401435        psString name = specItem->name; // The concept name
    402         const char *dbLookup = psMetadataLookupStr(&mdok, dbSpec, name);
    403         if (mdok && dbLookup) {
    404             psString sql = pmConceptsInterpolate(dbLookup, fpa, chip, cell);
    405 
    406             if (!p_psDBRunQuery(db, sql)) {
    407                 psWarning("Unable to query database for concept %s --- ignored.", name);
    408                 psFree(sql);
    409                 continue;
    410             }
    411             psFree(sql);
    412 
    413             psArray *rows = p_psDBFetchResult(db); // Rows returned from the query
    414             if (rows->n == 0) {
    415                 psWarning("No rows returned from database query for concept %s --- ignored.", name);
    416                 continue;
    417             }
    418             if (rows->n > 1) {
    419                 psWarning("Multiple rows returned from database query for concept %s --- using the first",
    420                           name);
    421             }
    422             psMetadata *row = rows->data[0]; // First (and only) row
    423             if (row->list->n > 1) {
    424                 psWarning("Multiple columns returned from database query for concept %s --- using the first",
    425                           name);
    426             }
    427             psMetadataItem *conceptItem = psMetadataGet(row, PS_LIST_HEAD); // Item of interest
    428 
    429             // Now we have the result
    430             if (!conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_DATABASE,
    431                               cameraFormat, target, fpa, chip, cell)) {
    432                 psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from database.\n",
    433                         name);
    434                 status = false;
    435             }
     436        psMetadataItem *conceptItem = p_pmConceptsReadSingleFromDatabase(name, dbSpec, db, fpa, chip, cell);
     437        if (conceptItem && !conceptParse(spec, conceptItem, PM_CONCEPT_SOURCE_DATABASE,
     438                                         cameraFormat, target, fpa, chip, cell)) {
     439            psError(PS_ERR_UNEXPECTED_NULL, false, "Unable to parse concept %s from database.\n", name);
     440            status = false;
    436441        }
    437442    } // Iterating through the concept specifications
Note: See TracChangeset for help on using the changeset viewer.