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

Last change on this file since 1190 was 1186, checked in by MatthewWhiting, 11 years ago

Fixes to get the plotting right. Ignoring zero/negative values when finding the z-range for the moment map plot. Getting the initial value of the max/min flux for the spectral plot right, in the case where the MW range is outside the requested subsection.

File size: 13.4 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        // This loop plots all spectra of selected objects in a single file
102        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
103          // for each object in the cube, assuming it is wanted:
104          if(objectChoice[nobj]) this->plotSource(this->objectList->at(nobj),newplot);
105        }// end of loop over objects.
106        cpgclos();
107       
108        // This loop plots spectra of selected objects in their own file
109        if(this->par.getFlagPlotIndividualSpectra()) std::cout << "\n";
110        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
111          if(objectChoice[nobj] && this->par.getFlagPlotIndividualSpectra()){
112            std::cout << "  Will output individual plot to "
113                      << getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size()) << "\n";
114            Plot::CutoutPlot indivplot;
115            indivplot.setUpPlot(getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size())+"/vcps");
116            this->plotSource(this->objectList->at(nobj),indivplot);
117            cpgclos();
118          }
119        }               
120      }
121    }
122    else{
123      Plot::SpectralPlot newplot;
124      if(newplot.setUpPlot(spectrafile.c_str())>0) {
125
126        // This loop plots all spectra of selected objects in a single file
127        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
128          // for each object in the cube, assuming it is wanted:
129          if(objectChoice[nobj])  this->plotSpectrum(nobj,newplot);
130        }// end of loop over objects.
131        cpgclos();
132
133        // This loop plots spectra of selected objects in their own file
134        if(this->par.getFlagPlotIndividualSpectra()) std::cout << "\n";
135        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
136          if(objectChoice[nobj] && this->par.getFlagPlotIndividualSpectra()){
137            std::cout << "  Will output individual plot to "
138                      << getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size()) << "\n";
139            Plot::SpectralPlot indivplot;
140            indivplot.setUpPlot(getIndivPlotName(this->par.getSpectraFile(),nobj+1,this->objectList->size())+"/vcps");
141            this->plotSpectrum(nobj,indivplot);
142            cpgclos();
143          }
144        }               
145
146      }
147     
148    }
149  }
150  //--------------------------------------------------------------------
151
152  void Cube::plotSpectrum(int objNum, Plot::SpectralPlot &plot)
153  {
154    ///  @details
155    /// The way to print out the spectrum of a Detection.
156    /// Makes use of the SpectralPlot class in plots.hh, which sizes
157    ///  everything correctly.
158    ///
159    /// The main choice for the user is whether to use the peak pixel, in
160    /// which case the spectrum is just that of the peak pixel, or the
161    /// sum, where the spectrum is summed over all spatial pixels that
162    /// are in the object.
163    ///
164    /// If a reconstruction has been done, that spectrum is plotted in
165    /// red, and if a baseline has been calculated that is also shown, in
166    /// yellow.  The spectral limits of the detection are marked in blue.
167    /// A 0th moment map of the detection is also plotted, with a scale
168    /// bar indicating the spatial size.
169    ///
170    /// \param objNum The number of the Detection to be plotted.
171    /// \param plot The SpectralPlot object defining the PGPLOT device
172    ///        to plot the spectrum on.
173
174    long zdim = this->axisDim[2];
175
176    this->objectList->at(objNum).calcFluxes(this->array, this->axisDim);
177
178    double minMWvel=0,maxMWvel=0,xval,yval,zval;
179    xval = double(this->objectList->at(objNum).getXcentre());
180    yval = double(this->objectList->at(objNum).getYcentre());
181    if(this->par.getFlagMW()){
182      zval = double(this->par.getMinMW());
183      minMWvel = this->head.pixToVel(xval,yval,zval);
184      zval = double(this->par.getMaxMW());
185      maxMWvel = this->head.pixToVel(xval,yval,zval);
186    }
187
188    float *specx  = new float[zdim];
189    float *specy  = new float[zdim];
190    float *specy2 = new float[zdim];
191    float *base   = new float[zdim];
192//     float *specx, *specy, *specy2, *base;
193
194    this->getSpectralArrays(objNum,specx,specy,specy2,base);
195
196    std::string fluxLabel = "Flux";
197    std::string fluxUnits = this->head.getFluxUnits();
198    std::string intFluxUnits;// = this->head.getIntFluxUnits();
199    // Rather than use the intFluxUnits from the header, which will be like Jy MHz,
200    // we just use the pixel units, removing the /beam if necessary.
201
202    if(fluxUnits.size()>5 &&
203       makelower(fluxUnits.substr(fluxUnits.size()-5,
204                                  fluxUnits.size()   )) == "/beam"){
205      intFluxUnits = fluxUnits.substr(0,fluxUnits.size()-5);
206    }
207    else intFluxUnits = fluxUnits;
208   
209
210    if(this->par.getSpectralMethod()=="sum"){
211      fluxLabel = "Integrated " + fluxLabel;
212      if(this->head.isWCS()) {
213        fluxLabel += " ["+intFluxUnits+"]";
214      }
215    }
216    else {// if(par.getSpectralMethod()=="peak"){
217      fluxLabel = "Peak " + fluxLabel;
218      if(this->head.isWCS()) fluxLabel += " ["+fluxUnits+"]";
219    }
220   
221    float vmax,vmin,width;
222    vmax = vmin = specx[0];
223    for(int i=1;i<zdim;i++){
224      if(specx[i]>vmax) vmax=specx[i];
225      if(specx[i]<vmin) vmin=specx[i];
226    }
227 
228    float max,min;
229    int loc=0;
230    if(this->par.getMinMW()>0) max = min = specy[0];
231    else{
232        loc = std::max(this->par.getMaxMW()+1,0);
233        max = min = specy[loc];
234    }
235    for(int i=0;i<zdim;i++){
236      if(!this->par.isInMW(i)){
237        if(specy[i]>max) max=specy[i];
238        if(specy[i]<min){
239          min=specy[i];
240          loc = i;
241        }
242      }
243    }
244
245    // widen the ranges slightly so that the top & bottom & edges don't
246    // lie on the axes.
247    width = max - min;
248    max += width * 0.05;
249    min -= width * 0.05;
250    width = vmax - vmin;
251    vmax += width * 0.01;
252    vmin -= width * 0.01;
253
254    // now plot the resulting spectrum
255    std::string label;
256    if(this->head.isWCS()){
257      label = this->head.getSpectralDescription() + " [" +
258        this->head.getSpectralUnits() + "]";
259      plot.gotoHeader(label);
260    }
261    else plot.gotoHeader("Spectral pixel value");
262
263    if(this->head.isWCS()){
264      label = this->objectList->at(objNum).outputLabelWCS();
265      plot.firstHeaderLine(label);
266      label = this->objectList->at(objNum).outputLabelFluxes();
267      plot.secondHeaderLine(label);
268    }
269    label = this->objectList->at(objNum).outputLabelWidths(this->head);
270    plot.thirdHeaderLine(label);
271    label = this->objectList->at(objNum).outputLabelPix();
272    plot.fourthHeaderLine(label);
273   
274    plot.gotoMainSpectrum(vmin,vmax,min,max,fluxLabel);
275    cpgline(zdim,specx,specy);
276    if(this->par.getFlagBaseline()){
277      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
278      cpgline(zdim,specx,base);
279      cpgsci(FOREGND);
280    }
281    if(this->reconExists){
282      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
283      cpgline(zdim,specx,specy2);   
284      cpgsci(FOREGND);
285    }
286    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
287    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
288
289    if(this->par.getSpectralMethod()=="peak")
290      plot.drawThresholds(this->par,this->Stats);
291
292    /**************************/
293    // ZOOM IN SPECTRALLY ON THE DETECTION.
294
295    double minvel,maxvel;
296    if(this->head.isWCS()) getSmallVelRange(this->objectList->at(objNum),this->head,&minvel,&maxvel);
297    else getSmallZRange(this->objectList->at(objNum),&minvel,&maxvel);
298
299    // Find new max & min flux values
300    std::swap(max,min);
301    int ct = 0;
302    for(int i=0;i<zdim;i++){
303      if((!this->par.isInMW(i))&&(specx[i]>=minvel)&&(specx[i]<=maxvel)){
304        ct++;
305        if(specy[i]>max) max=specy[i];
306        if(specy[i]<min) min=specy[i];
307        if(this->par.getFlagBaseline()){
308          if(base[i]>max) max=base[i];
309          if(base[i]<min) min=base[i];
310        }
311        if(this->reconExists){
312          if(specy2[i]>max) max=specy2[i];
313          if(specy2[i]<min) min=specy2[i];
314        }
315      }
316    }
317    // widen the flux range slightly so that the top & bottom don't lie
318    // on the axes.
319    width = max - min;
320    max += width * 0.05;
321    min -= width * 0.05;
322
323    plot.gotoZoomSpectrum(minvel,maxvel,min,max);
324    cpgline(zdim,specx,specy);
325    if(this->par.getFlagBaseline()){
326      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
327      cpgline(zdim,specx,base);
328      cpgsci(FOREGND);
329    }
330    if(this->reconExists){
331      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
332      cpgline(zdim,specx,specy2);   
333      cpgsci(FOREGND);
334    }
335    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
336    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
337   
338    if(this->par.getSpectralMethod()=="peak")
339      plot.drawThresholds(this->par,this->Stats);
340
341    /**************************/
342
343    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
344    if(this->numNondegDim>1){
345      plot.gotoMap();
346      this->drawMomentCutout(this->objectList->at(objNum));
347    }
348
349    delete [] specx;
350    delete [] specy;
351    delete [] specy2;
352    delete [] base;
353 
354  }
355  //--------------------------------------------------------------------
356
357
358  void Cube::plotSource(Detection obj, Plot::CutoutPlot &plot)
359  {
360    ///  @details
361    /// The way to print out the 2d image cutout of a Detection.
362    /// Makes use of the CutoutPlot class in plots.hh, which sizes
363    ///  everything correctly.
364    ///
365    /// A 0th moment map of the detection is plotted, with a scale
366    /// bar indicating the spatial size.
367    ///
368    /// Basic information on the source is printed next to it as well.
369    ///
370    /// \param obj The Detection to be plotted.
371    /// \param plot The PGPLOT device to plot the spectrum on.
372
373    obj.calcFluxes(this->array, this->axisDim);
374
375    std::string label;
376    plot.gotoHeader();
377
378    if(this->head.isWCS()){
379      label = obj.outputLabelWCS();
380      plot.firstHeaderLine(label);
381      label = obj.outputLabelFluxes();
382      plot.secondHeaderLine(label);
383    }
384    label = obj.outputLabelWidths(this->head);
385    plot.thirdHeaderLine(label);
386    label = obj.outputLabelPix();
387    plot.fourthHeaderLine(label);
388   
389    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
390    plot.gotoMap();
391    this->drawMomentCutout(obj);
392
393  }
394
395}
Note: See TracBrowser for help on using the repository browser.