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

Last change on this file since 1121 was 1118, checked in by MatthewWhiting, 12 years ago

Making sure the max/min for the cutout spectrum take into account the baseline and reconstructed arrays.

File size: 13.1 KB
RevLine 
[299]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// -----------------------------------------------------------------------
[3]28#include <iostream>
[424]29#include <fstream>
[3]30#include <iomanip>
31#include <sstream>
32#include <string>
33#include <cpgplot.h>
34#include <math.h>
[394]35#include <wcslib/wcs.h>
[393]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>
[985]41#include <duchamp/Cubes/cubeUtils.hh>
[393]42#include <duchamp/Cubes/plots.hh>
43#include <duchamp/Utils/utils.hh>
44#include <duchamp/Utils/mycpgplot.hh>
[258]45
[146]46using namespace mycpgplot;
[258]47using namespace PixelInfo;
[3]48
[378]49namespace duchamp
[3]50{
51
[475]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
[378]71  void Cube::outputSpectra()
72  {
[528]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.
[3]90
[378]91    if(this->fullCols.size()==0) this->setupColumns();
92    // in case cols haven't been set -- need the precisions for printing values.
93
[475]94    std::vector<bool> objectChoice = this->par.getObjectChoices(this->objectList->size());
95
[378]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
[623]101        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
[475]102          // for each object in the cube, assuming it is wanted:
103          if(objectChoice[nobj]) this->plotSource(this->objectList->at(nobj),newplot);
[378]104        }// end of loop over objects.
[475]105        cpgclos();
[485]106       
107        if(this->par.getFlagUsePrevious()) std::cout << "\n";
[623]108        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
[475]109          if(objectChoice[nobj] && this->par.getFlagUsePrevious()){
[485]110            std::cout << "  Will output individual plot to "
[475]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        }               
[378]118      }
[367]119    }
[378]120    else{
121      Plot::SpectralPlot newplot;
122      if(newplot.setUpPlot(spectrafile.c_str())>0) {
[367]123
[623]124        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
[475]125          // for each object in the cube, assuming it is wanted:
126          if(objectChoice[nobj])  this->plotSpectrum(nobj,newplot);
[378]127        }// end of loop over objects.
[475]128        cpgclos();
[367]129
[485]130        if(this->par.getFlagUsePrevious()) std::cout << "\n";
[623]131        for(size_t nobj=0;nobj<this->objectList->size();nobj++){
[475]132          if(objectChoice[nobj] && this->par.getFlagUsePrevious()){
[485]133            std::cout << "  Will output individual plot to "
[475]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
[378]142      }
[475]143     
[367]144    }
145  }
[424]146  //--------------------------------------------------------------------
[103]147
[424]148  void Cube::plotSpectrum(int objNum, Plot::SpectralPlot &plot)
149  {
[528]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.
[103]169
[378]170    long zdim = this->axisDim[2];
[3]171
[424]172    this->objectList->at(objNum).calcFluxes(this->array, this->axisDim);
[103]173
[634]174    double minMWvel=0,maxMWvel=0,xval,yval,zval;
[424]175    xval = double(this->objectList->at(objNum).getXcentre());
176    yval = double(this->objectList->at(objNum).getYcentre());
[378]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    }
[103]183
[378]184    float *specx  = new float[zdim];
185    float *specy  = new float[zdim];
186    float *specy2 = new float[zdim];
187    float *base   = new float[zdim];
[463]188//     float *specx, *specy, *specy2, *base;
[3]189
[424]190    this->getSpectralArrays(objNum,specx,specy,specy2,base);
[3]191
[378]192    std::string fluxLabel = "Flux";
[436]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.
[498]197
[499]198    if(fluxUnits.size()>5 &&
[498]199       makelower(fluxUnits.substr(fluxUnits.size()-5,
[436]200                                  fluxUnits.size()   )) == "/beam"){
201      intFluxUnits = fluxUnits.substr(0,fluxUnits.size()-5);
202    }
203    else intFluxUnits = fluxUnits;
204   
205
[378]206    if(this->par.getSpectralMethod()=="sum"){
207      fluxLabel = "Integrated " + fluxLabel;
[436]208      if(this->head.isWCS()) {
209        fluxLabel += " ["+intFluxUnits+"]";
210      }
[3]211    }
[378]212    else {// if(par.getSpectralMethod()=="peak"){
213      fluxLabel = "Peak " + fluxLabel;
[436]214      if(this->head.isWCS()) fluxLabel += " ["+fluxUnits+"]";
[45]215    }
[3]216   
[378]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    }
[142]223 
[378]224    float max,min;
225    int loc=0;
226    if(this->par.getMinMW()>0) max = min = specy[0];
[463]227    else max = min = specy[this->par.getMaxMW()+1];
[378]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        }
[3]235      }
236    }
[378]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;
[463]242    width = vmax - vmin;
[378]243    vmax += width * 0.01;
244    vmin -= width * 0.01;
[3]245
[378]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");
[3]254
[378]255    if(this->head.isWCS()){
[424]256      label = this->objectList->at(objNum).outputLabelWCS();
[378]257      plot.firstHeaderLine(label);
[424]258      label = this->objectList->at(objNum).outputLabelFluxes();
[378]259      plot.secondHeaderLine(label);
260    }
[424]261    label = this->objectList->at(objNum).outputLabelWidths();
[378]262    plot.thirdHeaderLine(label);
[424]263    label = this->objectList->at(objNum).outputLabelPix();
[378]264    plot.fourthHeaderLine(label);
[49]265   
[378]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);
[850]279    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
[3]280
[987]281    if(this->par.getSpectralMethod()=="peak")
282      plot.drawThresholds(this->par,this->Stats);
283
[378]284    /**************************/
285    // ZOOM IN SPECTRALLY ON THE DETECTION.
[3]286
[957]287    double minvel,maxvel;
[424]288    if(this->head.isWCS()) getSmallVelRange(this->objectList->at(objNum),this->head,&minvel,&maxvel);
289    else getSmallZRange(this->objectList->at(objNum),&minvel,&maxvel);
[3]290
[378]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];
[1118]299        if(this->par.getFlagBaseline()){
300          if(base[i]>max) max=base[i];
301          if(base[i]<min) min=base[i];
302        }
303        if(this->reconExists){
304          if(specy2[i]>max) max=specy2[i];
305          if(specy2[i]<min) min=specy2[i];
306        }
[378]307      }
[3]308    }
[378]309    // widen the flux range slightly so that the top & bottom don't lie
310    // on the axes.
311    width = max - min;
312    max += width * 0.05;
313    min -= width * 0.05;
[3]314
[378]315    plot.gotoZoomSpectrum(minvel,maxvel,min,max);
316    cpgline(zdim,specx,specy);
317    if(this->par.getFlagBaseline()){
318      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
319      cpgline(zdim,specx,base);
320      cpgsci(FOREGND);
321    }
322    if(this->reconExists){
323      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
324      cpgline(zdim,specx,specy2);   
325      cpgsci(FOREGND);
326    }
327    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
[850]328    drawSpectralRange(plot,this->objectList->at(objNum),this->head);
[3]329   
[987]330    if(this->par.getSpectralMethod()=="peak")
331      plot.drawThresholds(this->par,this->Stats);
332
[378]333    /**************************/
[3]334
[378]335    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
[985]336    if(this->numNondegDim>1){
337      plot.gotoMap();
338      this->drawMomentCutout(this->objectList->at(objNum));
339    }
[3]340
[378]341    delete [] specx;
342    delete [] specy;
343    delete [] specy2;
344    delete [] base;
[3]345 
[378]346  }
[424]347  //--------------------------------------------------------------------
[3]348
[850]349
[378]350  void Cube::plotSource(Detection obj, Plot::CutoutPlot &plot)
351  {
[528]352    ///  @details
353    /// The way to print out the 2d image cutout of a Detection.
354    /// Makes use of the CutoutPlot class in plots.hh, which sizes
355    ///  everything correctly.
356    ///
357    /// A 0th moment map of the detection is plotted, with a scale
358    /// bar indicating the spatial size.
359    ///
360    /// Basic information on the source is printed next to it as well.
361    ///
362    /// \param obj The Detection to be plotted.
363    /// \param plot The PGPLOT device to plot the spectrum on.
[367]364
[378]365    obj.calcFluxes(this->array, this->axisDim);
[367]366
[378]367    std::string label;
368    plot.gotoHeader();
[367]369
[378]370    if(this->head.isWCS()){
371      label = obj.outputLabelWCS();
372      plot.firstHeaderLine(label);
373      label = obj.outputLabelFluxes();
374      plot.secondHeaderLine(label);
375    }
376    label = obj.outputLabelWidths();
377    plot.thirdHeaderLine(label);
378    label = obj.outputLabelPix();
379    plot.fourthHeaderLine(label);
380   
381    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
382    plot.gotoMap();
383    this->drawMomentCutout(obj);
[367]384
385  }
386
387}
Note: See TracBrowser for help on using the repository browser.