source: trunk/src/Cubes/saveImage.cc @ 120

Last change on this file since 120 was 120, checked in by Matthew Whiting, 18 years ago

Introduced error and warning reporting functions, to normalise the format
of errors and warnings. Definitions of functions go in duchamp.cc.
Changed all code that reports errors/warnings to use these new functions.

Fixed a couple of bugs that affected the way 2D images were dealt with:
ReconSearch? now looks at how many dimensions there are in the data array
before choosing the dimension of the reconstruction, and the minChannels
test was improved for the case of minChannels=0.

Some minor additions made to the Guide as well.

File size: 7.3 KB
Line 
1#include <iostream>
2#include <sstream>
3#include <string>
4#include <wcs.h>
5#include <wcshdr.h>
6#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine wtbarr
7                         // (this is a problem when using cfitsio v.3 and g++ v.4)
8#include <fitsio.h>
9#include <duchamp.hh>
10#include <Cubes/cubes.hh>
11
12void write_header_info(fitsfile *fptr, Param &par, string nature);
13
14void Cube::saveReconstructedCube()
15{
16  /**
17   *  Cube::saveReconstructedCube()
18   *
19   *   A function to save the reconstructed and/or residual arrays.
20   *   A number of header keywords are written as well, indicating the nature of the
21   *    reconstruction that has been done.
22   *   The file is always written -- if the filename (as calculated based on the
23   *    recon parameters) exists, then it is overwritten.
24   */
25 
26  int newbitpix = FLOAT_IMG;
27
28  float *resid = new float[this->numPixels];
29  for(int i=0;i<this->numPixels;i++) resid[i] = this->array[i] - this->recon[i];
30  float blankval = this->par.getBlankPixVal();
31
32  long *fpixel = new long[this->numDim];
33  for(int i=0;i<this->numDim;i++) fpixel[i]=1;
34  int status = 0;  /* MUST initialize status */
35  fitsfile *fptrOld, *fptrNew;         
36  fits_open_file(&fptrOld,this->par.getImageFile().c_str(),READONLY,&status);
37  if (status) fits_report_error(stderr, status);
38 
39  if(this->par.getFlagOutputRecon()){
40    string fileout = "!" + this->par.outputReconFile(); // ! so that it writes over an existing file.
41
42    status = 0;
43    fits_create_file(&fptrNew,fileout.c_str(),&status);
44    if (status)
45      fits_report_error(stderr, status);
46    else
47      {
48        status = 0;
49        fits_movabs_hdu(fptrOld, 1, NULL, &status);
50        if (status) fits_report_error(stderr, status);
51        status = 0;
52        fits_copy_header(fptrOld, fptrNew, &status);
53        if (status) fits_report_error(stderr, status);
54        char *comment = new char[80];
55        long dud;
56        status = 0;
57        fits_update_key(fptrNew, TINT, "BITPIX", &newbitpix, "number of bits per data pixel", &status);
58        if (status) fits_report_error(stderr, status);
59        status = 0;
60        float bscale=1., bzero=0.;
61        fits_update_key(fptrNew, TFLOAT, "BSCALE", &bscale, "PHYSICAL = PIXEL*BSCALE + BZERO", &status);
62        fits_update_key(fptrNew, TFLOAT, "BZERO", &bzero, "", &status);
63        fits_set_bscale(fptrNew, 1., 0., &status);
64        if (status) fits_report_error(stderr, status);
65        // Need to correct the dimensions, if we have subsectioned the image...   
66        if(this->par.getFlagSubsection()){
67          fits_read_key(fptrOld, TLONG, "NAXIS1", &dud, comment, &status);
68          fits_update_key(fptrNew, TLONG, "NAXIS1", &(this->axisDim[0]), comment, &status);
69          fits_read_key(fptrOld, TLONG, "NAXIS2", &dud, comment, &status);
70          fits_update_key(fptrNew, TLONG, "NAXIS2", &(this->axisDim[1]), comment, &status);
71          fits_read_key(fptrOld, TLONG, "NAXIS3", &dud, comment, &status);
72          fits_update_key(fptrNew, TLONG, "NAXIS3", &(this->axisDim[2]), comment, &status);
73        }
74
75        write_header_info(fptrNew, this->par, "recon");
76
77        if(this->par.getFlagBlankPix())
78          fits_write_pixnull(fptrNew, TFLOAT, fpixel, this->numPixels, this->recon, &blankval, &status);
79        else  fits_write_pix(fptrNew, TFLOAT, fpixel, this->numPixels, this->recon, &status);
80
81        status = 0;
82        fits_close_file(fptrNew, &status);
83        if (status) fits_report_error(stderr, status);
84      }
85  }
86
87
88  if(this->par.getFlagOutputResid()){
89    string fileout = "!" + this->par.outputResidFile(); // ! so that it writes over an existing file.
90    status = 0;
91    fits_create_file(&fptrNew,fileout.c_str(),&status);
92    if (status)
93      fits_report_error(stderr, status);
94    else
95      {
96        status = 0;
97        fits_movabs_hdu(fptrOld, 1, NULL, &status);
98        if (status) fits_report_error(stderr, status);
99        status = 0;
100        fits_copy_header(fptrOld, fptrNew, &status);
101        if (status) fits_report_error(stderr, status);
102
103        status = 0;
104        fits_update_key(fptrNew, TINT, "BITPIX", &newbitpix, "number of bits per data pixel", &status);
105        if (status) fits_report_error(stderr, status);
106        status = 0;
107        float bscale=1., bzero=0.;
108        fits_update_key(fptrNew, TFLOAT, "BSCALE", &bscale, "PHYSICAL = PIXEL*BSCALE + BZERO", &status);
109        fits_update_key(fptrNew, TFLOAT, "BZERO", &bzero, "", &status);
110        fits_set_bscale(fptrNew, 1., 0., &status);
111        if (status) fits_report_error(stderr, status);
112
113        // Need to correct the dimensions, if we have subsectioned the image...
114        char *comment = new char[80];
115        long dud;
116        if(this->pars().getFlagSubsection()){
117          fits_read_key(fptrOld, TLONG, "NAXIS1", &dud, comment, &status);
118          fits_update_key(fptrNew, TLONG, "NAXIS1", &(this->axisDim[0]), comment, &status);
119          fits_read_key(fptrOld, TLONG, "NAXIS2", &dud, comment, &status);
120          fits_update_key(fptrNew, TLONG, "NAXIS2", &(this->axisDim[1]), comment, &status);
121          fits_read_key(fptrOld, TLONG, "NAXIS3", &dud, comment, &status);
122          fits_update_key(fptrNew, TLONG, "NAXIS3", &(this->axisDim[2]), comment, &status);
123        }
124
125        write_header_info(fptrNew, this->par, "resid");
126
127        if(this->par.getFlagBlankPix())
128          fits_write_pixnull(fptrNew, TFLOAT, fpixel, this->numPixels, resid, &blankval, &status);
129        else  fits_write_pix(fptrNew, TFLOAT, fpixel, this->numPixels, resid, &status);
130
131        fits_close_file(fptrNew, &status);
132      }
133  }
134
135  delete [] resid;
136  delete [] fpixel;
137
138}
139
140
141void write_header_info(fitsfile *fptr, Param &par, string nature)
142{
143  /**
144   *  write_header_info(fptr, par, nature)
145   *
146   *   A simple function that writes all the necessary keywords and comments
147   *    to the FITS header pointed to by fptr.
148   *   The keyword names and comments are taken from duchamp.hh
149   *   The parameter "nature" indicates what type of file is being written:
150   *    should be either "recon" or "resid".
151   */
152
153
154  int status = 0;
155  char *comment, *keyword;
156  string explanation = "",ReconResid="";
157
158  fits_write_history(fptr, (char *)header_history1.c_str(), &status);
159                                   
160  fits_write_history(fptr, (char *)header_history2.c_str(), &status);
161
162  fits_write_history(fptr, (char *)header_history_input.c_str(), &status);
163
164  fits_write_history(fptr, (char *)par.getImageFile().c_str(), &status);
165
166  if(par.getFlagSubsection()){
167    fits_write_comment(fptr, (char *)header_subsection_comment.c_str(), &status);
168    fits_write_key(fptr, TSTRING, (char *)keyword_subsection.c_str(),
169                   (char *)par.getSubsection().c_str(),
170                   (char *)comment_subsection.c_str(), &status);
171  }
172   
173  fits_write_comment(fptr, (char *)header_atrous_comment.c_str(), &status);
174
175  float valf = par.getAtrousCut();
176  fits_write_key(fptr, TFLOAT, (char *)keyword_snrRecon.c_str(), &valf,
177                 (char *)comment_snrRecon.c_str(), &status);
178
179  int vali = par.getReconDim();
180  fits_write_key(fptr, TINT, (char *)keyword_reconDim.c_str(), &vali,
181                 (char *)comment_reconDim.c_str(), &status);
182
183  vali = par.getMinScale();
184  fits_write_key(fptr, TINT, (char *)keyword_scaleMin.c_str(), &vali,
185                 (char *)comment_scaleMin.c_str(), &status);
186
187  vali = par.getFilterCode();
188  fits_write_key(fptr, TINT, (char *)keyword_filterCode.c_str(), &vali,
189                 (char *)comment_filterCode.c_str(), &status);
190
191  if(nature == "recon"){
192    explanation = "Duchamp: This is the RECONSTRUCTED cube";
193    ReconResid = "RECON";
194  }
195  else if(nature == "resid"){
196    explanation = "Duchamp: This is the RESIDUAL cube";
197    ReconResid = "RESID";
198  }
199  else duchampWarning("write_header_info","explanation not present!\n");
200  fits_write_comment(fptr, (char *)explanation.c_str(), &status);
201  fits_write_key(fptr, TSTRING, (char *)keyword_ReconResid.c_str(),
202                 (char *)ReconResid.c_str(), (char *)comment_ReconResid.c_str(), &status);
203
204}
Note: See TracBrowser for help on using the repository browser.