IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Aug 30, 2011, 3:50:05 PM (15 years ago)
Author:
bills
Message:

remove dead code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/fits/psFitsTableNew.c

    r32228 r32229  
    77 *  @author Bill Sweeney IfA
    88 *
    9  *  @version $Revision: 1.33 $ $Name: not supported by cvs2svn $
    10  *  @date $Date: 2008-07-04 03:18:06 $
    119 *
    12  *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     10 *  Copyright 2011 Institute for Astronomy, University of Hawaii
    1311 */
    1412
     
    3331#include "psAssert.h"
    3432
    35 #define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
     33// #define MAX_STRING_LENGTH 256  // maximum length string for FITS routines
    3634
    3735
     
    443441    }
    444442
    445 #ifdef notdef
    446     // Find the unique items in the array of metadata 'rows', and their sizes
    447     psMetadata *colSpecs = psMetadataAlloc(); // Column specifications
    448     size_t rowSize = 0;                 // Size (in bytes) of each row
    449     for (long i = 0; i < numRows; i++) {
    450         psMetadata* row = table->data[i];
    451 
    452         if (!row) {
    453             continue;
    454         }
    455         psMetadataIterator *rowIter = psMetadataIteratorAlloc(row, PS_LIST_HEAD, NULL); // Iterator
    456         psMetadataItem *colItem;        // Column item, from iteration
    457         while ((colItem = psMetadataGetAndIncrement(rowIter))) {
    458             if (!(PS_DATA_IS_PRIMITIVE(colItem->type) || colItem->type == PS_DATA_STRING ||
    459                     colItem->type == PS_DATA_VECTOR)) {
    460                 // unsupported type -- treating as an error
    461                 psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    462                         "Unsupported data type (%d) for Metadata Item '%s' in row %ld.",
    463                         colItem->type, colItem->name, i);
    464                 psFree(rowIter);
    465                 psFree(colSpecs);
    466                 return false;
    467             }
    468 
    469             size_t size = columnSize(colItem); // Size for this column
    470 
    471             // Check to see if we know about this one; or update the size if required
    472             psMetadataItem *colSpecItem = psMetadataLookup(colSpecs, colItem->name);
    473             if (!colSpecItem) {
    474                 // A new one!
    475                 colSpec *spec = psAlloc(sizeof(colSpec)); // Specification for this column
    476                 // BOOL type is not a valid vector type, so we translate it to U8
    477                 spec->type = colItem->type == PS_TYPE_BOOL ? PS_TYPE_U8 : colItem->type;
    478                 spec->size = size;
    479                 if (colItem->type == PS_DATA_VECTOR) {
    480                     psVector *vector = colItem->data.V; // The vector
    481                     spec->vectorType = vector->type.type;
    482                 }
    483                 psMetadataAddPtr(colSpecs, PS_LIST_TAIL, colItem->name, PS_DATA_UNKNOWN, "", spec);
    484                 psFree(spec);           // Drop reference
    485                 rowSize += PSELEMTYPE_SIZEOF(spec->type);
    486             } else {
    487                 colSpec *spec = colSpecItem->data.V; // The specification
    488                 if (size > spec->size) {
    489                     spec->size = size;
    490                 }
    491                 if (colItem->type != spec->type &&
    492                     colItem->type != PS_TYPE_BOOL && spec->type != PS_TYPE_U8) {
    493                     psWarning("Differing type found for column %s: %x vs %x --- using the first found.\n",
    494                               colSpecItem->name, colItem->type, spec->type);
    495                 }
    496                 if (colItem->type == PS_DATA_VECTOR) {
    497                     psVector *vector = colItem->data.V; // The vector
    498                     if (vector->type.type != spec->vectorType) {
    499                         psWarning("Differing vector type found for column %s: %x vs %x "
    500                                  "--- using the first found.\n", colSpecItem->name, vector->type.type,
    501                                  spec->vectorType);
    502                     }
    503                 }
    504             }
    505         }
    506         psFree(rowIter);
    507     }
    508 
    509     long numColumns = colSpecs->list->n;// Number of columns
    510     if (numColumns == 0) {
    511         // No table columns found
    512         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    513                 "Did not find any column data to write to a table.");
    514         psFree(colSpecs);
    515         return false;
    516     }
    517 #endif // notdef end of OLD column spec determination
    518 
    519443    // Create array of column names and types.
    520444    psArray *columnNames = psArrayAlloc(table->numCols); // Array of column names, for cfitsio
     
    597521            // colSpec *spec = colSpecItem->data.V; // The specification
    598522            if (PS_DATA_IS_PRIMITIVE(column->type)) {
    599 #ifdef notdef
    600                 size_t dataSize = PSELEMTYPE_SIZEOF(column->type); // Size (in bytes) of this type
    601                 psVector *columnData = psVectorAlloc(table->n, column->type); // The raw row data, to be written
    602                 psVectorInit(columnData, 0);
    603                 for (long i = 0; i < table->numRows; i++) {
    604                     psMetadata *row = table->data[i]; // The row of interest
    605                     psMetadataItem *dataItem = psMetadataLookup(row, colSpecItem->name); // Value of interest
    606                     if (dataItem) {
    607                         memcpy(&columnData->data.U8[i * dataSize], &dataItem->data, dataSize);
    608                     } else {
    609                         // this element is missing from this row; insert an appropriate-sized place holder
    610                         // XXX this should insert a NAN for float / double and an appropriate blank for int types
    611                         // XXX for the moment I am putting in 0.0
    612                         memset(&columnData->data.U8[i * dataSize], 0, dataSize);
    613                     }
    614                 }
    615 #endif
    616 
    617523                int fitsDataType;           // Data type for cfitsio
    618524                p_psFitsTypeToCfitsio(column->type, NULL, NULL, &fitsDataType);
     
    629535                switch (column->type) {
    630536                  case PS_DATA_STRING: {
    631 #ifdef notdef
    632                       psArray *strings = psArrayAlloc(table->n); // Array of strings
    633                       for (long i = 0; i < table->n; i++) {
    634                           psMetadata *row = table->data[i]; // The row of interest
    635                           strings->data[i] = psMemIncrRefCounter(psMetadataLookupStr(NULL, row,
    636                                                                                      colSpecItem->name));
    637                       }
    638                       fits_write_col_str(fits->fd, colNum, 1, 1, table->n, (char**)strings->data, &status);
    639 #endif
    640537                      fits_write_col_str(fits->fd, colNum, 1, 1, table->numRows, (char**)column->data.str, &status);
    641538                      // psFree(strings);
     
    647544                      psVectorInit(columnData, 0);
    648545                      for (long i = 0; i < table->numRows; i++) {
    649 #ifdef notdef
    650                           psMetadata *row = table->data[i]; // The row of interest
    651                           psMetadataItem* dataItem = psMetadataLookup(row, colSpecItem->name);
    652                           if (dataItem->type != PS_DATA_VECTOR) {
    653                               // Just in case --- get a zero instead of some weird result
    654                               continue;
    655                           }
    656                           psVector *vector = dataItem->data.V;
    657 #endif
    658546                          psVector *vector = column->data.vec[i];
    659547                          memcpy(&columnData->data.U8[i * dataSize * column->elementSize], vector->data.U8,
     
    692580}
    693581
    694 // END OF new insert table
    695 
    696582bool psFitsWriteTableNew(psFits* fits,
    697583                      const psMetadata* header,
     
    708594    return fitsInsertTableNew(fits, header, table, extname, true, writeData);
    709595}
    710 
    711 #ifdef notdef
    712 
    713 psArray* psFitsReadTableColumn(const psFits* fits,
    714                                const char* colname)
    715 {
    716     PS_ASSERT_FITS_NON_NULL(fits, NULL);
    717     PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
    718 
    719     if (!readTableCheck(fits)) {
    720         if (emptyTableCheck(fits)) {
    721             return psArrayAlloc(0);
    722         }
    723         psError(PS_ERR_BAD_FITS, true, "Extension is not a table");
    724         return NULL;
    725     }
    726 
    727     int colnum = 0;
    728     int status = 0;
    729 
    730     // find the column by name
    731     if (fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
    732         psFitsError(status, true, "Specified column, %s, was not found.", colname);
    733         return NULL;
    734     }
    735 
    736     // get the number of rows
    737     long numRows = psFitsTableSize(fits);
    738     if (numRows == -1) {
    739         return NULL;
    740     }
    741 
    742     // get the column length.
    743     int width;
    744     if (fits_get_col_display_width(fits->fd, colnum, &width, &status) != 0) {
    745         psFitsError(status, true, "Could not determine the datatype of the table column.");
    746         return NULL;
    747     }
    748 
    749     // allocate the buffers
    750     psArray* result = psArrayAlloc(numRows);
    751     for (int row = 0; row < numRows; row++) {
    752         result->data[row] = psStringAlloc(width);
    753     }
    754 
    755     fits_read_col_str(fits->fd, colnum, 1, 1, numRows, "", (char**)result->data, NULL, &status);
    756     if (psFitsError(status, true, "Failed to read table column.")) {
    757         psFree(result);
    758         return NULL;
    759     }
    760 
    761     return result;
    762 }
    763 
    764 psVector* psFitsReadTableColumnNum(const psFits* fits,
    765                                    const char* colname)
    766 {
    767     PS_ASSERT_FITS_NON_NULL(fits, NULL);
    768     PS_ASSERT_STRING_NON_EMPTY(colname, NULL);
    769 
    770     if (!readTableCheck(fits)) {
    771         psError(PS_ERR_BAD_FITS, true, "Extension is not a table");
    772         return NULL;
    773     }
    774 
    775     int status = 0;
    776     int colnum = 0;
    777 
    778     // find the column by name
    779     if (fits_get_colnum(fits->fd, CASESEN, (char*)colname, &colnum, &status) != 0) {
    780         psFitsError(status, true, "Specified column, %s, was not found.", colname);
    781         return NULL;
    782     }
    783 
    784     // get the number of rows
    785     long numRows = psFitsTableSize(fits);
    786     if (numRows == -1) {
    787         return NULL;
    788     }
    789 
    790     // get the column datatype.
    791     int typecode;
    792     long repeat;
    793     long width;
    794     if (fits_get_eqcoltype(fits->fd, colnum, &typecode, &repeat, &width, &status) != 0) {
    795         psFitsError(status, true, "Could not determine the datatype of the table column.");
    796         return NULL;
    797     }
    798 
    799     psVector* result = psVectorAlloc(numRows, p_psFitsTypeFromCfitsio(typecode));
    800 
    801     fits_read_col(fits->fd, typecode, colnum, 1, 1, numRows, NULL, (psPtr)(result->data.U8), NULL, &status);
    802     if (psFitsError(status, true, "Failed to read table column.")) {
    803         psFree(result);
    804         return NULL;
    805     }
    806 
    807     return result;
    808 }
    809 
    810 
    811 psArray* psFitsReadTable(const psFits* fits)
    812 {
    813     PS_ASSERT_FITS_NON_NULL(fits, NULL);
    814 
    815     if (!readTableCheck(fits)) {
    816         if (emptyTableCheck(fits)) {
    817             return psArrayAlloc(0);
    818         }
    819         psError(PS_ERR_BAD_FITS, true, "Extension is not a table");
    820         return NULL;
    821     }
    822 
    823     // get the number of rows
    824     long numRows = psFitsTableSize(fits);
    825     if (numRows == -1) {
    826         return NULL;
    827     }
    828 
    829     psArray* table = psArrayAlloc(numRows);
    830 
    831     for (int row = 0; row < numRows; row++) {
    832         psTrace("psLib.fits",5,"Reading row %i of %li\n", row, numRows);
    833         table->data[row] = psFitsReadTableRow(fits,row);
    834     }
    835 
    836     return table;
    837 }
    838 
    839 bool psFitsWriteTable(psFits* fits,
    840                       const psMetadata* header,
    841                       const psArray* table,
    842                       const char *extname)
    843 {
    844     PS_ASSERT_FITS_NON_NULL(fits, false);
    845     PS_ASSERT_FITS_WRITABLE(fits, false);
    846     if (!psFitsMoveLast(fits)) {
    847         psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table");
    848         return false;
    849     }
    850     return psFitsInsertTable(fits, header, table, extname, true);
    851 }
    852 
    853 
    854 // Return the size of the column
    855 static inline size_t columnSize(const psMetadataItem *item // Item for which to get the size
    856                                )
    857 {
    858     if (PS_DATA_IS_PRIMITIVE(item->type)) {
    859         return 1;
    860     }
    861     switch (item->type) {
    862     case PS_DATA_STRING:
    863         return strlen(item->data.V);
    864     case PS_DATA_VECTOR: {
    865             psVector *vector = item->data.V;
    866             return vector ? vector->n : 0;
    867         }
    868     default:
    869         psAbort("Shouldn't ever get here.");
    870     }
    871     return 0;
    872 }
    873 
    874 // Get the TFORM character, given a PS type
    875 static inline char getTForm(psDataType type)
    876 {
    877     switch (type) {
    878     case PS_TYPE_U8:
    879     case PS_TYPE_S8:
    880         return 'B';
    881     case PS_TYPE_S16:
    882         return 'I';
    883     case PS_TYPE_S32:
    884         return 'J';
    885     case PS_TYPE_U64:
    886     case PS_TYPE_S64:
    887         return 'K';
    888     case PS_TYPE_U16:
    889         return 'U';
    890     case PS_TYPE_U32:
    891         return 'V';
    892     case PS_TYPE_F32:
    893         return 'E';
    894     case PS_TYPE_F64:
    895         return 'D';
    896     case PS_TYPE_BOOL:
    897         return 'L';
    898     case PS_DATA_STRING:
    899         return 'A';
    900     default:
    901         psError(PS_ERR_UNKNOWN, true, "Unknown type: %x\n", type);
    902         return '?';
    903     }
    904 }
    905 
    906 
    907 // Column specification
    908 // Included here, because there's no need for the user to have access to it
    909 typedef struct {
    910     psDataType type;                    // psLib type (e.g., PS_DATA_STRING or PS_TYPE_F32)
    911     size_t size;                        // Size (number of repeats)
    912     psElemType vectorType;              // psLib type of vectors
    913 } colSpec;
    914 
    915 
    916 static bool fitsInsertTable(psFits* fits,             // FITS file
    917                             const psMetadata* header, // FITS header to write
    918                             const psArray* table,     // Table to write
    919                             const char *extname,      // Extension name to give table
    920                             bool after,               // Write table after current extension?
    921                             bool writeData            // Write data?
    922                             )
    923 {
    924     PS_ASSERT_FITS_NON_NULL(fits, false);
    925     PS_ASSERT_FITS_WRITABLE(fits, false);
    926     PS_ASSERT_ARRAY_NON_NULL(table, false);
    927 
    928     int status = 0;
    929 
    930     long numRows = table->n;
    931     if (writeData && numRows < 1) {
    932         // no table data, what can I do?
    933         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    934                 _("Can't create a table without any rows."));
    935         return false;
    936     }
    937 
    938     // Find the unique items in the array of metadata 'rows', and their sizes
    939     psMetadata *colSpecs = psMetadataAlloc(); // Column specifications
    940     size_t rowSize = 0;                 // Size (in bytes) of each row
    941     for (long i = 0; i < numRows; i++) {
    942         psMetadata* row = table->data[i];
    943         if (!row) {
    944             continue;
    945         }
    946         psMetadataIterator *rowIter = psMetadataIteratorAlloc(row, PS_LIST_HEAD, NULL); // Iterator
    947         psMetadataItem *colItem;        // Column item, from iteration
    948         while ((colItem = psMetadataGetAndIncrement(rowIter))) {
    949             if (!(PS_DATA_IS_PRIMITIVE(colItem->type) || colItem->type == PS_DATA_STRING ||
    950                     colItem->type == PS_DATA_VECTOR)) {
    951                 // unsupported type -- treating as an error
    952                 psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    953                         "Unsupported data type (%d) for Metadata Item '%s' in row %ld.",
    954                         colItem->type, colItem->name, i);
    955                 psFree(rowIter);
    956                 psFree(colSpecs);
    957                 return false;
    958             }
    959 
    960             size_t size = columnSize(colItem); // Size for this column
    961 
    962             // Check to see if we know about this one; or update the size if required
    963             psMetadataItem *colSpecItem = psMetadataLookup(colSpecs, colItem->name);
    964             if (!colSpecItem) {
    965                 // A new one!
    966                 colSpec *spec = psAlloc(sizeof(colSpec)); // Specification for this column
    967                 // BOOL type is not a valid vector type, so we translate it to U8
    968                 spec->type = colItem->type == PS_TYPE_BOOL ? PS_TYPE_U8 : colItem->type;
    969                 spec->size = size;
    970                 if (colItem->type == PS_DATA_VECTOR) {
    971                     psVector *vector = colItem->data.V; // The vector
    972                     spec->vectorType = vector->type.type;
    973                 }
    974                 psMetadataAddPtr(colSpecs, PS_LIST_TAIL, colItem->name, PS_DATA_UNKNOWN, "", spec);
    975                 psFree(spec);           // Drop reference
    976                 rowSize += PSELEMTYPE_SIZEOF(spec->type);
    977             } else {
    978                 colSpec *spec = colSpecItem->data.V; // The specification
    979                 if (size > spec->size) {
    980                     spec->size = size;
    981                 }
    982                 if (colItem->type != spec->type &&
    983                     colItem->type != PS_TYPE_BOOL && spec->type != PS_TYPE_U8) {
    984                     psWarning("Differing type found for column %s: %x vs %x --- using the first found.\n",
    985                               colSpecItem->name, colItem->type, spec->type);
    986                 }
    987                 if (colItem->type == PS_DATA_VECTOR) {
    988                     psVector *vector = colItem->data.V; // The vector
    989                     if (vector->type.type != spec->vectorType) {
    990                         psWarning("Differing vector type found for column %s: %x vs %x "
    991                                  "--- using the first found.\n", colSpecItem->name, vector->type.type,
    992                                  spec->vectorType);
    993                     }
    994                 }
    995             }
    996         }
    997         psFree(rowIter);
    998     }
    999 
    1000     long numColumns = colSpecs->list->n;// Number of columns
    1001     if (numColumns == 0) {
    1002         // No table columns found
    1003         psError(PS_ERR_BAD_PARAMETER_SIZE, true,
    1004                 "Did not find any column data to write to a table.");
    1005         psFree(colSpecs);
    1006         return false;
    1007     }
    1008 
    1009     // Create array of column names and types.
    1010     psArray *columnNames = psArrayAlloc(numColumns); // Array of column names, for cfitsio
    1011     psArray *columnTypes = psArrayAlloc(numColumns); // Array of column types, for cfitsio
    1012     psMetadataIterator *colSpecsIter = psMetadataIteratorAlloc(colSpecs, PS_LIST_HEAD, NULL); // Iterator
    1013     psMetadataItem *colSpecItem;        // Column specification item, from iteration
    1014     for (long i = 0; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); i++) {
    1015         colSpec *spec = colSpecItem->data.V; // The specification
    1016         columnNames->data[i] = psMemIncrRefCounter(colSpecItem->name);
    1017         psString colType = NULL;        // The column type
    1018         if (spec->type == PS_DATA_VECTOR) {
    1019             psStringAppend(&colType, "%zd%c", spec->size, getTForm(spec->vectorType));
    1020         } else {
    1021             psStringAppend(&colType, "%zd%c", spec->size, getTForm(spec->type));
    1022         }
    1023         columnTypes->data[i] = colType;
    1024     }
    1025 
    1026     // Create the table HDU
    1027     int numHDUs = psFitsGetSize(fits);  // Number of HDUs in file
    1028     if (numHDUs == 0) {
    1029         // We're creating the first extension
    1030         fits_create_tbl(fits->fd,
    1031                         BINARY_TBL,
    1032                         writeData ? numRows : 0, // number of rows in table
    1033                         numColumns, // number of columns in table
    1034                         (char**)columnNames->data, // names of the columns
    1035                         (char**)columnTypes->data, // format of the columns
    1036                         NULL, // physical unit of columns
    1037                         NULL, // skip extension name: we set the by hand below
    1038                         &status);
    1039     } else {
    1040         if (!after) {
    1041             if (psFitsGetExtNum(fits) == 0) {
    1042                 // We're creating a replacement primary HDU.
    1043                 // Set status to signal fits_insert_img to insert a new primary HDU
    1044                 status = PREPEND_PRIMARY;
    1045             } else {
    1046                 // Move back one to perform an insert after the previous HDU
    1047                 psFitsMoveExtNum(fits, -1, true);
    1048             }
    1049         }
    1050         // Insert the table
    1051         fits_insert_btbl(fits->fd,
    1052                          writeData ? numRows : 0, // number of rows in table
    1053                          numColumns, // number of columns in table
    1054                          (char**)columnNames->data, // names of the columns
    1055                          (char**)columnTypes->data, // format of the columns
    1056                          NULL, // physical unit of columns
    1057                          NULL, // skip extension name: we set this by hand below
    1058                          0, &status);
    1059     }
    1060     psFree(columnNames);
    1061     psFree(columnTypes);
    1062 
    1063     if (status != 0) {
    1064         psFitsError(status, true, "Unable to create FITS table with %ld columns and %ld rows",
    1065                     numColumns, table->n);
    1066         psFree(colSpecsIter);
    1067         psFree(colSpecs);
    1068         return false;
    1069     }
    1070 
    1071     // Write header
    1072     if (header && !psFitsWriteHeader(fits, header)) {
    1073         psError(PS_ERR_IO, false, "Unable to write FITS header.\n");
    1074         psFree(colSpecsIter);
    1075         psFree(colSpecs);
    1076         return false;
    1077     }
    1078 
    1079     // write the header, if any.
    1080     if (extname && strlen(extname) > 0) {
    1081         if (!psFitsSetExtName(fits, extname)) {
    1082             psError(PS_ERR_IO, false, "Unable to write FITS header extension name.\n");
    1083             psFree(colSpecsIter);
    1084             psFree(colSpecs);
    1085             return false;
    1086         }
    1087     }
    1088 
    1089     // cfitsio requires that we write the data by columns --- urgh!
    1090     if (writeData) {
    1091         psMetadataIteratorSet(colSpecsIter, PS_LIST_HEAD);
    1092         for (long colNum = 1; (colSpecItem = psMetadataGetAndIncrement(colSpecsIter)); colNum++) {
    1093             // Note: colNum is unit-indexed, because it's for cfitsio
    1094             colSpec *spec = colSpecItem->data.V; // The specification
    1095             if (PS_DATA_IS_PRIMITIVE(spec->type)) {
    1096                 size_t dataSize = PSELEMTYPE_SIZEOF(spec->type); // Size (in bytes) of this type
    1097                 psVector *columnData = psVectorAlloc(table->n, spec->type); // The raw row data, to be written
    1098                 psVectorInit(columnData, 0);
    1099                 for (long i = 0; i < table->n; i++) {
    1100                     psMetadata *row = table->data[i]; // The row of interest
    1101                     psMetadataItem *dataItem = psMetadataLookup(row, colSpecItem->name); // Value of interest
    1102                     if (dataItem) {
    1103                         memcpy(&columnData->data.U8[i * dataSize], &dataItem->data, dataSize);
    1104                     } else {
    1105                         // this element is missing from this row; insert an appropriate-sized place holder
    1106                         // XXX this should insert a NAN for float / double and an appropriate blank for int types
    1107                         // XXX for the moment I am putting in 0.0
    1108                         memset(&columnData->data.U8[i * dataSize], 0, dataSize);
    1109                     }
    1110                 }
    1111 
    1112                 int fitsDataType;           // Data type for cfitsio
    1113                 p_psFitsTypeToCfitsio(spec->type, NULL, NULL, &fitsDataType);
    1114                 fits_write_col(fits->fd,
    1115                                fitsDataType,
    1116                                colNum, // column number
    1117                                1, // first row
    1118                                1, // first element
    1119                                table->n, // number of rows
    1120                                columnData->data.U8, // the data
    1121                                &status);
    1122                 psFree(columnData);
    1123             } else {
    1124                 switch (spec->type) {
    1125                   case PS_DATA_STRING: {
    1126                       psArray *strings = psArrayAlloc(table->n); // Array of strings
    1127                       for (long i = 0; i < table->n; i++) {
    1128                           psMetadata *row = table->data[i]; // The row of interest
    1129                           strings->data[i] = psMemIncrRefCounter(psMetadataLookupStr(NULL, row,
    1130                                                                                      colSpecItem->name));
    1131                       }
    1132                       fits_write_col_str(fits->fd, colNum, 1, 1, table->n, (char**)strings->data, &status);
    1133                       psFree(strings);
    1134                       break;
    1135                   }
    1136                   case PS_DATA_VECTOR: {
    1137                       size_t dataSize = PSELEMTYPE_SIZEOF(spec->vectorType); // Size of data, in bytes
    1138                       psVector *columnData = psVectorAlloc(spec->size * table->n * dataSize, PS_TYPE_U8);
    1139                       psVectorInit(columnData, 0);
    1140                       for (long i = 0; i < table->n; i++) {
    1141                           psMetadata *row = table->data[i]; // The row of interest
    1142                           psMetadataItem* dataItem = psMetadataLookup(row, colSpecItem->name);
    1143                           if (dataItem->type != PS_DATA_VECTOR) {
    1144                               // Just in case --- get a zero instead of some weird result
    1145                               continue;
    1146                           }
    1147                           psVector *vector = dataItem->data.V;
    1148                           memcpy(&columnData->data.U8[i * dataSize * spec->size], vector->data.U8,
    1149                                  vector->n * dataSize);
    1150                       }
    1151 
    1152                       int fitsDataType;           // Data type for cfitsio
    1153                       p_psFitsTypeToCfitsio(spec->vectorType, NULL, NULL, &fitsDataType);
    1154                       fits_write_col(fits->fd, fitsDataType, colNum, 1, 1, table->n * spec->size,
    1155                                      columnData->data.U8, &status);
    1156                       psFree(columnData);
    1157                       break;
    1158                   }
    1159                   default:
    1160                     psAbort("Should never get here.\n");
    1161                 }
    1162             }
    1163 
    1164             // Check error status from writing column
    1165             if (status != 0) {
    1166                 psFitsError(status, true, "Unable to write column %ld of FITS table", colNum);
    1167                 psFree(colSpecsIter);
    1168                 psFree(colSpecs);
    1169                 return false;
    1170             }
    1171         }
    1172     }
    1173 
    1174     psFree(colSpecsIter);
    1175     psFree(colSpecs);
    1176 
    1177     // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
    1178     // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
    1179     // hurt.
    1180     ffrdef(fits->fd, &status);
    1181     if (psFitsError(status, true, "Could not re-scan HDU.")) {
    1182         return false;
    1183     }
    1184 
    1185     return true;
    1186 }
    1187 
    1188 
    1189 bool psFitsInsertTable(psFits* fits, const psMetadata* header, const psArray* table, const char *extname,
    1190                        bool after)
    1191 {
    1192     PS_ASSERT_FITS_NON_NULL(fits, false);
    1193     PS_ASSERT_FITS_WRITABLE(fits, false);
    1194     return fitsInsertTable(fits, header, table, extname, after, true);
    1195 }
    1196 
    1197 bool psFitsWriteTableEmpty(psFits *fits, const psMetadata *header, const psMetadata *columns,
    1198                            const char *extname)
    1199 {
    1200     PS_ASSERT_FITS_NON_NULL(fits, false);
    1201     PS_ASSERT_FITS_WRITABLE(fits, false);
    1202     if (!psFitsMoveLast(fits)) {
    1203         psError(PS_ERR_UNKNOWN, false, "Unable to move to last extension to write table");
    1204         return false;
    1205     }
    1206     psArray *table = psArrayAlloc(1);   // Dummy table carrying column definitions
    1207     table->data[0] = psMemIncrRefCounter((psPtr)columns); // Casting away const
    1208     bool status = fitsInsertTable(fits, header, table, extname, true, false); // Status of insertion
    1209     psFree(table);
    1210     return status;
    1211 }
    1212 
    1213 bool psFitsInsertTableEmpty(psFits *fits, const psMetadata *header, const psMetadata *columns,
    1214                             const char *extname, bool after)
    1215 {
    1216     PS_ASSERT_FITS_NON_NULL(fits, false);
    1217     PS_ASSERT_FITS_WRITABLE(fits, false);
    1218     psArray *table = psArrayAlloc(1);   // Dummy table carrying column definitions
    1219     table->data[0] = psMemIncrRefCounter((psPtr)columns); // Casting away const
    1220     bool status = fitsInsertTable(fits, header, table, extname, after, false); // Status of insertion
    1221     psFree(table);
    1222     return status;
    1223 }
    1224 
    1225 
    1226 bool psFitsUpdateTable(psFits* fits,
    1227                        const psMetadata* data,
    1228                        int row)
    1229 {
    1230     PS_ASSERT_FITS_NON_NULL(fits, false);
    1231     PS_ASSERT_FITS_WRITABLE(fits, false);
    1232     PS_ASSERT_METADATA_NON_NULL(data, false);
    1233     PS_ASSERT_INT_NONNEGATIVE(row, false);
    1234 
    1235     if (!readTableCheck(fits)) {
    1236         psError(PS_ERR_BAD_FITS, true, "Extension is not a table");
    1237         return NULL;
    1238     }
    1239 
    1240     int status = 0;
    1241     psMetadataIterator* iter = psMetadataIteratorAlloc((psPtr)data, PS_LIST_HEAD, NULL);
    1242     psMetadataItem* item;
    1243     while ( (item=psMetadataGetAndIncrement(iter)) != NULL) {
    1244         if (PS_DATA_IS_PRIMITIVE(item->type) ||
    1245                 item->type == PS_DATA_BOOL ||
    1246                 item->type == PS_DATA_STRING) {
    1247             // operating on primitive data type or string, i.e., not a complex object
    1248             int colnum = 0;
    1249 
    1250             if (fits_get_colnum(fits->fd, CASESEN, item->name, &colnum, &status) == 0) {
    1251                 // cooresponding column found in table
    1252                 int dataType;
    1253                 p_psFitsTypeToCfitsio(item->type, NULL, NULL, &dataType);
    1254 
    1255                 if (fits_write_col(fits->fd, dataType, colnum, row+1, 1, 1, &item->data, &status) != 0) {
    1256                     psFitsError(status, true, "Could not write data to file.");
    1257                     psFree(iter);
    1258                     return false;
    1259                 }
    1260             } else {
    1261                 // the column was not found.
    1262                 psWarning("No column with the name '%s' exists in the table.", item->name);
    1263             }
    1264         }
    1265     }
    1266 
    1267     psFree(iter);
    1268 
    1269     // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
    1270     // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
    1271     // hurt.
    1272     ffrdef(fits->fd, &status);
    1273     if (psFitsError(status, true, "Could not re-scan HDU.")) {
    1274         return false;
    1275     }
    1276 
    1277     return true;
    1278 }
    1279 
    1280 
    1281 psMetadata *psFitsReadTableAllColumns(const psFits *fits)
    1282 {
    1283     PS_ASSERT_FITS_NON_NULL(fits, NULL);
    1284 
    1285     if (!readTableCheck(fits)) {
    1286         if (emptyTableCheck(fits)) {
    1287             return psMetadataAlloc();
    1288         }
    1289         psError(PS_ERR_BAD_FITS, true, "Extension is not a table");
    1290         return NULL;
    1291     }
    1292 
    1293     int status = 0;                     // CFITSIO return status
    1294 
    1295     long numRows = 0;                   // Number of rows in table
    1296     int numCols = 0;                    // Number of columns in table
    1297     fits_get_num_rows(fits->fd, &numRows, &status);
    1298     fits_get_num_cols(fits->fd, &numCols, &status);
    1299     if (status) {
    1300         psFitsError(status, true, "Failed to determine the size of the current HDU table.");
    1301         return NULL;
    1302     }
    1303 
    1304     int hdutype;                        // Type of HDU: need to distinguish ASCII and binary tables
    1305     fits_get_hdu_type(fits->fd, &hdutype, &status);
    1306     if (status) {
    1307         psFitsError(status, true, "Could not determine the HDU type.");
    1308         return false;
    1309     }
    1310 
    1311     psMetadata *table = psMetadataAlloc();     // Table to return
    1312     for (int col = 1; col <= numCols; col++) { // Fortran indexing
    1313         char name[FLEN_VALUE];           // Column name
    1314         if (hdutype == BINARY_TBL) {
    1315             fits_get_bcolparms(fits->fd, col, name,
    1316                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
    1317         } else {
    1318             fits_get_acolparms(fits->fd, col, name,
    1319                                NULL, NULL, NULL, NULL, NULL, NULL, NULL, &status);
    1320         }
    1321 
    1322         int cfitsioType = 0;             // Column type from CFITSIO
    1323         long repeat;                     // Number of repeats
    1324         fits_get_eqcoltype(fits->fd, col, &cfitsioType, &repeat, NULL, &status);
    1325         if (status) {
    1326             psFitsError(status, true, "Could not determine the column data for %s", name);
    1327             psFree(table);
    1328             return false;
    1329         }
    1330 
    1331         psDataType pslibType = p_psFitsTypeFromCfitsio(cfitsioType); // Column type in psLib
    1332         if (pslibType == PS_DATA_STRING) {
    1333             // Strings
    1334             int width;                  // Width of strings
    1335             if (fits_get_col_display_width(fits->fd, col, &width, &status) != 0) {
    1336                 psFitsError(status, true, "Could not determine the width of column %s", name);
    1337                 psFree(table);
    1338                 return NULL;
    1339             }
    1340             psArray *array = psArrayAlloc(numRows); // Array of strings from table
    1341             for (int i = 0; i < numRows; i++) {
    1342                 array->data[i] = psStringAlloc(width);
    1343             }
    1344             fits_read_col_str(fits->fd, col, 1, 1, numRows, "", (char**)array->data, NULL, &status);
    1345             if (status) {
    1346                 psFitsError(status, true, "Failed to read column %s", name);
    1347                 psFree(array);
    1348                 psFree(table);
    1349                 return NULL;
    1350             }
    1351             if (!psMetadataAddArray(table, PS_LIST_TAIL, name, 0, NULL, array)) {
    1352                 psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
    1353                 psFree(array);
    1354                 psFree(table);
    1355                 return NULL;
    1356             }
    1357             psFree(array);
    1358         } else if (repeat == 1) {
    1359             // Single numbers
    1360             psVector* vector = psVectorAlloc(numRows, pslibType); // Vector from table
    1361             fits_read_col(fits->fd, cfitsioType, col, 1, 1, numRows, NULL,
    1362                           vector->data.U8, NULL, &status);
    1363             if (status) {
    1364                 psFitsError(status, true, "Failed to read column %s", name);
    1365                 psFree(vector);
    1366                 psFree(table);
    1367                 return NULL;
    1368             }
    1369             if (!psMetadataAddVector(table, PS_LIST_TAIL, name, 0, NULL, vector)) {
    1370                 psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
    1371                 psFree(vector);
    1372                 psFree(table);
    1373                 return NULL;
    1374             }
    1375             psFree(vector);
    1376         } else  {
    1377             // Vectors of numbers
    1378             psAssert(pslibType != PS_DATA_STRING, "Vectors of strings not handled");
    1379             psImage *image = psImageAlloc(repeat, numRows, pslibType); // Image to store vector of vectors
    1380             for (int row = 1, i = 0; row <= numRows; row++, i++) { // Fortran indexing for row
    1381                 int anynul = 0;         // Any nulls in what was read?
    1382                 fits_read_col(fits->fd, cfitsioType, col, row, 1, repeat, NULL,
    1383                               image->data.U8[i], &anynul, &status);
    1384                 if (psFitsError(status, true, "Failed to read column %s row %d", name, row)) {
    1385                     psFree(image);
    1386                     psFree(table);
    1387                     return NULL;
    1388                 }
    1389             }
    1390             if (!psMetadataAddImage(table, PS_LIST_TAIL, name, 0, NULL, image)) {
    1391                 psError(PS_ERR_BAD_FITS, false, "Unable to add column %s to table", name);
    1392                 psFree(image);
    1393                 psFree(table);
    1394                 return NULL;
    1395             }
    1396             psFree(image);
    1397         }
    1398     }
    1399 
    1400     return table;
    1401 }
    1402 
    1403 bool psFitsWriteTableAllColumns(psFits *fits, psMetadata *header, const psMetadata *table, const char *extname)
    1404 {
    1405     PS_ASSERT_FITS_NON_NULL(fits, false);
    1406     PS_ASSERT_FITS_WRITABLE(fits, false);
    1407     PS_ASSERT_METADATA_NON_NULL(table, false);
    1408 
    1409     psArray *columns = psListToArray(table->list); // Columns in psMetadataItems
    1410     int numCols = columns->n;                      // Number of columns
    1411     long numRows = 0;                              // Number of rows
    1412     psArray *names = psArrayAlloc(numCols);        // Column names
    1413     psArray *types = psArrayAlloc(numCols);        // Column types
    1414 
    1415     for (int i = 0; i < numCols; i++) {
    1416         psMetadataItem *colItem = columns->data[i]; // Column
    1417         names->data[i] = psMemIncrRefCounter(colItem->name);
    1418 
    1419         size_t size = 0;                   // Size of column
    1420         char tform = 0;                 // Type in character for FITS
    1421         long rows = 0;                   // Number of rows
    1422         switch (colItem->type) {
    1423           case PS_DATA_VECTOR:
    1424             size = 1;
    1425             psVector *vector = colItem->data.V; // Vector of interest
    1426             tform = getTForm(vector->type.type);
    1427             rows = vector->n;
    1428             break;
    1429           case PS_DATA_ARRAY:
    1430             tform = getTForm(PS_DATA_STRING);
    1431             psArray *array = colItem->data.V; // Array of interest
    1432             rows = array->n;
    1433             for (int i = 0; i < rows; i++) {
    1434                 const char *string = array->data[i];
    1435                 size = PS_MAX(size, strlen(string));
    1436             }
    1437             break;
    1438           case PS_DATA_IMAGE: ;
    1439             psImage *image = colItem->data.V; // Image of interest
    1440             tform = getTForm(image->type.type);
    1441             size = image->numCols;
    1442             rows = image->numRows;
    1443             break;
    1444           default:
    1445             psAbort("Unrecognised column type: %x", colItem->type);
    1446         }
    1447         psString type = NULL;           // Column type
    1448         psStringAppend(&type, "%zd%c", size, tform);
    1449         types->data[i] = type;
    1450         if (i == 0) {
    1451             numRows = rows;
    1452         } else if (numRows != rows) {
    1453             psError(PS_ERR_BAD_PARAMETER_SIZE, true, "Column %d has differing size: %ld vs %ld",
    1454                     i, rows, numRows);
    1455             psFree(names);
    1456             psFree(types);
    1457             psFree(columns);
    1458             return false;
    1459         }
    1460     }
    1461 
    1462     // Create the table HDU
    1463     int numHDUs = psFitsGetSize(fits);  // Number of HDUs in file
    1464     int status = 0;                     // Status from cfitsio
    1465     if (numHDUs == 0) {
    1466         // We're creating the first extension
    1467         fits_create_tbl(fits->fd, BINARY_TBL, numRows, numCols, (char**)names->data, (char**)types->data,
    1468                         NULL, NULL, &status);
    1469     } else {
    1470         fits_insert_btbl(fits->fd, numRows, numCols, (char**)names->data, (char**)types->data,
    1471                          NULL, NULL, 0, &status);
    1472     }
    1473     psFree(names);
    1474     psFree(types);
    1475     if (status) {
    1476         psFitsError(status, true, "Unable to create FITS table with %d columns and %ld rows",
    1477                     numCols, numRows);
    1478         psFree(columns);
    1479         return false;
    1480     }
    1481 
    1482     // Write header
    1483     if (header && !psFitsWriteHeader(fits, header)) {
    1484         psError(psErrorCodeLast(), false, "Unable to write FITS header.\n");
    1485         psFree(columns);
    1486         return false;
    1487     }
    1488     if (extname && strlen(extname) > 0 && !psFitsSetExtName(fits, extname)) {
    1489         psError(psErrorCodeLast(), false, "Unable to write FITS header extension name.\n");
    1490         psFree(columns);
    1491         return false;
    1492     }
    1493 
    1494     // cfitsio requires that we write the data by columns --- urgh!
    1495     for (long col = 1, i = 0; col <= numCols; col++, i++) {      // Fortran indexing
    1496         psMetadataItem *colItem = columns->data[i]; // Column
    1497         switch (colItem->type) {
    1498           case PS_DATA_VECTOR: {
    1499               psVector *vector = colItem->data.V; // Vector
    1500               int cfitsioType;                    // Data type for cfitsio
    1501               p_psFitsTypeToCfitsio(vector->type.type, NULL, NULL, &cfitsioType);
    1502               fits_write_col(fits->fd, cfitsioType, col, 1, 1, numRows, vector->data.U8, &status);
    1503               break;
    1504           }
    1505           case PS_DATA_ARRAY: {
    1506               psArray *array = colItem->data.V; // Array of strings
    1507               fits_write_col_str(fits->fd, col, 1, 1, numRows, (char**)array->data, &status);
    1508               break;
    1509           }
    1510           case PS_DATA_IMAGE: {
    1511               psImage *image = colItem->data.V;                                        // Image of interest
    1512               psDataType type = image->type.type;                                      // Type of data
    1513               psVector *vector = psVectorAlloc(image->numCols * image->numRows, type); // Vector from image
    1514               if (!p_psImageCopyToRawBuffer(vector->data.U8, image, type)) {
    1515                   psError(psErrorCodeLast(), false, "Unable to copy image to buffer");
    1516                   psFree(columns);
    1517                   return false;
    1518               }
    1519               int cfitsioType;            // Data type for cfitsio
    1520               p_psFitsTypeToCfitsio(type, NULL, NULL, &cfitsioType);
    1521               fits_write_col(fits->fd, cfitsioType, col, 1, 1, image->numRows * image->numCols,
    1522                              vector->data.U8, &status);
    1523               break;
    1524           }
    1525           default:
    1526             psAbort("Unrecognised column type: %x", colItem->type);
    1527         }
    1528         // Check error status from writing column
    1529         if (status) {
    1530             psFitsError(status, true, "Unable to write column %ld of FITS table", col);
    1531             psFree(columns);
    1532             return false;
    1533         }
    1534     }
    1535     psFree(columns);
    1536 
    1537     // This forces a re-scan of the header to ensure everything's kosher.  We found this occassionally
    1538     // necessary for compressed images, which are tables, so perhaps it helps here too.  I guess it can't
    1539     // hurt.
    1540     ffrdef(fits->fd, &status);
    1541     if (status) {
    1542         psFitsError(status, true, "Could not re-scan HDU.");
    1543         return false;
    1544     }
    1545 
    1546     return true;
    1547 }
    1548 #endif // notdef
Note: See TracChangeset for help on using the changeset viewer.