00001 #include "mex.h"
00002 #include <math.h>
00003 #include <string.h>
00004 #include "fitsio.h"
00005 #include "mexhead.h"
00006 #include "Doc/savefitsa_docstring.h"
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 #define NARGIN_MIN 2
00077 #define NARGIN_MAX 7
00078 #define NARGOUT_MIN 0
00079 #define NARGOUT_MAX 1
00080
00081 #define ARG_ARRAY 0
00082 #define ARG_FILENAME 1
00083 #define ARG_BITPIX 2
00084 #define ARG_BSCALE 3
00085 #define ARG_BZERO 4
00086 #define ARG_BLANK 5
00087 #define ARG_MODE 6
00088
00089 #define ARG_ERROR 0
00090
00091 #define PROGNAME savefitsa
00092 static const char *progname = "savefitsa";
00093 static const char *in_specs[NARGIN_MAX] = { "RA", "SV", "IS", "RS", "RS", "IS", "SV" };
00094 static const char *in_names[NARGIN_MAX] = { "array", "filename",
00095 "bitpix", "bscale", "bzero", "blank", "mode" };
00096 static const char *out_names[NARGOUT_MAX] = { "error" };
00097
00098
00099
00100
00101
00102 static
00103 void
00104 fits_printerror(int status)
00105 {
00106 char errmsg[81];
00107
00108 mexPrintf("%s: Runtime error (%s). Exiting.\n",
00109 progname,
00110 (status == 0) ? "not a FITSIO error" : "FITSIO trace follows");
00111 if (status != 0) {
00112 fits_get_errstatus(status, errmsg);
00113 mexPrintf("status = %d: %s\n", status, errmsg);
00114
00115 mexPrintf("Error message stack:\n");
00116 while (fits_read_errmsg(errmsg))
00117 mexPrintf("\t%s\n", errmsg);
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126 static
00127 char *
00128 extract_mode(char *mode, int *Mdate, int *Mhist, int *Mcsum)
00129 {
00130 char *word;
00131 char *sep = ", \t";
00132
00133 if (!mode) return "null";
00134 for (word = strtok(mode, sep); word; word = strtok(NULL, sep)) {
00135
00136 if (strcasecmp(word, "+date" ) == 0) { *Mdate = 1; }
00137 else if (strcasecmp(word, "-date" ) == 0) { *Mdate = 0; }
00138 else if (strcasecmp(word, "+history") == 0) { *Mhist = 1; }
00139 else if (strcasecmp(word, "-history") == 0) { *Mhist = 0; }
00140 else if (strcasecmp(word, "+check" ) == 0) { *Mcsum = 1; }
00141 else if (strcasecmp(word, "-check" ) == 0) { *Mcsum = 0; }
00142
00143 else return word;
00144 }
00145 return 0;
00146 }
00147
00148
00149
00150 static
00151 int
00152 fio_PutFITS(const mxArray *m, char *filename, int bitpix,
00153 double bscale, double bzero,
00154 double blank, int use_blank,
00155 int put_date, int put_hist, int put_csum)
00156 {
00157 fitsfile *fptr;
00158 int status = 0;
00159 long naxis;
00160 const mwSize *naxesM;
00161 long *naxesF;
00162 long nelem;
00163 long i;
00164 double *data;
00165
00166
00167 naxis = mxGetNumberOfDimensions(m);
00168 nelem = mxGetNumberOfElements(m);
00169 naxesM = mxGetDimensions(m);
00170 naxesF = mxCalloc(naxis, sizeof(long));
00171 for (i = 0; i < naxis; i++)
00172 naxesF[i] = (long) naxesM[i];
00173
00174 unlink(filename);
00175 fits_create_file(&fptr, filename, &status);
00176
00177 fits_create_img(fptr, bitpix, naxis, naxesF, &status);
00178 mxFree(naxesF);
00179
00180 if (bscale != 1 || bzero != 0) {
00181 fits_write_key(fptr, TDOUBLE, "BSCALE", &bscale, "scale", &status);
00182 fits_write_key(fptr, TDOUBLE, "BZERO", &bzero, "offset", &status);
00183 }
00184
00185
00186 if (use_blank) {
00187 int int_blank = blank;
00188 fits_write_key(fptr, TINT, "BLANK", &int_blank, "blank", &status);
00189 }
00190
00191 if (status) {
00192 fits_printerror(status);
00193 unlink(filename);
00194 return 1;
00195 }
00196
00197 data = mxGetPr(m);
00198 if ((bitpix < 0) || (use_blank == 0)) {
00199
00200 fits_write_img(fptr, TDOUBLE, 1L, nelem, data, &status);
00201 } else {
00202
00203
00204
00205
00206
00207 double *data2;
00208 const double blank_value = bscale*blank+bzero;
00209 if ((data2 = mxCalloc(nelem, sizeof(double))) == NULL) {
00210 fits_printerror(status);
00211 unlink(filename);
00212 return 1;
00213 }
00214 for (i = 0; i < nelem; i++)
00215 data2[i] = isnan(data[i]) ? blank_value : data[i];
00216 fits_write_img(fptr, TDOUBLE, 1L, nelem, data2, &status);
00217 mxFree(data2);
00218 }
00219
00220 if (put_date)
00221 fits_write_date(fptr, &status);
00222 if (put_hist)
00223 fits_write_history(fptr, "Saved from Matlab, savefitsa ver. 1.2", &status);
00224 if (put_csum)
00225 fits_write_chksum(fptr, &status);
00226
00227 if (status) {
00228 fits_printerror(status);
00229 unlink(filename);
00230 return 1;
00231 }
00232
00233 if (fits_close_file(fptr, &status)) {
00234
00235 fits_printerror(status);
00236 unlink(filename);
00237 return 1;
00238 }
00239
00240 return 0;
00241 }
00242
00243 #ifdef StaticP
00244 StaticP
00245 #endif
00246 void
00247 mexFunction(int nlhs,
00248 mxArray *plhs[],
00249 int nrhs,
00250 const mxArray *prhs[])
00251 {
00252 char *filename;
00253 char *mode, *word;
00254 int error;
00255 char errstr[256];
00256
00257 int bitpix = -64;
00258 double bscale = 1.0;
00259 double bzero = 0.0;
00260 int use_blank = 0;
00261 double blank;
00262
00263 int mode_date = 1;
00264 int mode_hist = 1;
00265 int mode_csum = 1;
00266
00267
00268 if (nrhs < 0) {
00269 plhs[0] = mxt_PackSignature((mxt_Signature) (-nrhs),
00270 NARGIN_MIN, NARGIN_MAX,
00271 NARGOUT_MIN, NARGOUT_MAX,
00272 in_names, in_specs, out_names, docstring);
00273 return;
00274 }
00275
00276 if ((nrhs < NARGIN_MIN) || (nrhs > NARGIN_MAX))
00277 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00278 "%s: Expect %d <= input args <= %d",
00279 progname, NARGIN_MIN, NARGIN_MAX), errstr));
00280 if ((nlhs < NARGOUT_MIN) || (nlhs > NARGOUT_MAX))
00281 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00282 "%s: Expect %d <= output args <= %d",
00283 progname, NARGOUT_MIN, NARGOUT_MAX), errstr));
00284 mexargparse(nrhs, prhs, in_names, in_specs, NULL, progname);
00285
00286
00287 start_sizechecking();
00288 sizeinit(prhs[ARG_FILENAME]);
00289 sizeisM(1);
00290 sizecheck_msg(progname, in_names, ARG_FILENAME);
00291
00292
00293 filename = mxArrayToString(prhs[ARG_FILENAME]);
00294 if (!filename)
00295 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00296 "%s: Trouble converting filename string",
00297 progname), errstr));
00298
00299
00300 if (nrhs > ARG_BITPIX)
00301 bitpix = (int) mxGetScalar(prhs[ARG_BITPIX]);
00302 if ((bitpix != 8) && (bitpix != 16) && (bitpix != 32) && (bitpix != 64) &&
00303 (bitpix != -32) && (bitpix != -64))
00304 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00305 "%s: can't do bitpix = %d.",
00306 progname, bitpix), errstr));
00307
00308
00309 if (nrhs > ARG_BSCALE)
00310 bscale = mxGetScalar(prhs[ARG_BSCALE]);
00311 if (nrhs > ARG_BZERO)
00312 bzero = mxGetScalar(prhs[ARG_BZERO]);
00313
00314
00315 if (nrhs > ARG_BLANK && bitpix > 0) {
00316 use_blank = 1;
00317 blank = mxGetScalar(prhs[ARG_BLANK]);
00318
00319 if (isnan(blank)) {
00320
00321 if (bitpix == 8) blank = 255.0;
00322 else if (bitpix == 16) blank = -32768.0;
00323 else if (bitpix == 32) blank = -2147483648.0;
00324 else if (bitpix == 64) blank = -4503599627370496.0;
00325 }
00326 }
00327
00328 if (nrhs > ARG_MODE) {
00329
00330 if ((mode = mxArrayToString(prhs[ARG_MODE])) == NULL)
00331 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00332 "%s: bad mode (non-string?). "
00333 "Could not convert mode arg to string.",
00334 progname), errstr));
00335 if ((word = extract_mode(mode, &mode_date, &mode_hist, &mode_csum)) != NULL)
00336 mexErrMsgTxt((snprintf(errstr, sizeof(errstr),
00337 "%s: bad word <%s> in mode <%.80s>",
00338 progname, word,
00339 mxArrayToString(prhs[ARG_MODE])), errstr));
00340 mxFree(mode);
00341 }
00342
00343
00344
00345 error = fio_PutFITS(prhs[ARG_ARRAY],
00346 filename,
00347 bitpix, bscale, bzero, blank, use_blank,
00348 mode_date, mode_hist, mode_csum);
00349 mxFree(filename);
00350
00351 plhs[ARG_ERROR] = mxCreateDoubleScalar((double) error);
00352 }
00353
00354
00355
00356 #ifdef MEX2C_TAIL_HOOK
00357 #include "mex2c_tail.h"
00358 #endif