source: tags/release-1.1/src/fitsHeader.cc @ 1391

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