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

Last change on this file since 1441 was 1418, checked in by MatthewWhiting, 10 years ago

Fixing a WARN message that comes from running wcsfix. This should improve the message as displayed in ticket #230

File size: 8.9 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>
[643]30#include <string.h>
[205]31#include <stdlib.h>
[394]32#include <wcslib/wcs.h>
33#include <wcslib/wcshdr.h>
[400]34#include <wcslib/fitshdr.h>
[394]35#include <wcslib/wcsfix.h>
36#include <wcslib/wcsunits.h>
[160]37#define WCSLIB_GETWCSTAB // define this so that we don't try and redefine
38                         //  wtbarr (this is a problem when using gcc v.4+
39#include <fitsio.h>
40#include <math.h>
[393]41#include <duchamp/duchamp.hh>
42#include <duchamp/fitsHeader.hh>
43#include <duchamp/Cubes/cubes.hh>
[160]44
[378]45namespace duchamp
[160]46{
47
[698]48  OUTCOME FitsHeader::defineWCS(std::string fname, Param &par)
[378]49  {
[971]50
51    OUTCOME returnValue=SUCCESS;
52    fitsfile *fptr;
53    int status = 0;
54    // Open the FITS file
55    if( fits_open_file(&fptr,fname.c_str(),READONLY,&status) ){
56      fits_report_error(stderr, status);
57      returnValue = FAILURE;
58    }
59    else {
60
61      returnValue = this->defineWCS(fptr,par);
62
63      // Close the FITS file
64      status = 0;
65      fits_close_file(fptr, &status);
66      if (status){
67        DUCHAMPWARN("Cube Reader","Error closing file: ");
68        fits_report_error(stderr, status);
69      }
70 
71    }
72    return returnValue;
73
74  }
75
76  OUTCOME FitsHeader::defineWCS(Param &par)
77  {
78    OUTCOME returnValue=SUCCESS;
79    if(this->fptr == 0) {
80      returnValue = FAILURE;
81      DUCHAMPERROR("Cube Reader", "FITS file not opened.");
82    }
83    else {
84      returnValue = this->defineWCS(this->fptr, par);
85    }
86    return returnValue;
87  }
88
89
90
91  OUTCOME FitsHeader::defineWCS(fitsfile *fptr, Param &par)
92  {
[528]93    ///   A function that reads the WCS header information from the
94    ///    FITS file given by fname
95    ///   It will also sort out the spectral axis, and covert to the correct
96    ///    velocity type, or frequency type if need be.
97    /// \param fname Fits file to read.
98    /// \param par Param set to help fix the units with.
[161]99
[1006]100    OUTCOME returnValue=SUCCESS;
101
102    int numAxes=0;
[1272]103    size_t *dimAxes = 0;
[378]104    int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
105    int nExc = 0,nkeys;
[971]106    int status = 0;
[1006]107    char *hdr=0;
[1298]108    struct wcsprm *localwcs=NULL;
[1006]109    int localnwcs;
[161]110
[378]111    // Get the dimensions of the FITS file -- number of axes and size of each.
112    status = 0;
113    if(fits_get_img_dim(fptr, &numAxes, &status)){
114      fits_report_error(stderr, status);
[1006]115      returnValue = FAILURE;
[378]116    }
[1006]117
118    if(returnValue == SUCCESS){
[1272]119      dimAxes = new size_t[numAxes];
[1006]120      for(int i=0;i<numAxes;i++) dimAxes[i]=1;
121      status = 0;
[1272]122      if(fits_get_img_size(fptr, numAxes, (long*)dimAxes, &status)){
[1006]123        fits_report_error(stderr, status);
124        returnValue = FAILURE;
125      }
[378]126    }
[161]127
[1006]128    if(returnValue == SUCCESS){
129      // Read in the entire PHU of the FITS file to a std::string.
130      // This will be read by the wcslib functions to extract the WCS.
131      status = 0;
132      fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
133      if( status ){
134        DUCHAMPWARN("Cube Reader","Error whilst reading FITS header to string: ");
135        fits_report_error(stderr, status);
136        return FAILURE;
137      }
[378]138    }
[971]139 
[1006]140    if(returnValue == SUCCESS){
141      // Define a temporary, local version of the WCS
142      localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
143      localwcs->flag=-1;
144     
145      // Initialise this temporary wcsprm structure
146      status = wcsini(true, numAxes, localwcs);
147      if(status){
148        DUCHAMPERROR("Cube Reader","wcsini failed! Code=" << status << ": " << wcs_errmsg[status]);
149        returnValue = FAILURE;
150      }
151      else{
152        int relax=1; // for wcspih -- admit all recognised informal WCS extensions
153        int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
154        int nreject;
155        // Parse the FITS header to fill in the wcsprm structure
156        status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
157        if(status){
158          // if here, something went wrong -- report what.
159          DUCHAMPERROR("Cube Reader","Could not parse header with wcspih!\nWCSLIB error code=" << status << ": " << wcs_errmsg[status]);
160          returnValue = FAILURE;
161        }
162        else  returnValue = this->defineWCS(localwcs, localnwcs, dimAxes, par);
163       
164      }
165    }
[161]166
[1006]167    // clean up allocated memory
168    if(localwcs > 0){
169      wcsvfree(&localnwcs,&localwcs);
170      wcsfree(localwcs);
171      free(localwcs);
172    }
173    if(hdr>0) free(hdr);
174    if(dimAxes>0) {
175      delete [] dimAxes;
176    }
177
178    return returnValue;
179
180  }
181
[1272]182  OUTCOME FitsHeader::defineWCS(wcsprm *theWCS, int nWCS, size_t *dimAxes, Param &par)
[1006]183  {
184 
185    int status=0;
186    int stat[NWCSFIX];
187    // Applies all necessary corrections to the wcsprm structure
188    //  (missing cards, non-standard units or spectral types, ...)
189    status = wcsfix(1, (const int*)dimAxes, theWCS, stat);
190    if(status) {
191      std::stringstream errmsg;
192      errmsg << "wcsfix failed with function status returns of:\n";
193      for(int i=0; i<NWCSFIX; i++)
194        if (stat[i] > 0)
195          errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
196                 << wcsfix_errmsg[stat[i]] << std::endl;
[1418]197      DUCHAMPWARN("Cube Reader", errmsg.str());
[378]198      return FAILURE;
[160]199    }
[1006]200    // Set up the wcsprm struct. Report if something goes wrong.
201    status = wcsset(theWCS);
[270]202    if(status){
[1006]203      DUCHAMPWARN("Cube Reader","wcsset failed with error code=" << status <<": "<<wcs_errmsg[status]);
[1005]204      return FAILURE;
[160]205    }
[1006]206    else{
207
[378]208      int stat[NWCSFIX];
[1006]209      // Re-do the corrections to account for things like NCP projections
210      status = wcsfix(1, (const int*)dimAxes, theWCS, stat);
[378]211      if(status) {
212        std::stringstream errmsg;
[913]213        errmsg << "wcsfix failed with function status returns of:\n";
[378]214        for(int i=0; i<NWCSFIX; i++)
215          if (stat[i] > 0)
216            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
217                   << wcsfix_errmsg[stat[i]] << std::endl;
[1418]218        DUCHAMPWARN("Cube Reader", errmsg.str() );
[378]219      }
[356]220
[573]221
[1006]222      char stype[5],scode[5],sname[22],units[8],ptype,xtype;
223      int restreq;
[378]224
[1006]225      if(par.getSpectralType()!=""){ // User wants to convert the spectral type
[947]226
[1006]227        std::string desiredType = par.getSpectralType();
228         
229        status = spctyp((char *)desiredType.c_str(),stype,scode,sname,units,&ptype,&xtype,&restreq);
230        if(status){
231          DUCHAMPERROR("Cube Reader", "Spectral type " << desiredType << " is not a valid spectral type. No translation done.");
232        }
233        else{
[948]234
[1006]235          if(desiredType.size()<4){
236            DUCHAMPERROR("Cube Reader", "Spectral Type " << desiredType << " requested, but this is too short. No translation done");
[949]237          }
238          else{
[1006]239            if(desiredType.size()<8){
240              if(desiredType.size()==4) desiredType+="-???";
241              else while (desiredType.size()<8) desiredType+="?";
[948]242            }
[1006]243          }
244          if(par.getRestFrequency()>0.){
245            theWCS->restfrq = par.getRestFrequency();
246          }
247          status = wcssptr(theWCS, &(theWCS->spec), (char *)desiredType.c_str());
248          if(status){
249            DUCHAMPWARN("Cube Reader","WCSSPTR failed when converting from type \"" << theWCS->ctype[theWCS->spec]
250                        << "\" to type \"" << desiredType << " with code=" << status << ": " << wcs_errmsg[status]);
251          }
252          else if(par.getRestFrequency()>0.) par.setFlagRestFrequencyUsed(true);
[948]253
[949]254
[948]255        }
256
[1006]257      }
[948]258
[1006]259      status = spctyp(theWCS->ctype[theWCS->spec],stype,scode,sname,units,&ptype,&xtype,&restreq);
[947]260
[1006]261      this->spectralType  = stype;
262      this->spectralDescription = sname;
263
264      // Save the wcs to the FitsHeader class that is running this function
265      this->setWCS(theWCS);
266      this->setNWCS(nWCS);
[508]267 
[1006]268      // Now that the WCS is defined, use it to set the offsets in the Param set
269      par.setOffsets(theWCS);
[508]270
[378]271    }
[160]272
[570]273    // work out whether the array is 2dimensional
[1006]274    if(theWCS->naxis==2) this->flag2D = true;
[570]275    else{
276      int numDim=0;
[1006]277      for(int i=0;i<wcs->naxis;i++) if(dimAxes[i]>1) numDim++;
[980]278      this->flag2D = (numDim==2);
[570]279    }
[1006]280   
[378]281    return SUCCESS;
[160]282
[1006]283   
[378]284  }
285
[1006]286
[160]287}
Note: See TracBrowser for help on using the repository browser.