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

Last change on this file since 177 was 147, checked in by Matthew Whiting, 18 years ago

Minor bugfix for spectral plotting. When the spectral axis passed zero, the
tick marks were generating very large plots (due to lots of ticks being drawn
in the same place). This has been fixed with more robust code.

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