source: trunk/src/Cubes/plots.hh @ 203

Last change on this file since 203 was 203, checked in by Matthew Whiting, 18 years ago
  • Explicitly defined the various template options for StatsContainer::madfmToSigma.
  • Added a new way to do the momentmap plots : plotMomentMap can now take a vector<string> as its argument, so that multiple plots can be written while only calculating the array values once. This speeds up this part of the program.
  • This mean some changes to the plots.hh file, so that we store the identifier for each plot/device, and have a new function that is a front-end to cpgslct.
  • More flexibility in the drawScale function, so that finer-scale images can be dealt with.
File size: 12.7 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      identifier = cpgopen(pgDestination.c_str());
63      if(identifier>0) cpgpap(paperWidth, paperHeight/paperWidth);
64                 // make paper size to fit on A4.
65      return identifier;
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    void  goToPlot(){cpgslct(identifier);}; // goes to the plot when more
231                                            //  than one are open
232
233  private:
234    int numOnPage;       // Number of spectra to put on one page.
235    int spectraCount;    // Number of spectra done so far: where on the page?
236    float mainCoords[4]; // Boundaries for the main spectrum [inches]
237    float zoomCoords[4]; // Boundaries for the zoomed-in spectrum [inches]
238    float mapCoords[4];  // Boundaries for the map box [inches]
239    float paperWidth;    // Width of plottable region of the paper [inches]
240    float paperHeight;   // Height of plottable region of the paper [inches]
241    float indexSize;     // PGPlot character height for tick mark labels
242    float labelSize;     // PGPlot character height for axis labels.
243    int   identifier;    // The identifier code used by cpgslct.
244   
245  };
246
247  //***************************************************************************
248
249  class ImagePlot
250  {
251    /**
252     *  ImagePlot class
253     *    A class to hold the dimensions and set up for the plots used by the
254     *     two functions below.
255     *    The physical dimensions (in inches) of the plot and the elements
256     *     within it are stored, including maximum widths and heights
257     *     (so that the plot will fit on an A4 page).
258     *    Simple accessor functions are provided to enable access to quantities
259     *     needed for pgplot routines.
260     */
261  public:
262    ImagePlot(){
263      paperWidth = 7.5; maxPaperHeight = 10.;
264      marginWidth = 0.8; wedgeWidth = 0.7;
265    };
266    ~ImagePlot(){};
267 
268    int  setUpPlot(string pgDestination, float x, float y){
269      /**
270       * setUpPlot(string pgDestination, float x, float y)
271       *  Opens a pgplot device and scales it to the correct shape.
272       *  In doing so, the dimensions for the image are set, and the required
273       *   aspect ratios of the image and of the plot are calculated.
274       *  If the resulting image is going to be tall enough to exceed the
275       *   maximum height (given the default width), then scale everything
276       *   down by enough to make the height equal to maxPaperHeight.
277       *  Returns the value returned by cpgopen --
278       *             if <= 0, then an error has occurred.
279       */
280      xdim = x;
281      ydim = y;
282      imageRatio= ydim / xdim;
283      aspectRatio =  (imageRatio*imageWidth() + 2*marginWidth) / paperWidth;
284      float correction;
285      if((imageRatio*imageWidth() + 2*marginWidth) > maxPaperHeight){
286        correction = maxPaperHeight / (imageRatio*imageWidth()+2*marginWidth);
287        paperWidth *= correction;
288        marginWidth *= correction;
289        wedgeWidth *= correction;
290      }
291      identifier = cpgopen(pgDestination.c_str());
292      if(identifier>0) cpgpap(paperWidth, aspectRatio);
293      return identifier;
294    }
295
296    void  drawMapBox(float x1, float x2, float y1, float y2,
297                     string xlabel, string ylabel){
298      /**
299       * drawMapBox()
300       *  Defines the region that the box containing the map is to go in,
301       *  and draws the box with limits given by the arguments.
302       *  The labels for the x and y axes are also given as arguments.
303       */
304      cpgvsiz(marginWidth, marginWidth + imageWidth(),
305              marginWidth, marginWidth + (imageWidth()*imageRatio));
306      cpgslw(2);
307      cpgswin(x1,x2,y1,y2);
308      cpgbox("bcst",0.,0,"bcst",0.,0);
309      cpgslw(1);
310      cpgbox("bcnst",0.,0,"bcnst",0.,0);
311      cpglab(xlabel.c_str(), ylabel.c_str(), "");
312    }
313    void  makeTitle(string title){
314      /**
315       *  makeTitle(string)
316       *    Writes the title for the plot, making it centred for the entire
317       *     plot and not just the map.
318       */
319      cpgvstd();
320      cpgmtxt("t", 2.7, 0.5, 0.5, title.c_str());
321    }
322
323    float imageWidth(){
324      /**
325       * imageWidth()
326       *   Returns the calculated total width of the image part of the
327       *    plot [inches]
328       */
329      return paperWidth - 2*marginWidth - wedgeWidth;
330    };       
331
332    float cmToCoord(float cm){return (cm/inchToCm) * ydim /
333                                (imageWidth()*imageRatio);};
334    float getMargin()     {return marginWidth;};
335    float getPaperWidth() {return paperWidth;};
336    float getImageHeight(){return imageWidth()*imageRatio;};
337    float getAspectRatio(){return aspectRatio;};
338    void  goToPlot(){cpgslct(identifier);}; // goes to the plot when more
339                                            //  than one are open
340
341  private:
342    float paperWidth;     // Default (maximum) width of "paper" [inches]
343    float maxPaperHeight; // Maximum allowed height of paper [inches]
344    float marginWidth;    // Width allowed for margins around main plot
345                          //   (ie. label & numbers) [inches]
346    float wedgeWidth;     // Width allowed for placement of wedge on
347                          //   right-hand side of plot. [inches]
348    float imageRatio;     // Aspect ratio of the image only
349                          //   (ie. y-value range / x-value range).
350    float aspectRatio;    // Aspect ratio of whole plot.
351    float xdim;           // Width of main plot, in display units.
352    float ydim;           // Height of main plot, in display units.
353    int   identifier;     // The identifier code used by cpgslct.
354  };
355
356}
357
358#endif
359
Note: See TracBrowser for help on using the repository browser.