source: tags/release-1.0.5/src/Utils/pgplot_related.c @ 1455

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

Minor edits, mostly to get pedantic compilation working.
Added an if clause to getImage, so that the spectral axis setup is not done
if we are examining a 2D image.

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