VistA-PGC/GrowthChart.class.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();
}
}
?>