site-accueil-insa/matomo/vendor/szymach/c-pchart/src/Data.php

1318 lines
39 KiB
PHP

<?php
namespace CpChart;
use Exception;
use RuntimeException;
/**
* Data - class to manipulate data arrays
*
* Version : 2.1.4
* Made by : Jean-Damien POGOLOTTI
* Last Update : 19/01/2014
*
* This file can be distributed under the license you can find at :
*
* http://www.pchart.net/license
*
* You can find the whole class documentation on the pChart web site.
*/
class Data
{
/**
* @var array
*/
public $Data = [];
/**
* @var array
*/
public $Palette = [
"0" => ["R" => 188, "G" => 224, "B" => 46, "Alpha" => 100],
"1" => ["R" => 224, "G" => 100, "B" => 46, "Alpha" => 100],
"2" => ["R" => 224, "G" => 214, "B" => 46, "Alpha" => 100],
"3" => ["R" => 46, "G" => 151, "B" => 224, "Alpha" => 100],
"4" => ["R" => 176, "G" => 46, "B" => 224, "Alpha" => 100],
"5" => ["R" => 224, "G" => 46, "B" => 117, "Alpha" => 100],
"6" => ["R" => 92, "G" => 224, "B" => 46, "Alpha" => 100],
"7" => ["R" => 224, "G" => 176, "B" => 46, "Alpha" => 100]
];
public function __construct()
{
$this->Data["XAxisDisplay"] = AXIS_FORMAT_DEFAULT;
$this->Data["XAxisFormat"] = null;
$this->Data["XAxisName"] = null;
$this->Data["XAxisUnit"] = null;
$this->Data["Abscissa"] = null;
$this->Data["AbsicssaPosition"] = AXIS_POSITION_BOTTOM;
$this->Data["Axis"][0]["Display"] = AXIS_FORMAT_DEFAULT;
$this->Data["Axis"][0]["Position"] = AXIS_POSITION_LEFT;
$this->Data["Axis"][0]["Identity"] = AXIS_Y;
}
/**
* Add a single point or an array to the given serie
* @param mixed $Values
* @param string $SerieName
* @return int
*/
public function addPoints($Values, $SerieName = "Serie1")
{
if (!isset($this->Data["Series"][$SerieName])) {
$this->initialise($SerieName);
}
if (is_array($Values)) {
foreach ($Values as $Value) {
$this->Data["Series"][$SerieName]["Data"][] = $Value;
}
} else {
$this->Data["Series"][$SerieName]["Data"][] = $Values;
}
if ($Values != VOID) {
$StrippedData = $this->stripVOID($this->Data["Series"][$SerieName]["Data"]);
if (empty($StrippedData)) {
$this->Data["Series"][$SerieName]["Max"] = 0;
$this->Data["Series"][$SerieName]["Min"] = 0;
return 0;
}
$this->Data["Series"][$SerieName]["Max"] = max($StrippedData);
$this->Data["Series"][$SerieName]["Min"] = min($StrippedData);
}
}
/**
* Strip VOID values
* @param mixed $Values
* @return array
*/
public function stripVOID($Values)
{
if (!is_array($Values)) {
return [];
}
$Result = [];
foreach ($Values as $Value) {
if ($Value != VOID) {
$Result[] = $Value;
}
}
return $Result;
}
/**
* Return the number of values contained in a given serie
* @param string $Serie
* @return int
*/
public function getSerieCount($Serie)
{
if (isset($this->Data["Series"][$Serie]["Data"])) {
return sizeof($this->Data["Series"][$Serie]["Data"]);
}
return 0;
}
/**
* Remove a serie from the pData object
* @param mixed $Series
*/
public function removeSerie($Series)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
unset($this->Data["Series"][$Serie]);
}
}
}
/**
* Return a value from given serie & index
* @param string $Serie
* @param int $Index
* @return mixed
*/
public function getValueAt($Serie, $Index = 0)
{
if (isset($this->Data["Series"][$Serie]["Data"][$Index])) {
return $this->Data["Series"][$Serie]["Data"][$Index];
}
return null;
}
/**
* Return the values array
* @param string $Serie
* @return mixed
*/
public function getValues($Serie)
{
if (isset($this->Data["Series"][$Serie]["Data"])) {
return $this->Data["Series"][$Serie]["Data"];
}
return null;
}
/**
* Reverse the values in the given serie
* @param mixed $Series
*/
public function reverseSerie($Series)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie]["Data"])) {
$this->Data["Series"][$Serie]["Data"] = array_reverse(
$this->Data["Series"][$Serie]["Data"]
);
}
}
}
/**
* Return the sum of the serie values
* @param string $Serie
* @return int|null
*/
public function getSum($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
return array_sum($this->Data["Series"][$Serie]["Data"]);
}
return null;
}
/**
* Return the max value of a given serie
* @param string $Serie
* @return mixed
*/
public function getMax($Serie)
{
if (isset($this->Data["Series"][$Serie]["Max"])) {
return $this->Data["Series"][$Serie]["Max"];
}
return null;
}
/**
* @param string $Serie
* @return mixed
*/
public function getMin($Serie)
{
if (isset($this->Data["Series"][$Serie]["Min"])) {
return $this->Data["Series"][$Serie]["Min"];
}
return null;
}
/**
* Set the description of a given serie
* @param mixed $Series
* @param string $Shape
*/
public function setSerieShape($Series, $Shape = SERIE_SHAPE_FILLEDCIRCLE)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["Shape"] = $Shape;
}
}
}
/**
* Set the description of a given serie
* @param string|array $Series
* @param string $Description
*/
public function setSerieDescription($Series, $Description = "My serie")
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["Description"] = $Description;
}
}
}
/**
* Set a serie as "drawable" while calling a rendering public function
* @param string|array $Series
* @param boolean $Drawable
*/
public function setSerieDrawable($Series, $Drawable = true)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["isDrawable"] = $Drawable;
}
}
}
/**
* Set the icon associated to a given serie
* @param mixed $Series
* @param mixed $Picture
*/
public function setSeriePicture($Series, $Picture = null)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["Picture"] = $Picture;
}
}
}
/**
* Set the name of the X Axis
* @param string $Name
*/
public function setXAxisName($Name)
{
$this->Data["XAxisName"] = $Name;
}
/**
* Set the display mode of the X Axis
* @param int $Mode
* @param array $Format
*/
public function setXAxisDisplay($Mode, $Format = null)
{
$this->Data["XAxisDisplay"] = $Mode;
$this->Data["XAxisFormat"] = $Format;
}
/**
* Set the unit that will be displayed on the X axis
* @param string $Unit
*/
public function setXAxisUnit($Unit)
{
$this->Data["XAxisUnit"] = $Unit;
}
/**
* Set the serie that will be used as abscissa
* @param string $Serie
*/
public function setAbscissa($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Abscissa"] = $Serie;
}
}
/**
* Set the position of the abscissa axis
* @param int $Position
*/
public function setAbsicssaPosition($Position = AXIS_POSITION_BOTTOM)
{
$this->Data["AbsicssaPosition"] = $Position;
}
/**
* Set the name of the abscissa axis
* @param string $Name
*/
public function setAbscissaName($Name)
{
$this->Data["AbscissaName"] = $Name;
}
/**
* Create a scatter group specified in X and Y data series
* @param string $SerieX
* @param string $SerieY
* @param int $ID
*/
public function setScatterSerie($SerieX, $SerieY, $ID = 0)
{
if (isset($this->Data["Series"][$SerieX]) && isset($this->Data["Series"][$SerieY])) {
$this->initScatterSerie($ID);
$this->Data["ScatterSeries"][$ID]["X"] = $SerieX;
$this->Data["ScatterSeries"][$ID]["Y"] = $SerieY;
}
}
/**
* Set the shape of a given sctatter serie
* @param int $ID
* @param int $Shape
*/
public function setScatterSerieShape($ID, $Shape = SERIE_SHAPE_FILLEDCIRCLE)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Shape"] = $Shape;
}
}
/**
* Set the description of a given scatter serie
* @param int $ID
* @param string $Description
*/
public function setScatterSerieDescription($ID, $Description = "My serie")
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Description"] = $Description;
}
}
/**
* Set the icon associated to a given scatter serie
* @param int $ID
* @param mixed $Picture
*/
public function setScatterSeriePicture($ID, $Picture = null)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Picture"] = $Picture;
}
}
/**
* Set a scatter serie as "drawable" while calling a rendering public function
* @param int $ID
* @param boolean $Drawable
*/
public function setScatterSerieDrawable($ID, $Drawable = true)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["isDrawable"] = $Drawable;
}
}
/**
* Define if a scatter serie should be draw with ticks
* @param int $ID
* @param int $Width
*/
public function setScatterSerieTicks($ID, $Width = 0)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Ticks"] = $Width;
}
}
/**
* Define if a scatter serie should be draw with a special weight
* @param int $ID
* @param int $Weight
*/
public function setScatterSerieWeight($ID, $Weight = 0)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Weight"] = $Weight;
}
}
/**
* Associate a color to a scatter serie
* @param int $ID
* @param array $Format
*/
public function setScatterSerieColor($ID, array $Format)
{
$R = isset($Format["R"]) ? $Format["R"] : 0;
$G = isset($Format["G"]) ? $Format["G"] : 0;
$B = isset($Format["B"]) ? $Format["B"] : 0;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
if (isset($this->Data["ScatterSeries"][$ID])) {
$this->Data["ScatterSeries"][$ID]["Color"]["R"] = $R;
$this->Data["ScatterSeries"][$ID]["Color"]["G"] = $G;
$this->Data["ScatterSeries"][$ID]["Color"]["B"] = $B;
$this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = $Alpha;
}
}
/**
* Compute the series limits for an individual and global point of view
* @return array
*/
public function limits()
{
$GlobalMin = ABSOLUTE_MAX;
$GlobalMax = ABSOLUTE_MIN;
foreach (array_keys($this->Data["Series"]) as $Key) {
if ($this->Data["Abscissa"] != $Key
&& $this->Data["Series"][$Key]["isDrawable"] == true
) {
if ($GlobalMin > $this->Data["Series"][$Key]["Min"]) {
$GlobalMin = $this->Data["Series"][$Key]["Min"];
}
if ($GlobalMax < $this->Data["Series"][$Key]["Max"]) {
$GlobalMax = $this->Data["Series"][$Key]["Max"];
}
}
}
$this->Data["Min"] = $GlobalMin;
$this->Data["Max"] = $GlobalMax;
return [$GlobalMin, $GlobalMax];
}
/**
* Mark all series as drawable
*/
public function drawAll()
{
foreach (array_keys($this->Data["Series"]) as $Key) {
if ($this->Data["Abscissa"] != $Key) {
$this->Data["Series"][$Key]["isDrawable"] = true;
}
}
}
/**
* Return the average value of the given serie
* @param string $Serie
* @return int|null
*/
public function getSerieAverage($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
return array_sum($SerieData) / sizeof($SerieData);
}
return null;
}
/**
* Return the geometric mean of the given serie
* @param string $Serie
* @return int|null
*/
public function getGeometricMean($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
$Seriesum = 1;
foreach ($SerieData as $Value) {
$Seriesum = $Seriesum * $Value;
}
return pow($Seriesum, 1 / sizeof($SerieData));
}
return null;
}
/**
* Return the harmonic mean of the given serie
* @param string $Serie
* @return int|null
*/
public function getHarmonicMean($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
$Seriesum = 0;
foreach ($SerieData as $Value) {
$Seriesum = $Seriesum + 1 / $Value;
}
return sizeof($SerieData) / $Seriesum;
}
return null;
}
/**
* Return the standard deviation of the given serie
* @param string $Serie
* @return double|null
*/
public function getStandardDeviation($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$Average = $this->getSerieAverage($Serie);
$SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
$DeviationSum = 0;
foreach ($SerieData as $Key => $Value) {
$DeviationSum = $DeviationSum + ($Value - $Average) * ($Value - $Average);
}
return sqrt($DeviationSum / count($SerieData));
}
return null;
}
/**
* Return the Coefficient of variation of the given serie
* @param string $Serie
* @return float|null
*/
public function getCoefficientOfVariation($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$Average = $this->getSerieAverage($Serie);
$StandardDeviation = $this->getStandardDeviation($Serie);
if ($StandardDeviation != 0) {
return $StandardDeviation / $Average;
}
}
return null;
}
/**
* Return the median value of the given serie
* @param string $Serie
* @return int|float
*/
public function getSerieMedian($Serie)
{
if (isset($this->Data["Series"][$Serie])) {
$SerieData = $this->stripVOID($this->Data["Series"][$Serie]["Data"]);
sort($SerieData);
$SerieCenter = floor(sizeof($SerieData) / 2);
if (isset($SerieData[$SerieCenter])) {
return $SerieData[$SerieCenter];
}
}
return null;
}
/**
* Return the x th percentil of the given serie
* @param string $Serie
* @param int $Percentil
* @return int|float| null
*/
public function getSeriePercentile($Serie = "Serie1", $Percentil = 95)
{
if (!isset($this->Data["Series"][$Serie]["Data"])) {
return null;
}
$Values = count($this->Data["Series"][$Serie]["Data"]) - 1;
if ($Values < 0) {
$Values = 0;
}
$PercentilID = floor(($Values / 100) * $Percentil + .5);
$SortedValues = $this->Data["Series"][$Serie]["Data"];
sort($SortedValues);
if (is_numeric($SortedValues[$PercentilID])) {
return $SortedValues[$PercentilID];
}
return null;
}
/**
* Add random values to a given serie
* @param string $SerieName
* @param array $Options
*/
public function addRandomValues($SerieName = "Serie1", array $Options = [])
{
$Values = isset($Options["Values"]) ? $Options["Values"] : 20;
$Min = isset($Options["Min"]) ? $Options["Min"] : 0;
$Max = isset($Options["Max"]) ? $Options["Max"] : 100;
$withFloat = isset($Options["withFloat"]) ? $Options["withFloat"] : false;
for ($i = 0; $i <= $Values; $i++) {
$Value = $withFloat ? rand($Min * 100, $Max * 100) / 100 : rand($Min, $Max);
$this->addPoints($Value, $SerieName);
}
}
/**
* Test if we have valid data
* @return boolean|null
*/
public function containsData()
{
if (!isset($this->Data["Series"])) {
return false;
}
foreach (array_keys($this->Data["Series"]) as $Key) {
if ($this->Data["Abscissa"] != $Key
&& $this->Data["Series"][$Key]["isDrawable"] == true
) {
return true;
}
}
return null;
}
/**
* Set the display mode of an Axis
* @param int $AxisID
* @param int $Mode
* @param array $Format
*/
public function setAxisDisplay($AxisID, $Mode = AXIS_FORMAT_DEFAULT, $Format = null)
{
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Display"] = $Mode;
if ($Format != null) {
$this->Data["Axis"][$AxisID]["Format"] = $Format;
}
}
}
/**
* Set the position of an Axis
* @param int $AxisID
* @param int $Position
*/
public function setAxisPosition($AxisID, $Position = AXIS_POSITION_LEFT)
{
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Position"] = $Position;
}
}
/**
* Associate an unit to an axis
* @param int $AxisID
* @param string $Unit
*/
public function setAxisUnit($AxisID, $Unit)
{
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Unit"] = $Unit;
}
}
/**
* Associate a name to an axis
* @param int $AxisID
* @param string $Name
*/
public function setAxisName($AxisID, $Name)
{
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Name"] = $Name;
}
}
/**
* Associate a color to an axis
* @param int $AxisID
* @param array $Format
*/
public function setAxisColor($AxisID, array $Format)
{
$R = isset($Format["R"]) ? $Format["R"] : 0;
$G = isset($Format["G"]) ? $Format["G"] : 0;
$B = isset($Format["B"]) ? $Format["B"] : 0;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Color"]["R"] = $R;
$this->Data["Axis"][$AxisID]["Color"]["G"] = $G;
$this->Data["Axis"][$AxisID]["Color"]["B"] = $B;
$this->Data["Axis"][$AxisID]["Color"]["Alpha"] = $Alpha;
}
}
/**
* Design an axis as X or Y member
* @param int $AxisID
* @param int $Identity
*/
public function setAxisXY($AxisID, $Identity = AXIS_Y)
{
if (isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Identity"] = $Identity;
}
}
/**
* Associate one data serie with one axis
* @param mixed $Series
* @param int $AxisID
*/
public function setSerieOnAxis($Series, $AxisID)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
$PreviousAxis = $this->Data["Series"][$Serie]["Axis"];
/* Create missing axis */
if (!isset($this->Data["Axis"][$AxisID])) {
$this->Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT;
$this->Data["Axis"][$AxisID]["Identity"] = AXIS_Y;
}
$this->Data["Series"][$Serie]["Axis"] = $AxisID;
/* Cleanup unused axis */
$Found = false;
foreach ($this->Data["Series"] as $Values) {
if ($Values["Axis"] == $PreviousAxis) {
$Found = true;
}
}
if (!$Found) {
unset($this->Data["Axis"][$PreviousAxis]);
}
}
}
/**
* Define if a serie should be draw with ticks
* @param mixed $Series
* @param int $Width
*/
public function setSerieTicks($Series, $Width = 0)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["Ticks"] = $Width;
}
}
}
/**
* Define if a serie should be draw with a special weight
* @param mixed $Series
* @param int $Weight
*/
public function setSerieWeight($Series, $Weight = 0)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Serie) {
if (isset($this->Data["Series"][$Serie])) {
$this->Data["Series"][$Serie]["Weight"] = $Weight;
}
}
}
/**
* Returns the palette of the given serie
* @param type $Serie
* @return null
*/
public function getSeriePalette($Serie)
{
if (!isset($this->Data["Series"][$Serie])) {
return null;
}
$Result = [];
$Result["R"] = $this->Data["Series"][$Serie]["Color"]["R"];
$Result["G"] = $this->Data["Series"][$Serie]["Color"]["G"];
$Result["B"] = $this->Data["Series"][$Serie]["Color"]["B"];
$Result["Alpha"] = $this->Data["Series"][$Serie]["Color"]["Alpha"];
return $Result;
}
/**
* Set the color of one serie
* @param mixed $Series
* @param array $Format
*/
public function setPalette($Series, array $Format = [])
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Key => $Serie) {
$R = isset($Format["R"]) ? $Format["R"] : 0;
$G = isset($Format["G"]) ? $Format["G"] : 0;
$B = isset($Format["B"]) ? $Format["B"] : 0;
$Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
if (isset($this->Data["Series"][$Serie])) {
$OldR = $this->Data["Series"][$Serie]["Color"]["R"];
$OldG = $this->Data["Series"][$Serie]["Color"]["G"];
$OldB = $this->Data["Series"][$Serie]["Color"]["B"];
$this->Data["Series"][$Serie]["Color"]["R"] = $R;
$this->Data["Series"][$Serie]["Color"]["G"] = $G;
$this->Data["Series"][$Serie]["Color"]["B"] = $B;
$this->Data["Series"][$Serie]["Color"]["Alpha"] = $Alpha;
/* Do reverse processing on the internal palette array */
foreach ($this->Palette as $Key => $Value) {
if ($Value["R"] == $OldR && $Value["G"] == $OldG && $Value["B"] == $OldB) {
$this->Palette[$Key]["R"] = $R;
$this->Palette[$Key]["G"] = $G;
$this->Palette[$Key]["B"] = $B;
$this->Palette[$Key]["Alpha"] = $Alpha;
}
}
}
}
}
/**
* Load a palette file
* @param string $FileName
* @param boolean $Overwrite
* @throws Exception
*/
public function loadPalette($FileName, $Overwrite = false)
{
$path = file_exists($FileName)
? $FileName
: sprintf('%s/../resources/palettes/%s', __DIR__, ltrim($FileName, '/'))
;
$fileHandle = @fopen($path, "r");
if (!$fileHandle) {
throw new Exception(sprintf(
'The requested palette "%s" was not found at path "%s"!',
$FileName,
$path
));
}
if ($Overwrite) {
$this->Palette = [];
}
while (!feof($fileHandle)) {
$line = fgets($fileHandle, 4096);
if (false === $line) {
continue;
}
$row = explode(',', $line);
if (empty($row)) {
continue;
}
if (count($row) !== 4) {
throw new RuntimeException(sprintf(
'A palette row must supply R, G, B and Alpha components, %s given!',
var_export($row, true)
));
}
list($R, $G, $B, $Alpha) = $row;
$ID = count($this->Palette);
$this->Palette[$ID] = [
"R" => trim($R),
"G" => trim($G),
"B" => trim($B),
"Alpha" => trim($Alpha)
];
}
fclose($fileHandle);
/* Apply changes to current series */
$ID = 0;
if (isset($this->Data["Series"])) {
foreach ($this->Data["Series"] as $Key => $Value) {
if (!isset($this->Palette[$ID])) {
$this->Data["Series"][$Key]["Color"] = ["R" => 0, "G" => 0, "B" => 0, "Alpha" => 0];
} else {
$this->Data["Series"][$Key]["Color"] = $this->Palette[$ID];
}
$ID++;
}
}
}
/**
* Initialise a given scatter serie
* @param int $ID
* @return null
*/
public function initScatterSerie($ID)
{
if (isset($this->Data["ScatterSeries"][$ID])) {
return null;
}
$this->Data["ScatterSeries"][$ID]["Description"] = "Scatter " . $ID;
$this->Data["ScatterSeries"][$ID]["isDrawable"] = true;
$this->Data["ScatterSeries"][$ID]["Picture"] = null;
$this->Data["ScatterSeries"][$ID]["Ticks"] = 0;
$this->Data["ScatterSeries"][$ID]["Weight"] = 0;
if (isset($this->Palette[$ID])) {
$this->Data["ScatterSeries"][$ID]["Color"] = $this->Palette[$ID];
} else {
$this->Data["ScatterSeries"][$ID]["Color"]["R"] = rand(0, 255);
$this->Data["ScatterSeries"][$ID]["Color"]["G"] = rand(0, 255);
$this->Data["ScatterSeries"][$ID]["Color"]["B"] = rand(0, 255);
$this->Data["ScatterSeries"][$ID]["Color"]["Alpha"] = 100;
}
}
/**
* Initialise a given serie
* @param string $Serie
*/
public function initialise($Serie)
{
$ID = 0;
if (isset($this->Data["Series"])) {
$ID = count($this->Data["Series"]);
}
$this->Data["Series"][$Serie]["Description"] = $Serie;
$this->Data["Series"][$Serie]["isDrawable"] = true;
$this->Data["Series"][$Serie]["Picture"] = null;
$this->Data["Series"][$Serie]["Max"] = null;
$this->Data["Series"][$Serie]["Min"] = null;
$this->Data["Series"][$Serie]["Axis"] = 0;
$this->Data["Series"][$Serie]["Ticks"] = 0;
$this->Data["Series"][$Serie]["Weight"] = 0;
$this->Data["Series"][$Serie]["Shape"] = SERIE_SHAPE_FILLEDCIRCLE;
if (isset($this->Palette[$ID])) {
$this->Data["Series"][$Serie]["Color"] = $this->Palette[$ID];
} else {
$this->Data["Series"][$Serie]["Color"]["R"] = rand(0, 255);
$this->Data["Series"][$Serie]["Color"]["G"] = rand(0, 255);
$this->Data["Series"][$Serie]["Color"]["B"] = rand(0, 255);
$this->Data["Series"][$Serie]["Color"]["Alpha"] = 100;
}
$this->Data["Series"][$Serie]["Data"] = [];
}
/**
* @param int $NormalizationFactor
* @param mixed $UnitChange
* @param int $Round
*/
public function normalize($NormalizationFactor = 100, $UnitChange = null, $Round = 1)
{
$Abscissa = $this->Data["Abscissa"];
$SelectedSeries = [];
$MaxVal = 0;
foreach (array_keys($this->Data["Axis"]) as $AxisID) {
if ($UnitChange != null) {
$this->Data["Axis"][$AxisID]["Unit"] = $UnitChange;
}
foreach ($this->Data["Series"] as $SerieName => $Serie) {
if ($Serie["Axis"] == $AxisID
&& $Serie["isDrawable"] == true
&& $SerieName != $Abscissa
) {
$SelectedSeries[$SerieName] = $SerieName;
if (count($Serie["Data"]) > $MaxVal) {
$MaxVal = count($Serie["Data"]);
}
}
}
}
for ($i = 0; $i <= $MaxVal - 1; $i++) {
$Factor = 0;
foreach ($SelectedSeries as $Key => $SerieName) {
$Value = $this->Data["Series"][$SerieName]["Data"][$i];
if ($Value != VOID) {
$Factor = $Factor + abs($Value);
}
}
if ($Factor != 0) {
$Factor = $NormalizationFactor / $Factor;
foreach ($SelectedSeries as $Key => $SerieName) {
$Value = $this->Data["Series"][$SerieName]["Data"][$i];
if ($Value != VOID && $Factor != $NormalizationFactor) {
$this->Data["Series"][$SerieName]["Data"][$i] = round(abs($Value) * $Factor, $Round);
} elseif ($Value == VOID || $Value == 0) {
$this->Data["Series"][$SerieName]["Data"][$i] = VOID;
} elseif ($Factor == $NormalizationFactor) {
$this->Data["Series"][$SerieName]["Data"][$i] = $NormalizationFactor;
}
}
}
}
foreach ($SelectedSeries as $Key => $SerieName) {
$this->Data["Series"][$SerieName]["Max"] = max(
$this->stripVOID($this->Data["Series"][$SerieName]["Data"])
);
$this->Data["Series"][$SerieName]["Min"] = min(
$this->stripVOID($this->Data["Series"][$SerieName]["Data"])
);
}
}
/**
* Load data from a CSV (or similar) data source
* @param string $FileName
* @param array $Options
*/
public function importFromCSV($FileName, array $Options = [])
{
$Delimiter = isset($Options["Delimiter"]) ? $Options["Delimiter"] : ",";
$GotHeader = isset($Options["GotHeader"]) ? $Options["GotHeader"] : false;
$SkipColumns = isset($Options["SkipColumns"]) ? $Options["SkipColumns"] : [-1];
$DefaultSerieName = isset($Options["DefaultSerieName"]) ? $Options["DefaultSerieName"] : "Serie";
$Handle = @fopen($FileName, "r");
if ($Handle) {
$HeaderParsed = false;
$SerieNames = [];
while (!feof($Handle)) {
$Buffer = fgets($Handle, 4096);
$Buffer = str_replace(chr(10), "", $Buffer);
$Buffer = str_replace(chr(13), "", $Buffer);
$Values = preg_split("/" . $Delimiter . "/", $Buffer);
if ($Buffer != "") {
if ($GotHeader && !$HeaderParsed) {
foreach ($Values as $Key => $Name) {
if (!in_array($Key, $SkipColumns)) {
$SerieNames[$Key] = $Name;
}
}
$HeaderParsed = true;
} else {
if (!count($SerieNames)) {
foreach ($Values as $Key => $Name) {
if (!in_array($Key, $SkipColumns)) {
$SerieNames[$Key] = $DefaultSerieName . $Key;
}
}
}
foreach ($Values as $Key => $Value) {
if (!in_array($Key, $SkipColumns)) {
$this->addPoints($Value, $SerieNames[$Key]);
}
}
}
}
}
fclose($Handle);
}
}
/**
* Create a dataset based on a formula
*
* @param string $SerieName
* @param string $Formula
* @param array $Options
* @return null
*/
public function createFunctionSerie($SerieName, $Formula = "", array $Options = [])
{
$MinX = isset($Options["MinX"]) ? $Options["MinX"] : -10;
$MaxX = isset($Options["MaxX"]) ? $Options["MaxX"] : 10;
$XStep = isset($Options["XStep"]) ? $Options["XStep"] : 1;
$AutoDescription = isset($Options["AutoDescription"]) ? $Options["AutoDescription"] : false;
$RecordAbscissa = isset($Options["RecordAbscissa"]) ? $Options["RecordAbscissa"] : false;
$AbscissaSerie = isset($Options["AbscissaSerie"]) ? $Options["AbscissaSerie"] : "Abscissa";
if ($Formula == "") {
return null;
}
$Result = [];
$Abscissa = [];
for ($i = $MinX; $i <= $MaxX; $i = $i + $XStep) {
$Expression = "\$return = '!'.(" . str_replace("z", $i, $Formula) . ");";
if (@eval($Expression) === false) {
$return = VOID;
}
if ($return == "!") {
$return = VOID;
} else {
$return = $this->right($return, strlen($return) - 1);
}
if ($return == "NAN") {
$return = VOID;
}
if ($return == "INF") {
$return = VOID;
}
if ($return == "-INF") {
$return = VOID;
}
$Abscissa[] = $i;
$Result[] = $return;
}
$this->addPoints($Result, $SerieName);
if ($AutoDescription) {
$this->setSerieDescription($SerieName, $Formula);
}
if ($RecordAbscissa) {
$this->addPoints($Abscissa, $AbscissaSerie);
}
}
/**
* @param mixed $Series
*/
public function negateValues($Series)
{
if (!is_array($Series)) {
$Series = $this->convertToArray($Series);
}
foreach ($Series as $Key => $SerieName) {
if (isset($this->Data["Series"][$SerieName])) {
$Data = [];
foreach ($this->Data["Series"][$SerieName]["Data"] as $Key => $Value) {
if ($Value == VOID) {
$Data[] = VOID;
} else {
$Data[] = -$Value;
}
}
$this->Data["Series"][$SerieName]["Data"] = $Data;
$this->Data["Series"][$SerieName]["Max"] = max(
$this->stripVOID($this->Data["Series"][$SerieName]["Data"])
);
$this->Data["Series"][$SerieName]["Min"] = min(
$this->stripVOID($this->Data["Series"][$SerieName]["Data"])
);
}
}
}
/**
* Return the data & configuration of the series
* @return array
*/
public function getData()
{
return $this->Data;
}
/**
* Save a palette element
*
* @param integer $ID
* @param string $Color
*/
public function savePalette($ID, $Color)
{
$this->Palette[$ID] = $Color;
}
/**
* Return the palette of the series
* @return array
*/
public function getPalette()
{
return $this->Palette;
}
/**
* Called by the scaling algorithm to save the config
* @param mixed $Axis
*/
public function saveAxisConfig($Axis)
{
$this->Data["Axis"] = $Axis;
}
/**
* Save the Y Margin if set
* @param mixed $Value
*/
public function saveYMargin($Value)
{
$this->Data["YMargin"] = $Value;
}
/**
* Save extended configuration to the pData object
* @param string $Tag
* @param mixed $Values
*/
public function saveExtendedData($Tag, $Values)
{
$this->Data["Extended"][$Tag] = $Values;
}
/**
* Called by the scaling algorithm to save the orientation of the scale
* @param mixed $Orientation
*/
public function saveOrientation($Orientation)
{
$this->Data["Orientation"] = $Orientation;
}
/**
* Convert a string to a single elements array
* @param mixed $Value
* @return array
*/
public function convertToArray($Value)
{
return [$Value];
}
/**
* Class string wrapper
* @return string
*/
public function __toString()
{
return "pData object.";
}
/**
* @param string $value
* @param int $NbChar
* @return string
*/
public function left($value, $NbChar)
{
return substr($value, 0, $NbChar);
}
/**
* @param string $value
* @param int $NbChar
* @return string
*/
public function right($value, $NbChar)
{
return substr($value, strlen($value) - $NbChar, $NbChar);
}
/**
* @param string $value
* @param int $Depart
* @param int $NbChar
* @return string
*/
public function mid($value, $Depart, $NbChar)
{
return substr($value, $Depart - 1, $NbChar);
}
}