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

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

Making sure the flag2D only applies to 2D cases, not <=2D

File size: 8.4 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    this->naxis=0;
143    for(int i=0;i<numAxes;i++)
144      if(dimAxes[i]>1) this->naxis++;
145
146    int relax=1; // for wcspih -- admit all recognised informal WCS extensions
147    int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
148    int localnwcs, nreject;
149    // Parse the FITS header to fill in the wcsprm structure
150    status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
151    if(status){
152      // if here, something went wrong -- report what.
153      DUCHAMPWARN("Cube Reader","wcspih failed!\nWCSLIB error code=" << status << ": " << wcs_errmsg[status]);
154    }
155    else{ 
156      int stat[NWCSFIX];
157      // Applies all necessary corrections to the wcsprm structure
158      //  (missing cards, non-standard units or spectral types, ...)
159      status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
160      if(status) {
161        std::stringstream errmsg;
162        errmsg << "wcsfix failed with function status returns of:\n";
163        for(int i=0; i<NWCSFIX; i++)
164          if (stat[i] > 0)
165            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
166                   << wcsfix_errmsg[stat[i]] << std::endl;
167        DUCHAMPWARN("Cube Reader", errmsg);
168      }
169      // Set up the wcsprm struct. Report if something goes wrong.
170      status = wcsset(localwcs);
171      if(status){
172        DUCHAMPWARN("Cube Reader","wcsset failed with error code=" << status <<": "<<wcs_errmsg[status]);
173      }
174      else{
175
176        int stat[NWCSFIX];
177        // Re-do the corrections to account for things like NCP projections
178        status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
179        if(status) {
180          std::stringstream errmsg;
181          errmsg << "wcsfix failed with function status returns of:\n";
182          for(int i=0; i<NWCSFIX; i++)
183            if (stat[i] > 0)
184              errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
185                     << wcsfix_errmsg[stat[i]] << std::endl;
186          DUCHAMPWARN("Cube Reader", errmsg );
187        }
188
189
190        char stype[5],scode[5],sname[22],units[8],ptype,xtype;
191        int restreq;
192        struct wcserr *err;
193
194        if(par.getSpectralType()!=""){ // User wants to convert the spectral type
195
196          std::string desiredType = par.getSpectralType();
197         
198          status = spctype((char *)desiredType.c_str(),stype,scode,sname,units,&ptype,&xtype,&restreq,&err);
199          if(status){
200            DUCHAMPERROR("Cube Reader", "Spectral type " << desiredType << " is not a valid spectral type. No translation done.");
201          }
202          else{
203
204            if(desiredType.size()<4){
205              DUCHAMPERROR("Cube Reader", "Spectral Type " << desiredType << " requested, but this is too short. No translation done");
206            }
207            else{
208              if(desiredType.size()<8){
209                if(desiredType.size()==4) desiredType+="-???";
210                else while (desiredType.size()<8) desiredType+="?";
211              }
212            }
213            if(par.getRestFrequency()>0.){
214              localwcs->restfrq = par.getRestFrequency();
215            }
216            status = wcssptr(localwcs, &(localwcs->spec), (char *)desiredType.c_str());
217            if(status){
218              DUCHAMPWARN("Cube Reader","WCSSPTR failed when converting from type \"" << localwcs->ctype[localwcs->spec]
219                          << "\" to type \"" << desiredType << " with code=" << status << ": " << wcs_errmsg[status]);
220            }
221            else if(par.getRestFrequency()>0.) par.setFlagRestFrequencyUsed(true);
222
223
224          }
225
226        }
227
228         
229        status = spctype(localwcs->ctype[localwcs->spec],stype,scode,sname,units,&ptype,&xtype,&restreq,&err);
230
231        this->spectralType  = stype;
232        this->spectralDescription = sname;
233
234        // Save the wcs to the FitsHeader class that is running this function
235        this->setWCS(localwcs);
236        this->setNWCS(localnwcs);
237 
238        // Now that the WCS is defined, use it to set the offsets in the Param set
239        par.setOffsets(localwcs);
240
241      }
242    }
243
244    // work out whether the array is 2dimensional
245    if(localwcs->naxis==2) this->flag2D = true;
246    else{
247      int numDim=0;
248      for(int i=0;i<numAxes;i++) if(dimAxes[i]>1) numDim++;
249      this->flag2D = (numDim==2);
250    }
251
252    // clean up allocated memory
253    wcsvfree(&localnwcs,&localwcs);
254    wcsfree(localwcs);
255    free(localwcs);
256    free(hdr);
257    delete [] dimAxes;
258
259    return SUCCESS;
260
261  }
262
263}
Note: See TracBrowser for help on using the repository browser.