source: tags/release-1.0.5/src/Cubes/plots.hh @ 1455

Last change on this file since 1455 was 147, checked in by Matthew Whiting, 18 years ago

Minor bugfix for spectral plotting. When the spectral axis passed zero, the
tick marks were generating very large plots (due to lots of ticks being drawn
in the same place). This has been fixed with more robust code.

File size: 12.3 KB
Line 
1#ifndef PLOTS_H
2#define PLOTS_H
3
4#include <iostream>
5#include <sstream>
6#include <string>
7#include <math.h>
8#include <cpgplot.h>
9#include <Utils/mycpgplot.hh>
10
11using std::string;
12using std::stringstream;
13using namespace mycpgplot;
14
15namespace Plot
16{
17  const float inchToCm=2.54; // Conversion factor from inches to centimetres.
18  const float a4width=21.0;  // A4 width in cm
19  const float a4height=29.7; // A4 height in cm
20  const float psHoffset=0.35; // The default pgplot offset applied to ps files
21  const float psVoffset=0.25; // The default pgplot offset applied to ps files
22
23
24  //***************************************************************************
25
26  class SpectralPlot
27  {
28    /**
29     *  SpectralPlot class
30     *    A class to hold the dimensions and set up for the plotting of the
31     *     spectra (including the full spectra, the zoomed in part, and the
32     *     moment map).
33     *    The physical dimensions (in inches) of the plot and the elements
34     *     within it are stored, on the assumption that the plot will go on
35     *     an A4 page.
36     *    Simple accessor functions are provided to enable access to quantities
37     *     needed for pgplot routines.
38     */
39  public:
40    SpectralPlot(){
41      paperWidth=a4width/inchToCm - 2*psHoffset;
42      spectraCount=0;
43      numOnPage = 5;
44      indexSize = 0.6;
45      labelSize = 0.7;
46    };
47    ~SpectralPlot(){};
48
49    int setUpPlot(string pgDestination){
50      /** SpectralPlot::setUpPlot
51       *    Opens the designated pgplot device.
52       *    Scales the paper so that it fits on an A4 sheet (using known
53       *     values of the default pgplot offsets).
54       *    Returns the value returned by cpgopen --
55       *                      if <= 0, then an error has occurred.
56       */
57      paperHeight = paperWidth*M_SQRT2;
58      if(paperHeight+2*psVoffset > a4height){
59        paperHeight = a4height - 2*psVoffset;
60        paperWidth = paperHeight / M_SQRT2;
61      }
62      int flag = cpgopen(pgDestination.c_str());
63      if(flag>0) cpgpap(paperWidth, paperHeight/paperWidth);
64                 // make paper size to fit on A4.
65      return flag;
66    }
67
68    void calcCoords(){
69      /** SpectralPlot::calcCoords()
70       *    Calculates the boundaries for the various boxes, in inches measured
71       *     from the lower left corner.
72       *    Based on the fact that there are numOnPage spectra shown on each
73       *     page, going down the page in increasing number
74       *           -- given by spectraCount.
75       */
76      int posOnPage = (numOnPage - (spectraCount%numOnPage))%numOnPage;
77      mainCoords[0] = 2.0/inchToCm;
78      mainCoords[1] = 13.7/inchToCm;
79      zoomCoords[0] = 15.0/inchToCm;
80      zoomCoords[1] = 16.8/inchToCm;
81      mainCoords[2] = zoomCoords[2] = mapCoords[2] =
82        posOnPage*paperHeight/float(numOnPage) + 1.8/inchToCm;
83      mainCoords[3] = zoomCoords[3] = mapCoords[3] =
84        posOnPage*paperHeight/float(numOnPage) + 3.8/inchToCm;
85      mapCoords[0]  = 17.0/inchToCm;
86      mapCoords[1]  = mapCoords[0] + (mapCoords[3]-mapCoords[2]);
87   }
88
89    void gotoHeader(string xlabel){
90      /** SpectralPlot::gotoHeader(string)
91       *   Calls calcCoords, to calculate correct coordinates for this
92       *    spectrum.
93       *   Defines the region for the header information, making it centred
94       *    on the page.
95       *   Also writes the velocity (x axis) label, given by the string
96       *    argument.
97       */
98      if(spectraCount%numOnPage==0) cpgpage();
99      spectraCount++;
100      calcCoords();
101      cpgvsiz(0., paperWidth, mainCoords[2], mainCoords[3]); 
102      cpgsch(labelSize);
103      cpgmtxt("b",3.,0.5,0.5,xlabel.c_str());
104    }
105
106    /**
107     * Header line functions
108     *  Functions to write the header information above the boxes.
109     *  One for each line (position/velocity, widths & fluxes, pixel coords).
110     */
111    void firstHeaderLine(string line){cpgmtxt("t",3.8,0.5,0.5,line.c_str());};
112    void secondHeaderLine(string line){cpgmtxt("t",2.3,0.5,0.5,line.c_str());};
113    void thirdHeaderLine(string line){cpgmtxt("t",0.8,0.5,0.5,line.c_str());};
114
115    void gotoMainSpectrum(float x1, float x2, float y1, float y2,
116                          string ylabel){
117      /** SpectralPlot::gotoMainSpectrum()
118       *   Defines the region for the main spectrum.
119       *   Draws the box, with tick marks, and
120       *    writes the flux (y axis) label, given by the string argument.
121       */
122      cpgvsiz(mainCoords[0],mainCoords[1],mainCoords[2],mainCoords[3]);
123      cpgsch(indexSize);
124      cpgswin(x1,x2,y1,y2);
125      cpgbox("1bcnst",0.,0,"bcnst1v",0.,0);
126      cpgsch(labelSize);
127      cpgmtxt("l",4.,0.5,0.5,ylabel.c_str());
128    }
129
130    void gotoZoomSpectrum(float x1, float x2, float y1, float y2){
131      /** SpectralPlot::gotoZoomSpectrum()
132       *   Defines the region for the zoomed-in part of the spectrum.
133       *   Draws the box, with special tick marks on the bottom axis.
134       */
135      cpgvsiz(zoomCoords[0],zoomCoords[1],zoomCoords[2],zoomCoords[3]);
136      cpgsch(indexSize);
137      cpgswin(x1,x2,y1,y2);
138      cpgbox("bc",0.,0,"bcstn1v",0.,0);
139      float lengthL,lengthR,disp,tickpt,step;
140      stringstream label;
141      for(int i=1;i<10;i++){
142        tickpt = x1+(x2-x1)*float(i)/10.;  // spectral coord of the tick
143        switch(i)
144          {
145          case 2:
146          case 8:
147            lengthL = lengthR = 0.5;
148            disp = 0.3 + float(i-2)/6.; // i==2 --> disp=0.3, i==8 --> disp=1.3
149            label.str("");
150            label << tickpt;
151            // do a labelled tick mark
152            cpgtick(x1,y1,x2,y1,float(i)/10.,lengthL,lengthR,
153                    disp, 0., label.str().c_str());
154            break;
155          default:
156            label.str("");
157            lengthL = 0.25;
158            lengthR = 0.;
159            disp = 0.;  // not used in this case, but set it anyway.
160            break;
161          }
162        // first the bottom axis, just the ticks
163        if(fabs(tickpt)<(x2-x1)/1.e4) step = 2.*(x2-x1);
164        else step = tickpt;
165        cpgaxis("",
166                tickpt-0.001*(x2-x1), y1,
167                tickpt+0.001*(x2-x1), y1,
168                tickpt-0.001*(x2-x1), tickpt+0.001*(x2-x1),
169                step, -1, lengthL,lengthR, 0.5, disp, 0.);
170        //and now the top -- no labels, just tick marks
171        cpgtick(x1,y2,x2,y2,float(i)/10.,lengthL,lengthR,0.,0.,"");
172      }
173   }
174   
175    void gotoMap(){
176      /** SpectralPlot::gotoMap()
177       *   Defines the region for the moment map.
178       */
179      cpgvsiz(mapCoords[0],mapCoords[1],mapCoords[2],mapCoords[3]);
180      cpgsch(indexSize);
181    }
182
183    void drawVelRange(float v1, float v2){
184      /** SpectralPlot::drawVelRange(float v1, float v2)
185       *   Draws two vertical lines at the limits of velocity
186       *    given by the arguments.
187       */
188      int ci,ls;
189      float dud,min,max;
190      cpgqwin(&dud,&dud,&min,&max);
191      cpgqci(&ci);
192      cpgqls(&ls);
193      cpgsci(BLUE);
194      cpgsls(DASHED);
195      cpgmove(v1,min);  cpgdraw(v1,max);
196      cpgmove(v2,min);  cpgdraw(v2,max);
197      cpgsci(ci);
198      cpgsls(ls);
199    }
200   
201    void drawMWRange(float v1, float v2){
202      /** SpectralPlot::drawMWRange(float v1, float v2)
203       *   Draws a box showing the extent of channels masked by the
204       *     Milky Way parameters
205       */
206      int ci,fs;
207      float dud,min,max,height;
208      cpgqwin(&dud,&dud,&min,&max);
209      height = max-min;
210      max += 0.01*height;
211      min -= 0.01*height;
212      cpgqci(&ci);
213      cpgqfs(&fs);
214      setDarkGreen();
215      cpgsci(DARKGREEN);
216      cpgsfs(HATCHED);
217      cpgrect(v1,v2,min,max);
218      cpgsfs(OUTLINE);
219      cpgrect(v1,v2,min,max);
220      cpgsci(ci);
221      cpgsfs(fs);
222    }
223   
224    int   getNumOnPage(){return numOnPage;};
225    void  setNumOnPage(int i){numOnPage=i;};
226    float getPaperWidth(){return paperWidth;};
227    void  setPaperWidth(float f){paperWidth=f;};
228    float getPaperHeight(){return paperHeight;};
229    void  setPaperHeight(float f){paperHeight=f;};
230
231  private:
232    int numOnPage;       // Number of spectra to put on one page.
233    int spectraCount;    // Number of spectra done so far: where on the page?
234    float mainCoords[4]; // Boundaries for the main spectrum [inches]
235    float zoomCoords[4]; // Boundaries for the zoomed-in spectrum [inches]
236    float mapCoords[4];  // Boundaries for the map box [inches]
237    float paperWidth;    // Width of plottable region of the paper [inches]
238    float paperHeight;   // Height of plottable region of the paper [inches]
239    float indexSize;     // PGPlot character height for tick mark labels
240    float labelSize;     // PGPlot character height for axis labels.
241   
242  };
243
244  //***************************************************************************
245
246  class ImagePlot
247  {
248    /**
249     *  ImagePlot class
250     *    A class to hold the dimensions and set up for the plots used by the
251     *     two functions below.
252     *    The physical dimensions (in inches) of the plot and the elements
253     *     within it are stored, including maximum widths and heights
254     *     (so that the plot will fit on an A4 page).
255     *    Simple accessor functions are provided to enable access to quantities
256     *     needed for pgplot routines.
257     */
258  public:
259    ImagePlot(){
260      paperWidth = 7.5; maxPaperHeight = 10.;
261      marginWidth = 0.8; wedgeWidth = 0.7;
262    };
263    ~ImagePlot(){};
264 
265    int  setUpPlot(string pgDestination, float x, float y){
266      /**
267       * setUpPlot(string pgDestination, float x, float y)
268       *  Opens a pgplot device and scales it to the correct shape.
269       *  In doing so, the dimensions for the image are set, and the required
270       *   aspect ratios of the image and of the plot are calculated.
271       *  If the resulting image is going to be tall enough to exceed the
272       *   maximum height (given the default width), then scale everything
273       *   down by enough to make the height equal to maxPaperHeight.
274       *  Returns the value returned by cpgopen --
275       *             if <= 0, then an error has occurred.
276       */
277      xdim = x;
278      ydim = y;
279      imageRatio= ydim / xdim;
280      aspectRatio =  (imageRatio*imageWidth() + 2*marginWidth) / paperWidth;
281      float correction;
282      if((imageRatio*imageWidth() + 2*marginWidth) > maxPaperHeight){
283        correction = maxPaperHeight / (imageRatio*imageWidth()+2*marginWidth);
284        paperWidth *= correction;
285        marginWidth *= correction;
286        wedgeWidth *= correction;
287      }
288      int flag = cpgopen(pgDestination.c_str());
289      if(flag>0) cpgpap(paperWidth, aspectRatio);
290      return flag;
291    }
292
293    void  drawMapBox(float x1, float x2, float y1, float y2,
294                     string xlabel, string ylabel){
295      /**
296       * drawMapBox()
297       *  Defines the region that the box containing the map is to go in,
298       *  and draws the box with limits given by the arguments.
299       *  The labels for the x and y axes are also given as arguments.
300       */
301      cpgvsiz(marginWidth, marginWidth + imageWidth(),
302              marginWidth, marginWidth + (imageWidth()*imageRatio));
303      cpgslw(2);
304      cpgswin(x1,x2,y1,y2);
305      cpgbox("bcst",0.,0,"bcst",0.,0);
306      cpgslw(1);
307      cpgbox("bcnst",0.,0,"bcnst",0.,0);
308      cpglab(xlabel.c_str(), ylabel.c_str(), "");
309    }
310    void  makeTitle(string title){
311      /**
312       *  makeTitle(string)
313       *    Writes the title for the plot, making it centred for the entire
314       *     plot and not just the map.
315       */
316      cpgvstd();
317      cpgmtxt("t", 2.7, 0.5, 0.5, title.c_str());
318    }
319
320    float imageWidth(){
321      /**
322       * imageWidth()
323       *   Returns the calculated total width of the image part of the
324       *    plot [inches]
325       */
326      return paperWidth - 2*marginWidth - wedgeWidth;
327    };       
328
329    float cmToCoord(float cm){return (cm/inchToCm) * ydim /
330                                (imageWidth()*imageRatio);};
331    float getMargin()     {return marginWidth;};
332    float getPaperWidth() {return paperWidth;};
333    float getImageHeight(){return imageWidth()*imageRatio;};
334    float getAspectRatio(){return aspectRatio;};
335
336
337  private:
338    float paperWidth;     // Default (maximum) width of "paper" [inches]
339    float maxPaperHeight; // Maximum allowed height of paper [inches]
340    float marginWidth;    // Width allowed for margins around main plot
341                          //   (ie. label & numbers) [inches]
342    float wedgeWidth;     // Width allowed for placement of wedge on
343                          //   right-hand side of plot. [inches]
344    float imageRatio;     // Aspect ratio of the image only
345                          //   (ie. y-value range / x-value range).
346    float aspectRatio;    // Aspect ratio of whole plot.
347    float xdim;           // Width of main plot, in display units.
348    float ydim;           // Height of main plot, in display units.
349  };
350
351}
352
353#endif
354
Note: See TracBrowser for help on using the repository browser.