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

Last change on this file since 349 was 309, checked in by Matthew Whiting, 17 years ago

Mostly changes to fix some memory allocation/deallocation issues raised by valgrind. Minor changes to the Guide.

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