Changeset 28208 for trunk/psLib/src/fits/psFitsTable.c
- Timestamp:
- Jun 3, 2010, 5:18:11 PM (16 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/fits/psFitsTable.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/fits/psFitsTable.c
r26481 r28208 746 746 return true; 747 747 } 748 749 750 psMetadata *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 863 bool 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 int 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.
