]> git.sur5r.net Git - bacula/bacula/blob - gui/bacula-web/external_packages/phplot/phplot_data.php
commit changes
[bacula/bacula] / gui / bacula-web / external_packages / phplot / phplot_data.php
1 <?php
2 /* $Id$
3  * 
4  * Copyright (C) 2000 Afan Ottenheimer.  Released under
5  * the GPL and PHP licenses as stated in the the README file which
6  * should have been included with this document.
7
8  * This is an subclass for phplot.php and should only be
9  * called after phplot.ini has been called. This extends
10  * phplot by adding additional routines that can be used
11  * to modify the data arrays.
12  *
13  * Data must be a *numerical* array, this is enforced in SetDataValues() 
14  */
15
16 require_once("phplot.php");
17
18 class PHPlot_Data extends PHPlot 
19 {
20     /*!
21      * Constructor
22      */
23     function PHPlot_Data($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL)
24     { 
25         if (! isset($this->img)) { 
26             $this->PHPlot($which_width, $which_height, $which_output_file, $which_input_file);
27         }
28     }
29     
30     /*!
31      * Will scale all data rows
32      * Maybe later I will do a function that only scales some rows
33      * if $even is TRUE, data will be scaled with "even" factors. 
34      * \note Original code by Thiemo Nagel
35      */
36     function DoScaleData($even, $show_in_legend) 
37     {
38         $offset = 0;        // We use this not to read labels in text-data
39             
40         if ($this->data_type == 'text-data') {
41             $offset = 1;
42         } elseif ($this->data_type != 'data-data') {
43             $this->DrawError('wrong data type!!');
44             return FALSE;
45         }
46
47         // Determine maxima for each data row in array $max
48         // Put maximum of the maxima in $maxmax
49         $maxmax = 0;
50         for($i=0; $i < $this->num_data_rows; $i++) {
51             $rowsize = count($this->data[$i]);
52             for ($j=$offset; $j < $rowsize; $j++) {
53                 if ($this->data[$i][$j] > @ $max[$j])
54                     $max[$j] = $this->data[$i][$j];
55                 if (@ $max[$j] > $maxmax) 
56                     $maxmax = $max[$j];
57             }
58         }
59         
60         // determine amplification factor $amplify
61         $end = count($max) + $offset;
62         for ($i=$offset; $i < $end; $i++) {
63             if ($max[$i] == 0 || $max[$i] == $maxmax) {
64                 $amplify[$i] = 1;  // no divide by zero
65             } else {
66                 if ($even) {
67                     $amp = pow(10,round(log10($maxmax / $max[$i]))-1);
68                     if ($amp * $max[$i] * 5 < $maxmax) {
69                         $amp *= 5;
70                     } elseif ($amp * $max[$i] * 2 < $maxmax) {
71                         $amp *= 2;
72                     }
73                 } else {
74                     $amp = $maxmax / $max[$i];
75                     $digits = floor(log10($amp));
76                     $amp = round($amp/pow(10,$digits-1))*pow(10,$digits-1);
77                 }
78                 $amplify[$i] = $amp;
79             }
80             if ($amplify[$i] != 1 && $show_in_legend) 
81                 @ $this->legend[$i] .= "*$amplify[$i]";
82         }
83
84         // Amplify data
85         // On my machine, running 1000 iterations over 1000 rows of 12 elements each,
86         // the for loops were 43.2% faster (MBD)
87         for ($i = 0; $i < $this->num_data_rows; $i++) {
88             $rowsize = count($this->data[$i]);
89             for ($j=$offset; $j < $rowsize; $j++) {
90                 $this->data[$i][$j] *= $amplify[$j];
91             }
92         }
93
94         //Re-Scale Vertical Ticks if not already set
95         if ( ! $this->y_tick_increment) {
96             $this->SetYTickIncrement() ;
97         }
98
99         return TRUE;
100     } //function DoScaleData
101
102
103     /*!
104      * Computes a moving average of strength $interval for
105      * data row number $datarow, where 0 denotes the first
106      * row of y-data. 
107      *
108      *  \param int    datarow  Index of the row whereupon to make calculations
109      *  \param int    interval Number of elements to use in average ("strength")
110      *  \param bool   show     Whether to tell about the moving average in the legend.
111      *  \param string color    Color for the line to be drawn. This color is darkened. 
112      *                         Can be named or #RRGGBB.
113      *  \param int    width    Width of the line to be drawn.
114      *
115      *  \note Original idea by Theimo Nagel
116      */
117     function DoMovingAverage($datarow, $interval, $show=TRUE, $color=NULL, $width=NULL)
118     {
119         $off = 1;               // Skip record #0 (data label) 
120         
121         $this->PadArrays();
122         
123         if ($interval == 0) {
124             $this->DrawError('DoMovingAverage(): interval can\'t be 0');
125             return FALSE;
126         }
127
128         if ($datarow >= $this->records_per_group) {
129             $this->DrawError("DoMovingAverage(): Data row out of bounds ($datarow >= $this->records_per_group)");
130             return FALSE;
131         }
132         
133         if ($this->data_type == 'text-data') {
134             // Ok. No need to set the offset to skip more records.
135         } elseif ($this->data_type == 'data-data') {
136             $off++;             // first Y value at $data[][2]
137         } else {
138             $this->DrawError('DoMovingAverage(): wrong data type!!');
139             return FALSE;
140         }
141         
142         // Set color:
143         if ($color) {
144             array_push($this->ndx_data_colors, $this->SetIndexDarkColor($color));
145         } else {
146             array_push($this->ndx_data_colors, $this->SetIndexDarkColor($this->data_colors[$datarow]));
147         }
148         // Set line width:
149         if ($width) {
150             array_push($this->line_widths, $width);
151         } else {    
152             array_push($this->line_widths,  $this->line_widths[$datarow] * 2);
153         }
154         // Show in legend?
155         if ($show) {
156             $this->legend[$this->records_per_group-1] = "(MA[$datarow]:$interval)";
157         }
158
159         $datarow += $off;
160         for ($i = 0; $i < $this->num_data_rows; $i++) {
161             $storage[$i % $interval] = @ $this->data[$i][$datarow];
162             $ma = array_sum($storage);
163             $ma /= count($storage);
164             array_push($this->data[$i], $ma);   // Push the data onto the array
165             $this->num_recs[$i]++;              // Tell the drawing functions it is there
166         }
167         $this->records_per_group++;
168 //        $this->FindDataLimits();
169         return TRUE;
170     } //function DoMovingAverage()
171
172
173     /**
174      * Computes an exponentially smoothed moving average.
175      * @param int perc "smoothing percentage"
176      * FIXME!!! I haven't checked this.
177      */
178     function DoExponentialMovingAverage($datarow, $perc, $show_in_legend)
179     {
180         if ($this->data_type == 'text-data') {
181             $datarow++;
182         } elseif ($this->data_type != 'data-data') {
183             $this->DrawError('DoWeightedMovingAverage(): wrong data type!!');
184             return FALSE;
185         }
186         
187         if ($show_in_legend) {
188             $this->legend[$datarow] .= " (MA: $interval)";
189         }
190
191         $storage[0] = $this->data[0][$datarow];
192         for ($i=1;$i < $this->num_data_rows; $i++) {
193             $storage[$i] = @ $storage[$i-1] + $perc * ($this->data[$i][$datarow] - $storage[$i-1]);
194             $ma = array_sum($storage);
195             $ma /= count($storage);
196             $this->data[$i][$datarow] = $ma;
197         }
198         return TRUE;
199     } // function DoExponentialMovingAverage()
200
201     
202     /*!
203      * Removes the DataSet of number $index
204      */
205     function DoRemoveDataSet($index) 
206     {
207         $offset = 1;
208         if ($this->data_type == 'data-data') {
209             $offset++;
210         } elseif ($this->data_type != 'text-data') {
211             $this->DrawError('wrong data type!!');
212             return FALSE;
213         }
214     
215         $index += $offset;
216         foreach ($this->data as $key=>$val) {
217             foreach ($val as $key2=>$val2) {
218                 if ($key2 >= $index) {
219                     if (isset($this->data[$key][$key2+1])) {
220                         $this->data[$key][$key2] = $this->data[$key][$key2+1];
221                     } else {
222                         unset($this->data[$key][$key2]);
223                     }
224                 }
225             }
226         }
227     } // function DoRemoveDataSet
228     
229     
230     /*!
231      * Computes row x divided by row y, stores the result in row x
232      * and deletes row y
233      */
234     function DoDivision($x,$y) 
235     {
236         $offset = 1;
237         if ($this->data_type == 'data-data') {
238             $offset++;
239         } elseif ($this->data_type != 'text-data') {
240             $this->DrawError('wrong data type!!');
241             return FALSE;
242         }
243     
244         $x += $offset; $y += $offset;
245         reset($this->data);
246         while (list($key, $val) = each($this->data)) {
247             if ($this->data[$key][$y] == 0) {
248                 $this->data[$key][$x] = 0;
249             } else {
250                 $this->data[$key][$x] /= $this->data[$key][$y];
251             }
252         }
253     
254         $this->DoRemoveDataSet($y-$offset);
255     } // function DoDivision
256
257 } // class PHPlot_Data extends PHPlot
258 ?>