source: tags/release-1.2.2/src/Cubes/outputSpectra.cc

Last change on this file was 987, checked in by MatthewWhiting, 12 years ago

Enabling the plotting of the thresholds for the regular spectral output. This makes it much more clear how robust the detection is. This is only done for the peak flux spectrum - if spectralMethod = sum it is not plotted.

File size: 12.9 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 <fstream>
30#include <iomanip>
31#include <sstream>
32#include <string>
33#include <cpgplot.h>
34#include <math.h>
35#include <wcslib/wcs.h>
36#include <duchamp/param.hh>
37#include <duchamp/duchamp.hh>
38#include <duchamp/fitsHeader.hh>
39#include <duchamp/PixelMap/Object3D.hh>
40#include <duchamp/Cubes/cubes.hh>
41#include <duchamp/Cubes/cubeUtils.hh>
42#include <duchamp/Cubes/plots.hh>
43#include <duchamp/Utils/utils.hh>
44#include <duchamp/Utils/mycpgplot.hh>
45
46using namespace mycpgplot;
47using namespace PixelInfo;
48
49namespace duchamp
50{
51
52  std::string getIndivPlotName(std::string baseName, int objNum, int maxNumObj)
53  {
54    int width = int(floor(log10(float(maxNumObj))))+1;
55    if(baseName.substr(baseName.size()-3,baseName.size())==".ps"){
56      std::stringstream ss;
57      ss << baseName.substr(0,baseName.size()-3)
58         << "-" << std::setw(width) << std::setfill('0') << objNum
59         << ".ps";
60      return ss.str();
61    }
62    else{
63      std::stringstream ss;
64      ss << baseName
65         << "-" << std::setw(width) << std::setfill('0') << objNum
66         << ".ps";
67      return ss.str();
68    }
69  }
70
71  void Cube::outputSpectra()
72  {
73    ///  @details
74    /// The way to display individual detected objects. The standard way
75    /// is plot the full spectrum, plus a zoomed-in spectrum showing just
76    /// the object, plus the 0th-moment map. If there is no spectral
77    /// axis, just the 0th moment map is plotted (using
78    /// Cube::plotSource() rather than Cube::plotSpectrum()).
79    ///
80    /// It makes use of the SpectralPlot or CutoutPlot classes from
81    /// plots.h, which size everything correctly.
82    ///
83    /// The main choice for SpectralPlot() is whether to use the peak
84    /// pixel, in which case the spectrum is just that of the peak pixel,
85    /// or the sum, where the spectrum is summed over all spatial pixels
86    /// that are in the object.  If a reconstruction has been done, that
87    /// spectrum is plotted in red.  The limits of the detection are
88    /// marked in blue.  A 0th moment map of the detection is also
89    /// plotted, with a scale bar indicating the spatial scale.
90
91    if(this->fullCols.size()==0) this->setupColumns();
92    // in case cols haven't been set -- need the precisions for printing values.
93
94    std::vector<bool> objectChoice = this->par.getObjectChoices(this->objectList->size());
95
96    std::string spectrafile = this->par.getSpectraFile() + "/vcps";
97    if(this->getDimZ()<=1){
98      Plot::CutoutPlot newplot;
99      if(newplot.setUpPlot(spectrafile.c_str())>0) {
100
101        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
102          // for each object in the cube, assuming it is wanted:
103          if(objectChoice[nobj]) this->plotSource(this->objectList->at(nobj),newplot);
104        }// end of loop over objects.
105        cpgclos();
106       
107        if(this->par.getFlagUsePrevious()) std::cout << "\n";
108        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
109          if(objectChoice[nobj] && this->par.getFlagUsePrevious()){
110            std::cout << "  Will output individual plot to "
111                      << getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size()) << "\n";
112            Plot::CutoutPlot indivplot;
113            indivplot.setUpPlot(getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size())+"/vcps");
114            this->plotSource(this->objectList->at(nobj),indivplot);
115            cpgclos();
116          }
117        }               
118      }
119    }
120    else{
121      Plot::SpectralPlot newplot;
122      if(newplot.setUpPlot(spectrafile.c_str())>0) {
123
124        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
125          // for each object in the cube, assuming it is wanted:
126          if(objectChoice[nobj])  this->plotSpectrum(nobj,newplot);
127        }// end of loop over objects.
128        cpgclos();
129
130        if(this->par.getFlagUsePrevious()) std::cout << "\n";
131        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
132          if(objectChoice[nobj] && this->par.getFlagUsePrevious()){
133            std::cout << "  Will output individual plot to "
134                      << getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size()) << "\n";
135            Plot::SpectralPlot indivplot;
136            indivplot.setUpPlot(getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size())+"/vcps");
137            this->plotSpectrum(nobj,indivplot);
138            cpgclos();
139          }
140        }               
141
142      }
143     
144    }
145  }
146  //--------------------------------------------------------------------
147
148  void Cube::plotSpectrum(int objNum, Plot::SpectralPlot &plot)
149  {
150    ///  @details
151    /// The way to print out the spectrum of a Detection.
152    /// Makes use of the SpectralPlot class in plots.hh, which sizes
153    ///  everything correctly.
154    ///
155    /// The main choice for the user is whether to use the peak pixel, in
156    /// which case the spectrum is just that of the peak pixel, or the
157    /// sum, where the spectrum is summed over all spatial pixels that
158    /// are in the object.
159    ///
160    /// If a reconstruction has been done, that spectrum is plotted in
161    /// red, and if a baseline has been calculated that is also shown, in
162    /// yellow.  The spectral limits of the detection are marked in blue.
163    /// A 0th moment map of the detection is also plotted, with a scale
164    /// bar indicating the spatial size.
165    ///
166    /// \param objNum The number of the Detection to be plotted.
167    /// \param plot The SpectralPlot object defining the PGPLOT device
168    ///        to plot the spectrum on.
169
170    long zdim = this->axisDim[2];
171
172    this->objectList->at(objNum).calcFluxes(this->array, this->axisDim);
173
174    double minMWvel=0,maxMWvel=0,xval,yval,zval;
175    xval = double(this->objectList->at(objNum).getXcentre());
176    yval = double(this->objectList->at(objNum).getYcentre());
177    if(this->par.getFlagMW()){
178      zval = double(this->par.getMinMW());
179      minMWvel = this->head.pixToVel(xval,yval,zval);
180      zval = double(this->par.getMaxMW());
181      maxMWvel = this->head.pixToVel(xval,yval,zval);
182    }
183
184    float *specx  = new float[zdim];
185    float *specy  = new float[zdim];
186    float *specy2 = new float[zdim];
187    float *base   = new float[zdim];
188//     float *specx, *specy, *specy2, *base;
189
190    this->getSpectralArrays(objNum,specx,specy,specy2,base);
191
192    std::string fluxLabel = "Flux";
193    std::string fluxUnits = this->head.getFluxUnits();
194    std::string intFluxUnits;// = this->head.getIntFluxUnits();
195    // Rather than use the intFluxUnits from the header, which will be like Jy MHz,
196    // we just use the pixel units, removing the /beam if necessary.
197
198    if(fluxUnits.size()>5 &&
199       makelower(fluxUnits.substr(fluxUnits.size()-5,
200                                  fluxUnits.size()   )) == "/beam"){
201      intFluxUnits = fluxUnits.substr(0,fluxUnits.size()-5);
202    }
203    else intFluxUnits = fluxUnits;
204   
205
206    if(this->par.getSpectralMethod()=="sum"){
207      fluxLabel = "Integrated " + fluxLabel;
208      if(this->head.isWCS()) {
209        fluxLabel += " ["+intFluxUnits+"]";
210      }
211    }
212    else {// if(par.getSpectralMethod()=="peak"){
213      fluxLabel = "Peak " + fluxLabel;
214      if(this->head.isWCS()) fluxLabel += " ["+fluxUnits+"]";
215    }
216   
217    float vmax,vmin,width;
218    vmax = vmin = specx[0];
219    for(int i=1;i<zdim;i++){
220      if(specx[i]>vmax) vmax=specx[i];
221      if(specx[i]<vmin) vmin=specx[i];
222    }
223 
224    float max,min;
225    int loc=0;
226    if(this->par.getMinMW()>0) max = min = specy[0];
227    else max = min = specy[this->par.getMaxMW()+1];
228    for(int i=0;i<zdim;i++){
229      if(!this->par.isInMW(i)){
230        if(specy[i]>max) max=specy[i];
231        if(specy[i]<min){
232          min=specy[i];
233          loc = i;
234        }
235      }
236    }
237    // widen the ranges slightly so that the top & bottom & edges don't
238    // lie on the axes.
239    width = max - min;
240    max += width * 0.05;
241    min -= width * 0.05;
242    width = vmax - vmin;
243    vmax += width * 0.01;
244    vmin -= width * 0.01;
245
246    // now plot the resulting spectrum
247    std::string label;
248    if(this->head.isWCS()){
249      label = this->head.getSpectralDescription() + " [" +
250        this->head.getSpectralUnits() + "]";
251      plot.gotoHeader(label);
252    }
253    else plot.gotoHeader("Spectral pixel value");
254
255    if(this->head.isWCS()){
256      label = this->objectList->at(objNum).outputLabelWCS();
257      plot.firstHeaderLine(label);
258      label = this->objectList->at(objNum).outputLabelFluxes();
259      plot.secondHeaderLine(label);
260    }
261    label = this->objectList->at(objNum).outputLabelWidths();
262    plot.thirdHeaderLine(label);
263    label = this->objectList->at(objNum).outputLabelPix();
264    plot.fourthHeaderLine(label);
265   
266    plot.gotoMainSpectrum(vmin,vmax,min,max,fluxLabel);
267    cpgline(zdim,specx,specy);
268    if(this->par.getFlagBaseline()){
269      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
270      cpgline(zdim,specx,base);
271      cpgsci(FOREGND);
272    }
273    if(this->reconExists){
274      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
275      cpgline(zdim,specx,specy2);   
276      cpgsci(FOREGND);
277    }
278    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
279    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
280
281    if(this->par.getSpectralMethod()=="peak")
282      plot.drawThresholds(this->par,this->Stats);
283
284    /**************************/
285    // ZOOM IN SPECTRALLY ON THE DETECTION.
286
287    double minvel,maxvel;
288    if(this->head.isWCS()) getSmallVelRange(this->objectList->at(objNum),this->head,&minvel,&maxvel);
289    else getSmallZRange(this->objectList->at(objNum),&minvel,&maxvel);
290
291    // Find new max & min flux values
292    std::swap(max,min);
293    int ct = 0;
294    for(int i=0;i<zdim;i++){
295      if((!this->par.isInMW(i))&&(specx[i]>=minvel)&&(specx[i]<=maxvel)){
296        ct++;
297        if(specy[i]>max) max=specy[i];
298        if(specy[i]<min) min=specy[i];
299      }
300    }
301    // widen the flux range slightly so that the top & bottom don't lie
302    // on the axes.
303    width = max - min;
304    max += width * 0.05;
305    min -= width * 0.05;
306
307    plot.gotoZoomSpectrum(minvel,maxvel,min,max);
308    cpgline(zdim,specx,specy);
309    if(this->par.getFlagBaseline()){
310      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
311      cpgline(zdim,specx,base);
312      cpgsci(FOREGND);
313    }
314    if(this->reconExists){
315      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
316      cpgline(zdim,specx,specy2);   
317      cpgsci(FOREGND);
318    }
319    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
320    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
321   
322    if(this->par.getSpectralMethod()=="peak")
323      plot.drawThresholds(this->par,this->Stats);
324
325    /**************************/
326
327    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
328    if(this->numNondegDim>1){
329      plot.gotoMap();
330      this->drawMomentCutout(this->objectList->at(objNum));
331    }
332
333    delete [] specx;
334    delete [] specy;
335    delete [] specy2;
336    delete [] base;
337 
338  }
339  //--------------------------------------------------------------------
340
341
342  void Cube::plotSource(Detection obj, Plot::CutoutPlot &plot)
343  {
344    ///  @details
345    /// The way to print out the 2d image cutout of a Detection.
346    /// Makes use of the CutoutPlot class in plots.hh, which sizes
347    ///  everything correctly.
348    ///
349    /// A 0th moment map of the detection is plotted, with a scale
350    /// bar indicating the spatial size.
351    ///
352    /// Basic information on the source is printed next to it as well.
353    ///
354    /// \param obj The Detection to be plotted.
355    /// \param plot The PGPLOT device to plot the spectrum on.
356
357    obj.calcFluxes(this->array, this->axisDim);
358
359    std::string label;
360    plot.gotoHeader();
361
362    if(this->head.isWCS()){
363      label = obj.outputLabelWCS();
364      plot.firstHeaderLine(label);
365      label = obj.outputLabelFluxes();
366      plot.secondHeaderLine(label);
367    }
368    label = obj.outputLabelWidths();
369    plot.thirdHeaderLine(label);
370    label = obj.outputLabelPix();
371    plot.fourthHeaderLine(label);
372   
373    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
374    plot.gotoMap();
375    this->drawMomentCutout(obj);
376
377  }
378
379}
Note: See TracBrowser for help on using the repository browser.