[959] | 1 | <?php
|
---|
| 2 |
|
---|
| 3 | include ("jpgraph-2.1.1/src/jpgraph.php");
|
---|
| 4 | include ("jpgraph-2.1.1/src/jpgraph_line.php");
|
---|
| 5 | include ("jpgraph-2.1.1/src/jpgraph_regstat.php");
|
---|
| 6 |
|
---|
| 7 | /**
|
---|
| 8 | * GrowthChart class
|
---|
| 9 | *
|
---|
| 10 | * @author Jonathan Abbett <jonathan.abbett@childrens.harvard.edu>
|
---|
| 11 | * @version 1.1
|
---|
| 12 | * @copyright Jonathan Abbett and Children's Hospital Informatics Program, 2007
|
---|
| 13 | *
|
---|
| 14 | */
|
---|
| 15 | class GrowthChart
|
---|
| 16 | {
|
---|
| 17 | /**
|
---|
| 18 | * Male sex
|
---|
| 19 | *
|
---|
| 20 | */
|
---|
| 21 | const SEX_MALE = 1;
|
---|
| 22 | /**
|
---|
| 23 | * Female sex
|
---|
| 24 | *
|
---|
| 25 | */
|
---|
| 26 | const SEX_FEMALE = 2;
|
---|
| 27 |
|
---|
| 28 | private $style;
|
---|
| 29 | private $title;
|
---|
| 30 | private $sex;
|
---|
| 31 | private $maxAgeMonths;
|
---|
| 32 | private $patientXarray;
|
---|
| 33 | private $patientYarray;
|
---|
| 34 | private $width;
|
---|
| 35 | private $height;
|
---|
| 36 | /**
|
---|
| 37 | * Constructor, used to initialize necessary variables.
|
---|
| 38 | *
|
---|
| 39 | * @param string $style Chart style, from available dataset filenames, i.e. bmi-age, weight-length
|
---|
| 40 | * @param string $title Title for the graph, provided by M program
|
---|
| 41 | * @param integer $sex Patient sex, from available SEX constants
|
---|
| 42 | * @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.)
|
---|
| 43 | * @param integer $width Width of chart in pixels
|
---|
| 44 | * @param integer $height Height of chart in pixels
|
---|
| 45 | * @param array $patientXarray Array of decimals for patient X data (i.e. age in months)
|
---|
| 46 | * @param array $patientYarray Array of decimals for patient Y data (i.e. length, height, BMI, etc.)
|
---|
| 47 | * @return GrowthChart
|
---|
| 48 | */
|
---|
| 49 | public function GrowthChart($style, $title = null, $sex, $maxAgeMonths, $width = 800, $height = 800, $patientXarray = null, $patientYarray = null)
|
---|
| 50 | {
|
---|
| 51 | $this->style = $style;
|
---|
| 52 | $this->title = $title;
|
---|
| 53 | $this->sex = $sex;
|
---|
| 54 | $this->maxAgeMonths = $maxAgeMonths;
|
---|
| 55 | $this->width = $width;
|
---|
| 56 | $this->height = $height;
|
---|
| 57 | $this->patientXarray = $patientXarray;
|
---|
| 58 | $this->patientYarray = $patientYarray;
|
---|
| 59 | }
|
---|
| 60 |
|
---|
| 61 | private static function generateSourceXData($min, $max) {
|
---|
| 62 |
|
---|
| 63 | $data = array();
|
---|
| 64 |
|
---|
| 65 | $data[] = $min;
|
---|
| 66 |
|
---|
| 67 | for ($i = $min + 0.5; $i < $max; $i++) {
|
---|
| 68 | $data[] = $i;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | $data[] = $max;
|
---|
| 72 |
|
---|
| 73 | return $data;
|
---|
| 74 |
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | /**
|
---|
| 78 | * Renders the chart, outputting a PNG image.
|
---|
| 79 | *
|
---|
| 80 | */
|
---|
| 81 | public function render()
|
---|
| 82 | {
|
---|
| 83 |
|
---|
| 84 | // Create and set-up the graph
|
---|
| 85 | $g = new Graph($this->width, $this->height, "auto");
|
---|
| 86 | $g->SetColor('white');
|
---|
| 87 | $g->SetFrame(false);
|
---|
| 88 | $g->SetMargin(25,20,20,25);
|
---|
| 89 | $g->SetMarginColor('white');
|
---|
| 90 | // Load data from XML
|
---|
| 91 |
|
---|
| 92 | if ($this->sex == GrowthChart::SEX_MALE) {
|
---|
| 93 | $this->style .= '-male';
|
---|
| 94 | } else {
|
---|
| 95 | $this->style .= '-female';
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | if ($this->maxAgeMonths <= 36) {
|
---|
| 99 | $this->style .= '-infant';
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | $xml = simplexml_load_file("data/$this->style.xml");
|
---|
| 103 |
|
---|
| 104 | $xdata = GrowthChart::generateSourceXData((float)$xml->sourceXStart, (float)$xml->sourceXEnd);
|
---|
| 105 |
|
---|
| 106 | $g->SetScale("linlin", (float)$xml->yMin, (float)$xml->yMax, (float)$xml->xMin, (float)$xml->xMax);
|
---|
| 107 | if ((float)$xml->ticksMajor != 0) {
|
---|
| 108 | $g->yscale->ticks->Set((float)$xml->ticksMajor, (float)$xml->ticksMinor);
|
---|
| 109 | }
|
---|
| 110 | $g->xaxis->SetLabelFormat('%1.1f');
|
---|
| 111 | $g->xaxis->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
---|
| 112 | $g->xgrid->Show(true);
|
---|
| 113 | $g->yaxis->HideZeroLabel();
|
---|
| 114 | $g->yaxis->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
---|
| 115 | $g->ygrid->SetFill(true,'#EFEFEF@0.5','#FFFFFF@0.5');
|
---|
| 116 | if (!empty($this->title))
|
---|
| 117 | {
|
---|
| 118 | $g->title->Set($this->title);
|
---|
| 119 | $g->title->SetColor("red");
|
---|
| 120 | $g->title->SetFont( FF_FONT2, FS_BOLD);
|
---|
| 121 | }
|
---|
| 122 | $xml = simplexml_load_file("data/$this->style.xml");
|
---|
| 123 |
|
---|
| 124 |
|
---|
| 125 | foreach ($xml->percentile as $p) {
|
---|
| 126 |
|
---|
| 127 | $percentile = $p->label;
|
---|
| 128 | $yp = array();
|
---|
| 129 |
|
---|
| 130 | foreach ($p->value as $value) {
|
---|
| 131 | $yp[] = (float)$value;
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | // Create the spline
|
---|
| 135 | $spline = new Spline($xdata, $yp);
|
---|
| 136 |
|
---|
| 137 | // Get smoothed points
|
---|
| 138 | list($newx, $newy) = $spline->Get(100);
|
---|
| 139 |
|
---|
| 140 | $lplot = new LinePlot($newy, $newx);
|
---|
| 141 | $lplot->SetColor('#CCCCCC');
|
---|
| 142 |
|
---|
| 143 | if ($percentile == '50')
|
---|
| 144 | {
|
---|
| 145 | $lplot->SetColor('#666666');
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | // Add the plots to the graph and stroke
|
---|
| 149 | $g->Add($lplot);
|
---|
| 150 |
|
---|
| 151 | // Add percentile label to graph
|
---|
| 152 | $txt = new Text($percentile . ($percentile == '3' ? 'rd' : 'th'));
|
---|
| 153 | $txt->SetScalePos($xdata[sizeof($xdata)-1]+(float)$xml->percentileXNudge,$yp[sizeof($yp)-1]+(float)$xml->percentileYNudge);
|
---|
| 154 | $txt->SetColor('#666666');
|
---|
| 155 | $txt->SetFont(FF_TREBUCHE, FS_NORMAL, 9);
|
---|
| 156 | $g->AddText($txt);
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | if (!empty($this->patientXarray) && !empty($this->patientYarray) && sizeof($this->patientXarray) == sizeof($this->patientYarray))
|
---|
| 160 | {
|
---|
| 161 | $patientPlot = new LinePlot($this->patientYarray, $this->patientXarray);
|
---|
| 162 | $patientPlot->SetColor('orange');
|
---|
| 163 | $patientPlot->SetWeight(3);
|
---|
| 164 | $patientPlot->value->Show();
|
---|
| 165 | $patientPlot->value->SetColor('brown');
|
---|
| 166 | $patientPlot->value->SetFont(FF_COURIER, FS_BOLD);
|
---|
| 167 | $patientPlot->value->SetAlign('left', 'top');
|
---|
| 168 | $patientPlot->value->SetMargin(-5);
|
---|
| 169 | $patientPlot->mark->SetType(MARK_DIAMOND);
|
---|
| 170 | $patientPlot->mark->SetWidth(7);
|
---|
| 171 | $patientPlot->mark->SetColor('orange');
|
---|
| 172 | $patientPlot->mark->SetFillColor('red');
|
---|
| 173 |
|
---|
| 174 | $g->Add($patientPlot);
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 | $g->Stroke();
|
---|
| 178 | }
|
---|
| 179 | }
|
---|
| 180 |
|
---|
| 181 | ?>
|
---|