source: branches/fitshead-branch/Cubes/outputSpectra.cc @ 96

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

Two sets of large changes:
1) Added reconDim, to select which dimension of reconstruction to use.
2) Changed the way the MW channels are dealt with -- now not set to 0. but

simply ignored for searching purposes.

Summary of changes for each file:
duchamp.hh -- added keyword info for reconDim
param.hh -- Introduced reconDim and flagUsingBlank and isInMW.
param.cc -- Introduced reconDim and flagUsingBlank: initialisation etc commands
InputComplete? -- Added reconDim info
mainDuchamp.cc -- Removed the removeMW call. Changed search function names
docs/Guide.tex -- New code to deal with changes: reconDim, MW removal,

up-to-date output examples, better hints & notes section

Detection/thresholding_functions.cc -- minor typo correction

Cubes/cubes.hh -- added isBlank and removeMW functions in Image class, and

renamed search function prototypes

Cubes/cubes.cc -- added removeMW function for Image class, cleaned up

Cube::removeMW as well (although now not used)

Cubes/outputSpectra.cc -- Improved use of isBlank and isInMW functions: now

show MW channels but don't use them in calculating
the flux range

Cubes/getImage.cc -- added line to indicate whether the Param's blank value

is being used, rather than the FITS header.

Cubes/cubicSearch.cc -- renamed functions: front end is now CubicSearch?, and

searching function is search3DArray.

-- Improved way MW removal is dealt with. Changed

location of stats calculations.

Cubes/saveImage.cc -- added code for saving reconDim info
Cubes/readRecon.cc -- added code for reading reconDim info (and added status

intialisations before all cfitsio commands)

ATrous/ReconSearch.cc -- renamed functions: front end is now ReconSearch?, and

searching function is searchReconArray.
Using reconDim to decide which reconstruction to use.

-- Improved way MW removal is dealt with. Changed

location of stats calculations.

ATrous/atrous_1d_reconstruct.cc -- using Median stats
ATrous/atrous_2d_reconstruct.cc -- made code up to date, to conform with 1- &

3-d code. Removed boundary conditions.

ATrous/atrous_3d_reconstruct.cc -- corrected typo (avGapY /= float(xdim)).

Using median stats.

Cubes/cubicSearchNMerge.cc -- Deleted. (not used)
Cubes/readParams.cc -- Deleted. (not used)

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