source: tags/release-1.1.9/src/FitsIO/wcsIO.cc @ 1441

Last change on this file since 1441 was 700, checked in by MatthewWhiting, 14 years ago

Making use of the returned OUTCOME values.

File size: 9.9 KB
Line 
1// -----------------------------------------------------------------------
2// wcsIO.cc: Get the World Coordinate System for a particular FITS file.
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 <stdlib.h>
32#include <wcslib/wcs.h>
33#include <wcslib/wcshdr.h>
34#include <wcslib/fitshdr.h>
35#include <wcslib/wcsfix.h>
36#include <wcslib/wcsunits.h>
37#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine
38                         //  wtbarr (this is a problem when using gcc v.4+
39#include <fitsio.h>
40#include <math.h>
41#include <duchamp/duchamp.hh>
42#include <duchamp/fitsHeader.hh>
43#include <duchamp/Cubes/cubes.hh>
44
45namespace duchamp
46{
47
48  OUTCOME FitsHeader::defineWCS(std::string fname, Param &par)
49  {
50    ///   A function that reads the WCS header information from the
51    ///    FITS file given by fname
52    ///   It will also sort out the spectral axis, and covert to the correct
53    ///    velocity type, or frequency type if need be.
54    ///   It calls FitsHeader::readBUNIT so that the Integrated Flux units can
55    ///    be calculated by FitsHeader::fixUnits.
56    /// \param fname Fits file to read.
57    /// \param par Param set to help fix the units with.
58
59    fitsfile *fptr;
60    int numAxes;
61    int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
62    int nExc = 0,nkeys;
63    char *hdr;
64
65    // Open the FITS file
66    int status = 0;
67    if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
68      fits_report_error(stderr, status);
69      return FAILURE;
70    }
71
72    // Get the dimensions of the FITS file -- number of axes and size of each.
73    status = 0;
74    if(fits_get_img_dim(fptr, &numAxes, &status)){
75      fits_report_error(stderr, status);
76      return FAILURE;
77    }
78    long *dimAxes = new long[numAxes];
79    for(int i=0;i<numAxes;i++) dimAxes[i]=1;
80    status = 0;
81    if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
82      fits_report_error(stderr, status);
83      return FAILURE;
84    }
85
86    // Read in the entire PHU of the FITS file to a std::string.
87    // This will be read by the wcslib functions to extract the WCS.
88    status = 0;
89    fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
90    if( status ){
91      duchampWarning("Cube Reader",
92                     "Error whilst reading FITS header to string: ");
93      fits_report_error(stderr, status);
94      return FAILURE;
95    }
96
97    // Close the FITS file -- not needed any more in this function.
98    status = 0;
99    fits_close_file(fptr, &status);
100    if (status){
101      duchampWarning("Cube Reader","Error closing file: ");
102      fits_report_error(stderr, status);
103    }
104 
105    // Define a temporary, local version of the WCS
106    struct wcsprm *localwcs;
107    localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
108    localwcs->flag=-1;
109
110    // Initialise this temporary wcsprm structure
111    status = wcsini(true, numAxes, localwcs);
112    if(status){
113      std::stringstream errmsg;
114      errmsg << "wcsini failed! Code=" << status
115             << ": " << wcs_errmsg[status] << std::endl;
116      duchampError("Cube Reader",errmsg.str());
117      return FAILURE;
118    }
119
120    this->naxis=0;
121    for(int i=0;i<numAxes;i++)
122      if(dimAxes[i]>1) this->naxis++;
123
124    int relax=1; // for wcspih -- admit all recognised informal WCS extensions
125    int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
126    int localnwcs, nreject;
127    // Parse the FITS header to fill in the wcsprm structure
128    status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
129    if(status){
130      // if here, something went wrong -- report what.
131      std::stringstream errmsg;
132      errmsg << "wcspih failed!\nWCSLIB error code=" << status
133             << ": " << wcs_errmsg[status] << std::endl;
134      duchampWarning("Cube Reader",errmsg.str());
135    }
136    else{ 
137      int stat[NWCSFIX];
138      // Applies all necessary corrections to the wcsprm structure
139      //  (missing cards, non-standard units or spectral types, ...)
140      status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
141      if(status) {
142        std::stringstream errmsg;
143        errmsg << "wcsfix failed:\n";
144        errmsg << "Function status returns are:\n";
145        for(int i=0; i<NWCSFIX; i++)
146          if (stat[i] > 0)
147            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
148                   << wcsfix_errmsg[stat[i]] << std::endl;
149        duchampWarning("Cube Reader", errmsg.str() );
150      }
151      // Set up the wcsprm struct. Report if something goes wrong.
152      status = wcsset(localwcs);
153      if(status){
154        std::stringstream errmsg;
155        errmsg<<"wcsset failed!\n"
156              <<"WCSLIB error code=" << status
157              <<": "<<wcs_errmsg[status] << std::endl;
158        duchampWarning("Cube Reader",errmsg.str());
159      }
160      else{
161
162        int stat[NWCSFIX];
163        // Re-do the corrections to account for things like NCP projections
164        status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
165        if(status) {
166          std::stringstream errmsg;
167          errmsg << "wcsfix failed:\n";
168          errmsg << "Function status returns are:\n";
169          for(int i=0; i<NWCSFIX; i++)
170            if (stat[i] > 0)
171              errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
172                     << wcsfix_errmsg[stat[i]] << std::endl;
173          duchampWarning("Cube Reader", errmsg.str() );
174        }
175
176        if(localwcs->spec>=0){ //if there is a spectral axis
177
178          int index = localwcs->spec;
179          std::string desiredType,specType = localwcs->ctype[index];
180          std::string shortType = specType.substr(0,4);
181          if(shortType=="VELO" || shortType=="VOPT" || shortType=="ZOPT"
182             || shortType=="VRAD" || shortType=="BETA"){
183            if(localwcs->restfrq != 0){
184              // Set the spectral axis to a standard specification: VELO-F2V
185              desiredType = duchampVelocityType;
186              if(localwcs->restwav == 0)
187                localwcs->restwav = 299792458.0 /  localwcs->restfrq;
188              this->spectralDescription = duchampSpectralDescription[VELOCITY];
189            }
190            else{
191              // No rest frequency defined, so put spectral dimension in frequency.
192              // Set the spectral axis to a standard specification: FREQ
193              duchampWarning("Cube Reader",
194                             "No rest frequency defined. Using frequency units in spectral axis.\n");
195              desiredType = duchampFrequencyType;
196              par.setSpectralUnits("MHz");
197              if(strcmp(localwcs->cunit[index],"")==0){
198                duchampWarning("Cube Reader",
199                               "No frequency unit given. Assuming frequency axis is in Hz.\n");
200                strcpy(localwcs->cunit[index],"Hz");
201              }
202              this->spectralDescription = duchampSpectralDescription[FREQUENCY];
203            }
204          }
205          else {
206            desiredType = duchampFrequencyType;
207            par.setSpectralUnits("MHz");
208            if(strcmp(localwcs->cunit[index],"")==0){
209              duchampWarning("Cube Reader",
210                             "No frequency unit given. Assuming frequency axis is in Hz.\n");
211              strcpy(localwcs->cunit[index],"Hz");
212            }
213            this->spectralDescription = duchampSpectralDescription[FREQUENCY];
214          }     
215
216          // Now we need to make sure the spectral axis has the correct setup.
217          //  We use wcssptr to translate it if it is not of the desired type,
218          //  or if the spectral units are not defined.
219
220          bool needToTranslate = false;
221
222          //       if(strncmp(specType.c_str(),desiredType.c_str(),4)!=0)
223          //    needToTranslate = true;
224
225          std::string blankstring = "";
226          if(strcmp(localwcs->cunit[localwcs->spec],blankstring.c_str())==0)
227            needToTranslate = true;
228
229          if(needToTranslate){
230
231            if(strcmp(localwcs->ctype[localwcs->spec],"VELO")==0)
232              strcpy(localwcs->ctype[localwcs->spec],"VELO-F2V");
233
234            index = localwcs->spec;
235       
236            status = wcssptr(localwcs, &index, (char *)desiredType.c_str());
237            if(status){
238              std::stringstream errmsg;
239              errmsg<< "WCSSPTR failed! Code=" << status << ": "
240                    << wcs_errmsg[status] << std::endl
241                    << "(wanted to convert from type \"" << specType
242                    << "\" to type \"" << desiredType << "\")\n";
243              duchampWarning("Cube Reader",errmsg.str());
244
245            }
246
247          }
248   
249        } // end of if(localwcs->spec>=0)
250        else if(localwcs->naxis>2){
251
252          par.setSpectralUnits( wcs->cunit[2] );
253          this->spectralDescription = wcs->ctype[2];
254
255        }
256         
257        // Save the wcs to the FitsHeader class that is running this function
258        this->setWCS(localwcs);
259        this->setNWCS(localnwcs);
260 
261        // Now that the WCS is defined, use it to set the offsets in the Param set
262        par.setOffsets(localwcs);
263
264      }
265    }
266
267    // work out whether the array is 2dimensional
268    if(localwcs->naxis==2) this->flag2D = true;
269    else{
270      int numDim=0;
271      for(int i=0;i<numAxes;i++) if(dimAxes[i]>1) numDim++;
272      this->flag2D = (numDim<=2);
273    }
274
275    // clean up allocated memory
276    wcsvfree(&localnwcs,&localwcs);
277    wcsfree(localwcs);
278    free(localwcs);
279    free(hdr);
280    delete [] dimAxes;
281
282    // Get the brightness unit, so that we can set the units for the
283    //  integrated flux when we go to fixUnits.
284    if(this->readBUNIT(fname) == FAILURE) return FAILURE;
285
286    if(this->wcs->spec>=0) this->fixUnits(par);
287
288    return SUCCESS;
289
290  }
291
292}
Note: See TracBrowser for help on using the repository browser.