5 # Part of the Collection Workflow Integration System (CWIS) 6 # Copyright 2017 Edward Almasy and Internet Scout Research Group 7 # http://scout.wisc.edu/cwis/ 15 # ---- PUBLIC INTERFACE -------------------------------------------------- 28 # if data provided is an array of arrays, then just copy it in 29 if (is_array(reset(
$Data)))
33 # otherwise, normalize to array of arrays format 36 $this->SingleCategory = TRUE;
41 foreach (
$Data as $Name => $Val)
43 $this->Data[$Name] = [$Name => $Val];
60 self::AXIS_TIME_DAILY,
61 self::AXIS_TIME_WEEKLY,
62 self::AXIS_TIME_MONTHLY,
63 self::AXIS_TIME_YEARLY,
66 # toss exception if the given type is not valid 67 if (!in_array($NewValue, $ValidTypes))
69 throw new Exception(
"Invalid axis type for bar charts: ".$NewValue);
72 # otherwise, save the new type and clear any cached chart data 89 public function Zoom($NewValue)
91 $this->
Zoom = $NewValue;
138 # ---- PRIVATE INTERFACE -------------------------------------------------- 147 # [ CatNameOrTimestamp => [Data1 => Val, Data2 => Val, ...], ... ] 149 # and the format that C3 expects is 150 # [ "Data1", Val, Val, ... ] 151 # [ "Data2", Val, Val, ... ] 153 # extract the names of all the bars 155 foreach ($this->Data as $Entries)
157 foreach ($Entries as $BarName => $YVal)
159 $BarNames[$BarName] = 1;
162 $BarNames = array_keys($BarNames);
164 # start the chart off with no data 165 $this->Chart[
"data"][
"columns"] = [];
167 if ($this->
AxisType == self::AXIS_CATEGORY)
169 # for categorical plots, data stays in place 175 $this->Chart[
"axis"][
"x"][
"categories"] =
180 $this->Chart[
"axis"][
"x"][
"categories"] =
181 array_fill(0, count($BarNames),
"");
184 # and fix up the display for single-category charts 185 if ($this->SingleCategory)
187 $this->Chart[
"tooltip"][
"grouped"] = FALSE;
192 # for time series data, we need to sort our data into bins 195 # convert our timestamps to JS-friendly date strings 196 $Timestamps = array_keys(
$Data);
197 array_walk($Timestamps,
function(&$Val, $Key)
199 $Val = strftime(
"%Y-%m-%d", $Val);
201 array_unshift($Timestamps,
"x-timestamp-x");
203 # add this in to our data columns 204 $this->Chart[
"data"][
"columns"][]= $Timestamps;
207 # generate one row of data per bar to use for plotting 208 foreach ($BarNames as $BarName)
213 $this->LabelLUT[$MyLabel] = $BarName;
220 $DataRow = [$MyLabel];
221 foreach (
$Data as $Entries)
223 $DataRow[]= isset($Entries[$BarName]) ? $Entries[$BarName] : 0;
225 $this->Chart[
"data"][
"columns"][] = $DataRow;
228 $this->Chart[
"data"][
"type"] =
"bar";
230 if ($this->
AxisType == self::AXIS_CATEGORY)
232 $this->Chart[
"axis"][
"x"][
"type"] =
"category";
238 "x" =>
"x-timestamp-x",
239 "xFormat" =>
"%Y-%m-%d",
243 "type" =>
"timeseries",
249 if (!is_null($this->
YLabel))
256 $this->Chart[
"zoom"][
"enabled"] = TRUE;
261 $this->Chart[
"data"][
"groups"] = [
268 $this->Chart[
"axis"][
"rotated"] = TRUE;
273 $this->Chart[
"grid"][
"y"][
"show"] = TRUE;
286 # create an array to store the binned data 289 # iterate over all our input data. 290 foreach ($this->Data as $TS => $Entries)
292 # place this timestamp in the appropriate bin 295 # if we have no results in this bin, then these are 297 if (!isset($BinnedData[$TS]))
299 $BinnedData[$TS] = $Entries;
303 # otherwise, iterate over the keys we were given 304 foreach ($Entries as $Key => $Val)
306 # if we have a value for this key 307 if (isset($BinnedData[$TS][$Key]))
309 # then add this new value to it 310 $BinnedData[$TS][$Key] += $Val;
314 # otherwise, insert the new value 315 $BinnedData[$TS][$Key] = $Val;
324 # build up a revised data set with no gaps 326 # prime the revised set with the first element 327 $GaplessData[key($BinnedData)] = current($BinnedData);
329 # iterate over the remaining elements 330 while (($Row = next($BinnedData)) !== FALSE)
334 # if the next element is not the next bin, add an empty element 335 while (key($BinnedData) != $this->
NextBin(key($GaplessData)))
337 $GaplessData[$this->
NextBin(key($GaplessData))] =
338 array_fill_keys($BarNames, 0);
341 if ($BinsAdded > 1000)
344 "Over 1000 empty bins added. " 345 .
"Terminating possible infinite loop.");
349 # and add the current element 350 $GaplessData[key($BinnedData)] = $Row;
364 if (!preg_match(
"/^[0-9]+$/", $TS))
366 $TS = strtotime($TS);
371 case self::AXIS_TIME_DAILY:
372 return strtotime(strftime(
"%Y-%m-%d 00:00:00", $TS));
375 case self::AXIS_TIME_WEEKLY:
376 $DateInfo = strptime(strftime(
377 "%Y-%m-%d 00:00:00", $TS),
"%Y-%m-%d %H:%M:%S");
379 $Year = $DateInfo[
"tm_year"] + 1900;
380 $Month = $DateInfo[
"tm_mon"] + 1;
381 $Day = $DateInfo[
"tm_mday"] - $DateInfo[
"tm_wday"];
383 return mktime(0, 0, 0, $Month, $Day, $Year);
386 case self::AXIS_TIME_MONTHLY:
387 return strtotime(strftime(
"%Y-%m-01 00:00:00", $TS));
390 case self::AXIS_TIME_YEARLY:
391 return strtotime(strftime(
"%Y-01-01 00:00:00", $TS));
403 $ThisBin = strftime(
"%Y-%m-%d %H:%M:%S", $BinTS);
405 self::AXIS_TIME_DAILY =>
"day",
406 self::AXIS_TIME_WEEKLY =>
"week",
407 self::AXIS_TIME_MONTHLY =>
"month",
408 self::AXIS_TIME_YEARLY =>
"year",
411 return strtotime($ThisBin.
" + 1 ".$Units[$this->AxisType]);
423 foreach ($LongNames as $Name)
__construct($Data)
Class constructor.
YLabel($NewValue)
Set the Y axis label for a bar chart.
Base class for generating and displaying a chart.
Zoom($NewValue)
Enable/Disable zooming for this chart.
ShowCategoryLabels($NewValue)
Enable/disable display of category labels along the X axis on categorical charts (by default...
LegendLabels($LegendLabels)
Set shortened labels to be used in the legend of the chart.
NextBin($BinTS)
Get the next bin.
Gridlines($NewValue)
Enable/disable display of grid lines.
BinTimestamp($TS)
Determine which bin a specified timestamp belongs in.
AddToChart($Data)
Merge an array of settings into $this->Chart.
AxisType($NewValue)
Set the axis type of a bar chart (default is AXIS_CATEGORY).
Horizontal($NewValue)
Enable/disable horizontal display.
ShortCategoryNames($LongNames)
Get abbreviated category names (e.g., for the legend).
Stacked($NewValue)
Enable/Disable bar stacking.
PrepareData()
Prepare data for plotting.
LegendPosition($Position)
Set legend position.
Class for generating and displaying a bar chart.
SortDataIntoBins($BarNames)
Sort the user-provided data into bins with sizes given by $this->AxisType, filling in any gaps in the...