Changeset 41340 for trunk/Ohana/src/opihi/lib.shell/VectorIO.c
- Timestamp:
- Apr 16, 2020, 1:54:47 PM (6 years ago)
- File:
-
- 1 edited
-
trunk/Ohana/src/opihi/lib.shell/VectorIO.c (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/opihi/lib.shell/VectorIO.c
r41269 r41340 2 2 void gfits_compress_timing (); 3 3 4 static int VectorGetMaxStringLength (Vector *vec) {5 6 int MaxLength = 0;7 8 if (vec[0].type != OPIHI_STR) return 0;9 10 for (int i = 0; i < vec[0].Nelements; i++) {11 MaxLength = MAX (MaxLength, strlen(vec[0].elements.Str[i]));12 }13 return MaxLength;14 }15 16 4 // write a set of vectors to a FITS FTable structure (vectors names become fits column names) 17 5 static int WriteVectorTable (FTable *ftable, char *extname, Vector **vec, int Nvec, char *format, char nativeOrder) { … … 19 7 int j; 20 8 9 char *tformat = NULL; 10 21 11 Header *theader = ftable->header; 22 12 gfits_create_table_header (theader, "BINTABLE", extname); 23 13 24 // allocate an array of strings to represent the format for each output field 25 // formats include single column formats (BIJKDE) and multi-column formats (e.g., 2I) 26 // we will have no more than Nvec fields (but we can have fewer) 27 int Nfield = 0; 28 ALLOCATE_PTR (tformat, char *, Nvec); 29 ALLOCATE_PTR (Nelement, int, Nvec); 30 14 ALLOCATE (tformat, char, 2*Nvec); 31 15 if (format) { 32 // the bintable format string can defines the byte-width of each field and number of elements (columns per field). 33 // valid output columns are currently: 16 // the bintable format string can only define the byte-width of each field. valid output columns are currently: 34 17 // B (char), I (16 bit short), J (32 bit int), E (32 bit float), D (64 bit double). 35 // the format string is just the sequence of types, eg: LIIJEED. 36 // it may have spaces or integer element counts: 37 // "2D 4I EEJ" 38 39 // *** validate the format string 40 41 // as I parse each elements, if it is a digit, I need parse that value 42 18 // the format string is just the sequence of types, eg: LIIJEED 19 // validate the format string 43 20 char *ptr = format; 44 for (j = 0; j < Nvec; ) {21 for (j = 0; j < Nvec; j++) { 45 22 while (*ptr && OHANA_WHITESPACE (*ptr)) ptr++; 46 23 if (*ptr == 0) { … … 48 25 goto escape; 49 26 } 50 51 // is there a leading integer? 52 char *endptr; 53 Nelement[Nfield] = strtol (ptr, &endptr, 10); 54 if (endptr == ptr) { 55 Nelement[Nfield] = 1; 56 } 57 ptr = endptr; // this should now point at the letter that is the format type 58 if ((*ptr != 'B') && (*ptr != 'I') && (*ptr != 'J') && (*ptr != 'K') && (*ptr != 'D') && (*ptr != 'E') && (*ptr != 'A')) { 27 if ((*ptr != 'B') && (*ptr != 'I') && (*ptr != 'J') && (*ptr != 'K') && (*ptr != 'D') && (*ptr != 'E')) { 59 28 gprint (GP_ERR, "error in binary table format %s: invalid character %c\n", format, *ptr); 60 29 goto escape; 61 30 } 62 63 int Nchar = snprintf (tformat[Nfield], 0, "%d%c", Nelement[Nfield], *ptr); 64 ALLOCATE (tformat[Nfield], char, Nchar + 1); 65 int Nout = snprintf (tformat[Nfield], Nchar + 1, "%d%c", Nelement[Nfield], *ptr); 66 myAssert (Nout <= Nchar, "oops"); 67 68 // tformat[2*j + 0] = *ptr; 69 // tformat[2*j + 1] = 0; // a bit sleazy : use a 2xN string to store N 1-byte strings 70 71 // For numeric multi-valued fields, the number of elements from the format defines the number of 72 // vectors which go into that field. For string-type vectors, the format specifies the maximum number of characters 73 // that go into the field. 74 75 // for example, a format code of 3E should match a list of three numeric-type vectors while a format code of 15A should 76 // match a single string-type vector which will supply up to 15 chars per row. 77 78 if (*ptr != 'A') { 79 j += Nelement[Nfield]; // advance past Nelement vectors 80 } else { 81 if (vec[j][0].type != OPIHI_STR) { 82 gprint (GP_ERR, "error in binary table format %s (mismatch between string format and numeric vector %s)\n", format, vec[j][0].name); 83 goto escape; 84 } 85 j ++; // advance past a single string-type vector (validate that?) 86 } 87 if (j > Nvec) { 88 gprint (GP_ERR, "error in binary table format %s (too few vectors for listed field)\n", format); 89 goto escape; 90 } 91 31 tformat[2*j + 0] = *ptr; 32 tformat[2*j + 1] = 0; // a bit sleazy : use a 2xN string to store N 1-byte strings 92 33 ptr ++; 93 Nfield ++;94 34 } 95 35 while (*ptr && OHANA_WHITESPACE (*ptr)) ptr++; … … 100 40 } else { 101 41 for (j = 0; j < Nvec; j++) { 102 switch (vec[j][0].type) { 103 case OPIHI_FLT: 104 case OPIHI_INT: 105 // if the format is not defined, just use the native byte-widths 106 ALLOCATE (tformat[j], char, 2); 107 tformat[j][0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'K'; 108 tformat[j][1] = 0; 109 Nelement[j] = 1; 110 break; 111 case OPIHI_STR: 112 // we need to examine the vector to determine the length 113 Nelement[j] = VectorGetMaxStringLength(vec[j]); 114 int Nchar = snprintf (tformat[j], 0, "%d%c", Nelement[j], 'A'); 115 ALLOCATE (tformat[j], char, Nchar + 1); 116 int Nout = snprintf (tformat[j], Nchar + 1, "%d%c", Nelement[j], 'A'); 117 myAssert (Nout <= Nchar, "oops"); 118 break; 119 } 120 } 121 Nfield = Nvec; 42 // if the format is not defined, just use the native byte-widths 43 tformat[2*j + 0] = (vec[j][0].type == OPIHI_FLT) ? 'D' : 'K'; // this depends on opihi_int == int64_t for Int 44 tformat[2*j + 1] = 0; 45 } 122 46 } 123 47 … … 125 49 // output table (because the data goes to the named column below). need to enforce 126 50 // this somehow 127 int ivec = 0; 128 for (j = 0; j < Nfield; j++) { 129 // XX need to loop over fields, and skip the additional vectors that are part of a field 130 // this call supported multiple columns per named field 131 gfits_define_bintable_column (theader, tformat[j], vec[ivec][0].name, NULL, NULL, 1.0, 0.0); 132 if (vec[ivec][0].type == OPIHI_STR) { 133 ivec ++; 134 } else { 135 ivec += Nelement[j]; 136 } 137 } 138 139 // need to free the array 140 for (j = 0; j < Nfield; j++) { 141 free (tformat[j]); 51 for (j = 0; j < Nvec; j++) { 52 gfits_define_bintable_column (theader, &tformat[2*j], vec[j][0].name, NULL, NULL, 1.0, 0.0); 142 53 } 143 54 free (tformat); … … 146 57 gfits_create_table (theader, ftable); 147 58 148 // I need to add each vector in order, but I need to149 // track which field it corresponds to.150 151 59 // add the vectors to the output array 152 for (ivec = 0, j = 0; j < Nfield; j++) { 153 // the first vector provides the name for the field 154 char *fieldname = vec[ivec][0].name; 155 156 if (vec[ivec][0].type == OPIHI_STR) { 157 // string-type vectors need to be copied into a contiguous buffer with the right dimensions: 158 Vector *thisvec = vec[ivec]; 159 160 ALLOCATE_PTR (strbuffer, char, Nelement[j]*thisvec->Nelements); 161 for (int i = 0; i < thisvec->Nelements; i++) { 162 int nChar = MIN (strlen (thisvec->elements.Str[i]), Nelement[j]); 163 // fprintf (stderr, "%d %d %d : %d : %d : %s\n", ivec, j, i, Nelement[j], nChar, thisvec->elements.Str[i]); 164 memcpy (&strbuffer[i*Nelement[j]], thisvec->elements.Str[i], nChar); 165 } 166 gfits_set_bintable_column (theader, ftable, fieldname, strbuffer, thisvec->Nelements); 167 free (strbuffer); 168 ivec ++; 60 for (j = 0; j < Nvec; j++) { 61 if (vec[j][0].type == OPIHI_FLT) { 62 gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "double", vec[j][0].elements.Flt, vec[j][0].Nelements, nativeOrder); 169 63 } else { 170 for (int k = 0; k < Nelement[j]; k++, ivec++) { 171 Vector *thisvec = vec[ivec]; 172 switch (thisvec->type) { 173 case OPIHI_FLT: 174 gfits_set_bintable_column_reformat (theader, ftable, fieldname, "double", thisvec->elements.Flt, thisvec->Nelements, k, nativeOrder); 175 break; 176 case OPIHI_INT: 177 gfits_set_bintable_column_reformat (theader, ftable, fieldname, "int64_t", thisvec->elements.Int, thisvec->Nelements, k, nativeOrder); 178 break; 179 } 180 } 64 // gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int", vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder); 65 gfits_set_bintable_column_reformat (theader, ftable, vec[j][0].name, "int64_t", vec[j][0].elements.Int, vec[j][0].Nelements, nativeOrder); 181 66 } 182 67 } … … 225 110 } 226 111 227 // insert a new header line, return end pointer228 char *gfits_insert_header_line (Header *header, char *endptr, char *newline) {229 230 if (0) {231 char temp1[32], temp2[32];232 memset (temp1, 0, 32);233 memset (temp2, 0, 32);234 235 if (endptr) {236 memcpy (temp1, endptr, 8);237 }238 memcpy (temp2, newline, 8);239 fprintf (stderr, "insert: %s : %s\n", temp1, temp2);240 }241 242 /* find the END of the header, if not supplied */243 if (!endptr) {244 endptr = gfits_header_field (header, "END", 1);245 if (endptr == NULL) return NULL;246 }247 248 /* is there enough space for 1 more line? */249 if (header[0].datasize - (endptr - (header[0].buffer)) < 2*FT_LINE_LENGTH) {250 // no, so expand by a full header block (FT_RECORD_SIZE = 32*80 = 2880)251 header[0].datasize += FT_RECORD_SIZE;252 REALLOCATE (header[0].buffer, char, header[0].datasize);253 // re-find the "END" marker, in case new memory block is used254 endptr = gfits_header_field (header, "END", 1);255 if (endptr == NULL) return NULL;256 memset (endptr + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);257 }258 259 /* push END line back 1 */260 memmove ((endptr + FT_LINE_LENGTH), endptr, FT_LINE_LENGTH);261 memset (endptr, ' ', FT_LINE_LENGTH);262 263 strncpy (endptr, newline, 80);264 endptr += FT_LINE_LENGTH;265 266 return endptr;267 }268 269 static char *rawkeywords[] = {"SIMPLE", "BITPIX", "NAXIS", "PCOUNT", "GCOUNT", "EXTEND", "EXTNAME", "BSCALE", "BZERO", "TFIELDS", "TFORM", "TZERO", "TSCAL", " ", NULL};270 271 112 // write a set of vectors to a FITS file (vectors names become fits column names) 272 int WriteVectorTableFITS (char *filename, char *extname, Header *extraheader,Vector **vec, int Nvec, int append, char *compress, char *format, int Ntile) {113 int WriteVectorTableFITS (char *filename, char *extname, Vector **vec, int Nvec, int append, char *compress, char *format, int Ntile) { 273 114 274 115 Header rawheader; … … 298 139 rawtable.header = &rawheader; 299 140 if (!WriteVectorTable (&rawtable, extname, vec, Nvec, format, (compress != NULL))) goto escape; 300 // NOTE : for compression, the table is constructed in native by teorder141 // NOTE : for compression, the table is constructed in native by order 301 142 302 143 FTable *outtable = &rawtable; … … 322 163 323 164 if (!append) { 324 // generate a blank PHU header325 165 Header header; 326 166 Matrix matrix; … … 336 176 } 337 177 338 if (extraheader) {339 // copy keywords which are not the standard or table keywords340 char *buf = extraheader->buffer;341 char *endptr = NULL;342 for (int i = 0; i < extraheader->datasize; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {343 344 if (0) {345 char temp1[32];346 memset (temp1, 0, 32);347 memcpy (temp1, buf, 8);348 fprintf (stderr, "buffer: %s\n", temp1);349 }350 351 for (int j = 0; rawkeywords[j] != NULL; j++) {352 if (!strncmp (buf, rawkeywords[j], strlen(rawkeywords[j]))) goto skip_insert;353 }354 endptr = gfits_insert_header_line (outheader, endptr, buf);355 if (!endptr) {356 gprint (GP_ERR, "failed to update FITS header with extra keywords\n");357 return (FALSE);358 }359 skip_insert:360 continue;361 }362 }363 364 178 // write the actual table data 365 179 gfits_fwrite_Theader (f, outheader);
Note:
See TracChangeset
for help on using the changeset viewer.
