source: tags/release-1.1.2b/src/Cubes/outputSpectra.cc @ 1391

Last change on this file since 1391 was 392, checked in by MatthewWhiting, 17 years ago

Fixed up headers -- should have been done before tagging.

File size: 14.5 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 <iomanip>
30#include <sstream>
31#include <string>
32#include <cpgplot.h>
33#include <math.h>
34#include <wcs.h>
35#include <duchamp/param.hh>
36#include <duchamp/duchamp.hh>
37#include <duchamp/fitsHeader.hh>
38#include <duchamp/PixelMap/Object3D.hh>
39#include <duchamp/Cubes/cubes.hh>
40#include <duchamp/Cubes/plots.hh>
41#include <duchamp/Utils/utils.hh>
42#include <duchamp/Utils/mycpgplot.hh>
43
44using namespace mycpgplot;
45using namespace PixelInfo;
46
47namespace duchamp
48{
49
50  void getSmallVelRange(Detection &obj, FitsHeader head, float *minvel, float *maxvel);
51  void getSmallZRange(Detection &obj, float *minz, float *maxz);
52
53  void Cube::outputSpectra()
54  {
55    /**
56     * The way to display individual detected objects. The standard way
57     * is plot the full spectrum, plus a zoomed-in spectrum showing just
58     * the object, plus the 0th-moment map. If there is no spectral
59     * axis, just the 0th moment map is plotted (using
60     * Cube::plotSource() rather than Cube::plotSpectrum()).
61     *
62     * It makes use of the SpectralPlot or CutoutPlot classes from plots.h, which size
63     * everything correctly. 
64     *
65     * The main choice for SpectralPlot() is whether to use the peak
66     * pixel, in which case the spectrum is just that of the peak pixel,
67     * or the sum, where the spectrum is summed over all spatial pixels
68     * that are in the object.  If a reconstruction has been done, that
69     * spectrum is plotted in red.  The limits of the detection are
70     * marked in blue.  A 0th moment map of the detection is also
71     * plotted, with a scale bar indicating the spatial scale.
72     */
73
74    if(this->fullCols.size()==0) this->setupColumns();
75    // in case cols haven't been set -- need the precisions for printing values.
76
77    std::string spectrafile = this->par.getSpectraFile() + "/vcps";
78    if(this->getDimZ()<=1){
79      Plot::CutoutPlot newplot;
80      if(newplot.setUpPlot(spectrafile.c_str())>0) {
81
82        for(int nobj=0;nobj<this->objectList->size();nobj++){
83          // for each object in the cube:
84          this->plotSource(this->objectList->at(nobj),newplot);
85     
86        }// end of loop over objects.
87
88        cpgclos();
89      }
90    }
91    else{
92      Plot::SpectralPlot newplot;
93      if(newplot.setUpPlot(spectrafile.c_str())>0) {
94
95        for(int nobj=0;nobj<this->objectList->size();nobj++){
96          // for each object in the cube:
97          this->plotSpectrum(this->objectList->at(nobj),newplot);
98     
99        }// end of loop over objects.
100
101        cpgclos();
102      }
103    }
104  }
105
106  void Cube::plotSpectrum(Detection obj, Plot::SpectralPlot &plot)
107  {
108    /**
109     * The way to print out the spectrum of a Detection.
110     * Makes use of the SpectralPlot class in plots.hh, which sizes
111     *  everything correctly.
112     *
113     * The main choice for the user is whether to use the peak pixel, in
114     * which case the spectrum is just that of the peak pixel, or the
115     * sum, where the spectrum is summed over all spatial pixels that
116     * are in the object.
117     *
118     * If a reconstruction has been done, that spectrum is plotted in
119     * red, and if a baseline has been calculated that is also shown, in
120     * yellow.  The spectral limits of the detection are marked in blue.
121     * A 0th moment map of the detection is also plotted, with a scale
122     * bar indicating the spatial size.
123     *
124     * \param obj The Detection to be plotted.
125     * \param plot The PGPLOT device to plot the spectrum on.
126     */
127
128    long xdim = this->axisDim[0];
129    long ydim = this->axisDim[1];
130    long zdim = this->axisDim[2];
131
132    obj.calcFluxes(this->array, this->axisDim);
133
134    double minMWvel,maxMWvel,xval,yval,zval;
135    xval = double(obj.getXcentre());
136    yval = double(obj.getYcentre());
137    if(this->par.getFlagMW()){
138      zval = double(this->par.getMinMW());
139      minMWvel = this->head.pixToVel(xval,yval,zval);
140      zval = double(this->par.getMaxMW());
141      maxMWvel = this->head.pixToVel(xval,yval,zval);
142    }
143
144    float *specx  = new float[zdim];
145    float *specy  = new float[zdim];
146    for(int i=0;i<zdim;i++) specy[i] = 0.;
147    float *specy2 = new float[zdim];
148    for(int i=0;i<zdim;i++) specy2[i] = 0.;
149    float *base   = new float[zdim];
150    for(int i=0;i<zdim;i++) base[i] = 0.;
151
152    for(int i=0;i<zdim;i++) specy[i] = 0.;
153    if(this->par.getFlagATrous()) 
154      for(int i=0;i<zdim;i++) specy2[i] = 0.;
155   
156    if(this->head.isWCS())
157      for(zval=0;zval<zdim;zval++)
158        specx[int(zval)] = this->head.pixToVel(xval,yval,zval);
159    else
160      for(zval=0;zval<zdim;zval++) specx[int(zval)] = zval;
161
162    std::string fluxLabel = "Flux";
163 
164    float beamCorrection;
165    if(this->header().needBeamSize())
166      beamCorrection = this->par.getBeamSize();
167    else beamCorrection = 1.;
168
169    if(this->par.getSpectralMethod()=="sum"){
170      fluxLabel = "Integrated " + fluxLabel;
171      if(this->head.isWCS())
172        fluxLabel += " ["+this->head.getIntFluxUnits()+"]";
173      bool *done = new bool[xdim*ydim];
174      for(int i=0;i<xdim*ydim;i++) done[i]=false;
175      std::vector<Voxel> voxlist = obj.pixels().getPixelSet();
176      for(int pix=0;pix<voxlist.size();pix++){
177        int pos = voxlist[pix].getX() + xdim * voxlist[pix].getY();
178        if(!done[pos]){
179          done[pos] = true;
180          for(int z=0;z<zdim;z++){
181            if(!(this->isBlank(pos+z*xdim*ydim))){
182              specy[z] += this->array[pos + z*xdim*ydim] / beamCorrection;
183              if(this->reconExists)
184                specy2[z] += this->recon[pos + z*xdim*ydim] / beamCorrection;
185              if(this->par.getFlagBaseline())
186                base[z] += this->baseline[pos + z*xdim*ydim] / beamCorrection;
187            }       
188          }
189        }
190      }
191      delete [] done;
192    }
193    else {// if(par.getSpectralMethod()=="peak"){
194      fluxLabel = "Peak " + fluxLabel;
195      if(this->head.isWCS()) fluxLabel += " ["+this->head.getFluxUnits()+"]";
196      int pos = obj.getXPeak() + xdim*obj.getYPeak();
197      for(int z=0;z<zdim;z++){
198        specy[z] = this->array[pos + z*xdim*ydim];
199        if(this->reconExists)
200          specy2[z] = this->recon[pos + z*xdim*ydim];
201        if(this->par.getFlagBaseline())
202          base[z] = this->baseline[pos + z*xdim*ydim];
203      }
204    }
205   
206    float vmax,vmin,width;
207    vmax = vmin = specx[0];
208    for(int i=1;i<zdim;i++){
209      if(specx[i]>vmax) vmax=specx[i];
210      if(specx[i]<vmin) vmin=specx[i];
211    }
212 
213    float max,min;
214    int loc=0;
215    if(this->par.getMinMW()>0) max = min = specy[0];
216    else max = min = specx[this->par.getMaxMW()+1];
217    for(int i=0;i<zdim;i++){
218      if(!this->par.isInMW(i)){
219        if(specy[i]>max) max=specy[i];
220        if(specy[i]<min){
221          min=specy[i];
222          loc = i;
223        }
224      }
225    }
226    // widen the ranges slightly so that the top & bottom & edges don't
227    // lie on the axes.
228    width = max - min;
229    max += width * 0.05;
230    min -= width * 0.05;
231    width = vmax -vmin;
232    vmax += width * 0.01;
233    vmin -= width * 0.01;
234
235    // now plot the resulting spectrum
236    std::string label;
237    if(this->head.isWCS()){
238      label = this->head.getSpectralDescription() + " [" +
239        this->head.getSpectralUnits() + "]";
240      plot.gotoHeader(label);
241    }
242    else plot.gotoHeader("Spectral pixel value");
243
244    if(this->head.isWCS()){
245      label = obj.outputLabelWCS();
246      plot.firstHeaderLine(label);
247      label = obj.outputLabelFluxes();
248      plot.secondHeaderLine(label);
249    }
250    label = obj.outputLabelWidths();
251    plot.thirdHeaderLine(label);
252    label = obj.outputLabelPix();
253    plot.fourthHeaderLine(label);
254   
255    plot.gotoMainSpectrum(vmin,vmax,min,max,fluxLabel);
256    cpgline(zdim,specx,specy);
257    if(this->par.getFlagBaseline()){
258      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
259      cpgline(zdim,specx,base);
260      cpgsci(FOREGND);
261    }
262    if(this->reconExists){
263      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
264      cpgline(zdim,specx,specy2);   
265      cpgsci(FOREGND);
266    }
267    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
268    if(this->head.isWCS()) plot.drawVelRange(obj.getVelMin(),obj.getVelMax());
269    else plot.drawVelRange(obj.getZmin(),obj.getZmax());
270
271    /**************************/
272    // ZOOM IN SPECTRALLY ON THE DETECTION.
273
274    float minvel,maxvel;
275    if(this->head.isWCS()) getSmallVelRange(obj,this->head,&minvel,&maxvel);
276    else getSmallZRange(obj,&minvel,&maxvel);
277
278    // Find new max & min flux values
279    std::swap(max,min);
280    int ct = 0;
281    for(int i=0;i<zdim;i++){
282      if((!this->par.isInMW(i))&&(specx[i]>=minvel)&&(specx[i]<=maxvel)){
283        ct++;
284        if(specy[i]>max) max=specy[i];
285        if(specy[i]<min) min=specy[i];
286      }
287    }
288    // widen the flux range slightly so that the top & bottom don't lie
289    // on the axes.
290    width = max - min;
291    max += width * 0.05;
292    min -= width * 0.05;
293
294    plot.gotoZoomSpectrum(minvel,maxvel,min,max);
295    cpgline(zdim,specx,specy);
296    if(this->par.getFlagBaseline()){
297      cpgsci(DUCHAMP_BASELINE_SPECTRA_COLOUR);
298      cpgline(zdim,specx,base);
299      cpgsci(FOREGND);
300    }
301    if(this->reconExists){
302      cpgsci(DUCHAMP_RECON_SPECTRA_COLOUR);
303      cpgline(zdim,specx,specy2);   
304      cpgsci(FOREGND);
305    }
306    if(this->par.getFlagMW()) plot.drawMWRange(minMWvel,maxMWvel);
307    if(this->head.isWCS()) plot.drawVelRange(obj.getVelMin(),obj.getVelMax());
308    else plot.drawVelRange(obj.getZmin(),obj.getZmax());
309   
310    /**************************/
311
312    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
313    plot.gotoMap();
314    this->drawMomentCutout(obj);
315
316    delete [] specx;
317    delete [] specy;
318    delete [] specy2;
319    delete [] base;
320 
321  }
322
323
324  void getSmallVelRange(Detection &obj, FitsHeader head,
325                        float *minvel, float *maxvel)
326  {
327    /**
328     *  Routine to calculate the velocity range for the zoomed-in region.
329     *  This range should be the maximum of 20 pixels, or 3x the wdith of
330     *   the detection.
331     *  Need to :
332     *      Calculate pixel width of a 3x-detection-width region.
333     *      If smaller than 20, calculate velocities of central vel +- 10 pixels
334     *      If not, use the 3x-detection-width
335     *  Range returned via "minvel" and "maxvel" parameters.
336     *  \param obj Detection under examination.
337     *  \param head FitsHeader, containing the WCS information.
338     *  \param minvel Returned value of minimum velocity
339     *  \param maxvel Returned value of maximum velocity
340     */
341
342    double *pixcrd = new double[3];
343    double *world  = new double[3];
344    float minpix,maxpix;
345    // define new velocity extrema
346    //    -- make it 3x wider than the width of the detection.
347    *minvel = 0.5*(obj.getVelMin()+obj.getVelMax()) - 1.5*obj.getVelWidth();
348    *maxvel = 0.5*(obj.getVelMin()+obj.getVelMax()) + 1.5*obj.getVelWidth();
349    // Find velocity range in number of pixels:
350    world[0] = obj.getRA();
351    world[1] = obj.getDec();
352    world[2] = head.velToSpec(*minvel);
353    head.wcsToPix(world,pixcrd);
354    minpix = pixcrd[2];
355    world[2] = head.velToSpec(*maxvel);
356    head.wcsToPix(world,pixcrd);
357    maxpix = pixcrd[2];
358    if(maxpix<minpix) std::swap(maxpix,minpix);
359   
360    if((maxpix - minpix + 1) < 20){
361      pixcrd[0] = double(obj.getXcentre());
362      pixcrd[1] = double(obj.getYcentre());
363      pixcrd[2] = obj.getZcentre() - 10.;
364      head.pixToWCS(pixcrd,world);
365      //    *minvel = setVel_kms(wcs,world[2]);
366      *minvel = head.specToVel(world[2]);
367      pixcrd[2] = obj.getZcentre() + 10.;
368      head.pixToWCS(pixcrd,world);
369      //     *maxvel = setVel_kms(wcs,world[2]);
370      *maxvel = head.specToVel(world[2]);
371      if(*maxvel<*minvel) std::swap(*maxvel,*minvel);
372    }
373    delete [] pixcrd;
374    delete [] world;
375
376  }
377
378  void getSmallZRange(Detection &obj, float *minz, float *maxz)
379  {
380    /**
381     *  Routine to calculate the pixel range for the zoomed-in spectrum.
382     *  This range should be the maximum of 20 pixels, or 3x the width
383     *   of the detection.
384     *  Need to :
385     *      Calculate pixel width of a 3x-detection-width region.
386     *       If smaller than 20, use central pixel +- 10 pixels
387     *  Range returned via "minz" and "maxz" parameters.
388     *  \param obj Detection under examination.
389     *  \param minz Returned value of minimum z-pixel coordinate
390     *  \param maxz Returned value of maximum z-pixel coordinate
391     */
392
393    *minz = 2.*obj.getZmin() - obj.getZmax();
394    *maxz = 2.*obj.getZmax() - obj.getZmin();
395   
396    if((*maxz - *minz + 1) < 20){
397      *minz = obj.getZcentre() - 10.;
398      *maxz = obj.getZcentre() + 10.;
399    }
400
401  }
402
403
404  void Cube::plotSource(Detection obj, Plot::CutoutPlot &plot)
405  {
406    /**
407     * The way to print out the 2d image cutout of a Detection.
408     * Makes use of the CutoutPlot class in plots.hh, which sizes
409     *  everything correctly.
410     *
411     * A 0th moment map of the detection is plotted, with a scale
412     * bar indicating the spatial size.
413     *
414     * Basic information on the source is printed next to it as well.
415     *
416     * \param obj The Detection to be plotted.
417     * \param plot The PGPLOT device to plot the spectrum on.
418     */
419
420    obj.calcFluxes(this->array, this->axisDim);
421
422    std::string label;
423    plot.gotoHeader();
424
425    if(this->head.isWCS()){
426      label = obj.outputLabelWCS();
427      plot.firstHeaderLine(label);
428      label = obj.outputLabelFluxes();
429      plot.secondHeaderLine(label);
430    }
431    label = obj.outputLabelWidths();
432    plot.thirdHeaderLine(label);
433    label = obj.outputLabelPix();
434    plot.fourthHeaderLine(label);
435   
436    // DRAW THE MOMENT MAP OF THE DETECTION -- SUMMED OVER ALL CHANNELS
437    plot.gotoMap();
438    this->drawMomentCutout(obj);
439
440  }
441
442}
Note: See TracBrowser for help on using the repository browser.