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

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

Move the par.setOffsets call from getFITSdata to defineWCS, and fix up the allocation of arrays in getMetadata.

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    // Convert the flux Units if the user has so requested
195    this->convertFluxUnits();
196
197    return SUCCESS;   
198
199  }
200  //--------------------------------------------------------------------
201
202
203  void Cube::convertFluxUnits()
204  {
205    /**
206     *  If the user has requested new flux units (via the input
207     *  parameter newFluxUnits), this function converts the units
208     *  given by BUNIT to those given by newFluxUnits. If no simple
209     *  conversion can be found (by using wcsunits()) then nothing is
210     *  done and the user is informed, otherwise the
211     *  FitsHeader::fluxUnits parameter is updated and the pixel array
212     *  is converted accordingly.
213     *
214     */
215
216
217    if(this->par.getNewFluxUnits()!=""){
218
219      std::string oldUnit = this->head.getFluxUnits();
220      std::string newUnit = this->par.getNewFluxUnits();
221
222      if(oldUnit != newUnit){
223
224        if(this->par.isVerbose()){
225          std::cout << "Converting flux units from " << oldUnit << " to " << newUnit << "... ";
226          std::cout << std::flush;
227        }
228
229        double scale,offset,power;
230        int status = wcsunits(oldUnit.c_str(), newUnit.c_str(), &scale, &offset, &power);
231
232        if(status==0){
233       
234          this->head.setFluxUnits( newUnit );
235          this->head.setIntFluxUnits();
236
237          if(this->arrayAllocated){
238            for(int i=0;i<this->numPixels;i++)
239              if(!this->isBlank(i)) this->array[i] = pow(scale * array[i] + offset, power);
240          }
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.