Changeset 15731
- Timestamp:
- Dec 3, 2007, 4:36:49 PM (18 years ago)
- Location:
- branches/eam_branch_20071130/Ohana/src
- Files:
-
- 7 edited
-
addstar/src/addstar.c (modified) (2 diffs)
-
libdvo/include/dvo.h (modified) (1 diff)
-
libdvo/src/dvo_catalog.c (modified) (4 diffs)
-
libdvo/src/dvo_catalog_raw.c (modified) (1 diff)
-
libdvo/src/dvo_catalog_split.c (modified) (26 diffs)
-
libfits/include/gfitsio.h (modified) (1 diff)
-
libfits/table/F_write_T.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branch_20071130/Ohana/src/addstar/src/addstar.c
r15723 r15731 90 90 catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF; 91 91 catalog.Nsecfilt = GetPhotcodeNsecfilt (); 92 if (options.update) catalog.catflags = LOAD_AVES | LOAD_M EAS_META | LOAD_MISS | LOAD_SECF;92 if (options.update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF; 93 93 94 94 // open as read or write, depending on desire … … 142 142 if (Nsubset && !options.only_images) { 143 143 SetProtect (TRUE); 144 dvo_catalog_save (&catalog, VERBOSE); 144 if (options.update) { 145 dvo_catalog_update (&catalog, VERBOSE); 146 } else { 147 dvo_catalog_save (&catalog, VERBOSE); 148 } 145 149 SetProtect (FALSE); 146 150 } -
branches/eam_branch_20071130/Ohana/src/libdvo/include/dvo.h
r15725 r15731 23 23 typedef enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE} ElixirDetrendModes; 24 24 25 typedef enum {DVO_CAT_OPEN_FAIL, DVO_CAT_OPEN_OK, DVO_CAT_OPEN_EMPTY} ;25 typedef enum {DVO_CAT_OPEN_FAIL, DVO_CAT_OPEN_OK, DVO_CAT_OPEN_EMPTY} DVOCatalogOpenModes; 26 26 27 27 typedef enum { -
branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog.c
r15730 r15731 90 90 catalog[0].Nmeasure = 0; 91 91 catalog[0].Nmissing = 0; 92 93 catalog[0].Nave_disk = 0; 92 catalog[0].Nsecf_mem = 0; 93 94 catalog[0].Naves_disk = 0; 94 95 catalog[0].Nmeas_disk = 0; 95 96 catalog[0].Nmiss_disk = 0; 97 catalog[0].Nsecf_disk = 0; 98 99 catalog[0].Naves_off = 0; 96 100 catalog[0].Nmeas_off = 0; 101 catalog[0].Nmiss_off = 0; 102 catalog[0].Nsecf_off = 0; 97 103 98 104 /* pointers to SPLIT data files */ … … 269 275 } 270 276 271 // write out the data, unlink if empty? 272 // XXX consider conditions in which we can allow a save... 277 // write out the data, unlink if empty? 'save' means: write out all data currently in 278 // memory. NOTE: this is currently not always possible: for non-SPLIT moe files, this 279 // operation may require expanding the file size, which does not automatically happen 273 280 int dvo_catalog_save (Catalog *catalog, char VERBOSE) { 274 281 … … 294 301 } 295 302 296 # if (0) 297 // XXX deprecate this function: choice of update or not is made in dvo_catalog_save_split, etc303 // write out the in-memory data which extends beyond the data on disk. NOTE: this is 304 // currently only possible for the SPLIT mode. 298 305 int dvo_catalog_update (Catalog *catalog, char VERBOSE) { 299 306 300 // even if the data is sorted on disk, if we only load the MEAS_META, we are 301 // treating it as unsorted (eg, append only) 302 // XXX deprecate this statement? 303 XXX: 304 check on this; 305 if (catalog[0].catflags & LOAD_MEAS_META) { 306 catalog[0].sorted = FALSE; 307 } 307 // set the 'sorted' header keyword 308 catalog[0].sorted = FALSE; 309 gfits_modify (&catalog[0].header, "SORTED", "%t", 1, catalog[0].sorted); 308 310 309 311 /* update is only valid for catmode SPLIT */ 310 312 switch (catalog[0].catmode) { 311 313 case DVO_MODE_RAW: 312 dvo_catalog_save_raw (catalog, VERBOSE);314 fprintf (stderr, "not allowed for RAW mode\n"); 313 315 break; 314 316 case DVO_MODE_MEF: 315 dvo_catalog_save_mef (catalog, VERBOSE);317 fprintf (stderr, "not allowed for MEF mode\n"); 316 318 break; 317 319 case DVO_MODE_SPLIT: 318 /* new file needs to use save_catalog_split */ 319 if (catalog[0].Nave_disk == 0) { 320 dvo_catalog_save_split (catalog, VERBOSE); 321 } else { 322 dvo_catalog_update_split (catalog, VERBOSE); 323 } 320 dvo_catalog_update_split (catalog, VERBOSE); 324 321 break; 325 322 default: … … 330 327 return (TRUE); 331 328 } 332 # endif333 329 334 330 int dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend) { -
branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_raw.c
r15723 r15731 201 201 202 202 /* save the current number so we can do partial updates */ 203 catalog[0].Nave _disk= catalog[0].Naverage;203 catalog[0].Naves_disk = catalog[0].Naverage; 204 204 catalog[0].Nmeas_disk = catalog[0].Nmeasure; 205 205 catalog[0].Nmiss_disk = catalog[0].Nmissing; -
branches/eam_branch_20071130/Ohana/src/libdvo/src/dvo_catalog_split.c
r15730 r15731 6 6 // * ok 7 7 8 int dvo_catalog_open_subcat (Catalog *catalog, Catalog **Subcat, char *name, int VERBOSE) { 9 10 char *path; 8 int dvo_catalog_secfilt_to_primary (Catalog *catalog, SecFilt **myPrimary, SecFilt **mySecfilt, int *myNsecfilt) { 9 10 int i, j, Nallfilt, Nsecfilt, Ntotal; 11 12 SecFilt *primary; 13 SecFilt *secfilt; 14 15 if (catalog[0].secfilt == NULL) { 16 fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c)\n"); 17 exit (1); 18 } 19 secfilt = catalog[0].secfilt; 20 21 // XXX this translation only works if we have loaded / created a matched average/secfilt set 22 assert (catalog[0].Nsecf_mem == catalog[0].Nsecfilt*catalog[0].Naverage); 23 24 Nallfilt = catalog[0].Nsecfilt; 25 Nsecfilt = catalog[0].Nsecfilt - 1; 26 Ntotal = Nsecfilt * catalog[0].Naverage; 27 ALLOCATE (primary, SecFilt, catalog[0].Naverage); 28 ALLOCATE (secfilt, SecFilt, Ntotal); 29 30 for (i = 0; i < catalog[0].Naverage; i++) { 31 primary[i] = secfilt[i*Nallfilt + 0]; 32 for (j = 0; j < Nsecfilt; j++) { 33 secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1]; 34 } 35 } 36 catalog[0].Nsecfilt --; 37 catalog[0].Nsecf_mem = catalog[0].Naverage*catalog[0].Nsecfilt; 38 39 *myPrimary = primary; 40 *mySecfilt = secfilt; 41 *myNsecfilt = Nsecfilt; 42 } 43 44 int dvo_catalog_save_subcat (Catalog *catalog, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) { 45 46 Matrix matrix; 47 48 /* rewind file pointers and truncate (file is still open) */ 49 fseek (catalog->f, 0, SEEK_SET); 50 51 // write PHU header 52 if (!gfits_fwrite_header (catalog->f, &catalog->header)) { 53 fprintf (stderr, "can't write primary header"); 54 return (FALSE); 55 } 56 57 // write the PHU matrix; this is probably a NOP, do I have to keep it in? 58 gfits_create_matrix (&catalog->header, &matrix); 59 if (!gfits_fwrite_matrix (catalog->f, &matrix)) { 60 fprintf (stderr, "can't write primary matrix"); 61 gfits_free_matrix (&matrix); 62 return (FALSE); 63 } 64 gfits_free_matrix (&matrix); 65 66 // write the table data 67 if (!gfits_fwrite_ftable_range (catalog->f, ftable, start, Nrows, Ndisk, Ntotal)) { 68 fprintf (stderr, "can't write table data"); 69 return (FALSE); 70 } 71 return (TRUE); 72 } 73 74 int dvo_catalog_open_subcat (Catalog *catalog, Catalog **Subcat, Header *header, char *name, int VERBOSE) { 75 76 int status; 77 char *path, string[80]; 11 78 Catalog *subcat; 79 Matrix matrix; 12 80 13 81 /* in split mode, we need to init & open the corresponding measure file (even if we do not read … … 47 115 return (DVO_CAT_OPEN_FAIL); 48 116 } 117 gfits_free_matrix (&matrix); 49 118 /* read Measure table header */ 50 if (!gfits_fread_header (subcat[0].f, &header)) {119 if (!gfits_fread_header (subcat[0].f, header)) { 51 120 if (VERBOSE) fprintf (stderr, "can't read %s PHU header\n", name); 52 121 return (DVO_CAT_OPEN_FAIL); … … 68 137 /* ftable header storage for below */ 69 138 ftable.header = &header; 139 ftable.buffer = NULL; 140 header.buffer = NULL; 70 141 71 142 /* needed to find the split files below */ … … 130 201 131 202 /*** Measure Table ***/ 132 status = dvo_catalog_open_subcat (catalog, &catalog[0].measure_catalog, "MEASURE");203 status = dvo_catalog_open_subcat (catalog, &catalog[0].measure_catalog, ftable.header, "MEASURE", VERBOSE); 133 204 if (status == DVO_CAT_OPEN_FAIL) { 134 205 return (FALSE); … … 149 220 fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeas_disk); 150 221 } 151 gfits_free_header (&header);152 gfits_free_matrix (&matrix);153 222 catalog[0].Nmeasure = catalog[0].Nmeas_disk; 154 223 catalog[0].Nmeas_off = 0; … … 160 229 catalog[0].Nmeas_off = catalog[0].Nmeas_disk; 161 230 } 231 gfits_free_header (ftable.header); 162 232 163 233 /*** Missing Table ***/ 164 status = dvo_catalog_open_subcat (catalog, &catalog[0].missing_catalog, "MISSING");234 status = dvo_catalog_open_subcat (catalog, &catalog[0].missing_catalog, ftable.header, "MISSING", VERBOSE); 165 235 if (status == DVO_CAT_OPEN_FAIL) { 166 236 return (FALSE); 167 237 } 168 if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nm eas_disk > 0)) {238 if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmiss_disk > 0)) { 169 239 return (FALSE); 170 240 } … … 180 250 fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmiss_disk); 181 251 } 182 gfits_free_header (&header);183 gfits_free_matrix (&matrix);184 252 catalog[0].Nmissing = catalog[0].Nmiss_disk; 185 253 catalog[0].Nmiss_off = 0; … … 191 259 catalog[0].Nmiss_off = catalog[0].Nmiss_disk; 192 260 } 261 gfits_free_header (ftable.header); 193 262 194 263 /*** Secfilt Table ***/ 195 status = dvo_catalog_open_subcat (catalog, &catalog[0].secfilt_catalog, "SECFILT");264 status = dvo_catalog_open_subcat (catalog, &catalog[0].secfilt_catalog, ftable.header, "SECFILT", VERBOSE); 196 265 if (status == DVO_CAT_OPEN_FAIL) { 197 266 return (FALSE); … … 202 271 if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_SECF)) { 203 272 /* read secfilt table data */ 204 if (!gfits_fread_ftable_data ( secfilt[0].f, &ftable)) {273 if (!gfits_fread_ftable_data (catalog[0].secfilt_catalog[0].f, &ftable)) { 205 274 if (VERBOSE) fprintf (stderr, "can't read table secfilt data\n"); 206 275 return (FALSE); … … 218 287 tmpfilt = catalog[0].secfilt; 219 288 Ntmpfilt = catalog[0].Nsecfilt; 220 Nsecfilt = catalog[0].Nsecfilt + 1; 221 Ntotal = Nsecfilt * catalog[0].Naves_disk; 222 ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal); 289 290 catalog[0].Nsecfilt ++; 291 catalog[0].Nsecf_disk = catalog[0].Nsecfilt * catalog[0].Naves_disk; 292 Nsecfilt = catalog[0].Nsecfilt; 293 294 ALLOCATE (catalog[0].secfilt, SecFilt, catalog[0].Nsecf_disk); 223 295 for (i = 0; i < catalog[0].Naves_disk; i++) { 224 296 catalog[0].secfilt[i*Nsecfilt + 0] = primary[i]; … … 227 299 } 228 300 } 229 catalog[0].Nsecfilt = Nsecfilt;230 catalog[0].Nsecf_disk = Ntotal;231 301 free (primary); 232 302 } 233 gfits_free_header (&header);234 gfits_free_matrix (&matrix);235 303 catalog[0].Nsecf_mem = catalog[0].Nsecf_disk; 236 304 catalog[0].Nsecf_off = 0; … … 246 314 catalog[0].Nsecf_off = catalog[0].Nsecf_disk; 247 315 } 316 gfits_free_header (ftable.header); 248 317 249 318 return (TRUE); … … 252 321 // I need to always read both average and secfilt at the same time to correctly manage the 253 322 // primary secfilt values... 254 255 // XXX merge these? use the mode to choose which component? 256 257 int dvo_catalog_load_segment_split_average (Catalog *catalog, int start, int Nrows) { 258 259 // XXX check the open status of the FILE *f? 323 int dvo_catalog_load_segment_split (Catalog *catalog, int VERBOSE, int start, int Nrows) { 324 325 int Naverage, Nsecfilt, Nexpect, Nitems, Nmeasure, Nmissing; 326 Header header; 327 Matrix matrix; 328 VTable vtable; 329 SecFilt *primary; 330 331 /* vtable header storage for below */ 332 vtable.header = &header; 333 vtable.buffer = NULL; 334 header.buffer = NULL; 260 335 261 336 /*** Average (& SecFilt) Table ***/ … … 286 361 287 362 // XXX Vtable version is needed (merge Ftable and Vtable versions?) 288 catalog[0].average = VtableToAverage (& ftable, &Naverage, &catalog[0].catformat, &primary);363 catalog[0].average = VtableToAverage (&vtable, &Naverage, &catalog[0].catformat, &primary); 289 364 290 365 // XXX validate the sizes? start + Nrows < Naves_disk (no other constraints) … … 326 401 we need to interleave these magnitudes with the secfilt entries just loaded */ 327 402 if (primary != NULL) { 328 int Ntmpfilt, Ntotal,i, j;403 int Ntmpfilt, i, j; 329 404 SecFilt *tmpfilt; 330 405 tmpfilt = catalog[0].secfilt; … … 425 500 } 426 501 427 /* save_catalog_split writes complete new files from scratch*/502 /* save_catalog_split writes all data currently in memory to disk */ 428 503 int dvo_catalog_save_split (Catalog *catalog, char VERBOSE) { 429 504 … … 435 510 SecFilt *primary, *secfilt; 436 511 int i, j, Nsecfilt, Nallfilt, Ntotal; 512 int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new; 513 int first, start, Nrows; 437 514 438 515 ftable.header = &header; 439 440 if (catalog[0].Naverage == 0) { 516 ftable.buffer = NULL; 517 header.buffer = NULL; 518 519 // skip empty catalogs: it is illegal to have Measures without corresponding Averages 520 Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off); 521 if (Naves_disk_new == 0) { 441 522 if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n"); 442 523 return (TRUE); 443 524 } 444 525 445 /* for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary */ 446 if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR 447 (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS 448 if (catalog[0].secfilt == NULL) { 449 fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c)\n"); 450 exit (1); 451 } 452 secfilt = catalog[0].secfilt; 453 454 // XXX this translation only works if we have loaded / created a matched average/secfilt set 455 assert (catalog[0].Nsecf_mem == catalog[0].Nsecfilt*catalog[0].Naverage); 456 457 Nallfilt = catalog[0].Nsecfilt; 458 Nsecfilt = catalog[0].Nsecfilt - 1; 459 Ntotal = Nsecfilt * catalog[0].Naverage; 460 ALLOCATE (primary, SecFilt, catalog[0].Naverage); 461 ALLOCATE (secfilt, SecFilt, Ntotal); 462 463 for (i = 0; i < catalog[0].Naverage; i++) { 464 primary[i] = secfilt[i*Nallfilt + 0]; 465 for (j = 0; j < Nsecfilt; j++) { 466 secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1]; 467 } 468 } 469 catalog[0].Nsecfilt --; 470 catalog[0].Nsecf_mem = catalog[0].Naverage*catalog[0].Nsecfilt; 471 } else { 472 primary = NULL; 473 secfilt = catalog[0].secfilt; 474 Nsecfilt = catalog[0].Nsecfilt; 475 } 526 // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary 527 switch (catalog[0].catformat) { 528 case DVO_FORMAT_ELIXIR: // special case for ELIXIR 529 case DVO_FORMAT_LONEOS: // special case for LONEOS 530 dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt); 531 break; 532 default: 533 primary = NULL; 534 secfilt = catalog[0].secfilt; 535 Nsecfilt = catalog[0].Nsecfilt; 536 break; 537 } 538 539 Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off); 540 Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off); 541 Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off); 476 542 477 543 /* make sure header is consistent with data */ 478 gfits_modify (&catalog[0].header, "NSTARS", "%d", 1, catalog[0].Naverage);479 gfits_modify (&catalog[0].header, "NMEAS", "%d", 1, catalog[0].Nmeasure);480 gfits_modify (&catalog[0].header, "NMISS", "%d", 1, catalog[0].Nmissing);544 gfits_modify (&catalog[0].header, "NSTARS", "%d", 1, Naves_disk_new); 545 gfits_modify (&catalog[0].header, "NMEAS", "%d", 1, Nmeas_disk_new); 546 gfits_modify (&catalog[0].header, "NMISS", "%d", 1, Nmiss_disk_new); 481 547 gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt); 482 548 gfits_modify (&catalog[0].header, "EXTEND", "%t", 1, TRUE); 483 549 484 /* rewind file pointers and truncate (file is still open) */485 fseek (catalog[0].f, 0, SEEK_SET);486 487 /* write table PHU header - always write this out */488 /* XXX EAM : check if disk file size has changed */489 if (!gfits_fwrite_header (catalog[0].f, &catalog[0].header)) {490 fprintf (stderr, "can't write primary header");491 goto failure;492 }493 494 550 /* in split mode, we can save only part of the data */ 495 551 496 552 /*** Average Table ***/ 497 498 553 if (catalog[0].average != NULL) { 499 ftruncate (fileno (catalog[0].f), catalog[0].header.size); 500 501 /* this is probably a NOP, do I have to keep it in? */502 gfits_create_matrix (&catalog[0].header, &matrix);503 if (!gfits_fwrite_matrix (catalog[0].f, &matrix)) { 504 fprintf (stderr, "can't write primary matrix");505 goto failure;506 }507 gfits_free_matrix (&matrix);508 509 /* write out Average table (convert to FITS table format)*/510 if (!AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary)) {554 555 first = 0; // first row in memory to write 556 start = catalog[0].Naves_off; // first disk row to write 557 Nrows = catalog[0].Naverage - first; 558 559 assert (Nrows >= 0); 560 assert (first >= 0); 561 assert (first < catalog[0].Naverage); 562 assert (catalog[0].Naves_disk >= catalog[0].Naves_off); 563 564 /* convert internal to external format */ 565 if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) { 511 566 fprintf (stderr, "trouble converting format\n"); 512 567 goto failure; 513 568 } 514 if (!gfits_fwrite_Theader (catalog[0].f, &header)) { 515 fprintf (stderr, "can't write table header"); 516 goto failure; 517 } 518 if (!gfits_fwrite_table (catalog[0].f, &ftable)) { 519 fprintf (stderr, "can't write table data"); 520 goto failure; 521 } 569 570 if (!dvo_catalog_save_subset (catalog, ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) { 571 fprintf (stderr, "failure writing Average table\n"); 572 goto failure; 573 } 574 gfits_free_header (&header); 522 575 gfits_free_table (&ftable); 523 gfits_free_header (&header); 576 } else { 577 // even if we do not save the average table, we need to keep the header in sync 578 /* rewind file pointers and truncate (file is still open) */ 579 fseek (catalog[0].f, 0, SEEK_SET); 580 581 /* write table PHU header - always write this out */ 582 /* XXX EAM : check if disk file size has changed */ 583 if (!gfits_fwrite_header (catalog[0].f, &catalog[0].header)) { 584 fprintf (stderr, "can't write primary header"); 585 goto failure; 586 } 524 587 } 525 588 … … 527 590 if (catalog[0].measure != NULL) { 528 591 529 /* catalog file data is stored in separate structure */ 530 catfile = catalog[0].measure_catalog; 531 532 /* XXX EAM : warn about this condition; add code to handle? */ 533 if (catalog[0].Nmeas_off != 0) { 534 fprintf (stderr, "WARNING: LOAD_MEAS_META mixed with save??\n"); 535 fprintf (stderr, "WARNING: this should not be allowed to happen!\n"); 536 } 537 538 /* rewind file pointers and truncate (file is still open) */ 539 fseek (catfile[0].f, 0, SEEK_SET); 540 ftruncate (fileno (catfile[0].f), 0); 541 542 /* write table PHU header */ 543 if (!gfits_fwrite_header (catfile[0].f, &catfile[0].header)) { 544 fprintf (stderr, "can't write primary header"); 545 goto failure; 546 } 547 548 /* this is probably a NOP, do I have to keep it in? */ 549 gfits_create_matrix (&catfile[0].header, &matrix); 550 if (!gfits_fwrite_matrix (catfile[0].f, &matrix)) { 551 fprintf (stderr, "can't write primary matrix"); 552 goto failure; 553 } 554 gfits_free_matrix (&matrix); 555 556 /* write out Measure table (convert to FITS table format) */ 557 MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat); 558 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 559 fprintf (stderr, "can't write table header"); 560 goto failure; 561 } 562 if (!gfits_fwrite_table (catfile[0].f, &ftable)) { 563 fprintf (stderr, "can't write table data"); 564 goto failure; 565 } 592 first = 0; // first row in memory to write 593 start = catalog[0].Nmeas_off; // first disk row to write 594 Nrows = catalog[0].Nmeasure - first; 595 596 assert (Nrows >= 0); 597 assert (first >= 0); 598 assert (first < catalog[0].Nmeasure); 599 assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off); 600 601 // convert to external table format 602 if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) { 603 fprintf (stderr, "trouble converting format\n"); 604 goto failure; 605 } 606 607 // write out Measure table 608 if (!dvo_catalog_save_subset (catalog[0].measure_catalog, ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) { 609 fprintf (stderr, "trouble writing Measure table\n"); 610 goto failure; 611 } 612 gfits_free_header (&header); 566 613 gfits_free_table (&ftable); 567 gfits_free_header (&header);568 614 } 569 615 … … 571 617 if (catalog[0].missing != NULL) { 572 618 573 /* catalog data is stored in separate catalog */ 574 catfile = catalog[0].missing_catalog; 575 576 /* rewind file pointers and truncate (file is still open) */ 577 fseek (catfile[0].f, 0, SEEK_SET); 578 ftruncate (fileno (catfile[0].f), 0); 579 580 /* write table PHU header */ 581 if (!gfits_fwrite_header (catfile[0].f, &catfile[0].header)) { 582 fprintf (stderr, "can't write primary header"); 583 goto failure; 584 } 585 586 /* this is probably a NOP, do I have to keep it in? */ 587 gfits_create_matrix (&catfile[0].header, &matrix); 588 if (!gfits_fwrite_matrix (catfile[0].f, &matrix)) { 589 fprintf (stderr, "can't write primary matrix"); 590 goto failure; 591 } 592 gfits_free_matrix (&matrix); 593 594 /* write out Missing table (convert to FITS table format) */ 595 gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing); 596 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 597 fprintf (stderr, "can't write table header"); 598 goto failure; 599 } 600 if (!gfits_fwrite_table (catfile[0].f, &ftable)) { 601 fprintf (stderr, "can't write table data"); 602 goto failure; 603 } 619 if (catalog[0].Nmiss_off != 0) { 620 fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n"); 621 goto failure; 622 } 623 624 // convert to external table format 625 if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) { 626 fprintf (stderr, "trouble converting format\n"); 627 goto failure; 628 } 629 630 // write out Missing table (must write out entire table) 631 if (!dvo_catalog_save_subset (catalog[0].missing_catalog, ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) { 632 fprintf (stderr, "trouble writing Missing Table\n"); 633 goto failure; 634 } 635 gfits_free_header (&header); 604 636 gfits_free_table (&ftable); 605 gfits_free_header (&header);606 637 } 607 638 … … 609 640 if (catalog[0].secfilt != NULL) { 610 641 611 /* catalog file data is stored in a separate catalog structure */ 612 catfile = catalog[0].secfilt_catalog; 613 614 /* rewind file pointers and truncate (file is still open) */ 615 fseek (catfile[0].f, 0, SEEK_SET); 616 ftruncate (fileno (catfile[0].f), 0); 617 618 /* write table PHU header */ 619 if (!gfits_fwrite_header (catfile[0].f, &catfile[0].header)) { 620 fprintf (stderr, "can't write primary header"); 621 goto failure; 622 } 623 624 /* this is probably a NOP, do I have to keep it in? */ 625 gfits_create_matrix (&catfile[0].header, &matrix); 626 if (!gfits_fwrite_matrix (catfile[0].f, &matrix)) { 627 fprintf (stderr, "can't write primary matrix"); 628 goto failure; 629 } 630 gfits_free_matrix (&matrix); 631 632 /* write out SecFilt table (convert to FITS table format) */ 633 Nitems = catalog[0].Naverage * catalog[0].Nsecfilt; 634 SecFiltToFtable (&ftable, secfilt, Nitems, catalog[0].catformat); 635 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 636 fprintf (stderr, "can't write table header"); 637 goto failure; 638 } 639 if (!gfits_fwrite_table (catfile[0].f, &ftable)) { 640 fprintf (stderr, "can't write table data"); 641 goto failure; 642 } 642 first = 0; // first row in memory to write 643 start = catalog[0].Nsecf_off; // first disk row to write 644 Nitems = catalog[0].Nsecf_mem; 645 Nrows = Nitems - first; 646 647 assert (Nrows >= 0); 648 assert (first >= 0); 649 assert (first < Nitems); 650 assert (catalog[0].Nsecf_disk >= catalog[0].Nsecf_off); 651 652 // convert to external table format 653 SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat); 654 655 // write out SecFilt table 656 if (!dvo_catalog_save_subset (catalog[0].secfilt_catalog, ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) { 657 fprintf (stderr, "failure writing SecFilt table\n"); 658 goto failure; 659 } 660 gfits_free_header (&header); 643 661 gfits_free_table (&ftable); 644 gfits_free_header (&header);645 662 } 646 663 … … 650 667 free (secfilt); 651 668 } 652 653 669 return (TRUE); 654 670 655 671 failure: 656 672 /* free temp storage */ 673 gfits_free_header (&header); 674 gfits_free_table (&ftable); 657 675 if (primary != NULL) { 658 676 free (primary); … … 662 680 } 663 681 664 /* update_catalog_split only writes new lines to file. 665 * if file is empty, call save_catalog_split instead. 666 * XXX EAM : save_catalog SHOULD do this 667 */ 668 682 /* update_catalog_split only writes new lines to file. */ 669 683 int dvo_catalog_update_split (Catalog *catalog, char VERBOSE) { 670 684 … … 678 692 SecFilt *primary, *secfilt; 679 693 int j, Nsecfilt, Nallfilt, Ntotal; 694 int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new; 695 int first, start, Nrows; 680 696 681 697 ftable.header = &header; 682 vtable.header = &header; 683 684 if (catalog[0].Naverage == 0) { 698 ftable.buffer = NULL; 699 header.buffer = NULL; 700 701 // skip empty catalogs: it is illegal to have Measures without corresponding Averages 702 Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off); 703 if (Naves_disk_new == 0) { 685 704 if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n"); 686 705 return (TRUE); 687 706 } 688 707 689 /** for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary **/ 690 if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR 691 (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS 692 if (catalog[0].secfilt == NULL) { 693 fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c:544)\n"); 694 exit (1); 695 } 696 secfilt = catalog[0].secfilt; 697 698 Nallfilt = catalog[0].Nsecfilt; 699 Nsecfilt = catalog[0].Nsecfilt - 1; 700 Ntotal = Nsecfilt * catalog[0].Naverage; 701 ALLOCATE (primary, SecFilt, catalog[0].Naverage); 702 ALLOCATE (secfilt, SecFilt, Ntotal); 703 704 for (i = 0; i < catalog[0].Naverage; i++) { 705 primary[i] = secfilt[i*Nallfilt + 0]; 706 for (j = 0; j < Nsecfilt; j++) { 707 secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1]; 708 } 709 } 710 } else { 711 primary = NULL; 712 secfilt = catalog[0].secfilt; 713 Nsecfilt = catalog[0].Nsecfilt; 714 } 708 // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary 709 switch (catalog[0].catformat) { 710 case DVO_FORMAT_ELIXIR: // special case for ELIXIR 711 case DVO_FORMAT_LONEOS: // special case for LONEOS 712 dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt); 713 break; 714 default: 715 primary = NULL; 716 secfilt = catalog[0].secfilt; 717 Nsecfilt = catalog[0].Nsecfilt; 718 break; 719 } 720 721 Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off); 722 Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off); 723 Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off); 715 724 716 725 /* make sure header is consistent with data */ 717 gfits_modify (&catalog[0].header, "NSTARS", "%d", 1, catalog[0].Naverage);718 gfits_modify (&catalog[0].header, "NMEAS", "%d", 1, catalog[0].Nmeasure + catalog[0].Nmeas_off);719 gfits_modify (&catalog[0].header, "NMISS", "%d", 1, catalog[0].Nmissing);726 gfits_modify (&catalog[0].header, "NSTARS", "%d", 1, Naves_disk_new); 727 gfits_modify (&catalog[0].header, "NMEAS", "%d", 1, Nmeas_disk_new); 728 gfits_modify (&catalog[0].header, "NMISS", "%d", 1, Nmiss_disk_new); 720 729 gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt); 721 730 gfits_modify (&catalog[0].header, "EXTEND", "%t", 1, TRUE); 722 731 723 /* rewind file pointers and truncate (file is still open) */ 724 fseek (catalog[0].f, 0, SEEK_SET); 725 726 /* write table PHU header - always write this out */ 727 /* XXX EAM : check if disk file size has changed */ 728 if (!gfits_fwrite_header (catalog[0].f, &catalog[0].header)) { 729 fprintf (stderr, "can't write primary header"); 730 goto failure; 731 } 732 /* in split mode, we can save only part of the data */ 732 733 733 734 /*** Average Table ***/ 734 735 if (catalog[0].average != NULL) { 735 736 736 /* skip past matrix (already at end of header) */ 737 Nskip = gfits_data_size (&catalog[0].header); 738 fseek (catalog[0].f, Nskip, SEEK_CUR); 739 740 /* how many lines to write out? */ 741 Nout = catalog[0].Naverage - catalog[0].Nave_disk; 742 743 /* write out Average table (convert to FITS table format) */ 744 AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary); 745 /* convert only output rows to vtable */ 746 gfits_table_to_vtable (&ftable, &vtable, catalog[0].Nave_disk, Nout); 747 748 if (!gfits_fwrite_Theader (catalog[0].f, &header)) { 749 fprintf (stderr, "can't write table header"); 750 goto failure; 751 } 752 if (!gfits_fwrite_vtable (catalog[0].f, &vtable)) { 753 fprintf (stderr, "can't write table data"); 754 goto failure; 755 } 756 gfits_free_vtable (&vtable); 737 first = catalog[0].Naves_disk - catalog[0].Naves_off; // first row to write (memory) 738 start = catalog[0].Naves_disk; // first row to write (disk) 739 Nrows = catalog[0].Naverage - first; 740 741 assert (Nrows >= 0); 742 assert (first >= 0); 743 assert (first < catalog[0].Naverage); 744 assert (catalog[0].Naves_disk >= catalog[0].Naves_off); 745 746 /* convert internal to external format */ 747 if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) { 748 fprintf (stderr, "trouble converting format\n"); 749 goto failure; 750 } 751 752 if (!dvo_catalog_save_subset (catalog, ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) { 753 fprintf (stderr, "failure writing Average table\n"); 754 goto failure; 755 } 756 gfits_free_header (&header); 757 757 gfits_free_table (&ftable); 758 gfits_free_header (&header); 758 } else { 759 // even if we do not save the average table, we need to keep the header in sync 760 /* rewind file pointers and truncate (file is still open) */ 761 fseek (catalog[0].f, 0, SEEK_SET); 762 763 /* write table PHU header - always write this out */ 764 /* XXX EAM : check if disk file size has changed */ 765 if (!gfits_fwrite_header (catalog[0].f, &catalog[0].header)) { 766 fprintf (stderr, "can't write primary header"); 767 goto failure; 768 } 759 769 } 760 770 … … 762 772 if (catalog[0].measure != NULL) { 763 773 764 catfile = catalog[0].measure_catalog; 765 766 /* skip past PHU header and matrix */ 767 Nskip = catfile[0].header.size + gfits_data_size (&catfile[0].header); 768 fseek (catfile[0].f, Nskip, SEEK_SET); 769 770 Ndisk = catalog[0].Nmeas_disk; 771 Nstart = catalog[0].Nmeas_disk - catalog[0].Nmeas_off; /* where is first new line? */ 772 Nout = catalog[0].Nmeasure - Nstart; /* how many lines to write out? */ 773 Nlines = catalog[0].Nmeasure + catalog[0].Nmeas_off; /* how many lines total in file */ 774 775 /* convert to output format FITS table (only rows for output : 0 - Nout) */ 776 MeasureToFtable (&ftable, &catalog[0].measure[Nstart], Nout, catalog[0].catformat); 777 778 gfits_scan (&header, "NAXIS1", "%d", 1, &Nx); 779 gfits_scan (&header, "NAXIS2", "%d", 1, &Ny); 780 781 /* convert all output rows to vtable */ 782 ALLOCATE (vtable.row, int, MAX (1, Nout)); 783 ALLOCATE (vtable.buffer, char *, MAX (1, Nout)); 784 for (i = 0; i < Nout; i++) { 785 ALLOCATE (vtable.buffer[i], char, MAX (1, Nx)); 786 memcpy (vtable.buffer[i], &ftable.buffer[i*Nx], Nx); 787 vtable.row[i] = i + Ndisk; 788 } 789 790 /* modify vtable to represent full disk table */ 791 gfits_modify (&header, "NAXIS2", "%d", 1, Nlines); 792 header.Naxis[1] = Nlines; 793 794 vtable.size = gfits_data_size (&header); 795 vtable.Nrow = Nout; 796 vtable.pad = vtable.size - Nx*Ny; 797 798 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 799 fprintf (stderr, "can't write table header"); 800 goto failure; 801 } 802 if (!gfits_fwrite_vtable (catfile[0].f, &vtable)) { 803 fprintf (stderr, "can't write table data"); 804 goto failure; 805 } 806 gfits_free_vtable (&vtable); 774 first = catalog[0].Nmeas_disk - catalog[0].Nmeas_off; // first row in memory to write 775 start = catalog[0].Nmeas_off; // first disk row to write 776 Nrows = catalog[0].Nmeasure - first; 777 778 assert (Nrows >= 0); 779 assert (first >= 0); 780 assert (first < catalog[0].Nmeasure); 781 assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off); 782 783 // convert to external table format 784 if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) { 785 fprintf (stderr, "trouble converting format\n"); 786 goto failure; 787 } 788 789 // write out Measure table 790 if (!dvo_catalog_save_subset (catalog[0].measure_catalog, ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) { 791 fprintf (stderr, "trouble writing Measure table\n"); 792 goto failure; 793 } 794 gfits_free_header (&header); 807 795 gfits_free_table (&ftable); 808 gfits_free_header (&header); 809 } 810 811 /*** Missing Table ***/ 796 } 797 812 798 /* missing table CANNOT be written unsorted, thus it is always written 813 799 out in full */ 814 800 801 /*** Missing Table ***/ 802 815 803 if (catalog[0].missing != NULL) { 816 804 817 catfile = catalog[0].missing_catalog; 818 819 /* rewind file pointers and truncate (file is still open) */ 820 fseek (catfile[0].f, 0, SEEK_SET); 821 ftruncate (fileno (catfile[0].f), 0); 822 823 /* write table PHU header */ 824 if (!gfits_fwrite_header (catfile[0].f, &catfile[0].header)) { 825 fprintf (stderr, "can't write primary header"); 826 goto failure; 827 } 828 829 /* this is probably a NOP, do I have to keep it in? */ 830 gfits_create_matrix (&catfile[0].header, &matrix); 831 if (!gfits_fwrite_matrix (catfile[0].f, &matrix)) { 832 fprintf (stderr, "can't write primary matrix"); 833 goto failure; 834 } 835 gfits_free_matrix (&matrix); 836 837 /* write out Missing table (convert to FITS table format) */ 838 gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing); 839 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 840 fprintf (stderr, "can't write table header"); 841 goto failure; 842 } 843 if (!gfits_fwrite_table (catfile[0].f, &ftable)) { 844 fprintf (stderr, "can't write table data"); 845 goto failure; 846 } 805 if (catalog[0].Nmiss_off != 0) { 806 fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n"); 807 goto failure; 808 } 809 810 // convert to external table format 811 if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) { 812 fprintf (stderr, "trouble converting format\n"); 813 goto failure; 814 } 815 816 // write out Missing table (must write out entire table) 817 if (!dvo_catalog_save_subset (catalog[0].missing_catalog, ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) { 818 fprintf (stderr, "trouble writing Missing Table\n"); 819 goto failure; 820 } 821 gfits_free_header (&header); 847 822 gfits_free_table (&ftable); 848 gfits_free_header (&header);849 823 } 850 824 … … 852 826 if (catalog[0].secfilt != NULL) { 853 827 854 catfile = catalog[0].secfilt_catalog; 855 856 /* skip past PHU header and matrix */ 857 Nskip = catfile[0].header.size + gfits_data_size (&catfile[0].header); 858 fseek (catfile[0].f, Nskip, SEEK_SET); 859 860 /* how many lines to write out? */ 861 Nout = catalog[0].Nsecfilt * (catalog[0].Naverage - catalog[0].Nave_disk); 862 Ndisk = catalog[0].Nsecfilt * catalog[0].Nave_disk; 863 864 /* convert to output format FITS table */ 865 Nitems = catalog[0].Naverage * catalog[0].Nsecfilt; 866 SecFiltToFtable (&ftable, secfilt, Nitems, catalog[0].catformat); 867 /* convert only output rows to vtable */ 868 gfits_table_to_vtable (&ftable, &vtable, Ndisk, Nout); 869 870 if (!gfits_fwrite_Theader (catfile[0].f, &header)) { 871 fprintf (stderr, "can't write table header"); 872 goto failure; 873 } 874 if (!gfits_fwrite_vtable (catfile[0].f, &vtable)) { 875 fprintf (stderr, "can't write table data"); 876 goto failure; 877 } 878 gfits_free_vtable (&vtable); 828 first = catalog[0].Nsecf_disk - catalog[0].Nsecf_off; // first row in memory to write 829 start = catalog[0].Nsecf_off; // first disk row to write 830 Nitems = catalog[0].Nsecf_mem; 831 Nrows = Nitems - first; 832 833 assert (Nrows >= 0); 834 assert (first >= 0); 835 assert (first < Nitems); 836 assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off); 837 838 // convert to external table format 839 SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat); 840 841 // write out SecFilt table 842 if (!dvo_catalog_save_subset (catalog[0].secfilt_catalog, ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) { 843 fprintf (stderr, "failure writing SecFilt table\n"); 844 goto failure; 845 } 846 gfits_free_header (&header); 879 847 gfits_free_table (&ftable); 880 gfits_free_header (&header);881 848 } 882 849 … … 911 878 the vtable based on the ftable, but with Ny = Nmeasure */ 912 879 880 881 882 // * convert to an ftable 883 // * optionally write the PHU header/matrix 884 // * advance to the start of the output data block: 885 // ** Nx * catalog[0].Nmeas_off 886 // * write out the ftable data block 887 // * if Nmeas_off + Nmeasure >= Nmeas_disk, update padding 888 // ** start = Nmeas_off 889 // ** Nrows = Nmeasure 890 -
branches/eam_branch_20071130/Ohana/src/libfits/include/gfitsio.h
r15656 r15731 178 178 int gfits_fwrite_table PROTO((FILE *f, FTable *table)); 179 179 int gfits_fwrite_vtable PROTO((FILE *f, VTable *table)); 180 int gfits_fwrite_ftable_range PROTO((FILE *f, FTable *table, int start, int Nrows, int Ndisk, int Ntotal)); 180 181 int gfits_get_bintable_column PROTO((Header *header, FTable *table, char *label, void **data)); 181 182 int gfits_get_bintable_column_type PROTO((Header *header, char *label, char *type, int *Nval)); -
branches/eam_branch_20071130/Ohana/src/libfits/table/F_write_T.c
r7054 r15731 69 69 /* this will add data beyond the end of the table in the file if needed, 70 70 filling intervening gap with 0 */ 71 72 /*********************** fits read ftable data ***********************************/ 73 int gfits_fwrite_ftable_range (FILE *f, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) { 74 75 int Nbytes, Nwrite, Nskip, Nx, Npad; 76 char *pad; 77 78 if (start < 0) return (FALSE); 79 80 /* modify vtable to represent full disk table */ 81 gfits_modify (ftable[0].header, "NAXIS2", "%d", 1, Ntotal); 82 ftable[0].header[0].Naxis[1] = Ntotal; 83 84 Nx = ftable[0].header[0].Naxis[0]; // final output table size on disk 85 ftable[0].size = gfits_data_size (ftable[0].header); 86 87 Nskip = start * Nx; 88 Nbytes = Nrows * Nx; 89 90 // cursor must be at start of the table header 91 if (!gfits_fwrite_Theader (f, ftable[0].header)) { 92 fprintf (stderr, "can't write table header"); 93 return (FALSE); 94 } 95 96 // cursor must be at start of the table (after table header) 97 fseek (f, Nskip, SEEK_CUR); 98 Nwrite = fwrite (ftable[0].buffer, sizeof (char), Nbytes, f); 99 if (Nwrite != Nbytes) { 100 return (FALSE); 101 } 102 103 if (Ntotal >= Ndisk) { 104 Npad = ftable[0].size - Nx*Ntotal; 105 ALLOCATE (pad, char, Npad); 106 bzero (pad, Npad); 107 Nbytes = fwrite (pad, sizeof (char), Npad, f); 108 free (pad); 109 110 if (Nbytes != Npad) return (FALSE); 111 } 112 113 return (TRUE); 114 } 115
Note:
See TracChangeset
for help on using the changeset viewer.
