| 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 | ?>
 | 
|---|