00001 #include "drms.h"
00002 #include "drms_priv.h"
00003 #include "tasrw.h"
00004 #include "fitsexport.h"
00005
00006 const char kSIMPLE[] = "SIMPLE";
00007 const char kBITPIX[] = "BITPIX";
00008 const char kNAXIS[] = "NAXIS";
00009 const char kNAXISn[] = "NAXIS%d";
00010
00011 DRMS_Type_t drms_fitsrw_Bitpix2Type(int bitpix, int *err)
00012 {
00013 DRMS_Type_t type = DRMS_TYPE_CHAR;
00014 int error = 0;
00015
00016 switch(bitpix)
00017 {
00018 case 8:
00019 type = DRMS_TYPE_CHAR;
00020 break;
00021 case 16:
00022 type = DRMS_TYPE_SHORT;
00023 break;
00024 case 32:
00025 type = DRMS_TYPE_INT;
00026 break;
00027 case 64:
00028 type = DRMS_TYPE_LONGLONG;
00029 break;
00030 case -32:
00031 type = DRMS_TYPE_FLOAT;
00032 break;
00033 case -64:
00034 type = DRMS_TYPE_DOUBLE;
00035 break;
00036 default:
00037 fprintf(stderr, "ERROR: Invalid bitpix value %d\n", bitpix);
00038 error = 1;
00039 break;
00040 }
00041
00042 if (err)
00043 {
00044 *err = error;
00045 }
00046
00047 return type;
00048 }
00049
00050 int drms_fitsrw_Type2Bitpix(DRMS_Type_t type, int *err)
00051 {
00052 int bitpix = 0;
00053 int error = 0;
00054
00055 switch(type)
00056 {
00057 case DRMS_TYPE_CHAR:
00058 bitpix = 8;
00059 break;
00060 case DRMS_TYPE_SHORT:
00061 bitpix = 16;
00062 break;
00063 case DRMS_TYPE_INT:
00064 bitpix = 32;
00065 break;
00066 case DRMS_TYPE_LONGLONG:
00067 bitpix = 64;
00068 break;
00069 case DRMS_TYPE_FLOAT:
00070 bitpix = -32;
00071 break;
00072 case DRMS_TYPE_DOUBLE:
00073 case DRMS_TYPE_TIME:
00074 bitpix = -64;
00075 break;
00076 case DRMS_TYPE_STRING:
00077 default:
00078 fprintf(stderr, "ERROR: Unsupported DRMS type %d\n", (int)type);
00079 error = 1;
00080 break;
00081 }
00082
00083 if (err)
00084 {
00085 *err = error;
00086 }
00087
00088 return bitpix;
00089 }
00090
00091 void drms_fitsrw_ShootBlanks(DRMS_Array_t *arr, long long blank)
00092 {
00093 if (arr->type != DRMS_TYPE_FLOAT &&
00094 arr->type != DRMS_TYPE_DOUBLE &&
00095 arr->type != DRMS_TYPE_TIME)
00096 {
00097 arraylen_t nelem = drms_array_count(arr);
00098 DRMS_Value_t val;
00099 long long dataval;
00100
00101 while (nelem > 0)
00102 {
00103 void *elem = (char *)arr->data + nelem - 1;
00104
00105 DRMS_VAL_SET(arr->type, elem, val);
00106 dataval = conv2longlong(arr->type, &(val.value), NULL);
00107
00108 if (dataval == blank)
00109 {
00110 drms_missing_vp(arr->type, elem);
00111 }
00112
00113 nelem--;
00114 }
00115 }
00116 }
00117
00118 int drms_fitsrw_CreateDRMSArray(CFITSIO_IMAGE_INFO *info, void *data, DRMS_Array_t **arrout)
00119 {
00120 DRMS_Array_t *retarr = NULL;
00121 int err = 0;
00122 DRMS_Type_t datatype;
00123 int drmsstatus = DRMS_SUCCESS;
00124 int naxis = 0;
00125 int axes[DRMS_MAXRANK] = {0};
00126 int ia;
00127
00128 if (info && data && arrout)
00129 {
00130 if (!(info->bitfield & kInfoPresent_SIMPLE) || !info->simple)
00131 {
00132 err = 1;
00133 fprintf(stderr, "Simple FITS file expected.\n");
00134 }
00135
00136 if (!err)
00137 {
00138 datatype = drms_fitsrw_Bitpix2Type(info->bitpix, &err);
00139 if (err)
00140 {
00141 fprintf(stderr, "BITPIX = %d not allowed\n", info->bitpix);
00142 }
00143 }
00144
00145 if (!err)
00146 {
00147 if (info->naxis >= 1 && info->naxis <= DRMS_MAXRANK)
00148 {
00149 naxis = info->naxis;
00150 }
00151 else
00152 {
00153 err = 1;
00154 fprintf(stderr,
00155 "%s = %d outside allowable DRMS range [1-%d].\n",
00156 kNAXIS,
00157 info->naxis,
00158 DRMS_MAXRANK);
00159 }
00160 }
00161
00162 if (!err)
00163 {
00164 for (ia = 0; ia < naxis; ia++)
00165 {
00166 axes[ia] = (int)(info->naxes[ia]);
00167 }
00168 }
00169
00170 if (!err)
00171 {
00172
00173 retarr = drms_array_create(datatype, naxis, axes, data, &drmsstatus);
00174 }
00175 else
00176 {
00177 err = 1;
00178 }
00179
00180 retarr->bzero = 0.0;
00181 retarr->bscale = 1.0;
00182
00183 if (!err && info->bitpix > 0)
00184 {
00185
00186
00187 if (info->bitfield & kInfoPresent_BLANK)
00188 {
00189 drms_fitsrw_ShootBlanks(retarr, info->blank);
00190 }
00191
00192 if (info->bitfield & kInfoPresent_BZERO)
00193 {
00194 retarr->bzero = info->bzero;
00195 }
00196
00197 if (info->bitfield & kInfoPresent_BSCALE)
00198 {
00199 retarr->bscale = info->bscale;
00200 }
00201 }
00202
00203 if (!err)
00204 {
00205 retarr->israw = 1;
00206 *arrout = retarr;
00207 }
00208 }
00209
00210 return err;
00211 }
00212
00213 int drms_fitsrw_SetImageInfo(DRMS_Array_t *arr, CFITSIO_IMAGE_INFO *info)
00214 {
00215 int err = 0;
00216 int ia;
00217
00218 if (info)
00219 {
00220 memset(info, 0, sizeof(CFITSIO_IMAGE_INFO));
00221 info->bitpix = drms_fitsrw_Type2Bitpix(arr->type, &err);
00222
00223 if (!err)
00224 {
00225 if (arr->naxis > 0)
00226 {
00227 info->naxis = arr->naxis;
00228 }
00229 else
00230 {
00231 err = 1;
00232 }
00233 }
00234
00235 if (!err)
00236 {
00237 for (ia = 0; ia < arr->naxis; ia++)
00238 {
00239 info->naxes[ia] = (long)(arr->axis[ia]);
00240 }
00241
00242 info->simple = 1;
00243 info->extend = 0;
00244 info->bitfield = (info->bitfield | kInfoPresent_SIMPLE);
00245
00246 if (info->bitpix > 0)
00247 {
00248
00249 DRMS_Type_Value_t missing;
00250 drms_missing(arr->type, &missing);
00251
00252 info->blank = conv2longlong(arr->type, &missing, NULL);
00253 info->bitfield = (info->bitfield | kInfoPresent_BLANK);
00254
00255 if (arr->israw)
00256 {
00257
00258
00259 #ifdef ICCCOMP
00260 #pragma warning (disable : 1572)
00261 #endif
00262 if (arr->bscale != 1.0 || fabs(arr->bzero) != 0.0)
00263 {
00264 info->bscale = arr->bscale;
00265 info->bzero = arr->bzero;
00266
00267 info->bitfield = (info->bitfield | kInfoPresent_BSCALE);
00268 info->bitfield = (info->bitfield | kInfoPresent_BZERO);
00269 }
00270 #ifdef ICCCOMP
00271 #pragma warning (default : 1572)
00272 #endif
00273 }
00274 }
00275 }
00276 }
00277
00278 return err;
00279 }
00280
00281 int drms_fitsrw_GetSimpleFromInfo(CFITSIO_IMAGE_INFO *info)
00282 {
00283 if (info->bitfield & kInfoPresent_SIMPLE)
00284 {
00285 return info->simple;
00286 }
00287 else
00288 {
00289
00290 return 1;
00291 }
00292 }
00293
00294 int drms_fitsrw_GetExtendFromInfo(CFITSIO_IMAGE_INFO *info)
00295 {
00296 if (info->bitfield & kInfoPresent_EXTEND)
00297 {
00298 return info->extend;
00299 }
00300 else
00301 {
00302
00303 return 0;
00304 }
00305 }
00306
00307 long long drms_fitsrw_GetBlankFromInfo(CFITSIO_IMAGE_INFO *info)
00308 {
00309 if (info->bitfield & kInfoPresent_BLANK)
00310 {
00311 return info->blank;
00312 }
00313 else
00314 {
00315
00316 DRMS_Type_Value_t missing;
00317 DRMS_Type_t dtype;
00318 int err;
00319
00320 dtype = drms_fitsrw_Bitpix2Type(info->bitpix, &err);
00321 if (!err)
00322 {
00323 drms_missing(dtype, &missing);
00324 }
00325 else
00326 {
00327
00328
00329 fprintf(stderr, "Unable to convert bitpix %d to a DRMS data type.\n", info->bitpix);
00330 drms_missing(DRMS_TYPE_CHAR, &missing);
00331 }
00332
00333 return conv2longlong(dtype, &missing, NULL);
00334 }
00335 }
00336
00337 double drms_fitsrw_GetBscaleFromInfo(CFITSIO_IMAGE_INFO *info)
00338 {
00339 if (info->bitfield & kInfoPresent_BSCALE)
00340 {
00341 return info->bscale;
00342 }
00343 else
00344 {
00345
00346 return 1.0;
00347 }
00348 }
00349
00350 double drms_fitsrw_GetBzeroFromInfo(CFITSIO_IMAGE_INFO *info)
00351 {
00352 if (info->bitfield & kInfoPresent_BZERO)
00353 {
00354 return info->bzero;
00355 }
00356 else
00357 {
00358
00359 return 0.0;
00360 }
00361 }
00362
00363 void drms_fitsrw_term(int verbose)
00364 {
00365 fitsrw_closefptrs(verbose);
00366 }
00367
00368 void drms_fitsrw_close(int verbose, const char *filename)
00369 {
00370 fitsrw_closefptrByName(verbose, filename);
00371 }
00372
00373 DRMS_Array_t *drms_fitsrw_read(DRMS_Env_t *env,
00374 const char *filename,
00375 int readraw,
00376 HContainer_t **keywords,
00377 int *status)
00378 {
00379 int statusint = DRMS_SUCCESS;
00380 CFITSIO_IMAGE_INFO *info = NULL;
00381 void *image = NULL;
00382 CFITSIO_KEYWORD* keylist = NULL;
00383 CFITSIO_KEYWORD* fitskey = NULL;
00384 int fitsrwstat = CFITSIO_SUCCESS;
00385 DRMS_Array_t *arr = NULL;
00386
00387
00388 fitsrwstat = fitsrw_read(env->verbose, filename, &info, &image, &keylist);
00389
00390 if (fitsrwstat != CFITSIO_SUCCESS)
00391 {
00392 statusint = DRMS_ERROR_FITSRW;
00393 fprintf(stderr, "FITSRW error '%d'.\n", fitsrwstat);
00394 }
00395 else
00396 {
00397
00398 if (drms_fitsrw_CreateDRMSArray(info, image, &arr))
00399 {
00400 statusint = DRMS_ERROR_ARRAYCREATEFAILED;
00401 }
00402 else
00403 {
00404
00405 if (!readraw && (arr->bscale != 1.0 || arr->bzero != 0.0))
00406 {
00407 drms_array_convert_inplace(arr->type, arr->bzero, arr->bscale, arr);
00408 arr->israw = 0;
00409 }
00410
00411
00412 if (keywords)
00413 {
00414 if (!*keywords)
00415 {
00416
00417 *keywords = hcon_create(sizeof(DRMS_Keyword_t),
00418 DRMS_MAXKEYNAMELEN,
00419 (void (*)(const void *)) drms_free_template_keyword_struct,
00420 NULL,
00421 NULL,
00422 NULL,
00423 0);
00424 }
00425
00426
00427
00428 fitskey = keylist;
00429 while (fitskey != NULL)
00430 {
00431
00432 if (fitsexport_mapimportkey(fitskey, NULL, NULL, *keywords, env->verbose))
00433 {
00434 fprintf(stderr, "Error importing fits keyword '%s'; skipping.\n", fitskey->key_name);
00435 }
00436
00437 fitskey = fitskey->next;
00438 }
00439 }
00440
00441
00442 cfitsio_free_these(&info, NULL, &keylist);
00443 }
00444 }
00445
00446 if (status)
00447 {
00448 *status = statusint;
00449 }
00450
00451 return arr;
00452 }
00453
00454
00455 void drms_fitsrw_freekeys(HContainer_t **keywords)
00456 {
00457 if (keywords)
00458 {
00459 DRMS_Keyword_t *key = NULL;
00460 HIterator_t *hit = hiter_create(*keywords);
00461
00462
00463 while ((key = hiter_getnext(hit)) != NULL)
00464 {
00465 if (!key->record && key->info)
00466 {
00467 if (key->info->type == DRMS_TYPE_STRING)
00468 {
00469 free((key->value).string_val);
00470 }
00471
00472 free(key->info);
00473 }
00474 }
00475
00476 hiter_destroy(&hit);
00477
00478 hcon_destroy(keywords);
00479 }
00480 }
00481
00482
00483 int drms_fitsrw_readslice(DRMS_Env_t *env,
00484 const char *filename,
00485 int naxis,
00486 int *start,
00487 int *end,
00488 DRMS_Array_t **arr)
00489 {
00490 int status = DRMS_SUCCESS;
00491 CFITSIO_IMAGE_INFO *info = NULL;
00492 void *image = NULL;
00493 int fitsrwstat = CFITSIO_SUCCESS;
00494
00495
00496
00497
00498
00499
00500 fitsrwstat = fitsrw_readslice(env->verbose, filename, start, end, &info, &image);
00501
00502 if (fitsrwstat != CFITSIO_SUCCESS)
00503 {
00504 status = DRMS_ERROR_FITSRW;
00505 fprintf(stderr, "FITSRW error '%d'.\n", fitsrwstat);
00506 }
00507 else
00508 {
00509 if (naxis != info->naxis)
00510 {
00511 fprintf(stderr, "TAS file axis mismatch.\n");
00512 status = DRMS_ERROR_FITSRW;
00513 }
00514 else
00515 {
00516 if (drms_fitsrw_CreateDRMSArray(info, image, arr))
00517 {
00518 status = DRMS_ERROR_ARRAYCREATEFAILED;
00519 }
00520 }
00521
00522
00523 cfitsio_free_these(&info, NULL, NULL);
00524 }
00525
00526 return status;
00527 }
00528
00529 int drms_fitsrw_write(DRMS_Env_t *env,
00530 const char *filename,
00531 const char* cparms,
00532 HContainer_t *keywords,
00533 DRMS_Array_t *arr)
00534 {
00535 int status = DRMS_SUCCESS;
00536 CFITSIO_IMAGE_INFO imginfo;
00537 void *image = NULL;
00538 CFITSIO_KEYWORD* keylist = NULL;
00539 HIterator_t hit;
00540 DRMS_Keyword_t *key = NULL;
00541 const char *keyname = NULL;
00542 int fitsrwstat;
00543
00544 if (arr && arr->data && keywords)
00545 {
00546
00547 hiter_new_sort(&hit, keywords, drms_keyword_ranksort);
00548 while ((key = hiter_getnext(&hit)) != NULL)
00549 {
00550 if (!drms_keyword_getimplicit(key))
00551 {
00552
00553
00554 if (fitsexport_exportkey(key, &keylist))
00555 {
00556 keyname = drms_keyword_getname(key);
00557 fprintf(stderr, "Couldn't export keyword '%s'.\n", keyname);
00558 }
00559 }
00560 }
00561
00562 if (keylist)
00563 {
00564 cfitsio_free_keys(&keylist);
00565 }
00566
00567
00568 image = arr->data;
00569
00570
00571 if (!drms_fitsrw_SetImageInfo(arr, &imginfo))
00572 {
00573 if (arr->type == DRMS_TYPE_STRING ||
00574 arr->type == DRMS_TYPE_TIME ||
00575 arr->type == DRMS_TYPE_RAW)
00576 {
00577 fprintf(stderr, "Type '%s' not supported in FITS.\n", drms_type2str(arr->type));
00578 status = DRMS_ERROR_FITSRW;
00579 }
00580 else
00581 {
00582 fitsrwstat = fitsrw_write(env->verbose, filename, &imginfo, image, cparms, keylist);
00583 if (fitsrwstat != CFITSIO_SUCCESS)
00584 {
00585 status = DRMS_ERROR_FITSRW;
00586 fprintf(stderr, "FITSRW error '%d'.\n", fitsrwstat);
00587 }
00588 }
00589 }
00590 else
00591 {
00592 fprintf(stderr, "Data array being exported is invalid.\n");
00593 status = DRMS_ERROR_FITSRW;
00594 }
00595 }
00596 else
00597 {
00598 fprintf(stderr, "WARNING: no data to write to FITS.\n");
00599 }
00600
00601 return status;
00602 }
00603
00604
00605 int drms_fitsrw_writeslice_ext(DRMS_Env_t *env,
00606 DRMS_Segment_t *seg,
00607 const char *filename,
00608 int naxis,
00609 int *start,
00610 int *end,
00611 int *finaldims,
00612 DRMS_Array_t *arrayout)
00613 {
00614 int status = DRMS_SUCCESS;
00615 int fitsrwstat = CFITSIO_SUCCESS;
00616
00617
00618
00619
00620 struct stat stbuf;
00621 if (stat(filename, &stbuf) == -1)
00622 {
00623 CFITSIO_IMAGE_INFO info;
00624 DRMS_Array_t arr;
00625 int usearrout;
00626 int idim;
00627
00628 memset(&arr, 0, sizeof(DRMS_Array_t));
00629
00630
00631
00632 if (seg->info->type != DRMS_TYPE_RAW)
00633 {
00634 arr.type = seg->info->type;
00635 arr.naxis = seg->info->naxis;
00636 memcpy(arr.axis, seg->axis, sizeof(int) * seg->info->naxis);
00637 arr.bzero = seg->bzero;
00638 arr.bscale = seg->bscale;
00639
00640
00641
00642 if (seg->bzero == 0.0 && seg->bscale == 1.0)
00643 {
00644 arr.israw = 0;
00645 }
00646 else
00647 {
00648 arr.israw = 1;
00649 }
00650
00651
00652 usearrout = 0;
00653
00654
00655
00656
00657
00658
00659 if (finaldims)
00660 {
00661
00662
00663
00664 idim = 0;
00665 while (idim < arr.naxis)
00666 {
00667 if (finaldims[idim] < arrayout->axis[idim])
00668 {
00669 status = DRMS_ERROR_INVALIDDIMS;
00670 break;
00671 }
00672 else
00673 {
00674 arr.axis[idim] = finaldims[idim];
00675 }
00676
00677 idim++;
00678 }
00679 }
00680 else
00681 {
00682 idim = 0;
00683 while (idim < arr.naxis - 1)
00684 {
00685 if (arr.axis[idim++] == 0)
00686 {
00687 usearrout = 1;
00688 break;
00689 }
00690 }
00691
00692 if (usearrout)
00693 {
00694 idim = 0;
00695 while (idim < arr.naxis - 1)
00696 {
00697 arr.axis[idim] = arrayout->axis[idim];
00698 idim++;
00699 }
00700 }
00701 }
00702
00703 if (status == DRMS_SUCCESS)
00704 {
00705 if (arr.axis[arr.naxis - 1] == 0)
00706 {
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716 arr.axis[arr.naxis - 1] = 1;
00717 }
00718
00719 if (!drms_fitsrw_SetImageInfo(&arr, &info))
00720 {
00721 if (fitsrw_writeintfile(env->verbose, filename, &info, NULL, seg->cparms, NULL) != CFITSIO_SUCCESS)
00722 {
00723 fprintf(stderr, "Couldn't create FITS file '%s'.\n", filename);
00724 status = DRMS_ERROR_CANTCREATETASFILE;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 }
00737 else
00738 {
00739 fprintf(stderr, "Couldn't set FITS file image info.\n");
00740 status = DRMS_ERROR_CANTCREATETASFILE;
00741 }
00742 }
00743 }
00744 else
00745 {
00746 status = DRMS_ERROR_INVALIDTYPE;
00747 }
00748 }
00749
00750 if (status == DRMS_SUCCESS)
00751 {
00752 if (naxis != arrayout->naxis)
00753 {
00754 fprintf(stderr, "TAS file axis mismatch.\n");
00755 status = DRMS_ERROR_FITSRW;
00756 }
00757 else
00758 {
00759
00760
00761 fitsrwstat = fitsrw_writeslice(env->verbose,
00762 filename,
00763 start,
00764 end,
00765 arrayout->data);
00766
00767
00768 if (fitsrwstat != CFITSIO_SUCCESS)
00769 {
00770 fprintf(stderr, "FITSRW error '%d'.\n", fitsrwstat);
00771 status = DRMS_ERROR_FITSRW;
00772 }
00773 }
00774 }
00775
00776 return status;
00777 }
00778
00779 int drms_fitsrw_writeslice(DRMS_Env_t *env,
00780 DRMS_Segment_t *seg,
00781 const char *filename,
00782 int naxis,
00783 int *start,
00784 int *end,
00785 DRMS_Array_t *arrayout)
00786 {
00787 return drms_fitsrw_writeslice_ext(env, seg, filename, naxis, start, end, NULL, arrayout);
00788 }