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

Last change on this file since 321 was 321, checked in by MatthewWhiting, 17 years ago
  • Solved most of the problem from ticket #12, where the integrated flux was being calculated differently on different machines. Now casting the spatial size of a detection to a double.
  • Solved ticket #13 as well, to allow compilation when PGPLOT is not available. Included moving cpgIsPS() to mycpgplot.cc.
File size: 14.6 KB
Line 
1/*
2// -----------------------------------------------------------------------
3// pgplot_related.c: New functions for use with PGPLOT.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29*/
30#include <stdio.h>
31#include <stdlib.h>
32#include <cpgplot.h>
33#include <math.h>
34#include <string.h>
35#include <ctype.h>
36
37#define WDGPIX 100  /* used by cpgwedglog
38                       --> number of increments in the wedge. */
39
40/*
41 This file contains the following programs, all in C code:
42
43  int cpgtest() --> a front-end to cpgqinf, to test whether a pgplot
44                    device is currently open.
45  void cpgwedglog(const char* side, float disp, float width,
46                  float fg, float bg, const char *label)
47                --> a C-code version of pgwedg, plotting the wedge
48                    scale in logarithmic units.
49  void cpgcumul(int npts, float *data, float datamin, float datamax,
50                       int pgflag)
51                --> a new pgplot routine that draws a cumulative
52                    distribution. Uses _swap and _sort.
53  void cpghistlog(npts, data, datamin, datamax, nbin, pgflag)
54                --> as for cpghist, with the y-axis on a logarithmic scale.
55
56*/
57
58
59/********************************************************************/
60/*   CPGTEST                                                        */
61/********************************************************************/
62
63int cpgtest()
64{
65  /**
66   *     A front-end to cpgqinf, to test whether a pgplot device is
67   *     currently open. Returns 1 if there is, else 0.
68   */
69  char answer[10];                 /* The PGQINF return string */
70  int answer_len = sizeof(answer); /* allocated size of answer[] */
71  cpgqinf("STATE", answer, &answer_len);
72  return strcmp(answer, "OPEN") == 0;
73}
74
75/********************************************************************/
76/*   CPGWEDGLOG                                                     */
77/********************************************************************/
78
79void cpgwedglog(const char* side, float disp, float width, float fg, float bg,
80                const char *label)
81{
82  /**
83   *     A C-code version of PGWEDG that writes the scale of the wedge in
84   *      logarithmic coordinates. All parameters are exactly as for cpgwedg.
85   */
86 
87  float wxa,wxb,wya,wyb, xa,xb,ya,yb; /* Temporary window coord storage.*/
88  float vxa,vxb,vya,vyb;              /* Viewport coords of wedge. */
89  float oldch, newch;                 /* Original and annotation character
90                                         heights. */
91  float ndcsiz;                       /* Size of unit character height
92                                         (NDC units). */
93  int horiz;                          /* Logical: True (=1) if wedge plotted
94                                         horizontally. */
95  int image;                          /* Logical: Use PGIMAG (T=1) or
96                                         PGGRAY (F=0). */
97
98  int nside,i;                        /* nside = symbolic version of side. */
99  const int bot=1,top=2,lft=3,rgt=4;
100  float wedwid, wdginc, vwidth, vdisp, xch, ych, labwid, fg1, bg1;
101  float txtfrc=0.6;                   /* Set the fraction of WIDTH used
102                                             for anotation. */
103  float txtsep=2.2;                   /* Char separation between numbers
104                                             and LABEL. */
105  float wdgarr[WDGPIX];               /* Array to draw wedge in. */
106  float tr[6] = {0.0,1.0,0.0,0.0,0.0,1.0};
107
108/*   if(pgnoto("pgwedg")) return; */
109
110  /* Get a numeric version of SIDE. */
111  if(tolower(side[0])=='b'){
112    nside = bot;
113    horiz = 1;
114  }
115  else if(tolower(side[0]=='t')){
116    nside = top;
117    horiz = 1;
118  }
119  else if(tolower(side[0]=='l')){
120    nside = lft;
121    horiz = 0;
122  }
123  else if(tolower(side[0]=='r')){
124    nside = rgt;
125    horiz = 0;
126  }
127  /*   else gwarn("Invalid \"SIDE\" argument in PGWEDG.");  */
128  else fprintf(stdout,"%%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
129
130  /* Determine which routine to use. */
131  if(strlen(side)<2) image = 0;
132  else if(tolower(side[1])=='i') image = 1;
133  else if(tolower(side[1])=='g') image = 0;
134  else fprintf(stdout,"%%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
135
136  cpgbbuf();
137
138  /* Store the current world and viewport coords and the character height. */
139  cpgqwin(&wxa, &wxb, &wya, &wyb);
140  cpgqvp(0, &xa, &xb, &ya, &yb);
141  cpgqch(&oldch);
142
143  /* Determine the unit character height in NDC coords. */
144  cpgsch(1.0);
145  cpgqcs(0, &xch, &ych);
146  if(horiz == 1)  ndcsiz = ych;
147  else ndcsiz = xch;
148
149  /* Convert 'WIDTH' and 'DISP' into viewport units. */
150  vwidth = width * ndcsiz * oldch;
151  vdisp  = disp * ndcsiz * oldch;
152
153  /* Determine the number of character heights required under the wedge. */
154  labwid = txtsep;
155  if(strcmp(label," ")!=0) labwid = labwid + 1.0;
156 
157  /* Determine and set the character height required to fit the wedge
158     anotation text within the area allowed for it. */
159  newch = txtfrc*vwidth / (labwid*ndcsiz);
160  cpgsch(newch);
161
162  /* Determine the width of the wedge part of the plot minus the anotation.
163     (NDC units). */
164  wedwid = vwidth * (1.0-txtfrc);
165
166  /* Use these to determine viewport coordinates for the wedge + annotation.*/
167  vxa = xa;
168  vxb = xb;
169  vya = ya;
170  vyb = yb;
171  if(nside==bot){
172    vyb = ya - vdisp;
173    vya = vyb - wedwid;
174  }
175  else if(nside==top) {
176    vya = yb + vdisp;
177    vyb = vya + wedwid;
178  }
179  else if(nside==lft) {
180    vxb = xa - vdisp;
181    vxa = vxb - wedwid;
182  }
183  else if(nside==rgt) {
184    vxa = xb + vdisp;
185    vxb = vxa + wedwid;
186  }
187
188  /* Set the viewport for the wedge. */
189  cpgsvp(vxa, vxb, vya, vyb);
190
191  /* Swap FG/BG if necessary to get axis direction right. */
192/*   fg1 = max(fg,bg); */
193/*   bg1 = min(fg,bg); */
194  if(fg>bg) {
195    fg1 = fg;
196    bg1 = bg;
197  }
198  else {
199    fg1 = bg;
200    bg1 = fg;
201  }
202
203
204  /* Create a dummy wedge array to be plotted. */
205  wdginc = (fg1-bg1)/(WDGPIX-1);
206  for(i=0;i<WDGPIX;i++)  wdgarr[i] = bg1 + (i-1) * wdginc;
207
208  /* Draw the wedge then change the world coordinates for labelling. */
209  if (horiz==1) {
210    cpgswin(1.0, (float)WDGPIX, 0.9, 1.1);
211    if (image==1) cpgimag(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
212    else          cpggray(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
213    cpgswin(bg1,fg1,0.0,1.0);
214  }
215  else{
216    cpgswin(0.9, 1.1, 1.0, (float)WDGPIX);
217    if (image==1) cpgimag(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
218    else          cpggray(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
219    cpgswin(0.0, 1.0, bg1, fg1);
220  }
221
222  /* Draw a labelled frame around the wedge -- using a logarithmic scale! */
223  if(nside==bot)  cpgbox("BCNSTL",0.0,0,"BC",0.0,0);
224  else if(nside==top) cpgbox("BCMSTL",0.0,0,"BC",0.0,0);
225  else if(nside==lft) cpgbox("BC",0.0,0,"BCNSTL",0.0,0);
226  else if(nside==rgt) cpgbox("BC",0.0,0,"BCMSTL",0.0,0);
227
228  /* Write the units label. */
229  if((strcmp(label," ")!=0)) cpgmtxt(side,txtsep,1.0,1.0,label);
230
231  /* Reset the original viewport and world coordinates. */
232  cpgsvp(xa,xb,ya,yb);
233  cpgswin(wxa,wxb,wya,wyb);
234  cpgsch(oldch);
235  cpgebuf();
236
237}
238
239
240/********************************************************************/
241/*   CPGCUMUL                                                       */
242/********************************************************************/
243
244void _swap(float *a, float *b)
245{
246  float t;
247  t=*a; *a=*b; *b=t;
248}
249
250void _sort(float *array, int begin, int end)
251{
252  float pivot = array[begin];
253  int i = begin + 1, j = end, k = end;
254  float t;
255
256  while (i < j) {
257    if (array[i] < pivot) i++;
258    else if (array[i] > pivot) {
259      j--; k--;
260      t = array[i];
261      array[i] = array[j];
262      array[j] = array[k];
263      array[k] = t; }
264    else {
265      j--;
266      _swap(&array[i], &array[j]);
267    }  }
268  i--;
269  _swap(&array[begin], &array[i]);       
270  if (i - begin > 1)
271    _sort(array, begin, i);
272  if (end - k   > 1)
273    _sort(array, k, end);                     
274}
275
276
277void cpgcumul(int npts, float *data, float datamin, float datamax, int pgflag)
278{
279  /**
280   *  A new pgplot routine that draws a cumulative distribution.
281   *   The use of pgflag is similar to cpghist & cpghist_log:
282
283   *   <ul><li> 0 --> draw a new graph using cpgenv, going from 0 to 1
284   *                  on the y-axis.
285   *       <li> 2 --> draw the plot on the current graph, without
286   *                  re-drawing any axes. 
287   *   </ul>
288   */
289
290  int i;
291  float *sorted;
292  float MINCOUNT=0.;
293
294  sorted = (float *)calloc(npts,sizeof(float));
295  for(i=0;i<npts;i++) sorted[i] = data[i];
296  _sort(sorted,0,npts);
297
298  cpgbbuf();
299
300  /* DEFINE ENVIRONMENT IF NECESSARY */
301  if(pgflag == 0) cpgenv(datamin,datamax,MINCOUNT,1.0001,0,0);
302  if(pgflag == 2) cpgswin(datamin,datamax,MINCOUNT,1.);
303
304  /* DRAW LINE */
305  cpgmove(datamin,MINCOUNT);
306  for(i=0;i<npts;i++) cpgdraw(sorted[i],(float)(i+1)/(float)(npts));
307  cpgdraw(datamax,1.);
308
309  cpgebuf();
310 
311  free(sorted);
312
313}
314
315/********************************************************************/
316/*   CPGHISTLOG                                                     */
317/********************************************************************/
318
319void cpghistlog(int npts, float *data, float datamin, float datamax, int nbin,
320                int pgflag)
321{
322  /**
323   *  Works exactly as for cpghist, except the y-axis is a logarithmic scale.
324   *
325   */
326
327
328  int i,bin;
329  float *num;
330  float maxNum,binSize,x1,x2,y1,y2,older,newer,fraction;
331  float MINCOUNT=-0.2;
332
333  num = (float *)calloc(nbin,sizeof(float));
334
335  cpgbbuf();
336
337  /* HOW MANY VALUES IN EACH BIN? */
338  for(i=0; i<npts; i++){
339    fraction = (data[i] - datamin) / (datamax - datamin);
340    bin = (int)( floor(fraction*nbin) );
341    if((bin>=0)&&(bin<nbin)) num[bin]+=1.;
342  }
343  for(i=0; i<nbin;i++){
344    if(num[i]>0) num[i] = log10(num[i]);
345    else num[i] = MINCOUNT;
346  }
347  maxNum = num[0];
348  for(i=1; i<nbin; i++) if(num[i]>maxNum) maxNum = num[i];
349  binSize = (datamax - datamin) / (float)nbin;
350
351  /* BOUNDARIES OF PLOT */
352  x1 = datamin;
353  x2 = datamax;
354  y1 = MINCOUNT;
355  y2 = ceil(maxNum);
356
357  /* DEFINE ENVIRONMENT IF NECESSARY */
358  if(pgflag%2 == 0) cpgenv(x1,x2,y1,y2,0,20);
359
360  /* DRAW HISTOGRAM */
361  if(pgflag/2 == 0){
362    older = 0.;
363    x2 = datamin;
364    cpgmove(datamin,MINCOUNT);
365    for(i=0;i<nbin;i++){
366      newer = num[i];
367      x1 = x2;
368      x2 = datamin + i*binSize;
369      if(newer!=MINCOUNT){
370        if(newer<=older){
371          cpgmove(x1,newer);
372          cpgdraw(x2,newer);
373        }
374        else{
375          cpgmove(x1,older);
376          cpgdraw(x1,newer);
377          cpgdraw(x2,newer);
378        }
379      }
380      cpgdraw(x2,MINCOUNT);
381      older=newer;
382    }
383  }
384  else if(pgflag/2 == 1){
385    older = 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) cpgrect(x1,x2,0.,newer);     
392    }
393  }
394  else if(pgflag/2 == 2){
395    older = 0.;
396    cpgmove(datamin,MINCOUNT);
397    x2 = datamin;
398    for(i=0;i<nbin;i++){
399      newer = num[i];
400      x1 = x2;
401      x2 = datamin + i*binSize;
402      if((newer==MINCOUNT)&&(older==MINCOUNT)) cpgmove(x2,MINCOUNT);
403      else {
404        cpgdraw(x1,newer);
405        if(newer==MINCOUNT) cpgmove(x2,newer);
406        else cpgdraw(x2,newer);
407      }
408      older = newer;
409    }
410  }
411
412  cpgebuf();
413   
414}
415
416/* /\********************************************************************\/ */
417/* /\*   CPGVERTHIST                                                    *\/ */
418/* /\********************************************************************\/ */
419
420/* void cpgverthist(int npts, float *data, float datamin, float datamax, int nbin,  */
421/*               int pgflag) */
422/* { */
423/*   /\** */
424/*    *  Works exactly as for cpghist, except the histogram is draw vertically. */
425/*    * */
426/*    *\/ */
427
428
429/*   int i,bin; */
430/*   float *num; */
431/*   float maxNum,binSize,x1,x2,y1,y2,older,newer,fraction; */
432/*   float MINCOUNT=-0.2; */
433
434/*   num = (float *)calloc(nbin,sizeof(float)); */
435
436/*   cpgbbuf(); */
437
438/*   /\* HOW MANY VALUES IN EACH BIN? *\/ */
439/*   for(i=0; i<npts; i++){ */
440/*     fraction = (data[i] - datamin) / (datamax - datamin); */
441/*     bin = (int)( floor(fraction*nbin) ); */
442/*     if((bin>=0)&&(bin<nbin)) num[bin]+=1.; */
443/*   } */
444/*   for(i=0; i<nbin;i++){ */
445/*     if(num[i]>0) num[i] = log10(num[i]); */
446/*     else num[i] = MINCOUNT; */
447/*   } */
448/*   maxNum = num[0]; */
449/*   for(i=1; i<nbin; i++) if(num[i]>maxNum) maxNum = num[i]; */
450/*   binSize = (datamax - datamin) / (float)nbin; */
451
452/*   /\* BOUNDARIES OF PLOT *\/ */
453/*   x1 = datamin; */
454/*   x2 = datamax; */
455/*   y1 = MINCOUNT; */
456/*   y2 = ceil(maxNum); */
457
458/*   /\* DEFINE ENVIRONMENT IF NECESSARY *\/ */
459/*   if(pgflag%2 == 0) cpgenv(x1,x2,y1,y2,0,20); */
460
461/*   /\* DRAW HISTOGRAM *\/ */
462/*   if(pgflag/2 == 0){ */
463/*     older = 0.; */
464/*     x2 = datamin; */
465/*     cpgmove(datamin,MINCOUNT); */
466/*     for(i=0;i<nbin;i++){ */
467/*       newer = num[i]; */
468/*       x1 = x2; */
469/*       x2 = datamin + i*binSize; */
470/*       if(newer!=MINCOUNT){ */
471/*      if(newer<=older){ */
472/*        cpgmove(x1,newer); */
473/*        cpgdraw(x2,newer); */
474/*      } */
475/*      else{ */
476/*        cpgmove(x1,older); */
477/*        cpgdraw(x1,newer); */
478/*        cpgdraw(x2,newer); */
479/*      } */
480/*       } */
481/*       cpgdraw(x2,MINCOUNT); */
482/*       older=newer; */
483/*     } */
484/*   } */
485/*   else if(pgflag/2 == 1){ */
486/*     older = MINCOUNT; */
487/*     x2 = datamin; */
488/*     for(i=0;i<nbin;i++){ */
489/*       newer = num[i]; */
490/*       x1 = x2; */
491/*       x2 = datamin + i*binSize; */
492/*       if(newer!=MINCOUNT) cpgrect(x1,x2,0.,newer);    */
493/*     } */
494/*   } */
495/*   else if(pgflag/2 == 2){ */
496/*     older = 0.; */
497/*     cpgmove(datamin,MINCOUNT); */
498/*     x2 = datamin; */
499/*     for(i=0;i<nbin;i++){ */
500/*       newer = num[i]; */
501/*       x1 = x2; */
502/*       x2 = datamin + i*binSize; */
503/*       if((newer==MINCOUNT)&&(older==MINCOUNT)) cpgmove(x2,MINCOUNT); */
504/*       else { */
505/*      cpgdraw(x1,newer); */
506/*      if(newer==MINCOUNT) cpgmove(x2,newer); */
507/*      else cpgdraw(x2,newer); */
508/*       } */
509/*       older = newer; */
510/*     } */
511/*   } */
512
513/*   cpgebuf(); */
514   
515/* } */
516
Note: See TracBrowser for help on using the repository browser.