IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 24, 2010, 2:59:09 PM (16 years ago)
Author:
Paul Price
Message:

Merging trunk in advance of reintegrating into trunk.

Location:
branches/pap
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/pap

  • branches/pap/psLib/src/fits/psFitsTable.c

    r26481 r28484  
    746746    return true;
    747747}
     748
     749
     750psMetadata *psFitsReadTableAllColumns(const psFits *fits)
     751{
     752    PS_ASSERT_FITS_NON_NULL(fits, NULL);
     753
     754    if (!readTableCheck(fits)) {
     755        return NULL;
     756    }
     757
     758    int status = 0;                     // CFITSIO return status
     759
     760    long numRows = 0;                   // Number of rows in table
     761    int numCols = 0;                    // Number of columns in table
     762    fits_get_num_rows(fits->fd, &numRows, &status);
     763    fits_get_num_cols(fits->fd, &numCols, &status);
     764    if (psFitsError(status, true, "Failed to determine the size of the current HDU table.")) {
     765        return NULL;
     766    }
     767
     768    int hdutype;                        // Type of HDU: need to distinguish ASCII and binary tables
     769    fits_get_hdu_type(fits->fd, &hdutype, &status);
     770    if (psFitsError(status, true, "Could not determine the HDU type.")) {
     771        return false;
     772    }
     773
     774    psMetadata *table = psMetadataAlloc();     // Table to return
     775    for (int col = 1; col <= numCols; col++) { // Fortran indexing
     776        char name[FLEN_VALUE];           // Column name
     777        if (hdutype == BINARY_TBL) {
     778            fits_get_bcolparms(fits->fd, col, name,
     779                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
     780        } else {
     781            fits_get_acolparms(fits->fd, col, name,
     782                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
     783        }
     784
     785        int cfitsioType = 0;             // Column type from CFITSIO
     786        long repeat;                     // Number of repeats
     787        fits_get_eqcoltype(fits->fd, col, &cfitsioType, &repeat, NULL, &status);
     788        if (psFitsError(status, true, "Could not determine the column data for %s", name)) {
     789            psFree(table);
     790            return false;
     791        }
     792
     793        psDataType pslibType = p_psFitsTypeFromCfitsio(cfitsioType); // Column type in psLib
     794        if (pslibType == PS_DATA_STRING) {
     795            // Strings
     796            int width;                  // Width of strings
     797            if (fits_get_col_display_width(fits->fd, col, &width, &status) != 0) {
     798                psFitsError(status, true, "Could not determine the width of column %s", name);
     799                psFree(table);
     800                return NULL;
     801            }
     802            psArray *array = psArrayAlloc(numRows); // Array of strings from table
     803            for (int i = 0; i < numRows; i++) {
     804                array->data[i] = psStringAlloc(width);
     805            }
     806            fits_read_col_str(fits->fd, col, 1, 1, numRows, "", (char**)array->data, NULL, &status);
     807            if (psFitsError(status, true, "Failed to read column %s", name)) {
     808                psFree(array);
     809                psFree(table);
     810                return NULL;
     811            }
     812            if (!psMetadataAddArray(table, PS_LIST_TAIL, name, 0, NULL, array)) {
     813                psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
     814                psFree(array);
     815                psFree(table);
     816                return NULL;
     817            }
     818            psFree(array);
     819        } else if (repeat == 1) {
     820            // Single numbers
     821            psVector* vector = psVectorAlloc(numRows, pslibType); // Vector from table
     822            fits_read_col(fits->fd, cfitsioType, col, 1, 1, numRows, NULL,
     823                          vector->data.U8, NULL, &status);
     824            if (psFitsError(status, true, "Failed to read column %s", name)) {
     825                psFree(vector);
     826                psFree(table);
     827                return NULL;
     828            }
     829            if (!psMetadataAddVector(table, PS_LIST_TAIL, name, 0, NULL, vector)) {
     830                psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
     831                psFree(vector);
     832                psFree(table);
     833                return NULL;
     834            }
     835            psFree(vector);
     836        } else  {
     837            // Vectors of numbers
     838            psAssert(pslibType != PS_DATA_STRING, "Vectors of strings not handled");
     839            psImage *image = psImageAlloc(repeat, numRows, pslibType); // Image to store vector of vectors
     840            for (int row = 1, i = 0; row <= numRows; row++, i++) { // Fortran indexing for row
     841                int anynul = 0;         // Any nulls in what was read?
     842                fits_read_col(fits->fd, cfitsioType, col, row, 1, repeat, NULL,
     843                              image->data.U8[i], &anynul, &status);
     844                if (psFitsError(status, true, "Failed to read column %s row %d", name, row)) {
     845                    psFree(image);
     846                    psFree(table);
     847                    return NULL;
     848                }
     849            }
     850            if (!psMetadataAddImage(table, PS_LIST_TAIL, name, 0, NULL, image)) {
     851                psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
     852                psFree(image);
     853                psFree(table);
     854                return NULL;
     855            }
     856            psFree(image);
     857        }
     858    }
     859
     860    return table;
     861}
     862
     863bool psFitsWriteTableAllColumns(psFits *fits, psMetadata *header, const psMetadata *table, const char *extname)
     864{
     865    PS_ASSERT_FITS_NON_NULL(fits, false);
     866    PS_ASSERT_FITS_WRITABLE(fits, false);
     867    PS_ASSERT_METADATA_NON_NULL(table, false);
     868
     869    psArray *columns = psListToArray(table->list); // Columns in psMetadataItems
     870    int numCols = columns->n;                      // Number of columns
     871    long numRows = 0;                              // Number of rows
     872    psArray *names = psArrayAlloc(numCols);        // Column names
     873    psArray *types = psArrayAlloc(numCols);        // Column types
     874
     875    for (int i = 0; i < numCols; i++) {
     876        psMetadataItem *colItem = columns->data[i]; // Column
     877        names->data[i] = psMemIncrRefCounter(colItem->name);
     878
     879        size_t size = 0;                   // Size of column
     880        char tform = 0;                 // Type in character for FITS
     881        long rows = 0;                   // Number of rows
     882        switch (colItem->type) {
     883          case PS_DATA_VECTOR:
     884            size = 1;
     885            psVector *vector = colItem->data.V; // Vector of interest
     886            tform = getTForm(vector->type.type);
     887            rows = vector->n;
     888            break;
     889          case PS_DATA_ARRAY:
     890            tform = getTForm(PS_DATA_STRING);
     891            psArray *array = colItem->data.V; // Array of interest
     892            rows = array->n;
     893            for (int i = 0; i < rows; i++) {
     894                const char *string = array->data[i];
     895                size = PS_MAX(size, strlen(string));
     896            }
     897            break;
     898          case PS_DATA_IMAGE: ;
     899            psImage *image = colItem->data.V; // Image of interest
     900            tform = getTForm(image->type.type);
     901            size = image->numCols;
     902            rows = image->numRows;
     903            break;
     904          default:
     905            psAbort("Unrecognised column type: %x", colItem->type);
     906        }
     907        psString type = NULL;           // Column type
     908        psStringAppend(&type, "%zd%c", size, tform);
     909        types->data[i] = type;
     910        if (i == 0) {
     911            numRows = rows;
     912        } else if (numRows != rows) {
     913            psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Column %d has differing size: %ld vs %ld",
     914                    i, rows, numRows);
     915            psFree(names);
     916            psFree(types);
     917            psFree(columns);
     918            return false;
     919        }
     920    }
     921
     922    // Create the table HDU
     923    int numHDUs = psFitsGetSize(fits);  // Number of HDUs in file
     924    int status = 0;                     // Status from cfitsio
     925    if (numHDUs == 0) {
     926        // We're creating the first extension
     927        fits_create_tbl(fits->fd, BINARY_TBL, numRows, numCols, (char**)names->data, (char**)types->data,
     928                        NULL, NULL, &status);
     929    } else {
     930        fits_insert_btbl(fits->fd, numRows, numCols, (char**)names->data, (char**)types->data,
     931                         NULL, NULL, 0, &status);
     932    }
     933    psFree(names);
     934    psFree(types);
     935    if (psFitsError(status, true, "Unable to create FITS table with %d columns and %ld rows",
     936                    numCols, numRows)) {
     937        psFree(columns);
     938        return false;
     939    }
     940
     941    // Write header
     942    if (header && !psFitsWriteHeader(fits, header)) {
     943        psError(psErrorCodeLast(), false, "Unable to write FITS header.\n");
     944        psFree(columns);
     945        return false;
     946    }
     947    if (extname && strlen(extname) > 0 && !psFitsSetExtName(fits, extname)) {
     948        psError(psErrorCodeLast(), false, "Unable to write FITS header extension name.\n");
     949        psFree(columns);
     950        return false;
     951    }
     952
     953    // cfitsio requires that we write the data by columns --- urgh!
     954    for (long col = 1, i = 0; col <= numCols; col++, i++) {      // Fortran indexing
     955        psMetadataItem *colItem = columns->data[i]; // Column
     956        switch (colItem->type) {
     957          case PS_DATA_VECTOR: {
     958              psVector *vector = colItem->data.V; // Vector
     959              int cfitsioType;                    // Data type for cfitsio
     960              p_psFitsTypeToCfitsio(vector->type.type, NULL, NULL, &cfitsioType);
     961              fits_write_col(fits->fd, cfitsioType, col, 1, 1, numRows, vector->data.U8, &status);
     962              break;
     963          }
     964          case PS_DATA_ARRAY: {
     965              psArray *array = colItem->data.V; // Array of strings
     966              fits_write_col_str(fits->fd, col, 1, 1, numRows, (char**)array->data, &status);
     967              break;
     968          }
     969          case PS_DATA_IMAGE: {
     970              psImage *image = colItem->data.V;                                        // Image of interest
     971              psDataType type = image->type.type;                                      // Type of data
     972              psVector *vector = psVectorAlloc(image->numCols * image->numRows, type); // Vector from image
     973              if (!p_psImageCopyToRawBuffer(vector->data.U8, image, type)) {
     974                  psError(psErrorCodeLast(), false, "Unable to copy image to buffer");
     975                  psFree(columns);
     976                  return false;
     977              }
     978              int cfitsioType;            // Data type for cfitsio
     979              p_psFitsTypeToCfitsio(type, NULL, NULL, &cfitsioType);
     980              fits_write_col(fits->fd, cfitsioType, col, 1, 1, image->numRows * image->numCols,
     981                             vector->data.U8, &status);
     982              break;
     983          }
     984          default:
     985            psAbort("Unrecognised column type: %x", colItem->type);
     986        }
     987        // Check error status from writing column
     988        if (psFitsError(status, true, "Unable to write column %ld of FITS table", col)) {
     989            psFree(columns);
     990            return false;
     991        }
     992    }
     993    psFree(columns);
     994
     995    // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
     996    // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
     997    // hurt.
     998    ffrdef(fits->fd, &status);
     999    if (psFitsError(status, true, "Could not re-scan HDU.")) {
     1000        return false;
     1001    }
     1002
     1003    return true;
     1004}
Note: See TracChangeset for help on using the changeset viewer.