source: trunk/workflow/inc/phplot/phplot_data.php @ 7655

Revision 7655, 8.7 KB checked in by douglasz, 11 years ago (diff)

Ticket #3236 - Melhorias de performance no codigo do Expresso.

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