181 lines
6.6 KiB
PHP
181 lines
6.6 KiB
PHP
|
<?php
|
||
|
|
||
|
include ("jpgraph-2.1.1/src/jpgraph.php");
|
||
|
include ("jpgraph-2.1.1/src/jpgraph_line.php");
|
||
|
include ("jpgraph-2.1.1/src/jpgraph_regstat.php");
|
||
|
|
||
|
/**
|
||
|
* GrowthChart class
|
||
|
*
|
||
|
* @author Jonathan Abbett <jonathan.abbett@childrens.harvard.edu>
|
||
|
* @version 1.1
|
||
|
* @copyright Jonathan Abbett and Children's Hospital Informatics Program, 2007
|
||
|
*
|
||
|
*/
|
||
|
class GrowthChart
|
||
|
{
|
||
|
/**
|
||
|
* Male sex
|
||
|
*
|
||
|
*/
|
||
|
const SEX_MALE = 1;
|
||
|
/**
|
||
|
* Female sex
|
||
|
*
|
||
|
*/
|
||
|
const SEX_FEMALE = 2;
|
||
|
|
||
|
private $style;
|
||
|
private $title;
|
||
|
private $sex;
|
||
|
private $maxAgeMonths;
|
||
|
private $patientXarray;
|
||
|
private $patientYarray;
|
||
|
private $width;
|
||
|
private $height;
|
||
|
/**
|
||
|
* Constructor, used to initialize necessary variables.
|
||
|
*
|
||
|
* @param string $style Chart style, from available dataset filenames, i.e. bmi-age, weight-length
|
||
|
* @param string $title Title for the graph, provided by M program
|
||
|
* @param integer $sex Patient sex, from available SEX constants
|
||
|
* @param decimal $maxAgeMonths The greatest patient age used in the chart, used to decide whether chart is infant (0-36 mo.) or regular (2-20 yrs.)
|
||
|
* @param integer $width Width of chart in pixels
|
||
|
* @param integer $height Height of chart in pixels
|
||
|
* @param array $patientXarray Array of decimals for patient X data (i.e. age in months)
|
||
|
* @param array $patientYarray Array of decimals for patient Y data (i.e. length, height, BMI, etc.)
|
||
|
* @return GrowthChart
|
||
|
*/
|
||
|
public function GrowthChart($style, $title = null, $sex, $maxAgeMonths, $width = 800, $height = 800, $patientXarray = null, $patientYarray = null)
|
||
|
{
|
||
|
$this->style = $style;
|
||
|
$this->title = $title;
|
||
|
$this->sex = $sex;
|
||
|
$this->maxAgeMonths = $maxAgeMonths;
|
||
|
$this->width = $width;
|
||
|
$this->height = $height;
|
||
|
$this->patientXarray = $patientXarray;
|
||
|
$this->patientYarray = $patientYarray;
|
||
|
}
|
||
|
|
||
|
private static function generateSourceXData($min, $max) {
|
||
|
|
||
|
$data = array();
|
||
|
|
||
|
$data[] = $min;
|
||
|
|
||
|
for ($i = $min + 0.5; $i < $max; $i++) {
|
||
|
$data[] = $i;
|
||
|
}
|
||
|
|
||
|
$data[] = $max;
|
||
|
|
||
|
return $data;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renders the chart, outputting a PNG image.
|
||
|
*
|
||
|
*/
|
||
|
public function render()
|
||
|
{
|
||
|
|
||
|
// Create and set-up the graph
|
||
|
$g = new Graph($this->width, $this->height, "auto");
|
||
|
$g->SetColor('white');
|
||
|
$g->SetFrame(false);
|
||
|
$g->SetMargin(25,20,20,25);
|
||
|
$g->SetMarginColor('white');
|
||
|
// Load data from XML
|
||
|
|
||
|
if ($this->sex == GrowthChart::SEX_MALE) {
|
||
|
$this->style .= '-male';
|
||
|
} else {
|
||
|
$this->style .= '-female';
|
||
|
}
|
||
|
|
||
|
if ($this->maxAgeMonths <= 36) {
|
||
|
$this->style .= '-infant';
|
||
|
}
|
||
|
|
||
|
$xml = simplexml_load_file("data/$this->style.xml");
|
||
|
|
||
|
$xdata = GrowthChart::generateSourceXData((float)$xml->sourceXStart, (float)$xml->sourceXEnd);
|
||
|
|
||
|
$g->SetScale("linlin", (float)$xml->yMin, (float)$xml->yMax, (float)$xml->xMin, (float)$xml->xMax);
|
||
|
if ((float)$xml->ticksMajor != 0) {
|
||
|
$g->yscale->ticks->Set((float)$xml->ticksMajor, (float)$xml->ticksMinor);
|
||
|
}
|
||
|
$g->xaxis->SetLabelFormat('%1.1f');
|
||
|
$g->xaxis->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
||
|
$g->xgrid->Show(true);
|
||
|
$g->yaxis->HideZeroLabel();
|
||
|
$g->yaxis->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
||
|
$g->ygrid->SetFill(true,'#EFEFEF@0.5','#FFFFFF@0.5');
|
||
|
if (!empty($this->title))
|
||
|
{
|
||
|
$g->title->Set($this->title);
|
||
|
$g->title->SetColor("red");
|
||
|
$g->title->SetFont( FF_FONT2, FS_BOLD);
|
||
|
}
|
||
|
$xml = simplexml_load_file("data/$this->style.xml");
|
||
|
|
||
|
|
||
|
foreach ($xml->percentile as $p) {
|
||
|
|
||
|
$percentile = $p->label;
|
||
|
$yp = array();
|
||
|
|
||
|
foreach ($p->value as $value) {
|
||
|
$yp[] = (float)$value;
|
||
|
}
|
||
|
|
||
|
// Create the spline
|
||
|
$spline = new Spline($xdata, $yp);
|
||
|
|
||
|
// Get smoothed points
|
||
|
list($newx, $newy) = $spline->Get(100);
|
||
|
|
||
|
$lplot = new LinePlot($newy, $newx);
|
||
|
$lplot->SetColor('#CCCCCC');
|
||
|
|
||
|
if ($percentile == '50')
|
||
|
{
|
||
|
$lplot->SetColor('#666666');
|
||
|
}
|
||
|
|
||
|
// Add the plots to the graph and stroke
|
||
|
$g->Add($lplot);
|
||
|
|
||
|
// Add percentile label to graph
|
||
|
$txt = new Text($percentile . ($percentile == '3' ? 'rd' : 'th'));
|
||
|
$txt->SetScalePos($xdata[sizeof($xdata)-1]+(float)$xml->percentileXNudge,$yp[sizeof($yp)-1]+(float)$xml->percentileYNudge);
|
||
|
$txt->SetColor('#666666');
|
||
|
$txt->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
||
|
$g->AddText($txt);
|
||
|
}
|
||
|
|
||
|
if (!empty($this->patientXarray) && !empty($this->patientYarray) && sizeof($this->patientXarray) == sizeof($this->patientYarray))
|
||
|
{
|
||
|
$patientPlot = new LinePlot($this->patientYarray, $this->patientXarray);
|
||
|
$patientPlot->SetColor('orange');
|
||
|
$patientPlot->SetWeight(3);
|
||
|
$patientPlot->value->Show();
|
||
|
$patientPlot->value->SetColor('brown');
|
||
|
$patientPlot->value->SetFont(FF_COURIER, FS_BOLD);
|
||
|
$patientPlot->value->SetAlign('left', 'top');
|
||
|
$patientPlot->value->SetMargin(-5);
|
||
|
$patientPlot->mark->SetType(MARK_DIAMOND);
|
||
|
$patientPlot->mark->SetWidth(7);
|
||
|
$patientPlot->mark->SetColor('orange');
|
||
|
$patientPlot->mark->SetFillColor('red');
|
||
|
|
||
|
$g->Add($patientPlot);
|
||
|
}
|
||
|
|
||
|
$g->Stroke();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
?>
|