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
RevLine 
[301]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// -----------------------------------------------------------------------
[160]28#include <iostream>
29#include <string>
[205]30#include <stdlib.h>
[160]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>
[272]41#include <fitsHeader.hh>
[160]42#include <Cubes/cubes.hh>
43
[232]44int FitsHeader::defineWCS(std::string fname, Param &par)
[160]45{
46  /**
47   *   A function that reads the WCS header information from the
[204]48   *    FITS file given by fname
[160]49   *   It will also sort out the spectral axis, and covert to the correct
50   *    velocity type, or frequency type if need be.
[192]51   *   It calls FitsHeader::readBUNIT so that the Integrated Flux units can
[161]52   *    be calculated by FitsHeader::fixUnits.
[221]53   * \param fname Fits file to read.
54   * \param par Param set to help fix the units with.
[160]55   */
56
57  fitsfile *fptr;
[270]58  int numAxes;
[160]59  int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
60  int nExc = 0,nkeys;
61  char *hdr;
[161]62
63  // Open the FITS file
[160]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  }
[161]69
70  // Get the dimensions of the FITS file -- number of axes and size of each.
[160]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  }
[161]83
[232]84  // Read in the entire PHU of the FITS file to a std::string.
[161]85  // This will be read by the wcslib functions to extract the WCS.
[160]86  status = 0;
87  fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
88  if( status ){
[300]89    duchampWarning("Cube Reader",
90                   "Error whilst reading FITS header to string: ");
[160]91    fits_report_error(stderr, status);
92    return FAILURE;
93  }
[161]94
95  // Close the FITS file -- not needed any more in this function.
[160]96  status = 0;
97  fits_close_file(fptr, &status);
98  if (status){
[293]99    duchampWarning("Cube Reader","Error closing file: ");
[160]100    fits_report_error(stderr, status);
101  }
102 
[300]103  // Define a temporary, local version of the WCS
[204]104  struct wcsprm *localwcs;
[205]105  localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
[204]106  localwcs->flag=-1;
[161]107
[300]108  // Initialise this temporary wcsprm structure
[270]109  status = wcsini(true, numAxes, localwcs);
110  if(status){
[160]111    std::stringstream errmsg;
[205]112    errmsg << "wcsini failed! Code=" << status
113           << ": " << wcs_errmsg[status] << std::endl;
[293]114    duchampError("Cube Reader",errmsg.str());
[160]115    return FAILURE;
116  }
[161]117
[300]118  this->naxis=0;
119  for(int i=0;i<numAxes;i++)
120    if(dimAxes[i]>1) this->naxis++;
[271]121
[161]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
[204]125  int localnwcs, nreject;
[161]126  // Parse the FITS header to fill in the wcsprm structure
[270]127  status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
128  if(status){
[161]129    // if here, something went wrong -- report what.
[160]130    std::stringstream errmsg;
[205]131    errmsg << "wcspih failed!\nWCSLIB error code=" << status
132           << ": " << wcs_errmsg[status] << std::endl;
[293]133    duchampWarning("Cube Reader",errmsg.str());
[160]134  }
135  else{ 
[187]136    int stat[NWCSFIX];
[161]137    // Applies all necessary corrections to the wcsprm structure
138    //  (missing cards, non-standard units or spectral types, ...)
[270]139    status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
140    if(status) {
[160]141      std::stringstream errmsg;
142      errmsg << "wcsfix failed:\n";
143      for(int i=0; i<NWCSFIX; i++)
144        if (stat[i] > 0)
[205]145          errmsg << "WCSLIB error code=" << status << ": "
146                 << wcsfix_errmsg[stat[i]] << std::endl;
[293]147      duchampWarning("Cube Reader", errmsg.str() );
[160]148    }
[161]149
150    // Set up the wcsprm struct. Report if something goes wrong.
[270]151    status = wcsset(localwcs);
152    if(status){
[160]153      std::stringstream errmsg;
[187]154      errmsg<<"wcsset failed!\n"
[205]155            <<"WCSLIB error code=" << status
156            <<": "<<wcs_errmsg[status] << std::endl;
[293]157      duchampWarning("Cube Reader",errmsg.str());
[160]158    }
159
[300]160    if(this->naxis>2){  // if there is a spectral axis
161     
[204]162      int index = localwcs->spec;
[232]163      std::string desiredType,specType = localwcs->ctype[index];
[300]164
[204]165      if(localwcs->restfrq != 0){
[160]166        // Set the spectral axis to a standard specification: VELO-F2V
167        desiredType = duchampVelocityType;
[204]168        if(localwcs->restwav == 0)
169          localwcs->restwav = 299792458.0 /  localwcs->restfrq;
[186]170        this->spectralDescription = duchampSpectralDescription[VELOCITY];
[160]171      }
172      else{
173        // No rest frequency defined, so put spectral dimension in frequency.
174        // Set the spectral axis to a standard specification: FREQ
[293]175        duchampWarning("Cube Reader",
[160]176       "No rest frequency defined. Using frequency units in spectral axis.\n");
177        desiredType = duchampFrequencyType;
178        par.setSpectralUnits("MHz");
[204]179        if(strcmp(localwcs->cunit[index],"")==0){
[293]180          duchampWarning("Cube Reader",
[160]181          "No frequency unit given. Assuming frequency axis is in Hz.\n");
[204]182          strcpy(localwcs->cunit[index],"Hz");
[160]183        }
[186]184        this->spectralDescription = duchampSpectralDescription[FREQUENCY];
[160]185      }
[161]186
[224]187
[228]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
[224]192      bool needToTranslate = false;
193
194      if(strncmp(specType.c_str(),desiredType.c_str(),4)!=0)
195        needToTranslate = true;
196
[232]197      std::string blankstring = "";
[226]198      if(strcmp(localwcs->cunit[localwcs->spec],blankstring.c_str())==0)
[224]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       
[270]208        status = wcssptr(localwcs, &index, (char *)desiredType.c_str());
209        if(status){
[224]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";
[293]215          duchampWarning("Cube Reader",errmsg.str());
[224]216
217        }
218
219      }
[160]220   
221    } // end of if(numAxes>2)
222   
[161]223    // Save the wcs to the FitsHeader class that is running this function
[204]224    this->setWCS(localwcs);
225    this->setNWCS(localnwcs);
[160]226
227  }
228
[309]229  // clean up allocated memory
[205]230  wcsvfree(&localnwcs,&localwcs);
[309]231  wcsfree(localwcs);
232  free(localwcs);
233  free(hdr);
[205]234  delete [] dimAxes;
235
[161]236  // Get the brightness unit, so that we can set the units for the
237  //  integrated flux when we go to fixUnits.
[192]238  this->readBUNIT(fname);
[160]239
[271]240  if(numAxes>2) this->fixUnits(par);
[160]241
242  return SUCCESS;
243
244}
Note: See TracBrowser for help on using the repository browser.