source: trunk/src/Utils/wcsFunctions.cc @ 491

Last change on this file since 491 was 491, checked in by MatthewWhiting, 16 years ago

Some changes prompted by askapsoft development.

File size: 13.7 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  int specAxis = wcs->spec;
56  if(specAxis<0) specAxis=2;
57  if(specAxis>=naxis) specAxis = naxis-1;
58
59  double *newpix = new double[naxis*npts];
60  // correct from 0-indexed to 1-indexed pixel array
61  for(int i=0;i<naxis;i++) newpix[i] = 1.;
62  newpix[wcs->lng] += pix[0];
63  newpix[wcs->lat] += pix[1];
64  newpix[specAxis]+= pix[2];
65
66  int    *stat      = new int[npts];
67  double *imgcrd    = new double[naxis*npts];
68  double *tempworld = new double[naxis*npts];
69  double *phi       = new double[npts];
70  double *theta     = new double[npts];
71  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
72                phi, theta, tempworld, stat);
73  if(status>0){
74    std::stringstream errmsg;
75    errmsg << "WCS Error Code = " << status <<": " << wcs_errmsg[status]
76           << "\nstat value is " << stat[0] << std::endl;
77    duchamp::duchampError("pixToWCSSingle",errmsg.str());
78  }
79
80  //return just the spatial/velocity information
81  world[0] = tempworld[wcs->lng];
82  world[1] = tempworld[wcs->lat];
83  world[2] = tempworld[specAxis];
84
85  delete [] stat;
86  delete [] imgcrd;
87  delete [] tempworld;
88  delete [] phi;
89  delete [] theta;
90  delete [] newpix;
91  return status;
92}
93
94int wcsToPixSingle(struct wcsprm *wcs, const double *world, double *pix)
95{
96  /**
97   *   Uses wcs to convert the three-dimensional world coordinate position
98   *    referenced by world to pixel coordinates, which are placed in the
99   *    array pix[].
100   *   Assumes that world only has one point (three values eg RA Dec Velocity)
101   *   Offsets the pixel values by 1 to account for the C arrays being
102   *    indexed to 0.
103   *
104   * \param wcs The wcsprm struct containing the WCS information.
105   * \param world The array of world coordinates.
106   * \param pix The returned array of pixel coordinates.
107   */
108
109  int naxis=wcs->naxis,npts=1,status;
110  int specAxis = wcs->spec;
111  if(specAxis<0) specAxis=2;
112  if(specAxis>=naxis) specAxis = naxis-1;
113
114  double *tempworld = new double[naxis*npts];
115  for(int i=0;i<naxis;i++) tempworld[i] = wcs->crval[i];
116  tempworld[wcs->lng]  = world[0];
117  tempworld[wcs->lat]  = world[1];
118  tempworld[specAxis] = world[2];
119
120  int    *stat    = new int[npts];
121  double *temppix = new double[naxis*npts];
122  double *imgcrd  = new double[naxis*npts];
123  double *phi     = new double[npts];
124  double *theta   = new double[npts];
125
126  status=wcss2p(wcs, npts, naxis, tempworld,
127                phi, theta, imgcrd, temppix, stat);
128
129  if( status > 0 ){
130    std::stringstream errmsg;
131    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
132           << "\nstat value is " << stat[0] << std::endl;
133    duchamp::duchampError("wcsToPixSingle",errmsg.str());
134  }
135
136  pix[0] = temppix[wcs->lng] - 1.;
137  pix[1] = temppix[wcs->lat] - 1.;
138  pix[2] = temppix[specAxis] - 1.;
139  // correct from 1-indexed to 0-indexed pixel array
140  //  and only return the spatial & frequency information
141
142  delete [] stat;
143  delete [] imgcrd;
144  delete [] temppix;
145  delete [] phi;
146  delete [] theta;
147  delete [] tempworld;
148  return status;
149}
150
151int pixToWCSMulti(struct wcsprm *wcs, const double *pix,
152                  double *world, const int npts)
153{
154  /**
155   *   Uses wcs to convert the three-dimensional pixel positions referenced
156   *    by pix to world coordinates, which are placed in the array world[].
157   *   pix is assumed to hold the positions of npts points.
158   *   Offsets these pixel values by 1 to account for the C arrays being
159   *    indexed to 0.
160   *
161   * \param wcs The wcsprm struct containing the WCS information.
162   * \param pix The array of pixel coordinates.
163   * \param world The returned array of world coordinates.
164   * \param npts The number of distinct pixels in the arrays.
165   */
166
167  int naxis=wcs->naxis,status;
168  int specAxis = wcs->spec;
169  if(specAxis<0) specAxis=2;
170  if(specAxis>=naxis) specAxis = naxis-1;
171
172  // correct from 0-indexed to 1-indexed pixel array
173  // Add entries for any other axes that are present, keeping the
174  //   order of pixel positions the same
175  double *newpix = new double[naxis*npts];
176  for(int pt=0;pt<npts;pt++){
177    for(int i=0;i<naxis;i++) newpix[pt*naxis+i] = 1.;
178    newpix[pt*naxis+wcs->lng]  += pix[pt*3+0];
179    newpix[pt*naxis+wcs->lat]  += pix[pt*3+1];
180    newpix[pt*naxis+specAxis] += pix[pt*3+2];
181  }
182
183  int    *stat      = new int[npts];
184  double *imgcrd    = new double[naxis*npts];
185  double *tempworld = new double[naxis*npts];
186  double *phi       = new double[npts];
187  double *theta     = new double[npts];
188  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
189                phi, theta, tempworld, stat);
190  if(status>0){
191    std::stringstream errmsg;
192    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
193           << "\nstat value is " << stat[0] << std::endl;
194    duchamp::duchampError("pixToWCSMulti",errmsg.str());
195  }
196  else{
197    //return just the spatial/velocity information, keeping the
198    //  order of the pixel positions the same.
199    for(int pt=0;pt<npts;pt++){
200      world[pt*3+0] = tempworld[pt*naxis + wcs->lng];
201      world[pt*3+1] = tempworld[pt*naxis + wcs->lat];
202      world[pt*3+2] = tempworld[pt*naxis + specAxis];
203    }
204   
205  }
206
207  delete [] stat;
208  delete [] imgcrd;
209  delete [] tempworld;
210  delete [] phi;
211  delete [] theta;
212  delete [] newpix;
213  return status;
214}
215
216int wcsToPixMulti(struct wcsprm *wcs, const double *world,
217                  double *pix, const int npts)
218{
219  /**
220   *   Uses wcs to convert the three-dimensional world coordinate position
221   *    referenced by world to pixel coordinates, which are placed in the
222   *    array pix[].
223   *   world is assumed to hold the positions of npts points.
224   *   Offsets the pixel values by 1 to account for the C arrays being
225   *    indexed to 0.
226   *
227   * \param wcs The wcsprm struct containing the WCS information.
228   * \param world The array of world coordinates.
229   * \param pix The returned array of pixel coordinates.
230   * \param npts The number of distinct pixels in the arrays.
231   */
232
233  int naxis=wcs->naxis,status=0;
234  int specAxis = wcs->spec;
235  if(specAxis<0) specAxis=2;
236  if(specAxis>=naxis) specAxis = naxis-1;
237
238  // Test to see if there are other axes present, eg. stokes
239  if(wcs->naxis>naxis) naxis = wcs->naxis;
240
241  // Add entries for any other axes that are present, keeping the
242  //   order of pixel positions the same
243  double *tempworld = new double[naxis*npts];
244  for(int pt=0;pt<npts;pt++){
245    for(int axis=0;axis<naxis;axis++)
246      tempworld[pt*naxis+axis] = wcs->crval[axis];
247    tempworld[pt*naxis + wcs->lng]  = world[pt*3+0];
248    tempworld[pt*naxis + wcs->lat]  = world[pt*3+1];
249    tempworld[pt*naxis + specAxis] = world[pt*3+2];
250  }
251
252  int    *stat   = new int[npts];
253  double *temppix = new double[naxis*npts];
254  double *imgcrd = new double[naxis*npts];
255  double *phi    = new double[npts];
256  double *theta  = new double[npts];
257  status=wcss2p(wcs,npts,naxis,tempworld,phi,theta,
258                imgcrd,temppix,stat);
259  if(status>0){
260    std::stringstream errmsg;
261    errmsg << "WCS Error Code = " <<status<<": " <<wcs_errmsg[status]
262           << "\nstat value is " << stat[0] << std::endl;
263    duchamp::duchampError("wcsToPixMulti",errmsg.str());
264  }
265  else{
266    // correct from 1-indexed to 0-indexed pixel array
267    //  and return just the spatial/velocity information,
268    //  keeping the order of the pixel positions the same.
269    for(int pt=0;pt<npts;pt++){
270      pix[pt*naxis + 0] = temppix[pt*naxis + wcs->lng] - 1.;
271      pix[pt*naxis + 1] = temppix[pt*naxis + wcs->lat] - 1.;
272      pix[pt*naxis + 2] = temppix[pt*naxis + specAxis] - 1.;
273    }
274  }
275
276  delete [] stat;
277  delete [] imgcrd;
278  delete [] temppix;
279  delete [] phi;
280  delete [] theta;
281  delete [] tempworld;
282  return status;
283}
284
285double pixelToVelocity(struct wcsprm *wcs, double &x, double &y, double &z,
286                       std::string velUnits)
287{
288  /**
289   *   Uses wcs to convert the three-dimensional pixel position (x,y,z)
290   *   to world coordinates.
291   *   Returns the velocity in the units given by velUnits.
292   *
293   * \param wcs  The wcsprm struct containing the WCS information.
294   * \param x The x pixel coordinate.
295   * \param y The y pixel coordinate.
296   * \param z The z pixel coordinate.
297   * \param velUnits The string containing the units of the output velocity.
298   * \return The velocity of the pixel.
299   */
300
301  int naxis=wcs->naxis,status=0;
302  int    *stat   = new int[1];
303  double *pixcrd = new double[naxis];
304  double *imgcrd = new double[naxis];
305  double *world  = new double[naxis];
306  double *phi    = new double[1];
307  double *theta  = new double[1];
308
309  int specAxis = wcs->spec;
310  if(specAxis<0) specAxis=2;
311  if(specAxis>=naxis) specAxis = naxis-1;
312
313  // correct from 0-indexed to 1-indexed pixel array by adding 1 to
314  // pixel values.
315  for(int i=0;i<naxis;i++) pixcrd[i] = 1.;
316  pixcrd[wcs->lng] += x;
317  pixcrd[wcs->lat] += y;
318  pixcrd[specAxis]+= z;
319  status=wcsp2s(wcs, 1, naxis, pixcrd, imgcrd,
320                phi, theta, world, stat);
321  if(status>0){
322    std::stringstream errmsg;
323    errmsg <<"WCS Error Code = "<<status<<": "<<wcs_errmsg[status]
324           << "\nstat value is "<<stat[0]<<std::endl;
325    duchamp::duchampError("pixelToVelocity",errmsg.str());
326  }
327
328  double vel = coordToVel(wcs, world[specAxis], velUnits);
329
330  delete [] stat;
331  delete [] pixcrd;
332  delete [] imgcrd;
333  delete [] world;
334  delete [] phi;
335  delete [] theta;
336 
337  return vel;
338}
339 
340double coordToVel(struct wcsprm *wcs, const double coord,
341                  std::string outputUnits)
342{
343  /**
344   *   Convert the wcs coordinate given by coord to a velocity in km/s.
345   *   Does this by checking the ztype parameter in wcs to see if it is
346   *    FREQ or otherwise, and converts accordingly.
347   *
348   * \param wcs  The wcsprm struct containing the WCS information.
349   * \param coord The input WCS coordinate.
350   * \param outputUnits The string containing the units of the output velocity.
351   * \return The velocity of the input coord value.
352   */
353
354  static int errflag = 0;
355  double scale, offset, power;
356  int specIndex = wcs->spec;
357  if(specIndex<0) specIndex = 2;
358  if(specIndex>=naxis) specIndex = naxis-1;
359  int status = wcsunits( wcs->cunit[specIndex], outputUnits.c_str(),
360                         &scale, &offset, &power);
361
362  if(status > 0){
363    if(errflag==0){
364      std::stringstream errmsg;
365      errmsg << "WCSUNITS Error Code = " << status << ":"
366             << wcsunits_errmsg[status];
367      if(status == 10) errmsg << "\nTried to get conversion from "
368                              << wcs->cunit[specIndex]
369                              << " to " << outputUnits.c_str();
370      errmsg << "\nUsing coordinate value instead.\n";
371      duchamp::duchampError("coordToVel", errmsg.str());
372      errflag = 1;
373    }
374    return coord;
375  }
376  else return pow( (coord*scale + offset), power);
377
378}
379
380double velToCoord(struct wcsprm *wcs, const float velocity,
381                  std::string outputUnits)
382{
383  /**
384   *   Convert the velocity given to the appropriate world coordinate for wcs.
385   *   Does this by checking the ztype parameter in wcs to see if it is
386   *    FREQ or otherwise, and converts accordingly.
387   *
388   * \param wcs  The wcsprm struct containing the WCS information.
389   * \param velocity The input velocity.
390   * \param outputUnits The string containing the units of the input velocity.
391   * \return The WCS coordinate corresponding to the input velocity.
392   */
393
394  double scale, offset, power;
395  int specIndex = wcs->spec;
396  if(specIndex<0) specIndex = 2;
397  if(specIndex>=naxis) specIndex = naxis-1;
398  int status = wcsunits( outputUnits.c_str(), wcs->cunit[specIndex],
399                         &scale, &offset, &power);
400
401  if(status > 0){
402    std::stringstream errmsg;
403    errmsg << "WCSUNITS Error Code = " << status << ":"
404           << wcsunits_errmsg[status] << "\nUsing coordinate value instead.\n";
405    duchamp::duchampError("velToCoord",errmsg.str());
406    return velocity;
407  }
408  else return (pow(velocity, 1./power) - offset) / scale;
409 
410}
Note: See TracBrowser for help on using the repository browser.