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

Last change on this file since 1441 was 1418, checked in by MatthewWhiting, 10 years ago

Fixing a WARN message that comes from running wcsfix. This should improve the message as displayed in ticket #230

File size: 8.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
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    size_t *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=NULL;
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 size_t[numAxes];
120      for(int i=0;i<numAxes;i++) dimAxes[i]=1;
121      status = 0;
122      if(fits_get_img_size(fptr, numAxes, (long*)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, size_t *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.str());
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.str() );
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.