source: tags/release-1.1.5/src/Cubes/getImage.cc @ 1441

Last change on this file since 1441 was 443, checked in by MatthewWhiting, 16 years ago

Improving the getMetadata() functionality, including adding an axisDimAllocated flag to keep track of the allocation of memory.

File size: 8.3 KB
Line 
1// -----------------------------------------------------------------------
2// getImage.cc: Read in a FITS file to a Cube object.
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
28#include <iostream>
29#include <string>
30#include <string.h>
31#include <wcslib/wcs.h>
32#include <wcslib/wcshdr.h>
33#include <wcslib/fitshdr.h>
34#include <wcslib/wcsfix.h>
35#include <wcslib/wcsunits.h>
36#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine
37                         //  wtbarr (this is a problem when using gcc v.4+)
38#include <fitsio.h>
39#include <math.h>
40#include <duchamp/duchamp.hh>
41#include <duchamp/param.hh>
42#include <duchamp/fitsHeader.hh>
43#include <duchamp/Cubes/cubes.hh>
44
45namespace duchamp
46{
47
48  std::string imageType[4] = {"point", "spectrum", "image", "cube"};
49
50  int Cube::getMetadata(){ 
51    /**
52     * A front-end to the Cube::getMetadata() function, that does
53     *  subsection checks. Does the flux unit conversion if the user
54     *  has requested it. Assumes the Param is set up properly.
55     */
56    std::string fname = par.getImageFile();
57    if(par.getFlagSubsection()) fname+=par.getSubsection();
58
59    int result = getMetadata(fname);
60   
61    if(result==SUCCESS){
62      // Convert the flux Units if the user has so requested
63      this->convertFluxUnits();
64    }
65
66    return result;
67  }
68  //--------------------------------------------------------------------
69
70  int Cube::getMetadata(std::string fname)
71  {
72    /**
73     * Read in the metadata associated with the cube from the file
74     *  fname (assumed to be in FITS format).  Function is a front end
75     *  to the I/O functions in the FitsIO/ directory.  This function
76     *  will check that the file exists, report the dimensions and
77     *  then get other functions to read the WCS and necessary header
78     *  keywords. This function does not read in the data array --
79     *  that is done by Cube::getCube(). Note that no conversion of
80     *  flux units is done -- you need to call Cube::getMetadata() or
81     *  do it separately.
82     *  \param fname A std::string with name of FITS file.
83     *  \return SUCCESS or FAILURE.
84     */
85
86    int numAxes, status = 0;  /* MUST initialize status */
87    fitsfile *fptr;         
88
89    int exists;
90    fits_file_exists(fname.c_str(),&exists,&status);
91    if(exists<=0){
92      fits_report_error(stderr, status);
93      std::stringstream errmsg;
94      errmsg << "Requested image (" << fname << ") does not exist!\n";
95      duchampError("Cube Reader", errmsg.str());
96      return FAILURE;
97    }
98
99    // Open the FITS file -- make sure it exists
100    status = 0;
101    if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
102      fits_report_error(stderr, status);
103      if(((status==URL_PARSE_ERROR)||(status==BAD_NAXIS))
104         &&(this->pars().getFlagSubsection()))
105        duchampError("Cube Reader",
106                     "It may be that the subsection you've entered is invalid.\n\
107Either it has the wrong number of axes, or one axis has too large a range.\n");
108      return FAILURE;
109    }
110
111    // Read the size information -- number and lengths of all axes.
112    // Just use this for reporting purposes.
113    status = 0;
114    if(fits_get_img_dim(fptr, &numAxes, &status)){
115      fits_report_error(stderr, status);
116      return FAILURE;
117    }
118    long *dimAxes = new long[numAxes];
119    for(int i=0;i<numAxes;i++) dimAxes[i]=1;
120    status = 0;
121    if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
122      fits_report_error(stderr, status);
123      return FAILURE;
124    }
125
126    // allocate the dimension array in the Cube.
127    this->axisDim = new long[numAxes];
128    this->axisDimAllocated = true;
129    for(int i=0;i<numAxes;i++) this->axisDim[i] = dimAxes[i];
130 
131    // Close the FITS file.
132    status = 0;
133    fits_close_file(fptr, &status);
134    if (status){
135      duchampWarning("Cube Reader","Error closing file: ");
136      fits_report_error(stderr, status);
137    }
138
139    // Report the size of the FITS file
140    if(this->par.isVerbose()){
141      std::cout << "Dimensions of FITS file: ";
142      int dim = 0;
143      std::cout << dimAxes[dim];
144      while(dim+1<numAxes) std::cout << "x" << dimAxes[++dim];
145      std::cout << std::endl;
146    }
147
148    delete [] dimAxes;
149
150    // Get the WCS information
151    this->head.defineWCS(fname, this->par);
152
153    if(!this->head.isWCS())
154      duchampWarning("Cube Reader","WCS is not good enough to be used.\n");
155
156    // Read the necessary header information, and copy some of it into the Param.
157    this->head.readHeaderInfo(fname, this->par);
158
159    return SUCCESS;
160
161  }
162  //--------------------------------------------------------------------
163
164
165  int Cube::getCube(std::string fname)
166  {
167    /**
168     * Read in a cube from the file fname (assumed to be in FITS
169     *  format).  Function is a front end to the data I/O function in
170     *  the FitsIO/ directory.  This function calls the getMetadata()
171     *  function, then reads in the actual data array.
172     *  \param fname A std::string with name of FITS file.
173     *  \return SUCCESS or FAILURE.
174     */
175
176    this->getMetadata(fname);
177
178    // Get the data array from the FITS file.
179    // Report the dimensions of the data array that was read (this can be
180    //   different to the full FITS array).
181    if(this->par.isVerbose()) std::cout << "Reading data ... "<<std::flush;
182    if(this->getFITSdata(fname)) return FAILURE;
183
184    if(this->axisDim[2] == 1){
185      this->par.setMinChannels(0);
186    }
187
188    if(this->par.isVerbose()){
189      std::cout << "Done. Data array has dimensions: ";
190      std::cout << this->axisDim[0];
191      if(this->axisDim[1]>1) std::cout  <<"x"<< this->axisDim[1];
192      if(this->axisDim[2]>1) std::cout  <<"x"<< this->axisDim[2];
193      std::cout << "\n";
194    }   
195
196    // Convert the flux Units if the user has so requested
197    this->convertFluxUnits();
198
199    return SUCCESS;   
200
201  }
202  //--------------------------------------------------------------------
203
204
205  void Cube::convertFluxUnits()
206  {
207    /**
208     *  If the user has requested new flux units (via the input
209     *  parameter newFluxUnits), this function converts the units
210     *  given by BUNIT to those given by newFluxUnits. If no simple
211     *  conversion can be found (by using wcsunits()) then nothing is
212     *  done and the user is informed, otherwise the
213     *  FitsHeader::fluxUnits parameter is updated and the pixel array
214     *  is converted accordingly.
215     *
216     */
217
218
219    if(this->par.getNewFluxUnits()!=""){
220
221      std::string oldUnit = this->head.getFluxUnits();
222      std::string newUnit = this->par.getNewFluxUnits();
223
224      if(oldUnit != newUnit){
225
226        if(this->par.isVerbose()){
227          std::cout << "Converting flux units from " << oldUnit << " to " << newUnit << "... ";
228          std::cout << std::flush;
229        }
230
231        double scale,offset,power;
232        int status = wcsunits(oldUnit.c_str(), newUnit.c_str(), &scale, &offset, &power);
233
234        if(status==0){
235       
236          this->head.setFluxUnits( newUnit );
237          this->head.setIntFluxUnits();
238
239          for(int i=0;i<this->numPixels;i++)
240            if(!this->isBlank(i)) this->array[i] = pow(scale * array[i] + offset, power);
241          if(this->par.isVerbose()) {
242            std::cout << " Done.\n";
243          }
244        }
245        else{
246          std::stringstream ss;
247          ss << "Could not convert units from " << oldUnit << " to " << newUnit
248             << ".\nLeaving BUNIT as " << oldUnit << "\n";
249          if(this->par.isVerbose()) std::cout << "\n";
250          duchampWarning("convertFluxUnits", ss.str());
251        }
252      }
253    }
254
255  }
256
257
258}
Note: See TracBrowser for help on using the repository browser.