Skip to content

Commit

Permalink
New histogram graph type
Browse files Browse the repository at this point in the history
  • Loading branch information
goat1000 committed Jun 5, 2015
1 parent c2ddab9 commit a693082
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 12 deletions.
143 changes: 143 additions & 0 deletions SVGGraphHistogram.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
/**
* Copyright (C) 2015 Graham Breach
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* For more information, please contact <[email protected]>
*/

require_once 'SVGGraphBarGraph.php';

class Histogram extends BarGraph {

protected $label_centre = FALSE;
protected $force_assoc = TRUE;
protected $minimum_units_y = 1;

protected $increment = NULL;
protected $percentage = false;


/**
* Process the values
*/
public function Values($values)
{
if(!empty($values)) {
parent::Values($values);
$values = array();

// find min, max, strip out nulls
$min = $max = NULL;
foreach($this->values[0] as $item) {
if(!is_null($item->value)) {
if(is_null($min) || $item->value < $min)
$min = $item->value;
if(is_null($max) || $item->value > $max)
$max = $item->value;
$values[] = $item->value;
}
}

// calculate increment?
if($this->increment <= 0) {
$diff = $max - $min;
if($diff <= 0) {
$inc = 1;
} else {
$inc = pow(10, floor(log10($diff)));
$d1 = $diff / $inc;
if(($inc != 1 || !is_integer($diff)) && $d1 < 4) {
if($d1 < 3)
$inc *= 0.2;
else
$inc *= 0.5;
}
}
$this->increment = $inc;
}

// prefill the map with nulls
$map = array();
$start = $this->Interval($min);
$end = $this->Interval($max, true) + $this->increment / 2;
for($i = $start; $i < $end; $i += $this->increment) {
$key = Graph::NumString($i);
$map[$key] = null;
}

foreach($values as $val) {
$k = Graph::NumString($this->Interval($val));
if(!array_key_exists($k, $map))
$map[$k] = 1;
else
$map[$k]++;
}

if($this->percentage) {
$total = count($values);
$pmap = array();
foreach($map as $k => $v)
$pmap[$k] = 100 * $v / $total;
$values = $pmap;
} else {
$values = $map;
}

// turn off structured data
$this->structure = NULL;
$this->structured_data = FALSE;
}
parent::Values($values);
}

/**
* Returns the start (or next) interval for a value
*/
public function Interval($value, $next = false)
{
$n = floor($value / $this->increment);
if($next)
++$n;
return $n * $this->increment;
}

/**
* Sets up the colour class with corrected number of colours
*/
protected function ColourSetup($count, $datasets = NULL)
{
// $count is off by 1 because the divisions are numbered
return parent::ColourSetup($count - 1, $datasets);
}

/**
* Override because of the shifted numbering
*/
protected function GridPosition($key, $ikey)
{
$position = null;
$zero = -0.01; // catch values close to 0
$axis = $this->x_axes[$this->main_x_axis];
$offset = $axis->Zero() + ($axis->Unit() * $ikey);
$g_limit = $this->g_width - ($axis->Unit() / 2);
if($offset >= $zero && floor($offset) <= $g_limit)
$position = $this->pad_left + $offset;

return $position;
}
}

22 changes: 20 additions & 2 deletions SVGGraphMultiScatterGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ protected function Draw()

$chunk_count = count($this->multi_graph);
$this->ColourSetup($this->multi_graph->ItemsCount(-1), $chunk_count);
$best_fit_above = $best_fit_below = '';
for($i = 0; $i < $chunk_count; ++$i) {
$bnum = 0;
$axis = $this->DatasetYAxis($i);
Expand All @@ -58,18 +59,35 @@ protected function Draw()

// draw the best-fit line for this data set
if($this->best_fit) {
$best_fit = $this->ArrayOption($this->best_fit, $i);
$bftype = $this->ArrayOption($this->best_fit, $i);
$colour = $this->ArrayOption($this->best_fit_colour, $i);
$stroke_width = $this->ArrayOption($this->best_fit_width, $i);
$dash = $this->ArrayOption($this->best_fit_dash, $i);
$body .= $this->BestFit($best_fit, $i, $colour, $stroke_width, $dash);
$opacity = $this->ArrayOption($this->best_fit_opacity, $i);
$above = $this->ArrayOption($this->best_fit_above, $i);

$best_fit = $this->BestFit($bftype, $i, $colour, $stroke_width, $dash,
$opacity);
if($above)
$best_fit_above .= $best_fit;
else
$best_fit_below .= $best_fit;
}
}

if($this->semantic_classes) {
$cls = array('class' => 'bestfit');
if(!empty($best_fit_below))
$best_fit_below = $this->Element('g', $cls, NULL, $best_fit_below);
if(!empty($best_fit_above))
$best_fit_above = $this->Element('g', $cls, NULL, $best_fit_above);
}
$body .= $best_fit_below;
$body .= $this->Guidelines(SVGG_GUIDELINE_ABOVE);
$body .= $this->Axes();
$body .= $this->CrossHairs();
$body .= $this->DrawMarkers();
$body .= $best_fit_above;
return $body;
}

Expand Down
5 changes: 4 additions & 1 deletion SVGGraphPointGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,8 @@ public function MarkerLabel($dataset, $index, &$item, $x, $y)
/**
* Find the best fit line for the data points
*/
protected function BestFit($type, $dataset, $colour, $stroke_width, $dash)
protected function BestFit($type, $dataset, $colour, $stroke_width, $dash,
$opacity)
{
// only straight lines supported for now
if($type != 'straight')
Expand Down Expand Up @@ -460,6 +461,8 @@ protected function BestFit($type, $dataset, $colour, $stroke_width, $dash)
$path['stroke-width'] = $stroke_width;
if(!empty($dash))
$path['stroke-dasharray'] = $dash;
if($opacity != 1)
$path['opacity'] = $opacity;

return $this->Element('path', $path);
}
Expand Down
26 changes: 17 additions & 9 deletions SVGGraphScatterGraph.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,29 @@ protected function Draw()
++$bnum;
}

$best_fit_above = $best_fit_below = '';
if($this->best_fit) {
$best_fit = is_array($this->best_fit) ? $this->best_fit[0] :
$this->best_fit;
$colour = is_array($this->best_fit_colour) ? $this->best_fit_colour[0] :
$this->best_fit_colour;
$stroke_width = is_array($this->best_fit_width) ?
$this->best_fit_width[0] : $this->best_fit_width;
$dash = is_array($this->best_fit_dash) ?
$this->best_fit_dash[0] : $this->best_fit_dash;
$body .= $this->BestFit($best_fit, 0, $colour, $stroke_width, $dash);
$bftype = $this->ArrayOption($this->best_fit, 0);
$colour = $this->ArrayOption($this->best_fit_colour, 0);
$stroke_width = $this->ArrayOption($this->best_fit_width, 0);
$dash = $this->ArrayOption($this->best_fit_dash, 0);
$opacity = $this->ArrayOption($this->best_fit_opacity, 0);
$best_fit = $this->BestFit($bftype, 0, $colour, $stroke_width, $dash,
$opacity);
if($this->semantic_classes)
$best_fit = $this->Element('g', array('class' => 'bestfit'), NULL,
$best_fit);
if($this->ArrayOption($this->best_fit_above, 0))
$best_fit_above = $best_fit;
else
$best_fit_below = $best_fit;
}
$body .= $best_fit_below;
$body .= $this->Guidelines(SVGG_GUIDELINE_ABOVE);
$body .= $this->Axes();
$body .= $this->CrossHairs();
$body .= $this->DrawMarkers();
$body .= $best_fit_above;
return $body;
}

Expand Down
9 changes: 9 additions & 0 deletions svggraph.ini
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,17 @@ best_fit_line = null
best_fit_width = 1
best_fit_colour = "rgb(0,0,0)"
best_fit_dash = null
best_fit_opacity = 1
best_fit_above = false

[MultiScatterGraph]
scatter_2d = false
best_fit_line = null
best_fit_width = 1
best_fit_colour = "rgb(0,0,0)"
best_fit_dash = null
best_fit_opacity = 1
best_fit_above = false

[StackedBarGraph]
bar_space = 10
Expand Down Expand Up @@ -484,3 +488,8 @@ stack_group = null
[BarAndLineGraph]
line_dataset = 1

[Histogram]
increment = null
percentage = false
bar_space = 0

0 comments on commit a693082

Please sign in to comment.