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

Last change on this file was 528, checked in by MatthewWhiting, 15 years ago

Changing the documentation comments to match the askapsoft style. Also have split ChanMap? and Object3D into separate files.

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