source: tags/release-1.2.2/src/Cubes/spectraUtils.cc

Last change on this file was 998, checked in by MatthewWhiting, 12 years ago

Moving the two drawSpectralRange functions from spectraUtils.cc to plotting.cc - they need the pgplot-related functions, and if pgplot wasn't enabled they were causing build errors where they were.

File size: 13.1 KB
Line 
1// -----------------------------------------------------------------------
2// spectraUtils.cc: Utility functions to obtain & manipulate spectra
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 <fstream>
30#include <iomanip>
31#include <sstream>
32#include <string>
33#include <vector>
34#include <math.h>
35#include <wcslib/wcs.h>
36#include <duchamp/Cubes/cubeUtils.hh>
37#include <duchamp/param.hh>
38#include <duchamp/duchamp.hh>
39#include <duchamp/fitsHeader.hh>
40#include <duchamp/PixelMap/Object3D.hh>
41#include <duchamp/Cubes/cubes.hh>
42#include <duchamp/Cubes/plots.hh>
43#include <duchamp/Utils/utils.hh>
44
45using namespace PixelInfo;
46
47namespace duchamp
48{
49
50  void getSpecAbscissae(Detection &object, FitsHeader &head, size_t zdim, float *abscissae)
51  {
52    /// @details
53    ///  A function that returns an array of
54    ///  frequency/velocity/channel/etc values (that can be used as the
55    ///  abscissae on the spectral plot).
56    ///  \param object The object on which our spectrum is centered (in
57    ///  case the spectral value changes with x & y
58    ///  \param head The FitsHeader set of parameters that determine the coordinate transformation.
59    ///  \param zdim The length of the spectral axis
60    ///  \param abscissae The array of spectral values -- must be allocated first
61
62    getSpecAbscissae(head,object.getXcentre(),object.getYcentre(),zdim, abscissae);
63  }
64
65  void getSpecAbscissae(FitsHeader &head, float xpt, float ypt, size_t zdim, float *abscissae)
66  {
67    /// @details
68    ///  A function that returns an array of
69    ///  frequency/velocity/channel/etc values (that can be used as the
70    ///  horizontal axis on the spectral plot).
71    ///  \param head The FitsHeader set of parameters that determine the coordinate transformation.
72    ///  \param xpt The x-value of the spatial position on which our spectrum is centred.
73    ///  \param ypt The y-value of the spatial position on which our spectrum is centred.
74    ///  \param zdim The length of the spectral axis
75    ///  \param abscissae The array of spectral values -- must be allocated first.
76
77    if(head.isWCS()){
78      double xval = double(xpt);
79      double yval = double(ypt);
80      for(double zval=0;zval<zdim;zval++)
81        abscissae[int(zval)] = head.pixToVel(xval,yval,zval);
82    }
83    else
84      for(double zval=0;zval<zdim;zval++) abscissae[int(zval)] = zval;
85
86  }
87  //--------------------------------------------------------------------
88
89  void getIntSpec(Detection &object, float *fluxArray, size_t *dimArray, std::vector<bool> mask,
90                  float beamCorrection, float *spec)
91  {
92    /// @details
93    ///  The base function that extracts an integrated spectrum for a
94    ///  given object from a pixel array. The spectrum is returned as
95    ///  the integrated flux, corrected for the beam using the given
96    ///  correction factor.
97    ///   \param object The Detection in question
98    ///   \param fluxArray The full array of pixel values.
99    ///   \param dimArray The axis dimensions for the fluxArray
100    ///   \param mask A mask array indicating whether given pixels are valid
101    ///   \param beamCorrection How much to divide the summed spectrum
102    ///   by to return the integrated flux.
103    ///   \param spec The integrated spectrum for the object -- must be allocated first.
104
105    for(size_t i=0;i<dimArray[2];i++) spec[i] = 0.;
106    size_t xySize = dimArray[0]*dimArray[1];
107    bool *done = new bool[xySize];
108    for(size_t i=0;i<xySize;i++) done[i]=false;
109    std::vector<Voxel> voxlist = object.getPixelSet();
110    std::vector<Voxel>::iterator vox;
111    for(vox=voxlist.begin();vox<voxlist.end();vox++){
112      size_t pos = vox->getX() + dimArray[0] * vox->getY();
113      if(!done[pos]){
114        done[pos] = true;
115        for(size_t z=0;z<dimArray[2];z++){
116          if(mask[pos+z*xySize]){
117            spec[z] += fluxArray[pos + z*xySize] / beamCorrection;
118          }         
119        }
120      }
121    }
122    delete [] done;
123
124  }
125  //--------------------------------------------------------------------
126
127  void getPeakSpec(Detection &object, float *fluxArray, size_t *dimArray, bool *mask, float *spec)
128  {
129    /// @details
130    ///  The base function that extracts an peak spectrum for a
131    ///  given object from a pixel array. The spectrum is returned as
132    ///  the integrated flux, corrected for the beam using the given
133    ///  correction factor.
134    ///   \param object The Detection in question
135    ///   \param fluxArray The full array of pixel values.
136    ///   \param dimArray The axis dimensions for the fluxArray
137    ///   \param mask A mask array indicating whether given pixels are valid
138    ///   \param spec The peak spectrum for the object -- must be allocated first
139
140    if((object.getXPeak()<0 || object.getXPeak()>=int(dimArray[0])) || (object.getYPeak()<0 || object.getYPeak()>=int(dimArray[1]))){
141      DUCHAMPWARN("getPeakSpec","Object peak outside array boundaries");
142      for (size_t z=0;z<dimArray[2];z++) spec[z]=0.;
143    }
144    else{
145      size_t xySize = dimArray[0]*dimArray[1];
146      size_t pos = object.getXPeak() + dimArray[0]*object.getYPeak();
147      for(size_t z=0;z<dimArray[2];z++){
148        if(mask[pos + z*xySize])
149          spec[z] = fluxArray[pos + z*xySize];
150      }
151    }
152  }
153  //--------------------------------------------------------------------
154
155
156  void Cube::getSpectralArrays(int objNum, float *specx, float *specy,
157                               float *specRecon, float *specBase)
158  {
159    /// @details
160    ///  A utility function that goes and calculates, for a given
161    ///  Detection, the spectral arrays, according to whether we want
162    ///  the peak or integrated flux. The arrays can be used by
163    ///  Cube::plotSpectrum() and Cube::writeSpectralData(). The arrays
164    ///  calculated are listed below. Their length is given by the
165    ///  length of the Cube's spectral dimension.
166    ///
167    ///  Note that the arrays need to be allocated prior to calling
168    ///  this function.
169    ///
170    ///  \param objNum The number of the object under
171    ///         consideration. If negative, we extract the single
172    ///         spectrum at (x,y)=(0,0) (useful for the 1D case).
173    ///  \param specx The array of frequency/velocity/channel/etc
174    ///         values (the x-axis on the spectral plot).
175    ///  \param specy The array of flux values, matching the specx
176    ///         array.
177    ///  \param specRecon The reconstructed or smoothed array, done in
178    ///         the same way as specy.
179    ///  \param specBase The fitted baseline values, done in the same
180    ///         way as specy.
181
182    size_t xdim = this->axisDim[0];
183    size_t ydim = this->axisDim[1];
184    size_t zdim = this->axisDim[2];
185       
186    for(size_t i=0;i<zdim;i++){
187      specy[i]     = 0.;
188      specRecon[i] = 0.;
189      specBase[i]  = 0.;
190    }
191
192    double xloc,yloc;
193    size_t spatpos=0;
194    std::vector<Voxel> voxlist;
195    if(objNum>=0){
196      if(this->par.getSpectralMethod()=="sum"){
197        xloc=double(this->objectList->at(objNum).getXcentre());
198        yloc=double(this->objectList->at(objNum).getYcentre());
199        voxlist = this->objectList->at(objNum).getPixelSet();
200      }
201      else{
202        spatpos = this->objectList->at(objNum).getXPeak() +
203        xdim*this->objectList->at(objNum).getYPeak();
204      }
205    }
206
207    if(this->head.isWCS()){
208//       double xval = double(this->objectList->at(objNum).getXcentre());
209//       double yval = double(this->objectList->at(objNum).getYcentre());
210//       for(double zval=0;zval<zdim;zval++)
211//      specx[int(zval)] = this->head.pixToVel(xval,yval,zval);
212      for(double zval=0;zval<zdim;zval++)
213        specx[int(zval)] = this->head.pixToVel(xloc,yloc,zval);
214    }
215    else
216      for(double zval=0;zval<zdim;zval++) specx[int(zval)] = zval;
217       
218    float beamCorrection;
219    if(this->header().needBeamSize())
220      beamCorrection = this->head.beam().area();
221    else beamCorrection = 1.;
222       
223    if(objNum>=0 && this->par.getSpectralMethod()=="sum"){
224      bool *done = new bool[xdim*ydim];
225      for(size_t i=0;i<xdim*ydim;i++) done[i]=false;
226//       std::vector<Voxel> voxlist = this->objectList->at(objNum).getPixelSet();
227      std::vector<Voxel>::iterator vox;
228      for(vox=voxlist.begin();vox<voxlist.end();vox++){
229        spatpos = vox->getX() + xdim * vox->getY();
230        if(!done[spatpos]){
231          done[spatpos] = true;
232          for(size_t z=0;z<zdim;z++){
233            if(!(this->isBlank(spatpos+z*xdim*ydim))){
234              specy[z] += this->array[spatpos + z*xdim*ydim] / beamCorrection;
235              if(this->reconExists)
236                specRecon[z] += this->recon[spatpos + z*xdim*ydim] / beamCorrection;
237              if(this->par.getFlagBaseline())
238                specBase[z] += this->baseline[spatpos + z*xdim*ydim] / beamCorrection;
239            }       
240          }
241        }
242      }
243      delete [] done;
244    }
245    else {// if(par.getSpectralMethod()=="peak"){
246//       size_t spatpos = this->objectList->at(objNum).getXPeak() +
247//      xdim*this->objectList->at(objNum).getYPeak();
248      for(size_t z=0;z<zdim;z++){
249        specy[z] = this->array[spatpos + z*xdim*ydim];
250        if(this->reconExists)
251          specRecon[z] = this->recon[spatpos + z*xdim*ydim];
252        if(this->par.getFlagBaseline())
253          specBase[z] = this->baseline[spatpos + z*xdim*ydim];
254      }
255    }
256
257  }
258  //--------------------------------------------------------------------
259
260  void getSmallVelRange(Detection &obj, FitsHeader &head,
261                        double *minvel, double *maxvel)
262  {
263    ///  @details
264    ///  Routine to calculate the velocity range for the zoomed-in region.
265    ///  This range should be the maximum of 20 pixels, or 3x the wdith of
266    ///   the detection.
267    ///  Need to :
268    ///      Calculate pixel width of a 3x-detection-width region.
269    ///      If smaller than 20, calculate velocities of central vel +- 10 pixels
270    ///      If not, use the 3x-detection-width
271    ///  Range returned via "minvel" and "maxvel" parameters.
272    ///  \param obj Detection under examination.
273    ///  \param head FitsHeader, containing the WCS information.
274    ///  \param minvel Returned value of minimum velocity
275    ///  \param maxvel Returned value of maximum velocity
276
277    double *pixcrd = new double[3];
278    double *world  = new double[3];
279    float minpix,maxpix;
280    // define new velocity extrema
281    //    -- make it 3x wider than the width of the detection.
282    *minvel = 0.5*(obj.getVelMin()+obj.getVelMax()) - 1.5*obj.getVelWidth();
283    *maxvel = 0.5*(obj.getVelMin()+obj.getVelMax()) + 1.5*obj.getVelWidth();
284    // Find velocity range in number of pixels:
285    world[0] = obj.getRA();
286    world[1] = obj.getDec();
287    world[2] = head.velToSpec(*minvel);
288    head.wcsToPix(world,pixcrd);
289    minpix = pixcrd[2];
290    world[2] = head.velToSpec(*maxvel);
291    head.wcsToPix(world,pixcrd);
292    maxpix = pixcrd[2];
293    if(maxpix<minpix) std::swap(maxpix,minpix);
294   
295    if((maxpix - minpix + 1) < 20){
296      pixcrd[0] = double(obj.getXcentre());
297      pixcrd[1] = double(obj.getYcentre());
298      pixcrd[2] = obj.getZcentre() - 10.;
299      head.pixToWCS(pixcrd,world);
300      //    *minvel = setVel_kms(wcs,world[2]);
301      *minvel = head.specToVel(world[2]);
302      pixcrd[2] = obj.getZcentre() + 10.;
303      head.pixToWCS(pixcrd,world);
304      //     *maxvel = setVel_kms(wcs,world[2]);
305      *maxvel = head.specToVel(world[2]);
306      if(*maxvel<*minvel) std::swap(*maxvel,*minvel);
307    }
308    delete [] pixcrd;
309    delete [] world;
310
311  }
312  //--------------------------------------------------------------------
313
314  void getSmallZRange(Detection &obj, double *minz, double *maxz)
315  {
316    ///  @details
317    ///  Routine to calculate the pixel range for the zoomed-in spectrum.
318    ///  This range should be the maximum of 20 pixels, or 3x the width
319    ///   of the detection.
320    ///  Need to :
321    ///      Calculate pixel width of a 3x-detection-width region.
322    ///       If smaller than 20, use central pixel +- 10 pixels
323    ///  Range returned via "minz" and "maxz" parameters.
324    ///  \param obj Detection under examination.
325    ///  \param minz Returned value of minimum z-pixel coordinate
326    ///  \param maxz Returned value of maximum z-pixel coordinate
327
328    *minz = 2.*obj.getZmin() - obj.getZmax();
329    *maxz = 2.*obj.getZmax() - obj.getZmin();
330   
331    if((*maxz - *minz + 1) < 20){
332      *minz = obj.getZcentre() - 10.;
333      *maxz = obj.getZcentre() + 10.;
334    }
335
336  }
337  //--------------------------------------------------------------------
338
339}
Note: See TracBrowser for help on using the repository browser.