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

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

Making use of the closeStatus flag (to avoid compiler warnings), and providing a warning note for the user.

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