source: tags/release-1.1.4/src/Utils/wcsFunctions.cc @ 1441

Last change on this file since 1441 was 394, checked in by MatthewWhiting, 17 years ago

Fixing wcslib include calls so that it is a bit more robust.

File size: 13.1 KB
Line 
1// -----------------------------------------------------------------------
2// wcsFunctions.cc: Functions to convert between pixel and world
3//                  coordinates -- user-friendly front ends to the
4//                  WCSLIB functions.
5// -----------------------------------------------------------------------
6// Copyright (C) 2006, Matthew Whiting, ATNF
7//
8// This program is free software; you can redistribute it and/or modify it
9// under the terms of the GNU General Public License as published by the
10// Free Software Foundation; either version 2 of the License, or (at your
11// option) any later version.
12//
13// Duchamp is distributed in the hope that it will be useful, but WITHOUT
14// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16// for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with Duchamp; if not, write to the Free Software Foundation,
20// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
21//
22// Correspondence concerning Duchamp may be directed to:
23//    Internet email: Matthew.Whiting [at] atnf.csiro.au
24//    Postal address: Dr. Matthew Whiting
25//                    Australia Telescope National Facility, CSIRO
26//                    PO Box 76
27//                    Epping NSW 1710
28//                    AUSTRALIA
29// -----------------------------------------------------------------------
30#include <iostream>
31#include <sstream>
32#include <math.h>
33#include <wcslib/wcs.h>
34#include <wcslib/wcsunits.h>
35#include <duchamp/duchamp.hh>
36#include <duchamp/Utils/utils.hh>
37
38int pixToWCSSingle(struct wcsprm *wcs, const double *pix, double *world)
39{
40  /**
41   *   Uses wcs to convert the three-dimensional pixel position referenced
42   *    by pix to world coordinates, which are placed in the array world[].
43   *   Assumes that pix only has one point with an x,y,and z pixel positions.
44   *   If there are any other axes present (eg. Stokes), these are set to the
45   *    first pixel in that axis.
46   *   Offsets these pixel values by 1 to account for the C arrays being
47   *    indexed to 0.
48   *
49   * \param wcs The wcsprm struct containing the WCS information.
50   * \param pix The array of pixel coordinates.
51   * \param world The returned array of world coordinates.
52   */
53
54  int naxis=wcs->naxis,npts=1,status;
55
56  double *newpix = new double[naxis*npts];
57  // correct from 0-indexed to 1-indexed pixel array
58  for(int i=0;i<naxis;i++) newpix[i] = 1.;
59  newpix[wcs->lng] += pix[0];
60  newpix[wcs->lat] += pix[1];
61  newpix[wcs->spec]+= pix[2];
62
63  int    *stat      = new int[npts];
64  double *imgcrd    = new double[naxis*npts];
65  double *tempworld = new double[naxis*npts];
66  double *phi       = new double[npts];
67  double *theta     = new double[npts];
68  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
69                phi, theta, tempworld, stat);
70  if(status>0){
71    std::stringstream errmsg;
72    errmsg << "WCS Error Code = " << status <<": " << wcs_errmsg[status]
73           << "\nstat value is " << stat[0] << std::endl;
74    duchamp::duchampError("pixToWCSSingle",errmsg.str());
75  }
76
77  //return just the spatial/velocity information
78  world[0] = tempworld[wcs->lng];
79  world[1] = tempworld[wcs->lat];
80  world[2] = tempworld[wcs->spec];
81
82  delete [] stat;
83  delete [] imgcrd;
84  delete [] tempworld;
85  delete [] phi;
86  delete [] theta;
87  delete [] newpix;
88  return status;
89}
90
91int wcsToPixSingle(struct wcsprm *wcs, const double *world, double *pix)
92{
93  /**
94   *   Uses wcs to convert the three-dimensional world coordinate position
95   *    referenced by world to pixel coordinates, which are placed in the
96   *    array pix[].
97   *   Assumes that world only has one point (three values eg RA Dec Velocity)
98   *   Offsets the pixel values by 1 to account for the C arrays being
99   *    indexed to 0.
100   *
101   * \param wcs The wcsprm struct containing the WCS information.
102   * \param world The array of world coordinates.
103   * \param pix The returned array of pixel coordinates.
104   */
105
106  int naxis=wcs->naxis,npts=1,status;
107
108  double *tempworld = new double[naxis*npts];
109  for(int i=0;i<naxis;i++) tempworld[i] = wcs->crval[i];
110  tempworld[wcs->lng]  = world[0];
111  tempworld[wcs->lat]  = world[1];
112  tempworld[wcs->spec] = world[2];
113
114  int    *stat    = new int[npts];
115  double *temppix = new double[naxis*npts];
116  double *imgcrd  = new double[naxis*npts];
117  double *phi     = new double[npts];
118  double *theta   = new double[npts];
119
120  status=wcss2p(wcs, npts, naxis, tempworld,
121                phi, theta, imgcrd, temppix, stat);
122
123  if( status > 0 ){
124    std::stringstream errmsg;
125    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
126           << "\nstat value is " << stat[0] << std::endl;
127    duchamp::duchampError("wcsToPixSingle",errmsg.str());
128  }
129
130  pix[0] = temppix[wcs->lng] - 1.;
131  pix[1] = temppix[wcs->lat] - 1.;
132  pix[2] = temppix[wcs->spec] - 1.;
133  // correct from 1-indexed to 0-indexed pixel array
134  //  and only return the spatial & frequency information
135
136  delete [] stat;
137  delete [] imgcrd;
138  delete [] temppix;
139  delete [] phi;
140  delete [] theta;
141  delete [] tempworld;
142  return status;
143}
144
145int pixToWCSMulti(struct wcsprm *wcs, const double *pix,
146                  double *world, const int npts)
147{
148  /**
149   *   Uses wcs to convert the three-dimensional pixel positions referenced
150   *    by pix to world coordinates, which are placed in the array world[].
151   *   pix is assumed to hold the positions of npts points.
152   *   Offsets these pixel values by 1 to account for the C arrays being
153   *    indexed to 0.
154   *
155   * \param wcs The wcsprm struct containing the WCS information.
156   * \param pix The array of pixel coordinates.
157   * \param world The returned array of world coordinates.
158   * \param npts The number of distinct pixels in the arrays.
159   */
160
161  int naxis=wcs->naxis,status;
162
163  // correct from 0-indexed to 1-indexed pixel array
164  // Add entries for any other axes that are present, keeping the
165  //   order of pixel positions the same
166  double *newpix = new double[naxis*npts];
167  for(int pt=0;pt<npts;pt++){
168    for(int i=0;i<naxis;i++) newpix[pt*naxis+i] = 1.;
169    newpix[pt*naxis+wcs->lng]  += pix[pt*3+0];
170    newpix[pt*naxis+wcs->lat]  += pix[pt*3+1];
171    newpix[pt*naxis+wcs->spec] += pix[pt*3+2];
172  }
173
174  int    *stat      = new int[npts];
175  double *imgcrd    = new double[naxis*npts];
176  double *tempworld = new double[naxis*npts];
177  double *phi       = new double[npts];
178  double *theta     = new double[npts];
179  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
180                phi, theta, tempworld, stat);
181  if(status>0){
182    std::stringstream errmsg;
183    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
184           << "\nstat value is " << stat[0] << std::endl;
185    duchamp::duchampError("pixToWCSMulti",errmsg.str());
186  }
187  else{
188    //return just the spatial/velocity information, keeping the
189    //  order of the pixel positions the same.
190    for(int pt=0;pt<npts;pt++){
191      world[pt*3+0] = tempworld[pt*naxis + wcs->lng];
192      world[pt*3+1] = tempworld[pt*naxis + wcs->lat];
193      world[pt*3+2] = tempworld[pt*naxis + wcs->spec];
194    }
195   
196  }
197
198  delete [] stat;
199  delete [] imgcrd;
200  delete [] tempworld;
201  delete [] phi;
202  delete [] theta;
203  delete [] newpix;
204  return status;
205}
206
207int wcsToPixMulti(struct wcsprm *wcs, const double *world,
208                  double *pix, const int npts)
209{
210  /**
211   *   Uses wcs to convert the three-dimensional world coordinate position
212   *    referenced by world to pixel coordinates, which are placed in the
213   *    array pix[].
214   *   world is assumed to hold the positions of npts points.
215   *   Offsets the pixel values by 1 to account for the C arrays being
216   *    indexed to 0.
217   *
218   * \param wcs The wcsprm struct containing the WCS information.
219   * \param world The array of world coordinates.
220   * \param pix The returned array of pixel coordinates.
221   * \param npts The number of distinct pixels in the arrays.
222   */
223
224  int naxis=wcs->naxis,status=0;
225  // Test to see if there are other axes present, eg. stokes
226  if(wcs->naxis>naxis) naxis = wcs->naxis;
227
228  // Add entries for any other axes that are present, keeping the
229  //   order of pixel positions the same
230  double *tempworld = new double[naxis*npts];
231  for(int pt=0;pt<npts;pt++){
232    for(int axis=0;axis<naxis;axis++)
233      tempworld[pt*naxis+axis] = wcs->crval[axis];
234    tempworld[pt*naxis + wcs->lng]  = world[pt*3+0];
235    tempworld[pt*naxis + wcs->lat]  = world[pt*3+1];
236    tempworld[pt*naxis + wcs->spec] = world[pt*3+2];
237  }
238
239  int    *stat   = new int[npts];
240  double *temppix = new double[naxis*npts];
241  double *imgcrd = new double[naxis*npts];
242  double *phi    = new double[npts];
243  double *theta  = new double[npts];
244  status=wcss2p(wcs,npts,naxis,tempworld,phi,theta,
245                imgcrd,temppix,stat);
246  if(status>0){
247    std::stringstream errmsg;
248    errmsg << "WCS Error Code = " <<status<<": " <<wcs_errmsg[status]
249           << "\nstat value is " << stat[0] << std::endl;
250    duchamp::duchampError("wcsToPixMulti",errmsg.str());
251  }
252  else{
253    // correct from 1-indexed to 0-indexed pixel array
254    //  and return just the spatial/velocity information,
255    //  keeping the order of the pixel positions the same.
256    for(int pt=0;pt<npts;pt++){
257      pix[pt*naxis + 0] = temppix[pt*naxis + wcs->lng] - 1.;
258      pix[pt*naxis + 1] = temppix[pt*naxis + wcs->lat] - 1.;
259      pix[pt*naxis + 2] = temppix[pt*naxis + wcs->spec] - 1.;
260    }
261  }
262
263  delete [] stat;
264  delete [] imgcrd;
265  delete [] temppix;
266  delete [] phi;
267  delete [] theta;
268  delete [] tempworld;
269  return status;
270}
271
272double pixelToVelocity(struct wcsprm *wcs, double &x, double &y, double &z,
273                       std::string velUnits)
274{
275  /**
276   *   Uses wcs to convert the three-dimensional pixel position (x,y,z)
277   *   to world coordinates.
278   *   Returns the velocity in the units given by velUnits.
279   *
280   * \param wcs  The wcsprm struct containing the WCS information.
281   * \param x The x pixel coordinate.
282   * \param y The y pixel coordinate.
283   * \param z The z pixel coordinate.
284   * \param velUnits The string containing the units of the output velocity.
285   * \return The velocity of the pixel.
286   */
287
288  int naxis=wcs->naxis,status=0;
289  int    *stat   = new int[1];
290  double *pixcrd = new double[naxis];
291  double *imgcrd = new double[naxis];
292  double *world  = new double[naxis];
293  double *phi    = new double[1];
294  double *theta  = new double[1];
295  // correct from 0-indexed to 1-indexed pixel array by adding 1 to
296  // pixel values.
297  for(int i=0;i<naxis;i++) pixcrd[i] = 1.;
298  pixcrd[wcs->lng] += x;
299  pixcrd[wcs->lat] += y;
300  pixcrd[wcs->spec]+= z;
301  status=wcsp2s(wcs, 1, naxis, pixcrd, imgcrd,
302                phi, theta, world, stat);
303  if(status>0){
304    std::stringstream errmsg;
305    errmsg <<"WCS Error Code = "<<status<<": "<<wcs_errmsg[status]
306           << "\nstat value is "<<stat[0]<<std::endl;
307    duchamp::duchampError("pixelToVelocity",errmsg.str());
308  }
309
310  double vel = coordToVel(wcs, world[wcs->spec], velUnits);
311
312  delete [] stat;
313  delete [] pixcrd;
314  delete [] imgcrd;
315  delete [] world;
316  delete [] phi;
317  delete [] theta;
318 
319  return vel;
320}
321 
322double coordToVel(struct wcsprm *wcs, const double coord,
323                  std::string outputUnits)
324{
325  /**
326   *   Convert the wcs coordinate given by coord to a velocity in km/s.
327   *   Does this by checking the ztype parameter in wcs to see if it is
328   *    FREQ or otherwise, and converts accordingly.
329   *
330   * \param wcs  The wcsprm struct containing the WCS information.
331   * \param coord The input WCS coordinate.
332   * \param outputUnits The string containing the units of the output velocity.
333   * \return The velocity of the input coord value.
334   */
335
336  static int errflag = 0;
337  double scale, offset, power;
338  int specIndex = wcs->spec;
339  int status = wcsunits( wcs->cunit[specIndex], outputUnits.c_str(),
340                         &scale, &offset, &power);
341
342  if(status > 0){
343    if(errflag==0){
344      std::stringstream errmsg;
345      errmsg << "WCSUNITS Error Code = " << status << ":"
346             << wcsunits_errmsg[status];
347      if(status == 10) errmsg << "\nTried to get conversion from "
348                              << wcs->cunit[specIndex]
349                              << " to " << outputUnits.c_str();
350      errmsg << "\nUsing coordinate value instead.\n";
351      duchamp::duchampError("coordToVel", errmsg.str());
352      errflag = 1;
353    }
354    return coord;
355  }
356  else return pow( (coord*scale + offset), power);
357
358}
359
360double velToCoord(struct wcsprm *wcs, const float velocity,
361                  std::string outputUnits)
362{
363  /**
364   *   Convert the velocity given to the appropriate world coordinate for wcs.
365   *   Does this by checking the ztype parameter in wcs to see if it is
366   *    FREQ or otherwise, and converts accordingly.
367   *
368   * \param wcs  The wcsprm struct containing the WCS information.
369   * \param velocity The input velocity.
370   * \param outputUnits The string containing the units of the input velocity.
371   * \return The WCS coordinate corresponding to the input velocity.
372   */
373
374  double scale, offset, power;
375  int specIndex = wcs->spec;
376  int status = wcsunits( outputUnits.c_str(), wcs->cunit[specIndex],
377                         &scale, &offset, &power);
378
379  if(status > 0){
380    std::stringstream errmsg;
381    errmsg << "WCSUNITS Error Code = " << status << ":"
382           << wcsunits_errmsg[status] << "\nUsing coordinate value instead.\n";
383    duchamp::duchampError("velToCoord",errmsg.str());
384    return velocity;
385  }
386  else return (pow(velocity, 1./power) - offset) / scale;
387 
388}
Note: See TracBrowser for help on using the repository browser.