source: trunk/src/fitsHeader.cc @ 528

Last change on this file since 528 was 528, checked in by MatthewWhiting, 15 years ago

Changing the documentation comments to match the askapsoft style. Also have split ChanMap? and Object3D into separate files.

File size: 9.3 KB
Line 
1// -----------------------------------------------------------------------
2// fitsHeader.cc: Information about the FITS file's header.
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 <sstream>
30#include <string>
31#include <wcslib/wcs.h>
32#include <wcslib/wcsunits.h>
33#include <duchamp/duchamp.hh>
34#include <duchamp/param.hh>
35#include <duchamp/fitsHeader.hh>
36#include <duchamp/Utils/utils.hh>
37
38namespace duchamp
39{
40
41  FitsHeader::FitsHeader()
42  {
43    this->wcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
44    this->wcs->flag=-1;
45    wcsini(true, 3, this->wcs);
46    this->wcsIsGood = false;
47    this->nwcs = 0;
48    this->scale=1.;
49    this->offset=0.;
50    this->power=1.;
51    this->fluxUnits="counts";
52    this->intFluxUnits="counts";
53  }
54
55  FitsHeader::~FitsHeader()
56  {
57    /// @details Uses the WCSLIB function wcsvfree to clear the wcsprm struct.
58    wcsvfree(&nwcs,&wcs);
59  }
60
61  FitsHeader::FitsHeader(const FitsHeader& h)
62  {
63    operator=(h);
64  }
65
66  FitsHeader& FitsHeader::operator= (const FitsHeader& h)
67  {
68    if(this == &h) return *this;
69    this->wcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
70    this->wcs->flag     = -1;
71    wcsini(true, h.wcs->naxis, this->wcs);
72    wcscopy(true, h.wcs, this->wcs);
73    wcsset(this->wcs);
74    this->nwcs          = h.nwcs;
75    this->wcsIsGood     = h.wcsIsGood;
76    this->naxis         = h.naxis;
77    this->spectralUnits = h.spectralUnits;
78    this->fluxUnits     = h.fluxUnits;
79    this->intFluxUnits  = h.intFluxUnits;
80    this->beamSize      = h.beamSize;
81    this->bmajKeyword   = h.bmajKeyword;
82    this->bminKeyword   = h.bminKeyword;
83    this->bpaKeyword    = h.bpaKeyword;
84    this->blankKeyword  = h.blankKeyword;
85    this->bzeroKeyword  = h.bzeroKeyword;
86    this->bscaleKeyword = h.bscaleKeyword;
87    this->scale         = h.scale;
88    this->offset        = h.offset;
89    this->power         = h.power;
90    return *this;
91  }
92
93  void FitsHeader::setWCS(struct wcsprm *w)
94  {
95    ///  A function that assigns the wcs parameters, and runs
96    ///   wcsset to set it up correctly.
97    ///  Performs a check to see if the WCS is good (by looking at
98    ///   the lng and lat wcsprm parameters), and sets the wcsIsGood
99    ///   flag accordingly.
100    /// \param w A WCSLIB wcsprm struct with the correct parameters.
101
102    wcscopy(true, w, this->wcs);
103    wcsset(this->wcs);
104    if( (w->lng!=-1) && (w->lat!=-1) ) this->wcsIsGood = true;
105  }
106
107  struct wcsprm *FitsHeader::getWCS()
108  {
109    ///  A function that returns a properly initilized wcsprm object
110    ///  corresponding to the WCS.
111
112    struct wcsprm *wNew = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
113    wNew->flag=-1;
114    wcsini(true, this->wcs->naxis, wNew);
115    wcscopy(true, this->wcs, wNew);
116    wcsset(wNew);
117    return wNew;
118  }
119
120  int FitsHeader::wcsToPix(const double *world, double *pix)
121  {     
122    return wcsToPixSingle(this->wcs, world, pix); 
123  }
124  int FitsHeader::wcsToPix(const double *world, double *pix, const int npts)
125  {
126    return wcsToPixMulti(this->wcs, world, pix, npts); 
127  }
128  int FitsHeader::pixToWCS(const double *pix, double *world)
129  {   
130    return pixToWCSSingle(this->wcs, pix, world); 
131  }
132  int FitsHeader::pixToWCS(const double *pix, double *world, const int npts)
133  {
134    return pixToWCSMulti(this->wcs, pix,world, npts); 
135  }
136
137
138  double FitsHeader::pixToVel(double &x, double &y, double &z)
139  {
140    double vel;
141    if(this->wcsIsGood){
142      double *pix   = new double[3];
143      double *world = new double[3];
144      pix[0] = x; pix[1] = y; pix[2] = z;
145      pixToWCSSingle(this->wcs,pix,world);
146      vel = this->specToVel(world[2]);
147      delete [] pix;
148      delete [] world;
149    }
150    else vel = z;
151    return vel;
152  }
153
154  double* FitsHeader::pixToVel(double &x, double &y, double *zarray, int size)
155  {
156    double *newzarray = new double[size];
157    if(this->wcsIsGood){
158      double *pix   = new double[size*3];
159      for(int i=0;i<size;i++){
160        pix[3*i]   = x;
161        pix[3*i+1] = y;
162        pix[3*i+2] = zarray[i];
163      }
164      double *world = new double[size*3];
165      pixToWCSMulti(this->wcs,pix,world,size);
166      delete [] pix;
167      for(int i=0;i<size;i++) newzarray[i] = this->specToVel(world[3*i+2]);
168      delete [] world;
169    }
170    else{
171      for(int i=0;i<size;i++) newzarray[i] = zarray[i];
172    }
173    return newzarray;
174  }
175
176  double FitsHeader::specToVel(const double &coord)
177  {
178    double vel;
179    if(power==1.0) vel =  coord*this->scale + this->offset;
180    else vel = pow( (coord*this->scale + this->offset), this->power);
181    return vel;
182  }
183
184  double FitsHeader::velToSpec(const float &velocity)
185  {
186    //   return velToCoord(this->wcs,velocity,this->spectralUnits);};
187    return (pow(velocity, 1./this->power) - this->offset) / this->scale;
188  }
189
190  std::string FitsHeader::getIAUName(double ra, double dec)
191  {
192    if(strcmp(this->wcs->lngtyp,"RA")==0)
193      return getIAUNameEQ(ra, dec, this->wcs->equinox);
194    else
195      return getIAUNameGAL(ra, dec);
196  }
197
198  bool FitsHeader::needBeamSize()
199  {
200    ///  A function that tells you whether the beam correction is
201    ///  needed. It checks to see whether the flux units string ends in
202    ///  "/beam" (in which case the beam size etc is needed and
203    ///  integrated fluxes need to be corrected).
204    ///  /return True if FitsHeader::fluxUnits ends in "/beam". False
205    ///  otherwise.
206
207    int size = this->fluxUnits.size();
208    if(size<6) return false;
209    else {
210      std::string tailOfFluxUnits = makelower(this->fluxUnits.substr(size-5,size));
211      return (tailOfFluxUnits == "/beam");
212    }
213  }
214
215  void FitsHeader::fixUnits(Param &par)
216  {
217    ///  Put the units for the FITS header into some sort of standard form.
218    ///
219    ///  We first get the desired spectral units from the Parameter set,
220    ///  and then transform the spectral units of the wcsprm struct to
221    ///  those units. If this doesn't work, we leave them as they are. If
222    ///  they are blank, we make them SPC and give an error message --
223    ///  this should hopefully NOT happen.
224    ///
225    ///  We also work out the units for the integrated flux. If there are
226    ///  three axes, we just append the spectral units to the flux units
227    ///  (removing "/beam" if it is present). If there are just two, we
228    ///  simply keep it the same, removing the "/beam".
229    ///
230    ///  \param par The parameter set telling us what the desired
231    ///             spectral units are.
232
233    // define spectral units from the param set
234    this->spectralUnits = par.getSpectralUnits();
235    double sc=1.;
236    double of=0.;
237    double po=1.;
238    //   if((this->wcsIsGood) && (this->naxis>2)){
239    if(this->wcsIsGood){
240      int status = wcsunits( this->wcs->cunit[this->wcs->spec],
241                             (char *)this->spectralUnits.c_str(),
242                             &sc, &of, &po);
243      if(status > 0){
244        std::stringstream errmsg;
245        errmsg << "WCSUNITS Error, Code = " << status
246               << ": " << wcsunits_errmsg[status] << "\n";
247        if(status == 10)
248          errmsg << "Tried to get conversion from \""
249                 << this->wcs->cunit[this->wcs->spec] << "\" to \""
250                 << this->spectralUnits.c_str() << "\".\n";
251        this->spectralUnits = this->wcs->cunit[this->wcs->spec];
252        if(this->spectralUnits==""){
253          errmsg << "Spectral units not specified. "
254                 << "For data presentation, we will use dummy units of \"SPC\"."
255                 << "\n"
256                 << "Please report this occurence -- it should not happen now! "
257                 << "In the meantime, you may want to set the CUNIT"
258                 << this->wcs->spec + 1 <<" keyword to make this work.\n";
259          this->spectralUnits = "SPC";
260        }
261        duchampError("fixUnits", errmsg.str());
262      }
263
264    }
265    this->scale = sc;
266    this->offset= of;
267    this->power = po;
268
269    this->setIntFluxUnits();
270
271  }
272
273  void FitsHeader::setIntFluxUnits()
274  {
275
276    /// Work out the integrated flux units, based on the spectral
277    /// units. If flux is per beam, trim the /beam from the flux
278    /// units. Then, if as long as the image is 3D, multiply by the
279    /// spectral units.
280
281    if(this->fluxUnits.size()>5){
282   
283      if(makelower(this->fluxUnits.substr(this->fluxUnits.size()-5,
284                                          this->fluxUnits.size()   )) == "/beam"){
285        this->intFluxUnits = this->fluxUnits.substr(0,this->fluxUnits.size()-5);
286      }
287      else this->intFluxUnits = this->fluxUnits;
288
289    }
290
291    if(!this->flag2D) this->intFluxUnits += " " + this->spectralUnits;
292
293  }
294
295}
Note: See TracBrowser for help on using the repository browser.