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

Last change on this file since 224 was 224, checked in by Matthew Whiting, 17 years ago
  • Main change is to correct the problem reported in ticket #4, so that the velocity units are correctly dealt with. This entailed:
    • Changing the way wcssptr is called in FitsIO/wcsIO.cc, so that it is called when there is no CUNIT3 keyword, as well as when the type is different to that desired.
    • Changing the way fixUnits() will deal with missing units -- hopefully this will now not occur, and the error message has been changed accordingly.

Other changes include:

  • Making a new file cubes_extended.cc, that has those functions from cubes.cc that require external functions. This enables simpler compilation of test programs.
  • An additional clause in dataIO.cc to set the null value when the BLANK keyword is not present. However, this remains commented out, as I don't think it is necessary at this point, and there is a question about whether it is correct.
  • Other minor typo fixes.
File size: 8.2 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   *   A function that reads the WCS header information from the
20   *    FITS file given by fname
21   *   It will also sort out the spectral axis, and covert to the correct
22   *    velocity type, or frequency type if need be.
23   *   It calls FitsHeader::readBUNIT so that the Integrated Flux units can
24   *    be calculated by FitsHeader::fixUnits.
25   * \param fname Fits file to read.
26   * \param par Param set to help fix the units with.
27   */
28
29  fitsfile *fptr;
30  int bitpix,numAxes;
31  int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
32  int nExc = 0,nkeys;
33  char *hdr;
34
35  // Open the FITS file
36  int status = 0;
37  if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
38    fits_report_error(stderr, status);
39    return FAILURE;
40  }
41
42  // Get the dimensions of the FITS file -- number of axes and size of each.
43  status = 0;
44  if(fits_get_img_dim(fptr, &numAxes, &status)){
45    fits_report_error(stderr, status);
46    return FAILURE;
47  }
48  long *dimAxes = new long[numAxes];
49  for(int i=0;i<numAxes;i++) dimAxes[i]=1;
50  status = 0;
51  if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
52    fits_report_error(stderr, status);
53    return FAILURE;
54  }
55
56  // Read in the entire PHU of the FITS file to a string.
57  // This will be read by the wcslib functions to extract the WCS.
58  status = 0;
59  fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
60  if( status ){
61    duchampWarning("defineWCS","Error whilst reading FITS header to string: ");
62    fits_report_error(stderr, status);
63    return FAILURE;
64  }
65
66  // Close the FITS file -- not needed any more in this function.
67  status = 0;
68  fits_close_file(fptr, &status);
69  if (status){
70    duchampWarning("defineWCS","Error closing file: ");
71    fits_report_error(stderr, status);
72  }
73 
74  struct wcsprm *localwcs;
75  localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
76  localwcs->flag=-1;
77
78  // Initialise the wcsprm structure
79  if(status = wcsini(true, numAxes, localwcs)){
80    std::stringstream errmsg;
81    errmsg << "wcsini failed! Code=" << status
82           << ": " << wcs_errmsg[status] << std::endl;
83    duchampError("defineWCS",errmsg.str());
84    return FAILURE;
85  }
86
87  int relax=1; // for wcspih -- admit all recognised informal WCS extensions
88  int ctrl=2;  // for wcspih -- report each rejected card and its reason for
89               //               rejection
90  int localnwcs, nreject;
91  // Parse the FITS header to fill in the wcsprm structure
92  if(status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs)){
93    // if here, something went wrong -- report what.
94    std::stringstream errmsg;
95    errmsg << "wcspih failed!\nWCSLIB error code=" << status
96           << ": " << wcs_errmsg[status] << std::endl;
97    duchampWarning("defineWCS",errmsg.str());
98  }
99  else{ 
100    int stat[NWCSFIX];
101    // Applies all necessary corrections to the wcsprm structure
102    //  (missing cards, non-standard units or spectral types, ...)
103    if(status = wcsfix(1, (const int*)dimAxes, localwcs, stat)) {
104      std::stringstream errmsg;
105      errmsg << "wcsfix failed:\n";
106      for(int i=0; i<NWCSFIX; i++)
107        if (stat[i] > 0)
108          errmsg << "WCSLIB error code=" << status << ": "
109                 << wcsfix_errmsg[stat[i]] << std::endl;
110      duchampWarning("defineWCS", errmsg.str() );
111    }
112
113    // Set up the wcsprm struct. Report if something goes wrong.
114    if(status = wcsset(localwcs)){
115      std::stringstream errmsg;
116      errmsg<<"wcsset failed!\n"
117            <<"WCSLIB error code=" << status
118            <<": "<<wcs_errmsg[status] << std::endl;
119      duchampWarning("defineWCS",errmsg.str());
120    }
121
122    if(localwcs->naxis>2){  // if there is a spectral axis
123
124      int index = localwcs->spec;
125      string desiredType,specType = localwcs->ctype[index];
126//            << "  " << localwcs->ctype[localwcs->spec] << "\n";
127      if(localwcs->restfrq != 0){
128        // Set the spectral axis to a standard specification: VELO-F2V
129        desiredType = duchampVelocityType;
130        if(localwcs->restwav == 0)
131          localwcs->restwav = 299792458.0 /  localwcs->restfrq;
132        this->spectralDescription = duchampSpectralDescription[VELOCITY];
133      }
134      else{
135        // No rest frequency defined, so put spectral dimension in frequency.
136        // Set the spectral axis to a standard specification: FREQ
137        duchampWarning("defineWCS",
138       "No rest frequency defined. Using frequency units in spectral axis.\n");
139        desiredType = duchampFrequencyType;
140        par.setSpectralUnits("MHz");
141        if(strcmp(localwcs->cunit[index],"")==0){
142          duchampWarning("defineWCS",
143          "No frequency unit given. Assuming frequency axis is in Hz.\n");
144          strcpy(localwcs->cunit[index],"Hz");
145        }
146        this->spectralDescription = duchampSpectralDescription[FREQUENCY];
147      }
148
149
150      bool needToTranslate = false;
151
152      if(strncmp(specType.c_str(),desiredType.c_str(),4)!=0)
153        needToTranslate = true;
154
155      char *blankstring;
156      strcpy(blankstring,"");
157      if(strcmp(localwcs->cunit[localwcs->spec],blankstring)==0)
158        needToTranslate = true;
159
160      if(needToTranslate){
161
162        if(strcmp(localwcs->ctype[localwcs->spec],"VELO")==0)
163          strcpy(localwcs->ctype[localwcs->spec],"VELO-F2V");
164
165        index = localwcs->spec;
166       
167        if(status = wcssptr(localwcs, &index, (char *)desiredType.c_str())){
168          std::stringstream errmsg;
169          errmsg<< "WCSSPTR failed! Code=" << status << ": "
170                << wcs_errmsg[status] << std::endl
171                << "(wanted to convert from type \"" << specType
172                << "\" to type \"" << desiredType << "\")\n";
173          duchampWarning("defineWCS",errmsg.str());
174
175        }
176
177      }
178
179      /*
180
181      // Check to see if the spectral type (eg VELO-F2V) matches that wanted
182      //   from duchamp.hh. Only first four characters checked.
183
184      char *blankstring;
185      strcpy(blankstring,"");
186      if(strncmp(specType.c_str(),desiredType.c_str(),4)!=0){
187
188//      index = -1;
189        index = localwcs->spec;
190        // If not a match, translate the spectral axis to the desired type
191        if(status = wcssptr(localwcs, &index, (char *)desiredType.c_str())){
192          std::stringstream errmsg;
193          errmsg<< "WCSSPTR failed! Code=" << status << ": "
194                << wcs_errmsg[status] << std::endl
195                << "(wanted to convert from type \"" << specType
196                << "\" to type \"" << desiredType << "\")\n";
197          duchampWarning("defineWCS",errmsg.str());
198        }       
199
200      }
201      else if(strcmp(localwcs->cunit[localwcs->spec],blankstring)==0){
202        if(strcmp(localwcs->ctype[localwcs->spec],"VELO")==0)
203          strcpy(localwcs->ctype[localwcs->spec],"VELO-F2V");
204        string tempType = "FREQ-F2V";
205        std::stringstream errmsg;
206        status=0;
207        index = localwcs->spec;
208//      if(status=wcssptr(localwcs, &index, (char *)tempType.c_str())){
209//        errmsg<< "First one. Code=" << status << ": "
210//              << wcs_errmsg[status] << std::endl
211//              << "(wanted to convert from type \""
212//              << localwcs->ctype[localwcs->spec]
213//              << "\" to type \"" << tempType << "\")\n";
214//        duchampWarning("defineWCS 1", errmsg.str());
215//      }
216//      std::cerr<<"after #1: type = " << localwcs->ctype[localwcs->spec]
217//               << ", units = " << localwcs->cunit[localwcs->spec] << "\n";
218        status=0;
219        index = localwcs->spec;
220        errmsg.str("");
221        if(status=wcssptr(localwcs, &index, (char *)desiredType.c_str())){
222          errmsg<< "Second one. Code=" << status << ": "
223                << wcs_errmsg[status] << std::endl
224                << "(wanted to convert from type \""
225                << localwcs->ctype[localwcs->spec]
226                << "\" to type \"" << desiredType << "\")\n";
227          duchampWarning("defineWCS 2", errmsg.str());
228        }
229//      std::cerr<<"after #2: type = " << localwcs->ctype[localwcs->spec]
230//               << ", units = " << localwcs->cunit[localwcs->spec] << "\n";
231      }
232
233      */
234
235   
236    } // end of if(numAxes>2)
237   
238    // Save the wcs to the FitsHeader class that is running this function
239    this->setWCS(localwcs);
240    this->setNWCS(localnwcs);
241
242  }
243
244  wcsvfree(&localnwcs,&localwcs);
245  delete [] dimAxes;
246
247  // Get the brightness unit, so that we can set the units for the
248  //  integrated flux when we go to fixUnits.
249  this->readBUNIT(fname);
250
251  this->fixUnits(par);
252
253  return SUCCESS;
254
255}
Note: See TracBrowser for help on using the repository browser.