source: tags/release-1.2.2/src/FitsIO/wcsIO.cc

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

Making a separate fitsHeader function to handle the actual calculations etc for setting up the WCS. This way it can be used by external functions such as in askapsoft. Also improving the OUTCOME handling.

File size: 8.8 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    OUTCOME returnValue=SUCCESS;
101
102    int numAxes=0;
103    long *dimAxes = 0;
104    int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
105    int nExc = 0,nkeys;
106    int status = 0;
107    char *hdr=0;
108    struct wcsprm *localwcs;
109    int localnwcs;
110
111    // Get the dimensions of the FITS file -- number of axes and size of each.
112    status = 0;
113    if(fits_get_img_dim(fptr, &numAxes, &status)){
114      fits_report_error(stderr, status);
115      returnValue = FAILURE;
116    }
117
118    if(returnValue == SUCCESS){
119      dimAxes = new long[numAxes];
120      for(int i=0;i<numAxes;i++) dimAxes[i]=1;
121      status = 0;
122      if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
123        fits_report_error(stderr, status);
124        returnValue = FAILURE;
125      }
126    }
127
128    if(returnValue == SUCCESS){
129      // Read in the entire PHU of the FITS file to a std::string.
130      // This will be read by the wcslib functions to extract the WCS.
131      status = 0;
132      fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
133      if( status ){
134        DUCHAMPWARN("Cube Reader","Error whilst reading FITS header to string: ");
135        fits_report_error(stderr, status);
136        return FAILURE;
137      }
138    }
139 
140    if(returnValue == SUCCESS){
141      // Define a temporary, local version of the WCS
142      localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
143      localwcs->flag=-1;
144     
145      // Initialise this temporary wcsprm structure
146      status = wcsini(true, numAxes, localwcs);
147      if(status){
148        DUCHAMPERROR("Cube Reader","wcsini failed! Code=" << status << ": " << wcs_errmsg[status]);
149        returnValue = FAILURE;
150      }
151      else{
152        int relax=1; // for wcspih -- admit all recognised informal WCS extensions
153        int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
154        int nreject;
155        // Parse the FITS header to fill in the wcsprm structure
156        status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
157        if(status){
158          // if here, something went wrong -- report what.
159          DUCHAMPERROR("Cube Reader","Could not parse header with wcspih!\nWCSLIB error code=" << status << ": " << wcs_errmsg[status]);
160          returnValue = FAILURE;
161        }
162        else  returnValue = this->defineWCS(localwcs, localnwcs, dimAxes, par);
163       
164      }
165    }
166
167    // clean up allocated memory
168    if(localwcs > 0){
169      wcsvfree(&localnwcs,&localwcs);
170      wcsfree(localwcs);
171      free(localwcs);
172    }
173    if(hdr>0) free(hdr);
174    if(dimAxes>0) {
175      delete [] dimAxes;
176    }
177
178    return returnValue;
179
180  }
181
182  OUTCOME FitsHeader::defineWCS(wcsprm *theWCS, int nWCS, long *dimAxes, Param &par)
183  {
184 
185    int status=0;
186    int stat[NWCSFIX];
187    // Applies all necessary corrections to the wcsprm structure
188    //  (missing cards, non-standard units or spectral types, ...)
189    status = wcsfix(1, (const int*)dimAxes, theWCS, stat);
190    if(status) {
191      std::stringstream errmsg;
192      errmsg << "wcsfix failed with function status returns of:\n";
193      for(int i=0; i<NWCSFIX; i++)
194        if (stat[i] > 0)
195          errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
196                 << wcsfix_errmsg[stat[i]] << std::endl;
197      DUCHAMPWARN("Cube Reader", errmsg);
198      return FAILURE;
199    }
200    // Set up the wcsprm struct. Report if something goes wrong.
201    status = wcsset(theWCS);
202    if(status){
203      DUCHAMPWARN("Cube Reader","wcsset failed with error code=" << status <<": "<<wcs_errmsg[status]);
204      return FAILURE;
205    }
206    else{
207
208      int stat[NWCSFIX];
209      // Re-do the corrections to account for things like NCP projections
210      status = wcsfix(1, (const int*)dimAxes, theWCS, stat);
211      if(status) {
212        std::stringstream errmsg;
213        errmsg << "wcsfix failed with function status returns of:\n";
214        for(int i=0; i<NWCSFIX; i++)
215          if (stat[i] > 0)
216            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
217                   << wcsfix_errmsg[stat[i]] << std::endl;
218        DUCHAMPWARN("Cube Reader", errmsg );
219      }
220
221
222      char stype[5],scode[5],sname[22],units[8],ptype,xtype;
223      int restreq;
224
225      if(par.getSpectralType()!=""){ // User wants to convert the spectral type
226
227        std::string desiredType = par.getSpectralType();
228         
229        status = spctyp((char *)desiredType.c_str(),stype,scode,sname,units,&ptype,&xtype,&restreq);
230        if(status){
231          DUCHAMPERROR("Cube Reader", "Spectral type " << desiredType << " is not a valid spectral type. No translation done.");
232        }
233        else{
234
235          if(desiredType.size()<4){
236            DUCHAMPERROR("Cube Reader", "Spectral Type " << desiredType << " requested, but this is too short. No translation done");
237          }
238          else{
239            if(desiredType.size()<8){
240              if(desiredType.size()==4) desiredType+="-???";
241              else while (desiredType.size()<8) desiredType+="?";
242            }
243          }
244          if(par.getRestFrequency()>0.){
245            theWCS->restfrq = par.getRestFrequency();
246          }
247          status = wcssptr(theWCS, &(theWCS->spec), (char *)desiredType.c_str());
248          if(status){
249            DUCHAMPWARN("Cube Reader","WCSSPTR failed when converting from type \"" << theWCS->ctype[theWCS->spec]
250                        << "\" to type \"" << desiredType << " with code=" << status << ": " << wcs_errmsg[status]);
251          }
252          else if(par.getRestFrequency()>0.) par.setFlagRestFrequencyUsed(true);
253
254
255        }
256
257      }
258
259      status = spctyp(theWCS->ctype[theWCS->spec],stype,scode,sname,units,&ptype,&xtype,&restreq);
260
261      this->spectralType  = stype;
262      this->spectralDescription = sname;
263
264      // Save the wcs to the FitsHeader class that is running this function
265      this->setWCS(theWCS);
266      this->setNWCS(nWCS);
267 
268      // Now that the WCS is defined, use it to set the offsets in the Param set
269      par.setOffsets(theWCS);
270
271    }
272
273    // work out whether the array is 2dimensional
274    if(theWCS->naxis==2) this->flag2D = true;
275    else{
276      int numDim=0;
277      for(int i=0;i<wcs->naxis;i++) if(dimAxes[i]>1) numDim++;
278      this->flag2D = (numDim==2);
279    }
280   
281    return SUCCESS;
282
283   
284  }
285
286
287}
Note: See TracBrowser for help on using the repository browser.