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
RevLine 
[299]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// -----------------------------------------------------------------------
[3]28#include <iostream>
29#include <string>
[142]30#include <string.h>
[394]31#include <wcslib/wcs.h>
32#include <wcslib/wcshdr.h>
[400]33#include <wcslib/fitshdr.h>
[394]34#include <wcslib/wcsfix.h>
35#include <wcslib/wcsunits.h>
[142]36#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine
[321]37                         //  wtbarr (this is a problem when using gcc v.4+)
[66]38#include <fitsio.h>
[69]39#include <math.h>
[393]40#include <duchamp/duchamp.hh>
41#include <duchamp/param.hh>
42#include <duchamp/fitsHeader.hh>
43#include <duchamp/Cubes/cubes.hh>
[3]44
[378]45namespace duchamp
[3]46{
47
[378]48  std::string imageType[4] = {"point", "spectrum", "image", "cube"};
[3]49
[442]50  int Cube::getMetadata(){ 
51    /**
[443]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.
[442]55     */
56    std::string fname = par.getImageFile();
57    if(par.getFlagSubsection()) fname+=par.getSubsection();
[443]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;
[442]67  }
68  //--------------------------------------------------------------------
69
70  int Cube::getMetadata(std::string fname)
[378]71  {
72    /**
[442]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 --
[443]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.
[378]82     *  \param fname A std::string with name of FITS file.
83     *  \return SUCCESS or FAILURE.
84     */
[168]85
[378]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\
[164]107Either it has the wrong number of axes, or one axis has too large a range.\n");
[378]108      return FAILURE;
109    }
[3]110
[378]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    }
[443]125
[378]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    }
[3]133
[378]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    }
[103]142
[378]143    // Get the WCS information
144    this->head.defineWCS(fname, this->par);
[103]145
[378]146    if(!this->head.isWCS())
147      duchampWarning("Cube Reader","WCS is not good enough to be used.\n");
[3]148
[508]149    // allocate the dimension array in the Cube.
150    this->initialiseCube(dimAxes,false);
151
[442]152    // Read the necessary header information, and copy some of it into the Param.
153    this->head.readHeaderInfo(fname, this->par);
154
[508]155    delete [] dimAxes;
156
[442]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
[378]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;
[443]181
182    if(this->axisDim[2] == 1){
183      this->par.setMinChannels(0);
184    }
185
[378]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    }   
[46]193
[434]194    // Convert the flux Units if the user has so requested
195    this->convertFluxUnits();
196
[442]197    return SUCCESS;   
[3]198
[378]199  }
[442]200  //--------------------------------------------------------------------
[378]201
[434]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
[443]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.
[434]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
[443]222      if(oldUnit != newUnit){
[434]223
[443]224        if(this->par.isVerbose()){
225          std::cout << "Converting flux units from " << oldUnit << " to " << newUnit << "... ";
226          std::cout << std::flush;
227        }
[434]228
[443]229        double scale,offset,power;
230        int status = wcsunits(oldUnit.c_str(), newUnit.c_str(), &scale, &offset, &power);
231
232        if(status==0){
[434]233       
[443]234          this->head.setFluxUnits( newUnit );
235          this->head.setIntFluxUnits();
[434]236
[496]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          }
[443]241          if(this->par.isVerbose()) {
242            std::cout << " Done.\n";
243          }
[434]244        }
[443]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        }
[434]252      }
253    }
254
255  }
256
257
[3]258}
Note: See TracBrowser for help on using the repository browser.