source: tags/release-1.1.5/src/Cubes/plots.cc @ 1441

Last change on this file since 1441 was 419, checked in by MatthewWhiting, 16 years ago

Some minor fixes to correct compilation warnings. Moved Object3D::order() into the .cc file.

File size: 19.9 KB
Line 
1// -----------------------------------------------------------------------
2// plots.cc: Functions defining SpectralPlot and ImagePlot classes.
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 <sstream>
30#include <string>
31#include <math.h>
32#include <cpgplot.h>
33#include <duchamp/param.hh>
34#include <duchamp/duchamp.hh>
35#include <duchamp/Utils/mycpgplot.hh>
36#include <duchamp/Cubes/plots.hh>
37
38using std::stringstream;
39using namespace mycpgplot;
40
41namespace duchamp
42{
43
44  namespace Plot
45  {
46
47    //----------------------------------------------------------
48    // SpectralPlot functions
49    //----------------------------------------------------------
50
51    SpectralPlot::SpectralPlot(){
52      this->paperWidth=a4width/inchToCm - 2*psHoffset;
53      this->spectraCount=0;
54      this->numOnPage = 5;
55    }
56
57    SpectralPlot::~SpectralPlot(){}
58
59    SpectralPlot::SpectralPlot(const SpectralPlot& p)
60    {
61      operator=(p);
62    }
63
64    SpectralPlot& SpectralPlot::operator=(const SpectralPlot& p)
65    {
66      if(this==&p) return *this;
67      this->numOnPage = p.numOnPage;
68      this->spectraCount = p.spectraCount; 
69      for(int i=0;i<4;i++) this->mainCoords[i] = p.mainCoords[i];
70      for(int i=0;i<4;i++) this->zoomCoords[i] = p.zoomCoords[i];
71      for(int i=0;i<4;i++) this->mapCoords[i] = p.mapCoords[i];
72      this->paperWidth = p.paperWidth;   
73      this->paperHeight = p.paperHeight;   
74      this->identifier = p.identifier;   
75      return *this;
76    }
77
78    //----------------------------------------------------------
79    int SpectralPlot::setUpPlot(std::string pgDestination){
80      /**
81       * Opens the designated pgplot device.  Scales the paper so that
82       * it fits on an A4 sheet (using known values of the default
83       * pgplot offsets). 
84       *
85       * \param pgDestination The std::string indicating the PGPLOT device to
86       * be written to.
87       *
88       * \return The value returned by mycpgopen. If <= 0, then an error
89       * has occurred.
90       */
91      this->paperHeight = this->paperWidth*M_SQRT2;
92      if(this->paperHeight+2*Plot::psVoffset > Plot::a4height){
93        this->paperHeight = Plot::a4height - 2*Plot::psVoffset;
94        this->paperWidth = this->paperHeight / M_SQRT2;
95      }
96      this->identifier = mycpgopen(pgDestination);
97      if(this->identifier>0) cpgpap(this->paperWidth, this->paperHeight/this->paperWidth);
98      // make paper size to fit on A4.
99      return this->identifier;
100    }
101    //----------------------------------------------------------
102    void SpectralPlot::calcCoords(){
103      /**
104       * Calculates the boundaries for the various boxes, in inches measured
105       *  from the lower left corner.
106       * Based on the fact that there are numOnPage spectra shown on each
107       *  page, going down the page in increasing number (given by
108       *  SpectralPlot::spectraCount).
109       */
110      int posOnPage = (this->numOnPage -
111                       (this->spectraCount%this->numOnPage))
112        %this->numOnPage;
113      this->mainCoords[0] = Plot::spMainX1/inchToCm;
114      this->mainCoords[1] = Plot::spMainX2/inchToCm;
115      this->zoomCoords[0] = Plot::spZoomX1/inchToCm;
116      this->zoomCoords[1] = Plot::spZoomX2/inchToCm;
117      this->mainCoords[2] = this->zoomCoords[2] = this->mapCoords[2] =
118        posOnPage*paperHeight/float(this->numOnPage) + Plot::spMainY1/inchToCm;
119      this->mainCoords[3] = this->zoomCoords[3] = this->mapCoords[3] =
120        posOnPage*paperHeight/float(this->numOnPage) + Plot::spMainY2/inchToCm;
121      this->mapCoords[0]  = Plot::spMapX1/inchToCm;
122      this->mapCoords[1]  = this->mapCoords[0] + (this->mapCoords[3]-this->mapCoords[2]);
123    }
124    //----------------------------------------------------------
125    void SpectralPlot::gotoHeader(std::string xlabel){
126      /**
127       * Calls calcCoords, to calculate correct coordinates for this spectrum.
128       * Defines the region for the header information, making it centred
129       *  on the page.
130       * Also writes the velocity (x axis) label, given by the string argument.
131       * \param xlabel Label to go on the velocity/spectral axis.
132       */
133      if(spectraCount%numOnPage==0) cpgpage();
134      spectraCount++;
135      this->calcCoords();
136      cpgvsiz(0., this->paperWidth, this->mainCoords[2], this->mainCoords[3]); 
137      cpgsch(Plot::spLabelSize);
138      cpgmtxt("b",Plot::spXlabelOffset,0.5,0.5,xlabel.c_str());
139    }
140    //----------------------------------------------------------
141    void SpectralPlot::gotoMainSpectrum(float x1, float x2, float y1, float y2, std::string ylabel){
142      /**
143       *  Defines the region for the main spectrum.
144       *  Draws the box, with tick marks, and
145       *   writes the flux (y axis) label, given by the string argument.
146       * \param x1 Minimum X-coordinate of box.
147       * \param x2 Maximum X-coordinate of box.
148       * \param y1 Minimum Y-coordinate of box.
149       * \param y2 Maximum Y-coordinate of box.
150       * \param ylabel Label for the flux (Y) axis.
151       */
152      cpgvsiz(this->mainCoords[0],this->mainCoords[1],
153              this->mainCoords[2],this->mainCoords[3]);
154      cpgsch(Plot::spIndexSize);
155      cpgswin(x1,x2,y1,y2);
156      cpgbox("1bcnst",0.,0,"bcnst1v",0.,0);
157      cpgsch(Plot::spLabelSize);
158      cpgmtxt("l",Plot::spYlabelOffset,0.5,0.5,ylabel.c_str());
159    }
160    //----------------------------------------------------------
161    void SpectralPlot::gotoZoomSpectrum(float x1, float x2, float y1, float y2){
162      /**
163       *   Defines the region for the zoomed-in part of the spectrum.
164       *   Draws the box, with special tick marks on the bottom axis.
165       * \param x1 Minimum X-coordinate of box.
166       * \param x2 Maximum X-coordinate of box.
167       * \param y1 Minimum Y-coordinate of box.
168       * \param y2 Maximum Y-coordinate of box.
169       */
170      cpgvsiz(this->zoomCoords[0],this->zoomCoords[1],
171              this->zoomCoords[2],this->zoomCoords[3]);
172      cpgsch(Plot::spIndexSize);
173      cpgswin(x1,x2,y1,y2);
174      cpgbox("bc",0.,0,"bcstn1v",0.,0);
175      float lengthL,lengthR,disp,tickpt,step;
176      stringstream label;
177      for(int i=1;i<10;i++){
178        tickpt = x1+(x2-x1)*float(i)/10.;  // spectral coord of the tick
179        switch(i)
180          {
181          case 2:
182          case 8:
183            lengthL = lengthR = 0.5;
184            disp = 0.3 + float(i-2)/6.; // i==2 --> disp=0.3, i==8 --> disp=1.3
185            label.str("");
186            label << tickpt;
187            // do a labelled tick mark
188            cpgtick(x1,y1,x2,y1,float(i)/10.,lengthL,lengthR,
189                    disp, 0., label.str().c_str());
190            break;
191          default:
192            label.str("");
193            lengthL = 0.25;
194            lengthR = 0.;
195            disp = 0.;  // not used in this case, but set it anyway.
196            break;
197          }
198        // first the bottom axis, just the ticks
199        if(fabs(tickpt)<(x2-x1)/1.e4) step = 2.*(x2-x1);
200        else step = tickpt;
201        cpgaxis("",
202                tickpt-0.001*(x2-x1), y1,
203                tickpt+0.001*(x2-x1), y1,
204                tickpt-0.001*(x2-x1), tickpt+0.001*(x2-x1),
205                step, -1, lengthL,lengthR, 0.5, disp, 0.);
206        //and now the top -- no labels, just tick marks
207        cpgtick(x1,y2,x2,y2,float(i)/10.,lengthL,lengthR,0.,0.,"");
208      }
209    }
210    //----------------------------------------------------------
211    void SpectralPlot::gotoMap(){
212      cpgvsiz(this->mapCoords[0],this->mapCoords[1],
213              this->mapCoords[2],this->mapCoords[3]);
214      cpgsch(Plot::spIndexSize);
215    }
216    //----------------------------------------------------------
217    void SpectralPlot::drawVelRange(float v1, float v2){
218      /**
219       * Draws two vertical lines at the limits of velocity
220       *  given by the arguments.
221       * \param v1 Minimum velocity.
222       * \param v2 Maximum velocity.
223       */
224      int ci,ls;
225      float dud,min,max;
226      cpgqwin(&dud,&dud,&min,&max);
227      cpgqci(&ci);
228      cpgqls(&ls);
229      cpgsci(DUCHAMP_OBJECT_OUTLINE_COLOUR);
230      cpgsls(DASHED);
231      cpgmove(v1,min);  cpgdraw(v1,max);
232      cpgmove(v2,min);  cpgdraw(v2,max);
233      cpgsci(ci);
234      cpgsls(ls);
235    }
236    //----------------------------------------------------------
237    void SpectralPlot::drawMWRange(float v1, float v2){
238      /**
239       * Draws a box showing the extent of channels masked by the
240       *  Milky Way parameters
241       * \param v1 Minimum velocity of the Milky Way range.
242       * \param v2 Maximum velocity of the Milky Way range.
243       */
244      int ci,fs;
245      float dud,min,max,height;
246      cpgqwin(&dud,&dud,&min,&max);
247      height = max-min;
248      max += 0.01*height;
249      min -= 0.01*height;
250      cpgqci(&ci);
251      cpgqfs(&fs);
252      setDarkGreen();
253      cpgsci(DUCHAMP_MILKY_WAY_COLOUR);
254      cpgsfs(HATCHED);
255      cpgrect(v1,v2,min,max);
256      cpgsfs(OUTLINE);
257      cpgrect(v1,v2,min,max);
258      cpgsci(ci);
259      cpgsfs(fs);
260    }
261    //----------------------------------------------------------
262    // SpectralPlot functions...
263    //----------------------------------------------------------
264    void  SpectralPlot::firstHeaderLine(std::string line)
265    {
266      cpgsch(Plot::spTitleSize);
267      cpgmtxt("t",Plot::spTitleOffset1*Plot::spLabelSize/Plot::spTitleSize,
268              0.5,0.5,line.c_str());
269    }
270    void  SpectralPlot::secondHeaderLine(std::string line)
271    {
272      cpgsch(Plot::spLabelSize);
273      cpgmtxt("t",Plot::spTitleOffset2,0.5,0.5,line.c_str());
274    }
275    void  SpectralPlot::thirdHeaderLine(std::string line)
276    {
277      cpgsch(Plot::spLabelSize);
278      cpgmtxt("t",Plot::spTitleOffset3,0.5,0.5,line.c_str());
279    }
280    void  SpectralPlot::fourthHeaderLine(std::string line)
281    {
282      cpgsch(Plot::spLabelSize);
283      cpgmtxt("t",Plot::spTitleOffset4,0.5,0.5,line.c_str());
284    }
285    void  SpectralPlot::goToPlot(){cpgslct(this->identifier);}
286
287    //----------------------------------------------------------
288    //----------------------------------------------------------
289    // ImagePlot functions
290    //----------------------------------------------------------
291
292    ImagePlot::ImagePlot(){
293      this->paperWidth = 7.5;
294      this->maxPaperHeight = 10.;
295      this->marginWidth = 0.8;
296      this->wedgeWidth = 0.7;
297    }
298
299    ImagePlot::~ImagePlot(){}
300
301    ImagePlot::ImagePlot(const ImagePlot& p)
302    {
303      operator=(p);
304    }
305
306    ImagePlot& ImagePlot::operator=(const ImagePlot& p)
307    {
308      if(this==&p) return *this;
309      this->paperWidth = p.paperWidth;   
310      this->maxPaperHeight = p.maxPaperHeight;   
311      this->marginWidth = p.marginWidth;   
312      this->wedgeWidth = p.wedgeWidth;
313      this->imageRatio = p.imageRatio;
314      this->aspectRatio = p.aspectRatio;
315      this->xdim = p.xdim;
316      this->ydim = p.ydim;
317      this->identifier = p.identifier;   
318      return *this;
319    }
320
321    //----------------------------------------------------------
322
323    int ImagePlot::setUpPlot(std::string pgDestination, float x, float y){
324      /**
325       *  Opens a pgplot device and scales it to the correct shape.
326       *  In doing so, the dimensions for the image are set, and the required
327       *   aspect ratios of the image and of the plot are calculated.
328       *  If the resulting image is going to be tall enough to exceed the
329       *   maximum height (given the default width), then scale everything
330       *   down by enough to make the height equal to maxPaperHeight.
331       * \param pgDestination  The string indicating the PGPLOT device to be
332       *   written to.
333       * \param x The length of the X-axis.
334       * \param y The length of the Y-axis.
335       * \return The value returned by mycpgopen: if <= 0, then an error
336       *  has occurred.
337       */
338      this->xdim = x;
339      this->ydim = y;
340      this->imageRatio= this->ydim / this->xdim;
341      this->aspectRatio =  (this->imageRatio*this->imageWidth() + 2*this->marginWidth)
342        / this->paperWidth;
343      float correction;
344      if((this->imageRatio*this->imageWidth() + 2*this->marginWidth) >
345         this->maxPaperHeight){
346        correction = this->maxPaperHeight /
347          (this->imageRatio*this->imageWidth()+2*this->marginWidth);
348        this->paperWidth *= correction;
349        this->marginWidth *= correction;
350        this->wedgeWidth *= correction;
351      }
352      this->identifier = mycpgopen(pgDestination);
353      if(this->identifier>0) cpgpap(this->paperWidth, this->aspectRatio);
354      return this->identifier;
355    }
356    //----------------------------------------------------------
357    void ImagePlot::drawMapBox(float x1, float x2, float y1, float y2,
358                               std::string xlabel, std::string ylabel){
359      /**
360       *  Defines the region that the box containing the map is to go in,
361       *  and draws the box with limits given by the arguments.
362       *  Also writes labels on both X- and Y-axes.
363       * \param x1 Minimum X-axis value.
364       * \param x2 Maximum X-axis value.
365       * \param y1 Minimum Y-axis value.
366       * \param y2 Maximum Y-axis value.
367       * \param xlabel The label to be put on the X-axis.
368       * \param ylabel The label to be put on the Y-axis.
369       */
370      cpgvsiz(this->marginWidth, this->marginWidth + this->imageWidth(),
371              this->marginWidth, this->marginWidth + (this->imageWidth()*this->imageRatio));
372      cpgslw(2);
373      cpgswin(x1,x2,y1,y2);
374      cpgbox("bcst",0.,0,"bcst",0.,0);
375      cpgslw(1);
376      cpgbox("bcnst",0.,0,"bcnst",0.,0);
377      cpglab(xlabel.c_str(), ylabel.c_str(), "");
378    }
379    //----------------------------------------------------------
380    void ImagePlot::makeTitle(std::string title){
381      /**
382       *    Writes the title for the plot, making it centred for the entire
383       *     plot and not just the map.
384       *   \param title String with title for plot.
385       */
386      cpgvstd();
387      cpgmtxt("t", Plot::imTitleOffset, 0.5, 0.5, title.c_str());
388    }
389
390    void  ImagePlot::goToPlot(){cpgslct(this->identifier);}
391
392    float ImagePlot::imageWidth(){
393      return this->paperWidth - 2*this->marginWidth - this->wedgeWidth;
394    }
395
396    float ImagePlot::cmToCoord(float cm){
397      /** \param cm Distance to be converted.*/
398      return (cm/Plot::inchToCm) * this->ydim / (this->imageWidth()*this->imageRatio);
399    }
400
401
402    //----------------------------------------------------------
403    //----------------------------------------------------------
404    // CutoutPlot functions
405    //----------------------------------------------------------
406    //----------------------------------------------------------
407
408    CutoutPlot::CutoutPlot(){
409      this->paperWidth=a4width/inchToCm - 2*psHoffset;
410      this->sourceCount=0;
411      this->numOnPage = 7;
412    }
413
414    CutoutPlot::~CutoutPlot(){}
415
416    CutoutPlot::CutoutPlot(const CutoutPlot& p)
417    {
418      operator=(p);
419    }
420
421    CutoutPlot& CutoutPlot::operator=(const CutoutPlot& p)
422    {
423      if(this==&p) return *this;
424      this->numOnPage = p.numOnPage;
425      this->sourceCount = p.sourceCount; 
426      for(int i=0;i<4;i++) this->mainCoords[i] = p.mainCoords[i];
427      for(int i=0;i<4;i++) this->mapCoords[i] = p.mapCoords[i];
428      this->paperWidth = p.paperWidth;   
429      this->paperHeight = p.paperHeight;   
430      this->identifier = p.identifier;   
431      return *this;
432    }
433
434    //----------------------------------------------------------
435    int CutoutPlot::setUpPlot(std::string pgDestination){
436      /**
437       * Opens the designated pgplot device.  Scales the paper so that
438       * it fits on an A4 sheet (using known values of the default
439       * pgplot offsets). 
440       *
441       * \param pgDestination The std::string indicating the PGPLOT device to
442       * be written to.
443       *
444       * \return The value returned by mycpgopen. If <= 0, then an error
445       * has occurred.
446       */
447      this->paperHeight = this->paperWidth*M_SQRT2;
448      if(this->paperHeight+2*Plot::psVoffset > Plot::a4height){
449        this->paperHeight = Plot::a4height - 2*Plot::psVoffset;
450        this->paperWidth = this->paperHeight / M_SQRT2;
451      }
452      this->identifier = mycpgopen(pgDestination);
453      if(this->identifier>0) cpgpap(this->paperWidth, this->paperHeight/this->paperWidth);
454      // make paper size to fit on A4.
455      return this->identifier;
456    }
457    //----------------------------------------------------------
458    void CutoutPlot::calcCoords(){
459      /**
460       * Calculates the boundaries for the various boxes, in inches measured
461       *  from the lower left corner.
462       * Based on the fact that there are numOnPage spectra shown on each
463       *  page, going down the page in increasing number (given by
464       *  CutoutPlot::spectraCount).
465       */
466      int posOnPage = (this->numOnPage -
467                       (this->sourceCount%this->numOnPage))
468        %this->numOnPage;
469      this->mainCoords[0] = Plot::cuMainX1/inchToCm;
470      this->mainCoords[1] = Plot::cuMainX2/inchToCm;
471      this->mainCoords[2] = this->mapCoords[2] =
472        posOnPage*paperHeight/float(this->numOnPage) + Plot::cuMainY1/inchToCm;
473      this->mainCoords[3] = this->mapCoords[3] =
474        posOnPage*paperHeight/float(this->numOnPage) + Plot::cuMainY2/inchToCm;
475      this->mapCoords[0]  = Plot::cuMapX1/inchToCm;
476      this->mapCoords[1]  = this->mapCoords[0] + (this->mapCoords[3]-this->mapCoords[2]);
477    }
478    //----------------------------------------------------------
479    void CutoutPlot::gotoHeader(){
480      /**
481       * Calls calcCoords, to calculate correct coordinates for this spectrum.
482       * Defines the region for the header information, making it centred
483       *  on the page.
484       * Also writes the velocity (x axis) label, given by the string argument.
485       * \param xlabel Label to go on the velocity/spectral axis.
486       */
487      if(sourceCount%numOnPage==0) cpgpage();
488      sourceCount++;
489      this->calcCoords();
490      //     cpgvsiz(0., this->paperWidth, this->mainCoords[2], this->mainCoords[3]); 
491      cpgvsiz(this->mainCoords[0], this->mainCoords[1],
492              this->mainCoords[2], this->mainCoords[3]); 
493      cpgsch(Plot::spLabelSize);
494      //   cpgmtxt("b",Plot::spXlabelOffset,0.5,0.5,xlabel.c_str());
495      cpgswin(0.,1.,0.,1.);
496      //    cpgbox("bc",0,0,"bc",0,0);
497    }
498    //----------------------------------------------------------
499
500    void CutoutPlot::gotoMap(){
501      cpgvsiz(this->mapCoords[0],this->mapCoords[1],
502              this->mapCoords[2],this->mapCoords[3]);
503      cpgsch(Plot::spIndexSize);
504    }
505    //----------------------------------------------------------
506    // CutoutPlot functions...
507    //----------------------------------------------------------
508    void  CutoutPlot::firstHeaderLine(std::string line)
509    {
510      cpgsch(Plot::spTitleSize);
511      //     cpgmtxt("t",Plot::spTitleOffset1*Plot::spLabelSize/Plot::spTitleSize,
512      //            0.5,0.5,line.c_str());
513      cpgptxt(0.5,0.8,0.,0.5,line.c_str());
514    }
515    void  CutoutPlot::secondHeaderLine(std::string line)
516    {
517      cpgsch(Plot::spLabelSize);
518      //    cpgmtxt("t",Plot::spTitleOffset2,0.5,0.5,line.c_str());
519      cpgptxt(0.5,0.6,0.,0.5,line.c_str());
520    }
521    void  CutoutPlot::thirdHeaderLine(std::string line)
522    {
523      cpgsch(Plot::spLabelSize);
524      //    cpgmtxt("t",Plot::spTitleOffset3,0.5,0.5,line.c_str());
525      cpgptxt(0.5,0.4,0.,0.5,line.c_str());
526    }
527    void  CutoutPlot::fourthHeaderLine(std::string line)
528    {
529      cpgsch(Plot::spLabelSize);
530      //    cpgmtxt("t",Plot::spTitleOffset4,0.5,0.5,line.c_str());
531      cpgptxt(0.5,0.2,0.,0.5,line.c_str());
532    }
533    void  CutoutPlot::goToPlot(){cpgslct(this->identifier);}
534
535  }
536
537}
Note: See TracBrowser for help on using the repository browser.