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

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

Large range of changes -- related to image cutouts and spectral units mostly.

duchamp.hh -- changed name of spectral type, and introduced one for frequency.
Cubes/getImage.cc -- changed the way the spectral type and spectral units are

looked at. Now is able to use frequency units (defaults
to MHz) when there isn't a good velocity transformation
possible (ie. if there is no restfreq defined).

Cubes/drawMomentCutout.cc -- Range of changes here:

  • improved the way unwanted pixels (those BLANK and outside image coundaries) are dealt with in the image array in drawMomentCutout
  • removed the way the blank pixel information was changed. Now behaves in a consistent way whether or not there are blank pixels
  • improved call to plotBlankEdges()
  • added call to drawFieldEdge() -- a new function that draws a yellow line around the boundary of the pixels of the image.
  • improved the tick mark that shows the angular scale of the cutout. Now adaptable to any pixel scale.
  • added calls to cpgtest() to all functions

Also these files were changed in relation to these edits:
Utils/drawBlankEdges.cc -- improved execution, with "blank" array.
Cubes/cubes.cc -- added call to Param::drawBlankEdge in Cube::plotBlankEdges()
Cubes/outputSpectra.cc -- moved spectra away from left and right axes.
param.cc -- added necessary calls for the new parameter. Other minor changes

to formatting. Added a missed call to stringize.

mainDuchamp.cc -- added #include <param.hh>
param.hh -- Added a new parameter: blankEdge
Cubes/cubes.hh -- improved appearance of comments
Cubes/plots.hh -- improved appearance of comments
InputComplete? -- added new parameter.
docs/Guide.tex -- added text about blank edge plotting.
All six images were changed as well.

CHANGES -- some of these changes -- not up to date yet!

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