source: trunk/src/Utils/pgplot_related.c

Last change on this file was 1450, checked in by MatthewWhiting, 4 years ago

AXA-537 - Adding a bit more care in the pointer handling, particularly for the reconFilter in the copy constructor

File size: 15.5 KB
RevLine 
[303]1/*
[301]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// -----------------------------------------------------------------------
[303]29*/
[129]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
[155]37#define WDGPIX 100  /* used by cpgwedglog
38                       --> number of increments in the wedge. */
[129]39
[270]40/*
41 This file contains the following programs, all in C code:
[129]42
[270]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.
[146]55
[270]56*/
57
58
[129]59/********************************************************************/
[270]60/*   CPGTEST                                                        */
[129]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/********************************************************************/
[270]76/*   CPGWEDGLOG                                                     */
[129]77/********************************************************************/
78
[155]79void cpgwedglog(const char* side, float disp, float width, float fg, float bg,
80                const char *label)
[129]81{
82  /**
[155]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.
[129]85   */
86 
[155]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). */
[129]97
[155]98  int nside,i;                        /* nside = symbolic version of side. */
[129]99  const int bot=1,top=2,lft=3,rgt=4;
100  float wedwid, wdginc, vwidth, vdisp, xch, ych, labwid, fg1, bg1;
[155]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. */
[129]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. */
[634]111  nside=bot; /* initialise */
112  horiz=1;   /* initialise */
[129]113  if(tolower(side[0])=='b'){
114    nside = bot;
115    horiz = 1;
116  }
117  else if(tolower(side[0]=='t')){
118    nside = top;
119    horiz = 1;
120  }
121  else if(tolower(side[0]=='l')){
122    nside = lft;
123    horiz = 0;
124  }
125  else if(tolower(side[0]=='r')){
126    nside = rgt;
127    horiz = 0;
128  }
[155]129  /*   else gwarn("Invalid \"SIDE\" argument in PGWEDG.");  */
[270]130  else fprintf(stdout,"%%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
[129]131
132  /* Determine which routine to use. */
[634]133  image=0; /* initialise */
[129]134  if(strlen(side)<2) image = 0;
135  else if(tolower(side[1])=='i') image = 1;
136  else if(tolower(side[1])=='g') image = 0;
[270]137  else fprintf(stdout,"%%PGPLOT, Invalid \"SIDE\" argument in CPGWEDGLOG.");
[129]138
139  cpgbbuf();
140
141  /* Store the current world and viewport coords and the character height. */
142  cpgqwin(&wxa, &wxb, &wya, &wyb);
143  cpgqvp(0, &xa, &xb, &ya, &yb);
144  cpgqch(&oldch);
145
146  /* Determine the unit character height in NDC coords. */
147  cpgsch(1.0);
148  cpgqcs(0, &xch, &ych);
149  if(horiz == 1)  ndcsiz = ych;
150  else ndcsiz = xch;
151
152  /* Convert 'WIDTH' and 'DISP' into viewport units. */
153  vwidth = width * ndcsiz * oldch;
154  vdisp  = disp * ndcsiz * oldch;
155
156  /* Determine the number of character heights required under the wedge. */
157  labwid = txtsep;
158  if(strcmp(label," ")!=0) labwid = labwid + 1.0;
159 
160  /* Determine and set the character height required to fit the wedge
161     anotation text within the area allowed for it. */
162  newch = txtfrc*vwidth / (labwid*ndcsiz);
163  cpgsch(newch);
164
165  /* Determine the width of the wedge part of the plot minus the anotation.
166     (NDC units). */
167  wedwid = vwidth * (1.0-txtfrc);
168
[155]169  /* Use these to determine viewport coordinates for the wedge + annotation.*/
[129]170  vxa = xa;
171  vxb = xb;
172  vya = ya;
173  vyb = yb;
174  if(nside==bot){
175    vyb = ya - vdisp;
176    vya = vyb - wedwid;
177  }
178  else if(nside==top) {
179    vya = yb + vdisp;
180    vyb = vya + wedwid;
181  }
182  else if(nside==lft) {
183    vxb = xa - vdisp;
184    vxa = vxb - wedwid;
185  }
186  else if(nside==rgt) {
187    vxa = xb + vdisp;
188    vxb = vxa + wedwid;
189  }
190
191  /* Set the viewport for the wedge. */
192  cpgsvp(vxa, vxb, vya, vyb);
193
194  /* Swap FG/BG if necessary to get axis direction right. */
195/*   fg1 = max(fg,bg); */
196/*   bg1 = min(fg,bg); */
197  if(fg>bg) {
198    fg1 = fg;
199    bg1 = bg;
200  }
201  else {
202    fg1 = bg;
203    bg1 = fg;
204  }
205
206
207  /* Create a dummy wedge array to be plotted. */
208  wdginc = (fg1-bg1)/(WDGPIX-1);
209  for(i=0;i<WDGPIX;i++)  wdgarr[i] = bg1 + (i-1) * wdginc;
210
211  /* Draw the wedge then change the world coordinates for labelling. */
212  if (horiz==1) {
213    cpgswin(1.0, (float)WDGPIX, 0.9, 1.1);
214    if (image==1) cpgimag(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
215    else          cpggray(wdgarr, WDGPIX,1, 1,WDGPIX, 1,1, fg,bg, tr);
216    cpgswin(bg1,fg1,0.0,1.0);
217  }
218  else{
219    cpgswin(0.9, 1.1, 1.0, (float)WDGPIX);
220    if (image==1) cpgimag(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
221    else          cpggray(wdgarr, 1,WDGPIX, 1,1, 1,WDGPIX, fg,bg, tr);
222    cpgswin(0.0, 1.0, bg1, fg1);
223  }
224
225  /* Draw a labelled frame around the wedge -- using a logarithmic scale! */
226  if(nside==bot)  cpgbox("BCNSTL",0.0,0,"BC",0.0,0);
227  else if(nside==top) cpgbox("BCMSTL",0.0,0,"BC",0.0,0);
228  else if(nside==lft) cpgbox("BC",0.0,0,"BCNSTL",0.0,0);
229  else if(nside==rgt) cpgbox("BC",0.0,0,"BCMSTL",0.0,0);
230
231  /* Write the units label. */
232  if((strcmp(label," ")!=0)) cpgmtxt(side,txtsep,1.0,1.0,label);
233
234  /* Reset the original viewport and world coordinates. */
235  cpgsvp(xa,xb,ya,yb);
236  cpgswin(wxa,wxb,wya,wyb);
237  cpgsch(oldch);
238  cpgebuf();
239
240}
241
242
243/********************************************************************/
[270]244/*   CPGCUMUL                                                       */
[129]245/********************************************************************/
246
247void _swap(float *a, float *b)
248{
249  float t;
250  t=*a; *a=*b; *b=t;
251}
252
253void _sort(float *array, int begin, int end)
254{
255  float pivot = array[begin];
256  int i = begin + 1, j = end, k = end;
257  float t;
258
259  while (i < j) {
260    if (array[i] < pivot) i++;
261    else if (array[i] > pivot) {
262      j--; k--;
263      t = array[i];
264      array[i] = array[j];
265      array[j] = array[k];
266      array[k] = t; }
267    else {
268      j--;
269      _swap(&array[i], &array[j]);
270    }  }
271  i--;
272  _swap(&array[begin], &array[i]);       
273  if (i - begin > 1)
274    _sort(array, begin, i);
275  if (end - k   > 1)
276    _sort(array, k, end);                     
277}
278
279
280void cpgcumul(int npts, float *data, float datamin, float datamax, int pgflag)
281{
282  /**
[221]283   *  A new pgplot routine that draws a cumulative distribution.
[129]284   *   The use of pgflag is similar to cpghist & cpghist_log:
[269]285
286   *   <ul><li> 0 --> draw a new graph using cpgenv, going from 0 to 1
287   *                  on the y-axis.
288   *       <li> 2 --> draw the plot on the current graph, without
289   *                  re-drawing any axes. 
[221]290   *   </ul>
[129]291   */
292
293  int i;
294  float *sorted;
295  float MINCOUNT=0.;
296
297  sorted = (float *)calloc(npts,sizeof(float));
298  for(i=0;i<npts;i++) sorted[i] = data[i];
299  _sort(sorted,0,npts);
300
301  cpgbbuf();
302
[155]303  /* DEFINE ENVIRONMENT IF NECESSARY */
[129]304  if(pgflag == 0) cpgenv(datamin,datamax,MINCOUNT,1.0001,0,0);
305  if(pgflag == 2) cpgswin(datamin,datamax,MINCOUNT,1.);
306
[155]307  /* DRAW LINE */
[129]308  cpgmove(datamin,MINCOUNT);
309  for(i=0;i<npts;i++) cpgdraw(sorted[i],(float)(i+1)/(float)(npts));
310  cpgdraw(datamax,1.);
311
312  cpgebuf();
313 
314  free(sorted);
315
316}
317
318/********************************************************************/
[270]319/*   CPGHISTLOG                                                     */
[129]320/********************************************************************/
321
[155]322void cpghistlog(int npts, float *data, float datamin, float datamax, int nbin,
323                int pgflag)
[129]324{
325  /**
326   *  Works exactly as for cpghist, except the y-axis is a logarithmic scale.
327   *
328   */
329
330
331  int i,bin;
332  float *num;
333  float maxNum,binSize,x1,x2,y1,y2,older,newer,fraction;
334  float MINCOUNT=-0.2;
335
336  num = (float *)calloc(nbin,sizeof(float));
337
338  cpgbbuf();
339
[155]340  /* HOW MANY VALUES IN EACH BIN? */
[129]341  for(i=0; i<npts; i++){
342    fraction = (data[i] - datamin) / (datamax - datamin);
343    bin = (int)( floor(fraction*nbin) );
344    if((bin>=0)&&(bin<nbin)) num[bin]+=1.;
345  }
346  for(i=0; i<nbin;i++){
347    if(num[i]>0) num[i] = log10(num[i]);
348    else num[i] = MINCOUNT;
349  }
350  maxNum = num[0];
351  for(i=1; i<nbin; i++) if(num[i]>maxNum) maxNum = num[i];
352  binSize = (datamax - datamin) / (float)nbin;
353
[155]354  /* BOUNDARIES OF PLOT */
[129]355  x1 = datamin;
356  x2 = datamax;
357  y1 = MINCOUNT;
358  y2 = ceil(maxNum);
359
[155]360  /* DEFINE ENVIRONMENT IF NECESSARY */
[129]361  if(pgflag%2 == 0) cpgenv(x1,x2,y1,y2,0,20);
362
[155]363  /* DRAW HISTOGRAM */
[129]364  if(pgflag/2 == 0){
365    older = 0.;
366    x2 = datamin;
367    cpgmove(datamin,MINCOUNT);
368    for(i=0;i<nbin;i++){
369      newer = num[i];
370      x1 = x2;
371      x2 = datamin + i*binSize;
372      if(newer!=MINCOUNT){
373        if(newer<=older){
374          cpgmove(x1,newer);
375          cpgdraw(x2,newer);
376        }
377        else{
378          cpgmove(x1,older);
379          cpgdraw(x1,newer);
380          cpgdraw(x2,newer);
381        }
382      }
383      cpgdraw(x2,MINCOUNT);
384      older=newer;
385    }
386  }
387  else if(pgflag/2 == 1){
388    older = MINCOUNT;
389    x2 = datamin;
390    for(i=0;i<nbin;i++){
391      newer = num[i];
392      x1 = x2;
393      x2 = datamin + i*binSize;
394      if(newer!=MINCOUNT) cpgrect(x1,x2,0.,newer);     
395    }
396  }
397  else if(pgflag/2 == 2){
398    older = 0.;
399    cpgmove(datamin,MINCOUNT);
400    x2 = datamin;
401    for(i=0;i<nbin;i++){
402      newer = num[i];
403      x1 = x2;
404      x2 = datamin + i*binSize;
405      if((newer==MINCOUNT)&&(older==MINCOUNT)) cpgmove(x2,MINCOUNT);
406      else {
407        cpgdraw(x1,newer);
408        if(newer==MINCOUNT) cpgmove(x2,newer);
409        else cpgdraw(x2,newer);
410      }
411      older = newer;
412    }
413  }
414
[1450]415  if(num){
416      free(num);
417  }
[1448]418 
[129]419  cpgebuf();
420   
421}
422
[1130]423/********************************************************************/
424/*   CPGELLIPSE                                                     */
425/********************************************************************/
426
427
428void cpgellipse(float x0, float y0, float maj, float min, float pa)
429{
430  /*
431    Draw an ellipse, using the parametric equation u = a cos(t), v = b sin(t), where u and v are coordinates such that the position angle of the ellipse is zero.
432   */
433  double cospa,sinpa,u,v,x,y,t;
434  int it;
435  cospa = cos(pa*M_PI/180.);
436  sinpa = sin(pa*M_PI/180.);
437  u=maj;
438  v=0.;
439  x=u*cospa+v*sinpa;
440  y=u*sinpa-v*cospa;
441  cpgmove(x+x0,y+y0);
442  for(it=0;it<1000;it++){
443    t=it*2*M_PI/1000.;
444    u=maj*cos(t);
445    v=min*sin(t);
446    x=u*cospa+v*sinpa;
447    y=u*sinpa-v*cospa;
448    cpgdraw(x+x0,y+y0);
449  }
450}
451
452
[313]453/* /\********************************************************************\/ */
454/* /\*   CPGVERTHIST                                                    *\/ */
455/* /\********************************************************************\/ */
456
457/* void cpgverthist(int npts, float *data, float datamin, float datamax, int nbin,  */
458/*               int pgflag) */
459/* { */
460/*   /\** */
461/*    *  Works exactly as for cpghist, except the histogram is draw vertically. */
462/*    * */
463/*    *\/ */
464
465
466/*   int i,bin; */
467/*   float *num; */
468/*   float maxNum,binSize,x1,x2,y1,y2,older,newer,fraction; */
469/*   float MINCOUNT=-0.2; */
470
471/*   num = (float *)calloc(nbin,sizeof(float)); */
472
473/*   cpgbbuf(); */
474
475/*   /\* HOW MANY VALUES IN EACH BIN? *\/ */
476/*   for(i=0; i<npts; i++){ */
477/*     fraction = (data[i] - datamin) / (datamax - datamin); */
478/*     bin = (int)( floor(fraction*nbin) ); */
479/*     if((bin>=0)&&(bin<nbin)) num[bin]+=1.; */
480/*   } */
481/*   for(i=0; i<nbin;i++){ */
482/*     if(num[i]>0) num[i] = log10(num[i]); */
483/*     else num[i] = MINCOUNT; */
484/*   } */
485/*   maxNum = num[0]; */
486/*   for(i=1; i<nbin; i++) if(num[i]>maxNum) maxNum = num[i]; */
487/*   binSize = (datamax - datamin) / (float)nbin; */
488
489/*   /\* BOUNDARIES OF PLOT *\/ */
490/*   x1 = datamin; */
491/*   x2 = datamax; */
492/*   y1 = MINCOUNT; */
493/*   y2 = ceil(maxNum); */
494
495/*   /\* DEFINE ENVIRONMENT IF NECESSARY *\/ */
496/*   if(pgflag%2 == 0) cpgenv(x1,x2,y1,y2,0,20); */
497
498/*   /\* DRAW HISTOGRAM *\/ */
499/*   if(pgflag/2 == 0){ */
500/*     older = 0.; */
501/*     x2 = datamin; */
502/*     cpgmove(datamin,MINCOUNT); */
503/*     for(i=0;i<nbin;i++){ */
504/*       newer = num[i]; */
505/*       x1 = x2; */
506/*       x2 = datamin + i*binSize; */
507/*       if(newer!=MINCOUNT){ */
508/*      if(newer<=older){ */
509/*        cpgmove(x1,newer); */
510/*        cpgdraw(x2,newer); */
511/*      } */
512/*      else{ */
513/*        cpgmove(x1,older); */
514/*        cpgdraw(x1,newer); */
515/*        cpgdraw(x2,newer); */
516/*      } */
517/*       } */
518/*       cpgdraw(x2,MINCOUNT); */
519/*       older=newer; */
520/*     } */
521/*   } */
522/*   else if(pgflag/2 == 1){ */
523/*     older = MINCOUNT; */
524/*     x2 = datamin; */
525/*     for(i=0;i<nbin;i++){ */
526/*       newer = num[i]; */
527/*       x1 = x2; */
528/*       x2 = datamin + i*binSize; */
529/*       if(newer!=MINCOUNT) cpgrect(x1,x2,0.,newer);    */
530/*     } */
531/*   } */
532/*   else if(pgflag/2 == 2){ */
533/*     older = 0.; */
534/*     cpgmove(datamin,MINCOUNT); */
535/*     x2 = datamin; */
536/*     for(i=0;i<nbin;i++){ */
537/*       newer = num[i]; */
538/*       x1 = x2; */
539/*       x2 = datamin + i*binSize; */
540/*       if((newer==MINCOUNT)&&(older==MINCOUNT)) cpgmove(x2,MINCOUNT); */
541/*       else { */
542/*      cpgdraw(x1,newer); */
543/*      if(newer==MINCOUNT) cpgmove(x2,newer); */
544/*      else cpgdraw(x2,newer); */
545/*       } */
546/*       older = newer; */
547/*     } */
548/*   } */
549
550/*   cpgebuf(); */
551   
552/* } */
553
Note: See TracBrowser for help on using the repository browser.