source: trunk/src/Cubes/getImage.cc @ 513

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

New functionality to correctly check whether we have a 2D image or not.

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    // Close the FITS file.
127    status = 0;
128    fits_close_file(fptr, &status);
129    if (status){
130      duchampWarning("Cube Reader","Error closing file: ");
131      fits_report_error(stderr, status);
132    }
133
134    // Report the size of the FITS file
135    if(this->par.isVerbose()){
136      std::cout << "Dimensions of FITS file: ";
137      int dim = 0;
138      std::cout << dimAxes[dim];
139      while(dim+1<numAxes) std::cout << "x" << dimAxes[++dim];
140      std::cout << std::endl;
141    }
142
143    // Get the WCS information
144    this->head.defineWCS(fname, this->par);
145
146    if(!this->head.isWCS())
147      duchampWarning("Cube Reader","WCS is not good enough to be used.\n");
148
149    // allocate the dimension array in the Cube.
150    this->initialiseCube(dimAxes,false);
151
152    // Read the necessary header information, and copy some of it into the Param.
153    this->head.readHeaderInfo(fname, this->par);
154
155    delete [] dimAxes;
156
157    return SUCCESS;
158
159  }
160  //--------------------------------------------------------------------
161
162
163  int Cube::getCube(std::string fname)
164  {
165    /**
166     * Read in a cube from the file fname (assumed to be in FITS
167     *  format).  Function is a front end to the data I/O function in
168     *  the FitsIO/ directory.  This function calls the getMetadata()
169     *  function, then reads in the actual data array.
170     *  \param fname A std::string with name of FITS file.
171     *  \return SUCCESS or FAILURE.
172     */
173
174    this->getMetadata(fname);
175
176    // Get the data array from the FITS file.
177    // Report the dimensions of the data array that was read (this can be
178    //   different to the full FITS array).
179    if(this->par.isVerbose()) std::cout << "Reading data ... "<<std::flush;
180    if(this->getFITSdata(fname)) return FAILURE;
181
182    if(this->axisDim[2] == 1){
183      this->par.setMinChannels(0);
184    }
185
186    if(this->par.isVerbose()){
187      std::cout << "Done. Data array has dimensions: ";
188      std::cout << this->axisDim[0];
189      if(this->axisDim[1]>1) std::cout  <<"x"<< this->axisDim[1];
190      if(this->axisDim[2]>1) std::cout  <<"x"<< this->axisDim[2];
191      std::cout << "\n";
192    }   
193
194    // Check for 2D images
195    this->checkDim();
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          if(this->arrayAllocated){
240            for(int i=0;i<this->numPixels;i++)
241              if(!this->isBlank(i)) this->array[i] = pow(scale * array[i] + offset, power);
242          }
243          if(this->par.isVerbose()) {
244            std::cout << " Done.\n";
245          }
246        }
247        else{
248          std::stringstream ss;
249          ss << "Could not convert units from " << oldUnit << " to " << newUnit
250             << ".\nLeaving BUNIT as " << oldUnit << "\n";
251          if(this->par.isVerbose()) std::cout << "\n";
252          duchampWarning("convertFluxUnits", ss.str());
253        }
254      }
255    }
256
257  }
258
259
260}
Note: See TracBrowser for help on using the repository browser.