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

Last change on this file since 1391 was 299, checked in by Matthew Whiting, 17 years ago

Adding distribution text at the start of each file...

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