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

Last change on this file was 394, checked in by MatthewWhiting, 17 years ago

Fixing wcslib include calls so that it is a bit more robust.

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