source: trunk/src/Utils/pgplot_related.c @ 208

Last change on this file since 208 was 201, checked in by Matthew Whiting, 18 years ago
  • New functionality added: ability to smooth a cube (in each individual spectrum) using a hanning filter before searching.
  • This comes with associated input parameters: flagSmooth and hanningWidth.
  • Hanning smoothing implemented via a new class that does the smoothing
  • Other minor changes:
    • changed the way getIAUName is called.
    • new colour names in mycpgplot
    • a << operator for the StatsContainer? class
    • more robust ProgressBar? functions
    • updated the Makefile.in
File size: 10.9 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <cpgplot.h>
4#include <math.h>
5#include <string.h>
6#include <ctype.h>
7
8#define WDGPIX 100  /* used by cpgwedglog
9                       --> number of increments in the wedge. */
10
11/**
12 *  This file contains the following programs, all in C code:
13 *
14 *   int cpgtest() --> a front-end to cpgqinf, to test whether a pgplot
15 *                     device is currently open.
16 *   void cpgwedglog(const char* side, float disp, float width,
17 *                   float fg, float bg, const char *label)
18 *                 --> a C-code version of pgwedg, plotting the wedge
19 *                     scale in logarithmic units.
20 *   void cpgcumul(int npts, float *data, float datamin, float datamax,
21 *                        int pgflag)
22 *                 --> a new pgplot routine that draws a cumulative
23 *                     distribution. Uses _swap and _sort.
24 *   void cpghistlog(npts, data, datamin, datamax, nbin, pgflag)
25 *                 --> as for cpghist, with the y-axis on a logarithmic scale.
26 *
27 */
28
29
30/********************************************************************/
31/*   CPGTEST
32/********************************************************************/
33
34int cpgtest()
35{
36  /**
37   *  cpgtest
38   *     A front-end to cpgqinf, to test whether a pgplot device is
39   *     currently open. Returns 1 if there is, else 0.
40   */
41  char answer[10];                 /* The PGQINF return string */
42  int answer_len = sizeof(answer); /* allocated size of answer[] */
43  cpgqinf("STATE", answer, &answer_len);
44  return strcmp(answer, "OPEN") == 0;
45}
46
47/********************************************************************/
48/*   CPGTYPE
49/********************************************************************/
50
51int cpgIsPS()
52{
53  /**
54   *  cpgIsPS
55   *     A front-end to cpgqinf, that tests whether the device is using a
56   *     postscript (by which we mean "hardcopy") device
57   */
58  char answer[50];
59  int answer_len = sizeof(answer);
60  cpgqinf("TYPE", answer, &answer_len);
61  return ((answer[answer_len-2]=='P')&&((answer[answer_len-1]=='S')));
62}
63
64/********************************************************************/
65/*   CPGWEDGLOG
66/********************************************************************/
67
68void cpgwedglog(const char* side, float disp, float width, float fg, float bg,
69                const char *label)
70{
71  /**
72   *  cpgwedglog
73   *     A C-code version of PGWEDG that writes the scale of the wedge in
74   *      logarithmic coordinates. All parameters are exactly as for cpgwedg.
75   */
76 
77  float wxa,wxb,wya,wyb, xa,xb,ya,yb; /* Temporary window coord storage.*/
78  float vxa,vxb,vya,vyb;              /* Viewport coords of wedge. */
79  float oldch, newch;                 /* Original and annotation character
80                                         heights. */
81  float ndcsiz;                       /* Size of unit character height
82                                         (NDC units). */
83  int horiz;                          /* Logical: True (=1) if wedge plotted
84                                         horizontally. */
85  int image;                          /* Logical: Use PGIMAG (T=1) or
86                                         PGGRAY (F=0). */
87
88  int nside,i;                        /* nside = symbolic version of side. */
89  const int bot=1,top=2,lft=3,rgt=4;
90  float wedwid, wdginc, vwidth, vdisp, xch, ych, labwid, fg1, bg1;
91  float txtfrc=0.6;                   /* Set the fraction of WIDTH used
92                                             for anotation. */
93  float txtsep=2.2;                   /* Char separation between numbers
94                                             and LABEL. */
95  float wdgarr[WDGPIX];               /* Array to draw wedge in. */
96  float tr[6] = {0.0,1.0,0.0,0.0,0.0,1.0};
97
98/*   if(pgnoto("pgwedg")) return; */
99
100  /* Get a numeric version of SIDE. */
101  if(tolower(side[0])=='b'){
102    nside = bot;
103    horiz = 1;
104  }
105  else if(tolower(side[0]=='t')){
106    nside = top;
107    horiz = 1;
108  }
109  else if(tolower(side[0]=='l')){
110    nside = lft;
111    horiz = 0;
112  }
113  else if(tolower(side[0]=='r')){
114    nside = rgt;
115    horiz = 0;
116  }
117  /*   else gwarn("Invalid \"SIDE\" argument in PGWEDG.");  */
118  else fprintf(stdout,"%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
119
120  /* Determine which routine to use. */
121  if(strlen(side)<2) image = 0;
122  else if(tolower(side[1])=='i') image = 1;
123  else if(tolower(side[1])=='g') image = 0;
124  else fprintf(stdout,"%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
125
126  cpgbbuf();
127
128  /* Store the current world and viewport coords and the character height. */
129  cpgqwin(&wxa, &wxb, &wya, &wyb);
130  cpgqvp(0, &xa, &xb, &ya, &yb);
131  cpgqch(&oldch);
132
133  /* Determine the unit character height in NDC coords. */
134  cpgsch(1.0);
135  cpgqcs(0, &xch, &ych);
136  if(horiz == 1)  ndcsiz = ych;
137  else ndcsiz = xch;
138
139  /* Convert 'WIDTH' and 'DISP' into viewport units. */
140  vwidth = width * ndcsiz * oldch;
141  vdisp  = disp * ndcsiz * oldch;
142
143  /* Determine the number of character heights required under the wedge. */
144  labwid = txtsep;
145  if(strcmp(label," ")!=0) labwid = labwid + 1.0;
146 
147  /* Determine and set the character height required to fit the wedge
148     anotation text within the area allowed for it. */
149  newch = txtfrc*vwidth / (labwid*ndcsiz);
150  cpgsch(newch);
151
152  /* Determine the width of the wedge part of the plot minus the anotation.
153     (NDC units). */
154  wedwid = vwidth * (1.0-txtfrc);
155
156  /* Use these to determine viewport coordinates for the wedge + annotation.*/
157  vxa = xa;
158  vxb = xb;
159  vya = ya;
160  vyb = yb;
161  if(nside==bot){
162    vyb = ya - vdisp;
163    vya = vyb - wedwid;
164  }
165  else if(nside==top) {
166    vya = yb + vdisp;
167    vyb = vya + wedwid;
168  }
169  else if(nside==lft) {
170    vxb = xa - vdisp;
171    vxa = vxb - wedwid;
172  }
173  else if(nside==rgt) {
174    vxa = xb + vdisp;
175    vxb = vxa + wedwid;
176  }
177
178  /* Set the viewport for the wedge. */
179  cpgsvp(vxa, vxb, vya, vyb);
180
181  /* Swap FG/BG if necessary to get axis direction right. */
182/*   fg1 = max(fg,bg); */
183/*   bg1 = min(fg,bg); */
184  if(fg>bg) {
185    fg1 = fg;
186    bg1 = bg;
187  }
188  else {
189    fg1 = bg;
190    bg1 = fg;
191  }
192
193
194  /* Create a dummy wedge array to be plotted. */
195  wdginc = (fg1-bg1)/(WDGPIX-1);
196  for(i=0;i<WDGPIX;i++)  wdgarr[i] = bg1 + (i-1) * wdginc;
197
198  /* Draw the wedge then change the world coordinates for labelling. */
199  if (horiz==1) {
200    cpgswin(1.0, (float)WDGPIX, 0.9, 1.1);
201    if (image==1) cpgimag(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
202    else          cpggray(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
203    cpgswin(bg1,fg1,0.0,1.0);
204  }
205  else{
206    cpgswin(0.9, 1.1, 1.0, (float)WDGPIX);
207    if (image==1) cpgimag(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
208    else          cpggray(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
209    cpgswin(0.0, 1.0, bg1, fg1);
210  }
211
212  /* Draw a labelled frame around the wedge -- using a logarithmic scale! */
213  if(nside==bot)  cpgbox("BCNSTL",0.0,0,"BC",0.0,0);
214  else if(nside==top) cpgbox("BCMSTL",0.0,0,"BC",0.0,0);
215  else if(nside==lft) cpgbox("BC",0.0,0,"BCNSTL",0.0,0);
216  else if(nside==rgt) cpgbox("BC",0.0,0,"BCMSTL",0.0,0);
217
218  /* Write the units label. */
219  if((strcmp(label," ")!=0)) cpgmtxt(side,txtsep,1.0,1.0,label);
220
221  /* Reset the original viewport and world coordinates. */
222  cpgsvp(xa,xb,ya,yb);
223  cpgswin(wxa,wxb,wya,wyb);
224  cpgsch(oldch);
225  cpgebuf();
226
227}
228
229
230/********************************************************************/
231/*   CPGCUMUL
232/********************************************************************/
233
234void _swap(float *a, float *b)
235{
236  float t;
237  t=*a; *a=*b; *b=t;
238}
239
240void _sort(float *array, int begin, int end)
241{
242  float pivot = array[begin];
243  int i = begin + 1, j = end, k = end;
244  float t;
245
246  while (i < j) {
247    if (array[i] < pivot) i++;
248    else if (array[i] > pivot) {
249      j--; k--;
250      t = array[i];
251      array[i] = array[j];
252      array[j] = array[k];
253      array[k] = t; }
254    else {
255      j--;
256      _swap(&array[i], &array[j]);
257    }  }
258  i--;
259  _swap(&array[begin], &array[i]);       
260  if (i - begin > 1)
261    _sort(array, begin, i);
262  if (end - k   > 1)
263    _sort(array, k, end);                     
264}
265
266
267void cpgcumul(int npts, float *data, float datamin, float datamax, int pgflag)
268{
269  /**
270   *  cpgcumul(npts, data, datamin, datamax, pgflag)
271   *    A new pgplot routine that draws a cumulative distribution.
272   *   The use of pgflag is similar to cpghist & cpghist_log:
273   *    0 --> draw a new graph using cpgenv, going from 0 to 1 on the y-axis.
274   *    2 --> draw the plot on the current graph, without re-drawing any axes.
275   */
276
277  int i;
278  float *sorted;
279  float MINCOUNT=0.;
280
281  sorted = (float *)calloc(npts,sizeof(float));
282  for(i=0;i<npts;i++) sorted[i] = data[i];
283  _sort(sorted,0,npts);
284
285  cpgbbuf();
286
287  /* DEFINE ENVIRONMENT IF NECESSARY */
288  if(pgflag == 0) cpgenv(datamin,datamax,MINCOUNT,1.0001,0,0);
289  if(pgflag == 2) cpgswin(datamin,datamax,MINCOUNT,1.);
290
291  /* DRAW LINE */
292  cpgmove(datamin,MINCOUNT);
293  for(i=0;i<npts;i++) cpgdraw(sorted[i],(float)(i+1)/(float)(npts));
294  cpgdraw(datamax,1.);
295
296  cpgebuf();
297 
298  free(sorted);
299
300}
301
302/********************************************************************/
303/*   CPGHISTLOG
304/********************************************************************/
305
306void cpghistlog(int npts, float *data, float datamin, float datamax, int nbin,
307                int pgflag)
308{
309  /**
310   * cpghistlog(npts, data, datamin, datamax, nbin, pgflag)
311   *
312   *  Works exactly as for cpghist, except the y-axis is a logarithmic scale.
313   *
314   */
315
316
317  int i,bin;
318  float *num;
319  float maxNum,binSize,x1,x2,y1,y2,older,newer,fraction;
320  float MINCOUNT=-0.2;
321
322  num = (float *)calloc(nbin,sizeof(float));
323
324  cpgbbuf();
325
326  /* HOW MANY VALUES IN EACH BIN? */
327  for(i=0; i<npts; i++){
328    fraction = (data[i] - datamin) / (datamax - datamin);
329    bin = (int)( floor(fraction*nbin) );
330    if((bin>=0)&&(bin<nbin)) num[bin]+=1.;
331  }
332  for(i=0; i<nbin;i++){
333    if(num[i]>0) num[i] = log10(num[i]);
334    else num[i] = MINCOUNT;
335  }
336  maxNum = num[0];
337  for(i=1; i<nbin; i++) if(num[i]>maxNum) maxNum = num[i];
338  binSize = (datamax - datamin) / (float)nbin;
339
340  /* BOUNDARIES OF PLOT */
341  x1 = datamin;
342  x2 = datamax;
343  y1 = MINCOUNT;
344  y2 = ceil(maxNum);
345
346  /* DEFINE ENVIRONMENT IF NECESSARY */
347  if(pgflag%2 == 0) cpgenv(x1,x2,y1,y2,0,20);
348
349  /* DRAW HISTOGRAM */
350  if(pgflag/2 == 0){
351    older = 0.;
352    x2 = datamin;
353    cpgmove(datamin,MINCOUNT);
354    for(i=0;i<nbin;i++){
355      newer = num[i];
356      x1 = x2;
357      x2 = datamin + i*binSize;
358      if(newer!=MINCOUNT){
359        if(newer<=older){
360          cpgmove(x1,newer);
361          cpgdraw(x2,newer);
362        }
363        else{
364          cpgmove(x1,older);
365          cpgdraw(x1,newer);
366          cpgdraw(x2,newer);
367        }
368      }
369      cpgdraw(x2,MINCOUNT);
370      older=newer;
371    }
372  }
373  else if(pgflag/2 == 1){
374    older = MINCOUNT;
375    x2 = datamin;
376    for(i=0;i<nbin;i++){
377      newer = num[i];
378      x1 = x2;
379      x2 = datamin + i*binSize;
380      if(newer!=MINCOUNT) cpgrect(x1,x2,0.,newer);     
381    }
382  }
383  else if(pgflag/2 == 2){
384    older = 0.;
385    cpgmove(datamin,MINCOUNT);
386    x2 = datamin;
387    for(i=0;i<nbin;i++){
388      newer = num[i];
389      x1 = x2;
390      x2 = datamin + i*binSize;
391      if((newer==MINCOUNT)&&(older==MINCOUNT)) cpgmove(x2,MINCOUNT);
392      else {
393        cpgdraw(x1,newer);
394        if(newer==MINCOUNT) cpgmove(x2,newer);
395        else cpgdraw(x2,newer);
396      }
397      older = newer;
398    }
399  }
400
401  cpgebuf();
402   
403}
404
Note: See TracBrowser for help on using the repository browser.