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

Last change on this file since 1441 was 1430, checked in by MatthewWhiting, 7 years ago

Undoing previous commit, as I didn't mean to commit everything :)

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