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

Last change on this file since 972 was 971, checked in by MatthewWhiting, 12 years ago

A bunch of changes aimed at streamlining the FITS file access at the start, particularly for the case of large images where we access a subsection (this can be slow to access). We now only open the file once, and keep the fitsfile pointer in the FitsHeader? class. Once the image access is finished the file is closed.

File size: 8.4 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 <string.h>
31#include <stdlib.h>
32#include <wcslib/wcs.h>
33#include <wcslib/wcshdr.h>
34#include <wcslib/fitshdr.h>
35#include <wcslib/wcsfix.h>
36#include <wcslib/wcsunits.h>
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>
41#include <duchamp/duchamp.hh>
42#include <duchamp/fitsHeader.hh>
43#include <duchamp/Cubes/cubes.hh>
44
45namespace duchamp
46{
47
48  OUTCOME FitsHeader::defineWCS(std::string fname, Param &par)
49  {
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  {
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.
99
100    int numAxes;
101    int noComments = 1; //so that fits_hdr2str will ignore COMMENT, HISTORY etc
102    int nExc = 0,nkeys;
103    int status = 0;
104    char *hdr;
105
106    // Get the dimensions of the FITS file -- number of axes and size of each.
107    status = 0;
108    if(fits_get_img_dim(fptr, &numAxes, &status)){
109      fits_report_error(stderr, status);
110      return FAILURE;
111    }
112    long *dimAxes = new long[numAxes];
113    for(int i=0;i<numAxes;i++) dimAxes[i]=1;
114    status = 0;
115    if(fits_get_img_size(fptr, numAxes, dimAxes, &status)){
116      fits_report_error(stderr, status);
117      return FAILURE;
118    }
119
120    // Read in the entire PHU of the FITS file to a std::string.
121    // This will be read by the wcslib functions to extract the WCS.
122    status = 0;
123    fits_hdr2str(fptr, noComments, NULL, nExc, &hdr, &nkeys, &status);
124    if( status ){
125      DUCHAMPWARN("Cube Reader","Error whilst reading FITS header to string: ");
126      fits_report_error(stderr, status);
127      return FAILURE;
128    }
129 
130    // Define a temporary, local version of the WCS
131    struct wcsprm *localwcs;
132    localwcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
133    localwcs->flag=-1;
134
135    // Initialise this temporary wcsprm structure
136    status = wcsini(true, numAxes, localwcs);
137    if(status){
138      DUCHAMPERROR("Cube Reader","wcsini failed! Code=" << status << ": " << wcs_errmsg[status]);
139      return FAILURE;
140    }
141
142    this->naxis=0;
143    for(int i=0;i<numAxes;i++)
144      if(dimAxes[i]>1) this->naxis++;
145
146    int relax=1; // for wcspih -- admit all recognised informal WCS extensions
147    int ctrl=2;  // for wcspih -- report each rejected card and its reason for rejection
148    int localnwcs, nreject;
149    // Parse the FITS header to fill in the wcsprm structure
150    status=wcspih(hdr, nkeys, relax, ctrl, &nreject, &localnwcs, &localwcs);
151    if(status){
152      // if here, something went wrong -- report what.
153      DUCHAMPWARN("Cube Reader","wcspih failed!\nWCSLIB error code=" << status << ": " << wcs_errmsg[status]);
154    }
155    else{ 
156      int stat[NWCSFIX];
157      // Applies all necessary corrections to the wcsprm structure
158      //  (missing cards, non-standard units or spectral types, ...)
159      status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
160      if(status) {
161        std::stringstream errmsg;
162        errmsg << "wcsfix failed with function status returns of:\n";
163        for(int i=0; i<NWCSFIX; i++)
164          if (stat[i] > 0)
165            errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
166                   << wcsfix_errmsg[stat[i]] << std::endl;
167        DUCHAMPWARN("Cube Reader", errmsg);
168      }
169      // Set up the wcsprm struct. Report if something goes wrong.
170      status = wcsset(localwcs);
171      if(status){
172        DUCHAMPWARN("Cube Reader","wcsset failed with error code=" << status <<": "<<wcs_errmsg[status]);
173      }
174      else{
175
176        int stat[NWCSFIX];
177        // Re-do the corrections to account for things like NCP projections
178        status = wcsfix(1, (const int*)dimAxes, localwcs, stat);
179        if(status) {
180          std::stringstream errmsg;
181          errmsg << "wcsfix failed with function status returns of:\n";
182          for(int i=0; i<NWCSFIX; i++)
183            if (stat[i] > 0)
184              errmsg << i+1 << ": WCSFIX error code=" << stat[i] << ": "
185                     << wcsfix_errmsg[stat[i]] << std::endl;
186          DUCHAMPWARN("Cube Reader", errmsg );
187        }
188
189
190        char stype[5],scode[5],sname[22],units[8],ptype,xtype;
191        int restreq;
192        struct wcserr *err;
193
194        if(par.getSpectralType()!=""){ // User wants to convert the spectral type
195
196          std::string desiredType = par.getSpectralType();
197         
198          status = spctype((char *)desiredType.c_str(),stype,scode,sname,units,&ptype,&xtype,&restreq,&err);
199          if(status){
200            DUCHAMPERROR("Cube Reader", "Spectral type " << desiredType << " is not a valid spectral type. No translation done.");
201          }
202          else{
203
204            if(desiredType.size()<4){
205              DUCHAMPERROR("Cube Reader", "Spectral Type " << desiredType << " requested, but this is too short. No translation done");
206            }
207            else{
208              if(desiredType.size()<8){
209                if(desiredType.size()==4) desiredType+="-???";
210                else while (desiredType.size()<8) desiredType+="?";
211              }
212            }
213            if(par.getRestFrequency()>0.){
214              localwcs->restfrq = par.getRestFrequency();
215            }
216            status = wcssptr(localwcs, &(localwcs->spec), (char *)desiredType.c_str());
217            if(status){
218              DUCHAMPWARN("Cube Reader","WCSSPTR failed when converting from type \"" << localwcs->ctype[localwcs->spec]
219                          << "\" to type \"" << desiredType << " with code=" << status << ": " << wcs_errmsg[status]);
220            }
221            else if(par.getRestFrequency()>0.) par.setFlagRestFrequencyUsed(true);
222
223
224          }
225
226        }
227
228         
229        status = spctype(localwcs->ctype[localwcs->spec],stype,scode,sname,units,&ptype,&xtype,&restreq,&err);
230
231        this->spectralType  = stype;
232        this->spectralDescription = sname;
233
234        // Save the wcs to the FitsHeader class that is running this function
235        this->setWCS(localwcs);
236        this->setNWCS(localnwcs);
237 
238        // Now that the WCS is defined, use it to set the offsets in the Param set
239        par.setOffsets(localwcs);
240
241      }
242    }
243
244    // work out whether the array is 2dimensional
245    if(localwcs->naxis==2) this->flag2D = true;
246    else{
247      int numDim=0;
248      for(int i=0;i<numAxes;i++) if(dimAxes[i]>1) numDim++;
249      this->flag2D = (numDim<=2);
250    }
251
252    // clean up allocated memory
253    wcsvfree(&localnwcs,&localwcs);
254    wcsfree(localwcs);
255    free(localwcs);
256    free(hdr);
257    delete [] dimAxes;
258
259    return SUCCESS;
260
261  }
262
263}
Note: See TracBrowser for help on using the repository browser.