PLplot  5.10.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plhist.c
Go to the documentation of this file.
1 // Histogram plotter.
2 //
3 // Copyright (C) 2004-2014 Alan W. Irwin
4 //
5 // This file is part of PLplot.
6 //
7 // PLplot is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU Library General Public License as published
9 // by the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // PLplot is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Library General Public License for more details.
16 //
17 // You should have received a copy of the GNU Library General Public License
18 // along with PLplot; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 
22 #include "plplotP.h"
23 
24 //--------------------------------------------------------------------------
25 // void plhist()
26 //
27 // Draws a histogram of n values of a variable in array data[0..n-1] in
28 // the range datmin to datmax using nbin bins. If "flags"'s first bit is 1, the
29 // histogram is plotted in the current window. If not, the routine calls
30 // "plenv" to set up the graphics environment.
31 //
32 // If flags's second bit is set, then items which fall outside the bin
33 // range are ignored.
34 //
35 // If flags's third bit is set, the outside bars are the same size
36 // as the rest. The default old behaviour was for the first and last
37 // bars to expand visually to fill the entire available space.
38 //--------------------------------------------------------------------------
39 
40 void
41 c_plhist( PLINT n, const PLFLT *data, PLFLT datmin, PLFLT datmax,
42  PLINT nbin, PLINT flags )
43 {
44  PLINT i, bin;
45  PLFLT *x, *y, dx, ymax;
46 
47  if ( plsc->level < 1 )
48  {
49  plabort( "plhist: Please call plinit first" );
50  return;
51  }
52  if ( plsc->level < 3 && ( flags & 1 ) )
53  {
54  plabort( "plhist: Please set up window first" );
55  return;
56  }
57  if ( datmin >= datmax )
58  {
59  plabort( "plhist: Data range invalid" );
60  return;
61  }
62  if ( !( x = (PLFLT *) malloc( (size_t) nbin * sizeof ( PLFLT ) ) ) )
63  {
64  plabort( "plhist: Out of memory" );
65  return;
66  }
67  if ( !( y = (PLFLT *) malloc( (size_t) nbin * sizeof ( PLFLT ) ) ) )
68  {
69  free( (void *) x );
70  plabort( "plhist: Out of memory" );
71  return;
72  }
73 
74  dx = ( datmax - datmin ) / nbin;
75  for ( i = 0; i < nbin; i++ )
76  {
77  x[i] = datmin + i * dx;
78  y[i] = 0.0;
79  }
80 
81  for ( i = 0; i < n; i++ )
82  {
83  bin = (PLINT) ( ( data[i] - datmin ) / dx );
84  if ( ( flags & 2 ) == 0 )
85  {
86  bin = bin > 0 ? bin : 0;
87  bin = bin < nbin ? bin : nbin - 1;
88  y[bin]++;
89  }
90  else
91  {
92  if ( bin >= 0 && bin < nbin )
93  {
94  y[bin]++;
95  }
96  }
97  }
98 
99  if ( !( flags & 1 ) )
100  {
101  ymax = 0.0;
102  for ( i = 0; i < nbin; i++ )
103  ymax = MAX( ymax, y[i] );
104 
105  plenv( datmin, datmax, (PLFLT) 0.0, (PLFLT) ( 1.1 * ymax ), 0, 0 );
106  }
107  // We pass on the highest couple of bits to the 'plbin' routine
108  plbin( nbin, x, y, ( flags & ( 4 + 8 + 16 + 32 ) ) >> 2 );
109  free( (void *) x );
110  free( (void *) y );
111 }
112 
113 //--------------------------------------------------------------------------
114 // void plbin()
115 //
116 // Plot a histogram using the arrays x and y to represent data values
117 // and frequencies respectively. If flags first bit is false, x values
118 // denote the lower edge of the bin, and if it is true, they denote
119 // the center of the bin. If flags second bit is true, then we assume
120 // the edge bins are the same size as the rest (i.e. the edge bins
121 // needn't go as far as the variables vpwxmi, vpwxma below).
122 //--------------------------------------------------------------------------
123 
124 void
125 c_plbin( PLINT nbin, const PLFLT *x, const PLFLT *y, PLINT flags )
126 {
127  PLINT i;
128  PLFLT xmin, xmax, vpwxmi, vpwxma, vpwymi, vpwyma;
129 
130  if ( plsc->level < 3 )
131  {
132  plabort( "plbin: Please set up window first" );
133  return;
134  }
135 
136  // Check x[i] are in ascending order
137 
138  for ( i = 0; i < nbin - 1; i++ )
139  {
140  if ( x[i] >= x[i + 1] )
141  {
142  plabort( "plbin: Elements of x array must be increasing" );
143  return;
144  }
145  }
146 
147  plP_xgvpw( &vpwxmi, &vpwxma, &vpwymi, &vpwyma );
148  if ( !( flags & 1 ) )
149  {
150  for ( i = 0; i < nbin - 1; i++ )
151  {
152  if ( !( flags & 4 ) || ( y[i] != vpwymi ) )
153  {
154  pljoin( x[i], vpwymi, x[i], y[i] );
155  pljoin( x[i], y[i], x[i + 1], y[i] );
156  pljoin( x[i + 1], y[i], x[i + 1], vpwymi );
157  }
158  }
159  if ( flags & 2 )
160  {
161  if ( !( flags & 4 ) || ( y[i] != vpwymi ) )
162  {
163  int xm = (int) ( x[i] + ( x[i] - x[i - 1] ) );
164  pljoin( x[i], vpwymi, x[i], y[i] );
165  pljoin( x[i], y[i], xm, y[i] );
166  pljoin( xm, y[i], xm, vpwymi );
167  }
168  }
169  else
170  {
171  if ( x[i] < vpwxma )
172  {
173  if ( !( flags & 4 ) || ( y[i] != vpwymi ) )
174  {
175  pljoin( x[i], vpwymi, x[i], y[i] );
176  pljoin( x[i], y[i], vpwxma, y[i] );
177  pljoin( vpwxma, y[i], vpwxma, vpwymi );
178  }
179  }
180  }
181  }
182  else
183  {
184  if ( nbin < 2 )
185  return;
186  if ( flags & 2 )
187  {
188  xmin = MAX( vpwxmi, 0.5 * ( 3 * x[0] - x[1] ) );
189  }
190  else
191  {
192  xmin = vpwxmi;
193  }
194  // Vince fixed bug May 1998
195  xmax = MAX( 0.5 * ( x[0] + x[1] ), vpwxmi );
196  if ( xmin < xmax )
197  {
198  pljoin( xmin, vpwymi, xmin, y[0] );
199  pljoin( xmin, y[0], xmax, y[0] );
200  pljoin( xmax, y[0], xmax, vpwymi );
201  }
202  for ( i = 1; i < nbin - 1; i++ )
203  {
204  xmin = xmax;
205  xmax = MIN( 0.5 * ( x[i] + x[i + 1] ), vpwxma );
206  if ( !( flags & 4 ) || ( y[i] != vpwymi ) )
207  {
208  pljoin( xmin, vpwymi, xmin, y[i] );
209  pljoin( xmin, y[i], xmax, y[i] );
210  pljoin( xmax, y[i], xmax, vpwymi );
211  }
212  }
213  xmin = xmax;
214  xmax = vpwxma;
215  if ( flags & 2 )
216  {
217  xmax = MIN( vpwxma, 0.5 * ( 3 * x[i] - x[i - 1] ) );
218  }
219  else
220  {
221  xmax = vpwxma;
222  }
223  if ( xmin < xmax )
224  {
225  if ( !( flags & 4 ) || ( y[i] != vpwymi ) )
226  {
227  pljoin( xmin, vpwymi, xmin, y[i] );
228  pljoin( xmin, y[i], xmax, y[i] );
229  pljoin( xmax, y[i], xmax, vpwymi );
230  }
231  }
232  }
233 }