source: trunk/src/Cubes/outputSpectra.cc @ 269

Last change on this file since 269 was 269, checked in by Matthew Whiting, 17 years ago
  • Main changed is to enable outputSpectra to plot the spectral baseline if that has been fitted. This is done in yellow.
  • This meant we had to add code to fix the baseline array in the unTrimCube() function.
  • The trimming threshold for the baseline determination has dropped to 5sigma.
  • changed calls to swap to std::swap in sort.cc
  • Other minor comments changes.
File size: 10.5 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <sstream>
4#include <string>
5#include <cpgplot.h>
6#include <math.h>
7#include <wcs.h>
8#include <param.hh>
9#include <PixelMap/Object3D.hh>
10#include <Cubes/cubes.hh>
11#include <Cubes/plots.hh>
12#include <Utils/utils.hh>
13#include <Utils/mycpgplot.hh>
14
15using namespace mycpgplot;
16using namespace PixelInfo;
17
18void getSmallVelRange(Detection &obj, FitsHeader head, float *minvel, float *maxvel);
19void getSmallZRange(Detection &obj, float *minz, float *maxz);
20
21void Cube::outputSpectra()
22{
23  /**
24   * The way to print out the spectra of the detected objects.
25   * Make use of the SpectralPlot class in plots.h, which sizes everything
26   *   correctly.
27   * Main choice is whether to use the peak pixel, in which case the
28   *  spectrum is just that of the peak pixel, or the sum, where the
29   *  spectrum is summed over all spatial pixels that are in the object.
30   * If a reconstruction has been done, that spectrum is plotted in red.
31   * The limits of the detection are marked in blue.
32   * A 0th moment map of the detection is also plotted, with a scale bar
33   *  indicating the spatial scale.
34   */
35
36  if(this->fullCols.size()==0) this->setupColumns();
37  // in case cols haven't been set -- need the precisions for printing values.
38
39  std::string spectrafile = this->par.getSpectraFile() + "/vcps";
40  Plot::SpectralPlot newplot;
41  if(newplot.setUpPlot(spectrafile.c_str())>0) {
42
43    for(int nobj=0;nobj<this->objectList.size();nobj++){
44      // for each object in the cube:
45      this->plotSpectrum(this->objectList[nobj],newplot);
46     
47    }// end of loop over objects.
48
49    cpgclos();
50  }
51}
52
53void Cube::plotSpectrum(Detection obj, Plot::SpectralPlot &plot)
54{
55  /**
56   * The way to print out the spectrum of a Detection.
57   * Makes use of the SpectralPlot class in plots.hh, which sizes
58   *  everything correctly.
59   *
60   * The main choice for the user is whether to use the peak pixel, in
61   * which case the spectrum is just that of the peak pixel, or the
62   * sum, where the spectrum is summed over all spatial pixels that
63   * are in the object.
64   *
65   * If a reconstruction has been done, that spectrum is plotted in
66   * red, and if a baseline has been calculated that is also shown, in
67   * yellow.  The spectral limits of the detection are marked in blue.
68   * A 0th moment map of the detection is also plotted, with a scale
69   * bar indicating the spatial size.
70   *
71   * \param obj The Detection to be plotted.
72   * \param plot The PGPLOT device to plot the spectrum on.
73   */
74
75  long xdim = this->axisDim[0];
76  long ydim = this->axisDim[1];
77  long zdim = this->axisDim[2];
78  float beam = this->par.getBeamSize();
79
80  obj.calcFluxes(this->array, this->axisDim);
81
82  double minMWvel,maxMWvel,xval,yval,zval;
83  xval = double(obj.getXcentre());
84  yval = double(obj.getYcentre());
85  if(this->par.getFlagMW()){
86    zval = double(this->par.getMinMW());
87    minMWvel = this->head.pixToVel(xval,yval,zval);
88    zval = double(this->par.getMaxMW());
89    maxMWvel = this->head.pixToVel(xval,yval,zval);
90  }
91
92  float *specx  = new float[zdim];
93  float *specy  = new float[zdim];
94  for(int i=0;i<zdim;i++) specy[i] = 0.;
95  float *specy2 = new float[zdim];
96  for(int i=0;i<zdim;i++) specy2[i] = 0.;
97  float *base   = new float[zdim];
98  for(int i=0;i<zdim;i++) base[i] = 0.;
99
100  for(int i=0;i<zdim;i++) specy[i] = 0.;
101  if(this->par.getFlagATrous()) 
102    for(int i=0;i<zdim;i++) specy2[i] = 0.;
103   
104  if(this->head.isWCS())
105    for(zval=0;zval<zdim;zval++)
106      specx[int(zval)] = this->head.pixToVel(xval,yval,zval);
107  else
108    for(zval=0;zval<zdim;zval++) specx[int(zval)] = zval;
109
110  std::string fluxLabel = "Flux";
111
112  if(this->par.getSpectralMethod()=="sum"){
113    fluxLabel = "Integrated " + fluxLabel;
114    if(this->head.isWCS())
115      fluxLabel += " ["+this->head.getIntFluxUnits()+"]";
116    bool *done = new bool[xdim*ydim];
117    for(int i=0;i<xdim*ydim;i++) done[i]=false;
118    std::vector<Voxel> voxlist = obj.pixels().getPixelSet();
119    for(int pix=0;pix<voxlist.size();pix++){
120      int pos = voxlist[pix].getX() + xdim * voxlist[pix].getY();
121      if(!done[pos]){
122        done[pos] = true;
123        for(int z=0;z<zdim;z++){
124          if(!(this->isBlank(pos+z*xdim*ydim))){
125            specy[z] += this->array[pos + z*xdim*ydim] / beam;
126            if(this->reconExists)
127              specy2[z] += this->recon[pos + z*xdim*ydim] / beam;
128            if(this->par.getFlagBaseline())
129              base[z] += this->baseline[pos + z*xdim*ydim] / beam;
130          }         
131        }
132      }
133    }
134    delete [] done;
135  }
136  else {// if(par.getSpectralMethod()=="peak"){
137    fluxLabel = "Peak " + fluxLabel;
138    if(this->head.isWCS()) fluxLabel += " ["+this->head.getFluxUnits()+"]";
139    int pos = obj.getXPeak() + xdim*obj.getYPeak();
140    for(int z=0;z<zdim;z++){
141      specy[z] = this->array[pos + z*xdim*ydim];
142      if(this->reconExists)
143        specy2[z] = this->recon[pos + z*xdim*ydim];
144      if(this->par.getFlagBaseline())
145        base[z] = this->baseline[pos + z*xdim*ydim];
146    }
147  }
148   
149  float vmax,vmin,width;
150  vmax = vmin = specx[0];
151  for(int i=1;i<zdim;i++){
152    if(specx[i]>vmax) vmax=specx[i];
153    if(specx[i]<vmin) vmin=specx[i];
154  }
155 
156  float max,min;
157  int loc=0;
158  if(this->par.getMinMW()>0) max = min = specy[0];
159  else max = min = specx[this->par.getMaxMW()+1];
160  for(int i=0;i<zdim;i++){
161    if(!this->par.isInMW(i)){
162      if(specy[i]>max) max=specy[i];
163      if(specy[i]<min){
164        min=specy[i];
165        loc = i;
166      }
167    }
168  }
169  // widen the ranges slightly so that the top & bottom & edges don't
170  // lie on the axes.
171  width = max - min;
172  max += width * 0.05;
173  min -= width * 0.05;
174  width = vmax -vmin;
175  vmax += width * 0.01;
176  vmin -= width * 0.01;
177
178  // now plot the resulting spectrum
179  std::string label;
180  if(this->head.isWCS()){
181    label = this->head.getSpectralDescription() + " [" +
182      this->head.getSpectralUnits() + "]";
183    plot.gotoHeader(label);
184  }
185  else plot.gotoHeader("Spectral pixel value");
186
187  if(this->head.isWCS()){
188    label = obj.outputLabelWCS();
189    plot.firstHeaderLine(label);
190  }
191  label = obj.outputLabelInfo();
192  plot.secondHeaderLine(label);
193  label = obj.outputLabelPix();
194  plot.thirdHeaderLine(label);
195   
196  plot.gotoMainSpectrum(vmin,vmax,min,max,fluxLabel);
197  cpgline(zdim,specx,specy);
198  if(this->par.getFlagBaseline()){
199    cpgsci(YELLOW);
200    cpgline(zdim,specx,base);
201    cpgsci(FOREGND);
202  }
203  if(this->reconExists){
204    cpgsci(RED);
205    cpgline(zdim,specx,specy2);   
206    cpgsci(FOREGND);
207  }
208  if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
209  if(this->head.isWCS()) plot.drawVelRange(obj.getVelMin(),obj.getVelMax());
210  else plot.drawVelRange(obj.getZmin(),obj.getZmax());
211
212  /**************************/
213  // ZOOM IN SPECTRALLY ON THE DETECTION.
214
215  float minvel,maxvel;
216  if(this->head.isWCS()) getSmallVelRange(obj,this->head,&minvel,&maxvel);
217  else getSmallZRange(obj,&minvel,&maxvel);
218
219  // Find new max & min flux values
220  std::swap(max,min);
221  int ct = 0;
222  for(int i=0;i<zdim;i++){
223    if((!this->par.isInMW(i))&&(specx[i]>=minvel)&&(specx[i]<=maxvel)){
224      ct++;
225      if(specy[i]>max) max=specy[i];
226      if(specy[i]<min) min=specy[i];
227    }
228  }
229  // widen the flux range slightly so that the top & bottom don't lie
230  // on the axes.
231  width = max - min;
232  max += width * 0.05;
233  min -= width * 0.05;
234
235  plot.gotoZoomSpectrum(minvel,maxvel,min,max);
236  cpgline(zdim,specx,specy);
237  if(this->par.getFlagBaseline()){
238    cpgsci(YELLOW);
239    cpgline(zdim,specx,base);
240    cpgsci(FOREGND);
241  }
242  if(this->reconExists){
243    cpgsci(RED);
244    cpgline(zdim,specx,specy2);   
245    cpgsci(FOREGND);
246  }
247  if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
248  if(this->head.isWCS()) plot.drawVelRange(obj.getVelMin(),obj.getVelMax());
249  else plot.drawVelRange(obj.getZmin(),obj.getZmax());
250   
251  /**************************/
252
253  // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
254  plot.gotoMap();
255  this->drawMomentCutout(obj);
256
257  delete [] specx;
258  delete [] specy;
259  delete [] specy2;
260  delete [] base;
261 
262}
263
264
265void getSmallVelRange(Detection &obj, FitsHeader head,
266                      float *minvel, float *maxvel)
267{
268  /**
269   *  Routine to calculate the velocity range for the zoomed-in region.
270   *  This range should be the maximum of 20 pixels, or 3x the wdith of
271   *   the detection.
272   *  Need to :
273   *      Calculate pixel width of a 3x-detection-width region.
274   *      If smaller than 20, calculate velocities of central vel +- 10 pixels
275   *      If not, use the 3x-detection-width
276   *  Range returned via "minvel" and "maxvel" parameters.
277   *  \param obj Detection under examination.
278   *  \param head FitsHeader, containing the WCS information.
279   *  \param minvel Returned value of minimum velocity
280   *  \param maxvel Returned value of maximum velocity
281   */
282
283  double *pixcrd = new double[3];
284  double *world  = new double[3];
285  float minpix,maxpix;
286  // define new velocity extrema
287  //    -- make it 3x wider than the width of the detection.
288  *minvel = 0.5*(obj.getVelMin()+obj.getVelMax()) - 1.5*obj.getVelWidth();
289  *maxvel = 0.5*(obj.getVelMin()+obj.getVelMax()) + 1.5*obj.getVelWidth();
290  // Find velocity range in number of pixels:
291  world[0] = obj.getRA();
292  world[1] = obj.getDec();
293  world[2] = head.velToSpec(*minvel);
294  head.wcsToPix(world,pixcrd);
295  minpix = pixcrd[2];
296  world[2] = head.velToSpec(*maxvel);
297  head.wcsToPix(world,pixcrd);
298  maxpix = pixcrd[2];
299  if(maxpix<minpix) std::swap(maxpix,minpix);
300   
301  if((maxpix - minpix + 1) < 20){
302    pixcrd[0] = double(obj.getXcentre());
303    pixcrd[1] = double(obj.getYcentre());
304    pixcrd[2] = obj.getZcentre() - 10.;
305    head.pixToWCS(pixcrd,world);
306    //    *minvel = setVel_kms(wcs,world[2]);
307    *minvel = head.specToVel(world[2]);
308    pixcrd[2] = obj.getZcentre() + 10.;
309    head.pixToWCS(pixcrd,world);
310    //     *maxvel = setVel_kms(wcs,world[2]);
311    *maxvel = head.specToVel(world[2]);
312    if(*maxvel<*minvel) std::swap(*maxvel,*minvel);
313  }
314  delete [] pixcrd;
315  delete [] world;
316
317}
318
319void getSmallZRange(Detection &obj, float *minz, float *maxz)
320{
321  /**
322   *  Routine to calculate the pixel range for the zoomed-in spectrum.
323   *  This range should be the maximum of 20 pixels, or 3x the width
324   *   of the detection.
325   *  Need to :
326   *      Calculate pixel width of a 3x-detection-width region.
327   *       If smaller than 20, use central pixel +- 10 pixels
328   *  Range returned via "minz" and "maxz" parameters.
329   *  \param obj Detection under examination.
330   *  \param minz Returned value of minimum z-pixel coordinate
331   *  \param maxz Returned value of maximum z-pixel coordinate
332   */
333
334  *minz = 2.*obj.getZmin() - obj.getZmax();
335  *maxz = 2.*obj.getZmax() - obj.getZmin();
336   
337  if((*maxz - *minz + 1) < 20){
338    *minz = obj.getZcentre() - 10.;
339    *maxz = obj.getZcentre() + 10.;
340  }
341
342}
Note: See TracBrowser for help on using the repository browser.