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

Last change on this file was 205, checked in by Matthew Whiting, 18 years ago

Changes here mostly aimed at reducing/removing memory leaks. These were one of:

  • Forgetting to delete something allocated with "new". The Cube destructor has improved with the use of bool variables to keep track of when recon & baseline ahave been allocated.
  • Incorrectly using the wcs->flag parameter (eg. wcsIO had it set to -1 *after* calling wcsini)
  • Not closing a fits file once finished with (dataIO)
  • Allocating the wcsprm structs with calloc before calling wcsini, so that wcsvfree can work (it calls "free", so the memory needs to be allocated with calloc or malloc).

The only other change was the following:

  • A new way of doing the Cube::setCubeStats -- rather than calling the functions in getStats.cc, we explicitly do the calculations. This means we can sort the tempArray that has the BLANKS etc removed. This saves a great deal of memory usage on large FITS files (such as Enno's 2Gb one)
  • The old setCubeStats function is still there but called setCubeStatsOld.
File size: 5.9 KB
Line 
1#include <iostream>
2#include <string>
3#include <stdlib.h>
4#include <wcs.h>
5#include <wcshdr.h>
6#include <fitshdr.h>
7#include <wcsfix.h>
8#include <wcsunits.h>
9#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine
10                         //  wtbarr (this is a problem when using gcc v.4+
11#include <fitsio.h>
12#include <math.h>
13#include <duchamp.hh>
14#include <Cubes/cubes.hh>
15
16int FitsHeader::defineWCS(string fname, Param &par)
17{
18  /**
19   *  FitsHeader::defineWCS(string fname, Param &par)
20   *   A function that reads the WCS header information from the
21   *    FITS file given by fname
22   *   It will also sort out the spectral axis, and covert to the correct
23   *    velocity type, or frequency type if need be.
24   *   It calls FitsHeader::readBUNIT so that the Integrated Flux units can
25   *    be calculated by FitsHeader::fixUnits.
26   */
27
28  fitsfile *fptr;
29  int bitpix,numAxes;
30  int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
31  int nExc = 0,nkeys;
32  char *hdr;
33
34  // Open the FITS file
35  int status = 0;
36  if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
37    fits_report_error(stderr, status);
38    return FAILURE;
39  }
40
41  // Get the dimensions of the FITS file -- number of axes and size of each.
42  status = 0;
43  if(fits_get_img_dim(fptr, &numAxes, &status)){
44    fits_report_error(stderr, status);
45    return FAILURE;
46  }
47  long *dimAxes = new long[numAxes];
48  for(int i=0;i<numAxes;i++) dimAxes[i]=1;
49  status = 0;
50  if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
51    fits_report_error(stderr, status);
52    return FAILURE;
53  }
54
55  // Read in the entire PHU of the FITS file to a string.
56  // This will be read by the wcslib functions to extract the WCS.
57  status = 0;
58  fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
59  if( status ){
60    duchampWarning("defineWCS","Error whilst reading FITS header to string: ");
61    fits_report_error(stderr, status);
62    return FAILURE;
63  }
64
65  // Close the FITS file -- not needed any more in this function.
66  status = 0;
67  fits_close_file(fptr, &status);
68  if (status){
69    duchampWarning("defineWCS","Error closing file: ");
70    fits_report_error(stderr, status);
71  }
72 
73  struct wcsprm *localwcs;
74  localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
75  localwcs->flag=-1;
76
77  // Initialise the wcsprm structure
78  if(status = wcsini(true, numAxes, localwcs)){
79    std::stringstream errmsg;
80    errmsg << "wcsini failed! Code=" << status
81           << ": " << wcs_errmsg[status] << std::endl;
82    duchampError("defineWCS",errmsg.str());
83    return FAILURE;
84  }
85
86  int relax=1; // for wcspih -- admit all recognised informal WCS extensions
87  int ctrl=2;  // for wcspih -- report each rejected card and its reason for
88               //               rejection
89  int localnwcs, nreject;
90  // Parse the FITS header to fill in the wcsprm structure
91  if(status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs)){
92    // if here, something went wrong -- report what.
93    std::stringstream errmsg;
94    errmsg << "wcspih failed!\nWCSLIB error code=" << status
95           << ": " << wcs_errmsg[status] << std::endl;
96    duchampWarning("defineWCS",errmsg.str());
97  }
98  else{ 
99    int stat[NWCSFIX];
100    // Applies all necessary corrections to the wcsprm structure
101    //  (missing cards, non-standard units or spectral types, ...)
102    if(status = wcsfix(1, (const int*)dimAxes, localwcs, stat)) {
103      std::stringstream errmsg;
104      errmsg << "wcsfix failed:\n";
105      for(int i=0; i<NWCSFIX; i++)
106        if (stat[i] > 0)
107          errmsg << "WCSLIB error code=" << status << ": "
108                 << wcsfix_errmsg[stat[i]] << std::endl;
109      duchampWarning("defineWCS", errmsg.str() );
110    }
111
112    // Set up the wcsprm struct. Report if something goes wrong.
113    if(status = wcsset(localwcs)){
114      std::stringstream errmsg;
115      errmsg<<"wcsset failed!\n"
116            <<"WCSLIB error code=" << status
117            <<": "<<wcs_errmsg[status] << std::endl;
118      duchampWarning("defineWCS",errmsg.str());
119    }
120
121    if(localwcs->naxis>2){  // if there is a spectral axis
122
123      int index = localwcs->spec;
124      string desiredType,specType = localwcs->ctype[index];
125      if(localwcs->restfrq != 0){
126        // Set the spectral axis to a standard specification: VELO-F2V
127        desiredType = duchampVelocityType;
128        if(localwcs->restwav == 0)
129          localwcs->restwav = 299792458.0 /  localwcs->restfrq;
130        this->spectralDescription = duchampSpectralDescription[VELOCITY];
131      }
132      else{
133        // No rest frequency defined, so put spectral dimension in frequency.
134        // Set the spectral axis to a standard specification: FREQ
135        duchampWarning("defineWCS",
136       "No rest frequency defined. Using frequency units in spectral axis.\n");
137        desiredType = duchampFrequencyType;
138        par.setSpectralUnits("MHz");
139        if(strcmp(localwcs->cunit[index],"")==0){
140          duchampWarning("defineWCS",
141          "No frequency unit given. Assuming frequency axis is in Hz.\n");
142          strcpy(localwcs->cunit[index],"Hz");
143        }
144        this->spectralDescription = duchampSpectralDescription[FREQUENCY];
145      }
146
147      // Check to see if the spectral type (eg VELO-F2V) matches that wanted
148      //   from duchamp.hh. Only first four characters checked.
149      if(strncmp(specType.c_str(),desiredType.c_str(),4)!=0){
150        index = -1;
151        // If not a match, translate the spectral axis to the desired type
152        if(status = wcssptr(localwcs, &index, (char *)desiredType.c_str())){
153          std::stringstream errmsg;
154          errmsg<< "wcssptr failed! Code=" << status << ": "
155                << wcs_errmsg[status] << std::endl;
156          duchampWarning("defineWCS",errmsg.str());
157        }       
158      }
159   
160    } // end of if(numAxes>2)
161   
162    // Save the wcs to the FitsHeader class that is running this function
163    this->setWCS(localwcs);
164    this->setNWCS(localnwcs);
165
166  }
167
168  wcsvfree(&localnwcs,&localwcs);
169  delete [] dimAxes;
170
171  // Get the brightness unit, so that we can set the units for the
172  //  integrated flux when we go to fixUnits.
173  this->readBUNIT(fname);
174
175  this->fixUnits(par);
176
177  return SUCCESS;
178
179}
Note: See TracBrowser for help on using the repository browser.