source: trunk/src/FitsIO/wcsIO.cc @ 1005

Last change on this file since 1005 was 1005, checked in by MatthewWhiting, 12 years ago

Improving the error diagnosis

File size: 8.3 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
51    OUTCOME returnValue=SUCCESS;
52    fitsfile *fptr;
53    int status = 0;
54    // Open the FITS file
55    if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
56      fits_report_error(stderr, status);
57      returnValue = FAILURE;
58    }
59    else {
60
61      returnValue = this->defineWCS(fptr,par);
62
63      // Close the FITS file
64      status = 0;
65      fits_close_file(fptr, &status);
66      if (status){
67        DUCHAMPWARN("Cube Reader","Error closing file: ");
68        fits_report_error(stderr, status);
69      }
70 
71    }
72    return returnValue;
73
74  }
75
76  OUTCOME FitsHeader::defineWCS(Param &par)
77  {
78    OUTCOME returnValue=SUCCESS;
79    if(this->fptr == 0) {
80      returnValue = FAILURE;
81      DUCHAMPERROR("Cube Reader", "FITS file not opened.");
82    }
83    else {
84      returnValue = this->defineWCS(this->fptr, par);
85    }
86    return returnValue;
87  }
88
89
90
91  OUTCOME FitsHeader::defineWCS(fitsfile *fptr, Param &par)
92  {
93    ///   A function that reads the WCS header information from the
94    ///    FITS file given by fname
95    ///   It will also sort out the spectral axis, and covert to the correct
96    ///    velocity type, or frequency type if need be.
97    /// \param fname Fits file to read.
98    /// \param par Param set to help fix the units with.
99
100    int numAxes;
101    int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
102    int nExc = 0,nkeys;
103    int status = 0;
104    char *hdr;
105
106    // Get the dimensions of the FITS file -- number of axes and size of each.
107    status = 0;
108    if(fits_get_img_dim(fptr, &numAxes, &status)){
109      fits_report_error(stderr, status);
110      return FAILURE;
111    }
112    long *dimAxes = new long[numAxes];
113    for(int i=0;i<numAxes;i++) dimAxes[i]=1;
114    status = 0;
115    if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
116      fits_report_error(stderr, status);
117      return FAILURE;
118    }
119
120    // Read in the entire PHU of the FITS file to a std::string.
121    // This will be read by the wcslib functions to extract the WCS.
122    status = 0;
123    fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
124    if( status ){
125      DUCHAMPWARN("Cube Reader","Error whilst reading FITS header to string: ");
126      fits_report_error(stderr, status);
127      return FAILURE;
128    }
129 
130    // Define a temporary, local version of the WCS
131    struct wcsprm *localwcs;
132    localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
133    localwcs->flag=-1;
134
135    // Initialise this temporary wcsprm structure
136    status = wcsini(true, numAxes, localwcs);
137    if(status){
138      DUCHAMPERROR("Cube Reader","wcsini failed! Code=" << status << ": " << wcs_errmsg[status]);
139      return FAILURE;
140    }
141
142    int relax=1; // for wcspih -- admit all recognised informal WCS extensions
143    int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
144    int localnwcs, nreject;
145    // Parse the FITS header to fill in the wcsprm structure
146    status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
147    if(status){
148      // if here, something went wrong -- report what.
149      DUCHAMPERROR("Cube Reader","Could not parse header with wcspih!\nWCSLIB error code=" << status << ": " << wcs_errmsg[status]);
150      return FAILURE;
151    }
152    else{ 
153      int stat[NWCSFIX];
154      // Applies all necessary corrections to the wcsprm structure
155      //  (missing cards, non-standard units or spectral types, ...)
156      status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
157      if(status) {
158        std::stringstream errmsg;
159        errmsg << "wcsfix failed with function status returns of:\n";
160        for(int i=0; i<NWCSFIX; i++)
161          if (stat[i] > 0)
162            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
163                   << wcsfix_errmsg[stat[i]] << std::endl;
164        DUCHAMPWARN("Cube Reader", errmsg);
165      }
166      // Set up the wcsprm struct. Report if something goes wrong.
167      status = wcsset(localwcs);
168      if(status){
169        DUCHAMPWARN("Cube Reader","wcsset failed with error code=" << status <<": "<<wcs_errmsg[status]);
170      }
171      else{
172
173        int stat[NWCSFIX];
174        // Re-do the corrections to account for things like NCP projections
175        status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
176        if(status) {
177          std::stringstream errmsg;
178          errmsg << "wcsfix failed with function status returns of:\n";
179          for(int i=0; i<NWCSFIX; i++)
180            if (stat[i] > 0)
181              errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
182                     << wcsfix_errmsg[stat[i]] << std::endl;
183          DUCHAMPWARN("Cube Reader", errmsg );
184        }
185
186
187        char stype[5],scode[5],sname[22],units[8],ptype,xtype;
188        int restreq;
189
190        if(par.getSpectralType()!=""){ // User wants to convert the spectral type
191
192          std::string desiredType = par.getSpectralType();
193         
194          status = spctyp((char *)desiredType.c_str(),stype,scode,sname,units,&ptype,&xtype,&restreq);
195          if(status){
196            DUCHAMPERROR("Cube Reader", "Spectral type " << desiredType << " is not a valid spectral type. No translation done.");
197          }
198          else{
199
200            if(desiredType.size()<4){
201              DUCHAMPERROR("Cube Reader", "Spectral Type " << desiredType << " requested, but this is too short. No translation done");
202            }
203            else{
204              if(desiredType.size()<8){
205                if(desiredType.size()==4) desiredType+="-???";
206                else while (desiredType.size()<8) desiredType+="?";
207              }
208            }
209            if(par.getRestFrequency()>0.){
210              localwcs->restfrq = par.getRestFrequency();
211            }
212            status = wcssptr(localwcs, &(localwcs->spec), (char *)desiredType.c_str());
213            if(status){
214              DUCHAMPWARN("Cube Reader","WCSSPTR failed when converting from type \"" << localwcs->ctype[localwcs->spec]
215                          << "\" to type \"" << desiredType << " with code=" << status << ": " << wcs_errmsg[status]);
216            }
217            else if(par.getRestFrequency()>0.) par.setFlagRestFrequencyUsed(true);
218
219
220          }
221
222        }
223
224         
225        status = spctyp(localwcs->ctype[localwcs->spec],stype,scode,sname,units,&ptype,&xtype,&restreq);
226
227        this->spectralType  = stype;
228        this->spectralDescription = sname;
229
230        // Save the wcs to the FitsHeader class that is running this function
231        this->setWCS(localwcs);
232        this->setNWCS(localnwcs);
233 
234        // Now that the WCS is defined, use it to set the offsets in the Param set
235        par.setOffsets(localwcs);
236
237      }
238    }
239
240    // work out whether the array is 2dimensional
241    if(localwcs->naxis==2) this->flag2D = true;
242    else{
243      int numDim=0;
244      for(int i=0;i<numAxes;i++) if(dimAxes[i]>1) numDim++;
245      this->flag2D = (numDim==2);
246    }
247
248    // clean up allocated memory
249    wcsvfree(&localnwcs,&localwcs);
250    wcsfree(localwcs);
251    free(localwcs);
252    free(hdr);
253    delete [] dimAxes;
254
255    return SUCCESS;
256
257  }
258
259}
Note: See TracBrowser for help on using the repository browser.