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

Last change on this file since 1386 was 1386, checked in by MatthewWhiting, 10 years ago

Better error checking in the getMetadata function, so that we know if the opening of the FITS file fails (and exit rather than trying to read the metadata from it).

File size: 8.5 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  OUTCOME Cube::getMetadata()
51  { 
52    ///  @details
53    /// A front-end to the Cube::getMetadata() function, that does
54    ///  subsection checks. Does the flux unit conversion if the user
55    ///  has requested it. Assumes the Param is set up properly.
56
57    // int exists;
58    // fits_file_exists(fname.c_str(),&exists,&status);
59    // if(exists<=0){
60    //   fits_report_error(stderr, status);
61    //   DUCHAMPERROR("Cube Reader", Requested image (" << fname << ") does not exist!);
62    //   return FAILURE;
63    // }
64    if(this->par.checkImageExists() == FAILURE) return FAILURE;
65
66    std::string fname = par.getImageFile();
67    if(par.getFlagSubsection()) fname+=par.getSubsection();
68
69    OUTCOME result=SUCCESS;
70    int openStatus = this->head.openFITS(fname);
71    if (openStatus){
72        result = FAILURE;
73    }
74    else {
75
76        result = getMetadata(fname);
77   
78        if(result==SUCCESS){
79            // Convert the flux Units if the user has so requested
80            this->convertFluxUnits(this->head.getFluxUnits(),this->par.getNewFluxUnits());
81        }
82
83        int closeStatus = this->head.closeFITS();
84    }
85
86    return result;
87  }
88  //--------------------------------------------------------------------
89
90  OUTCOME Cube::getMetadata(std::string fname)
91  {
92    /// @details
93    /// Read in the metadata associated with the cube from the file
94    ///  fname (assumed to be in FITS format).  Function is a front end
95    ///  to the I/O functions in the FitsIO/ directory.  This function
96    ///  will check that the file exists, report the dimensions and
97    ///  then get other functions to read the WCS and necessary header
98    ///  keywords. This function does not read in the data array --
99    ///  that is done by Cube::getCube(). Note that no conversion of
100    ///  flux units is done -- you need to call Cube::getMetadata() or
101    ///  do it separately.
102    ///  \param fname A std::string with name of FITS file.
103    ///  \return SUCCESS or FAILURE.
104
105    int numAxes, status = 0;  /* MUST initialize status */
106
107    // Read the size information -- number and lengths of all axes.
108    // Just use this for reporting purposes.
109    status = 0;
110    if(fits_get_img_dim(this->head.FPTR(), &numAxes, &status)){
111      fits_report_error(stderr, status);
112      return FAILURE;
113    }
114
115    this->head.setNumAxes(numAxes);
116    long *dimAxes = new long[numAxes];
117    for(int i=0;i<numAxes;i++) dimAxes[i]=1;
118    status = 0;
119    if(fits_get_img_size(this->head.FPTR(), numAxes, dimAxes, &status)){
120      fits_report_error(stderr, status);
121      return FAILURE;
122    }
123
124    // Report the size of the FITS file
125    if(this->par.isVerbose()){
126      std::cout << "Dimensions of FITS file: ";
127      int dim = 0;
128      std::cout << dimAxes[dim];
129      while(dim+1<numAxes) std::cout << "x" << dimAxes[++dim];
130      std::cout << std::endl;
131    }
132
133
134    // Get the WCS information
135    if(this->head.defineWCS(this->par) == FAILURE) return FAILURE;
136
137    // Read the necessary header information, and copy some of it into the Param.
138    if(this->head.readHeaderInfo(this->par) == FAILURE){
139     DUCHAMPWARN("Cube Reader", "Problems with metadata, but will press on...");
140    }
141
142    if(!this->head.isWCS())
143      DUCHAMPWARN("Cube Reader","WCS is not good enough to be used.\n");
144
145    // allocate the dimension array in the Cube.
146    if(this->initialiseCube(dimAxes,false) == FAILURE) return FAILURE;
147
148    delete [] dimAxes;
149
150    return SUCCESS;
151
152  }
153  //--------------------------------------------------------------------
154
155
156  OUTCOME Cube::getCube(std::string fname)
157  {
158    /// @details
159    /// Read in a cube from the file fname (assumed to be in FITS
160    ///  format).  Function is a front end to the data I/O function in
161    ///  the FitsIO/ directory.  This function calls the getMetadata()
162    ///  function, then reads in the actual data array.
163    ///  \param fname A std::string with name of FITS file.
164    ///  \return SUCCESS or FAILURE.
165
166    if(this->head.openFITS(fname)) return FAILURE;
167
168    if(this->getMetadata(fname) == FAILURE) return FAILURE;
169
170    // Get the data array from the FITS file.
171    // Report the dimensions of the data array that was read (this can be
172    //   different to the full FITS array).
173    if(this->par.isVerbose()) std::cout << "Reading data ... "<<std::flush;
174    if(this->getFITSdata() == FAILURE) return FAILURE;
175
176    if(this->par.isVerbose()){
177      std::cout << "Done. Data array has dimensions: ";
178      std::cout << this->axisDim[0];
179      std::cout  <<"x"<< this->axisDim[1];
180      if(this->axisDim[2]>1) std::cout  <<"x"<< this->axisDim[2];
181      std::cout << "\n";
182    }   
183
184    // Convert the flux Units if the user has so requested
185    this->convertFluxUnits(this->head.getFluxUnits(),this->par.getNewFluxUnits(),ARRAY);
186
187    this->head.closeFITS();
188
189    return SUCCESS;   
190
191  }
192  //--------------------------------------------------------------------
193
194
195  void Cube::convertFluxUnits(std::string oldUnit, std::string newUnit, ARRAYREF whichArray)
196  {
197    /// @details
198    ///  If the user has requested new flux units (via the input
199    ///  parameter newFluxUnits), this function converts the units
200    ///  given by BUNIT to those given by newFluxUnits. If no simple
201    ///  conversion can be found (by using wcsunits()) then nothing is
202    ///  done and the user is informed, otherwise the
203    ///  FitsHeader::fluxUnits parameter is updated and the pixel array
204    ///  is converted accordingly.
205
206    if(newUnit!=""){
207
208      if(oldUnit != newUnit){
209
210        if(this->par.isVerbose()){
211          std::cout << "Converting flux units from " << oldUnit << " to " << newUnit << "... ";
212          std::cout << std::flush;
213        }
214
215        double scale,offset,power;
216        int status = wcsunits(oldUnit.c_str(), newUnit.c_str(), &scale, &offset, &power);
217
218        if(status==0){
219       
220          this->head.setFluxUnits( newUnit );
221          this->head.setIntFluxUnits();
222
223          if(whichArray == ARRAY){
224            if(this->arrayAllocated){
225              for(size_t i=0;i<this->numPixels;i++)
226                if(!this->isBlank(i)) this->array[i] = pow(scale * this->array[i] + offset, power);
227            }
228          }
229          else if(whichArray==RECON){
230            if(this->reconAllocated){
231              for(size_t i=0;i<this->numPixels;i++)
232                if(!this->isBlank(i)) this->recon[i] = pow(scale * this->recon[i] + offset, power);
233            }
234          }
235          else if(whichArray==BASELINE){
236            if(this->baselineAllocated){
237              for(size_t i=0;i<this->numPixels;i++)
238                if(!this->isBlank(i)) this->baseline[i] = pow(scale * this->baseline[i] + offset, power);
239            }
240          }
241          if(this->par.isVerbose()) {
242            std::cout << " Done.\n";
243          }
244        }
245        else{
246          if(this->par.isVerbose()) std::cout << "\n";
247          DUCHAMPWARN("convertFluxUnits", "Could not convert units from " << oldUnit << " to " << newUnit << ". Leaving BUNIT as " << oldUnit);
248        }
249      }
250    }
251
252  }
253
254
255}
Note: See TracBrowser for help on using the repository browser.