minor bug fix
[openemr.git] / library / openflashchart / graphs.php
blob933023d2ba5c31bf02b9906fb2b580683102b923
1 <?php
2 // Copyright (C) 2010 Brady Miller <brady@sparmy.com>
3 // Modified 2011 Rod Roark <rod@sunsetsystems.com>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // Flexible script for graphing entities in OpenEMR
12 //SANITIZE ALL ESCAPES
13 $sanitize_all_escapes=true;
16 //STOP FAKE REGISTER GLOBALS
17 $fake_register_globals=false;
20 require_once(dirname(__FILE__) . "/../../interface/globals.php");
21 require_once($GLOBALS['srcdir'] . "/openflashchart/php-ofc-library/open-flash-chart.php");
22 require_once($GLOBALS['srcdir'] . "/formdata.inc.php");
24 // Collect passed variable(s)
25 // $table is the sql table (or form name if LBF)
26 // $name identifies the desired data item
27 // $title is used as the title of the graph
28 $table = trim($_POST['table']);
29 $name = trim($_POST['name']);
30 $title = trim($_POST['title']);
32 $is_lbf = substr($table, 0, 3) === 'LBF';
34 // acl checks here
35 // For now, only allow access for med aco.
36 // This can be expanded depending on which table is accessed.
37 if (!acl_check('patients', 'med')) {
38 exit;
41 // Conversion functions/constants
42 function convertFtoC($a) {
43 return ($a-32)*0.5556;
45 function getLbstoKgMultiplier() {
46 return 0.45359237;
48 function getIntoCmMultiplier() {
49 return 2.54;
51 function getIdealYSteps($a) {
52 if ($a>1000) {
53 return 200;
55 else if ($a>500) {
56 return 100;
58 else if ($a>100) {
59 return 20;
61 else if ($a>50) {
62 return 10;
64 else {
65 return 5;
69 function graphsGetValues($name) {
70 global $is_lbf, $pid, $table;
71 if ($is_lbf) {
72 // Like below, but for LBF data.
73 $values = sqlStatement("SELECT " .
74 "ld.field_value AS " . add_escape_custom($name) . ", " .
75 "UNIX_TIMESTAMP(f.date) as unix_date " .
76 "FROM forms AS f, lbf_data AS ld WHERE " .
77 "f.pid = ? AND " .
78 "f.formdir = ? AND " .
79 "f.deleted = 0 AND " .
80 "ld.form_id = f.form_id AND " .
81 "ld.field_id = ? AND " .
82 "ld.field_value != '0' " .
83 "ORDER BY f.date",
84 array($pid, $table, $name));
86 else {
87 // Collect the pertinent info and ranges
88 // (Note am skipping values of zero, this could be made to be
89 // optional in the future when using lab values)
90 $values = SqlStatement("SELECT " .
91 add_escape_custom($name) . ", " .
92 "UNIX_TIMESTAMP(date) as unix_date " .
93 "FROM " . add_escape_custom($table) . " " .
94 "WHERE " . add_escape_custom($name) . " != 0 " .
95 "AND pid = ? ORDER BY date", array($pid));
97 return $values;
100 function graphsGetRanges($name) {
101 global $is_lbf, $pid, $table;
102 if ($is_lbf) {
103 // Like below, but for LBF data.
104 $ranges = sqlQuery("SELECT " .
105 "MAX(CONVERT(ld.field_value, SIGNED)) AS max_" . add_escape_custom($name) . ", " .
106 "MAX(UNIX_TIMESTAMP(f.date)) AS max_date, " .
107 "MIN(UNIX_TIMESTAMP(f.date)) AS min_date " .
108 "FROM forms AS f, lbf_data AS ld WHERE " .
109 "f.pid = ? AND " .
110 "f.formdir = ? AND " .
111 "f.deleted = 0 AND " .
112 "ld.form_id = f.form_id AND " .
113 "ld.field_id = ? AND " .
114 "ld.field_value != '0'",
115 array($pid, $table, $name));
117 else {
118 $ranges = SqlQuery("SELECT " .
119 "MAX(CONVERT(" . add_escape_custom($name) . ",SIGNED)) AS " .
120 "max_" . add_escape_custom($name) . ", " .
121 "MAX(UNIX_TIMESTAMP(date)) as max_date, " .
122 "MIN(UNIX_TIMESTAMP(date)) as min_date " .
123 "FROM " . add_escape_custom($table) . " " .
124 "WHERE " . add_escape_custom($name) . " != 0 " .
125 "AND pid = ?", array($pid));
127 return $ranges;
130 //Customizations (such as titles and conversions)
132 if ($is_lbf) {
133 $titleGraph = $title;
134 if ($name == 'bp_systolic' || $name == 'bp_diastolic') {
135 $titleGraph = xl("Blood Pressure") . " (" . xl("mmHg") . ")";
136 $titleGraphLine1 = xl("BP Systolic");
137 $titleGraphLine2 = xl("BP Diastolic");
140 else {
141 switch ($name) {
142 case "weight":
143 $titleGraph = $title." (".xl("lbs").")";
144 break;
145 case "weight_metric":
146 $titleGraph = $title." (".xl("kg").")";
147 $multiplier = getLbstoKgMultiplier();
148 $name = "weight";
149 break;
150 case "height":
151 $titleGraph = $title." (".xl("in").")";
152 break;
153 case "height_metric":
154 $titleGraph = $title." (".xl("cm").")";
155 $multiplier = getIntoCmMultiplier();
156 $name = "height";
157 break;
158 case "bps":
159 $titleGraph = xl("Blood Pressure")." (".xl("mmHg").")";
160 $titleGraphLine1 = xl("BP Systolic");
161 $titleGraphLine2 = xl("BP Diastolic");
162 break;
163 case "bpd":
164 $titleGraph = xl("Blood Pressure")." (".xl("mmHg").")";
165 $titleGraphLine1 = xl("BP Diastolic");
166 $titleGraphLine2 = xl("BP Systolic");
167 break;
168 case "pulse":
169 $titleGraph = $title." (".xl("per min").")";
170 break;
171 case "respiration":
172 $titleGraph = $title." (".xl("per min").")";
173 break;
174 case "temperature":
175 $titleGraph = $title." (".xl("F").")";
176 break;
177 case "temperature_metric":
178 $titleGraph = $title." (".xl("C").")";
179 $isConvertFtoC = 1;
180 $name="temperature";
181 break;
182 case "oxygen_saturation":
183 $titleGraph = $title." (".xl("%").")";
184 break;
185 case "head_circ":
186 $titleGraph = $title." (".xl("in").")";
187 break;
188 case "head_circ_metric":
189 $titleGraph = $title." (".xl("cm").")";
190 $multiplier = getIntoCmMultiplier();
191 $name="head_circ";
192 break;
193 case "waist_circ":
194 $titleGraph = $title." (".xl("in").")";
195 break;
196 case "waist_circ_metric":
197 $titleGraph = $title." (".xl("cm").")";
198 $multiplier = getIntoCmMultiplier();
199 $name="waist_circ";
200 break;
201 case "BMI":
202 $titleGraph = $title." (".xl("kg/m^2").")";
203 break;
204 default:
205 $titleGraph = $title;
209 // Collect info
210 if ($table) {
211 // Like below, but for LBF data.
212 $values = graphsGetValues($name);
213 $ranges = graphsGetRanges($name);
215 else {
216 exit;
219 // If less than 2 values, then exit
220 if (sqlNumRows($values) < 2) {
221 exit;
224 // If blood pressure, then collect the other reading to allow graphing both in same graph
225 $isBP = 0;
226 if ($is_lbf) {
227 if ($name == "bp_systolic" || $name == "bp_diastolic") {
228 // Set BP flag and collect other pressure reading
229 $isBP = 1;
230 if ($name == "bp_systolic") $name_alt = "bp_diastolic";
231 else $name_alt = "bp_systolic";
232 // Collect the pertinent vitals and ranges.
233 $values_alt = graphsGetValues($name_alt);
234 $ranges_alt = graphsGetRanges($name_alt);
237 else {
238 if ($name == "bps" || $name == "bpd") {
239 // Set BP flag and collect other pressure reading
240 $isBP = 1;
241 if ($name == "bps") $name_alt = "bpd";
242 if ($name == "bpd") $name_alt = "bps";
243 // Collect the pertinent vitals and ranges.
244 $values_alt = graphsGetValues($name_alt);
245 $ranges_alt = graphsGetRanges($name_alt);
249 // Prepare look and feel of data points
250 $s = new scatter_line( '#DB1750', 2 );
251 $def = new hollow_dot();
252 $def->size(4)->halo_size(3)->tooltip('#val#<br>#date:Y-m-d H:i#');
253 $s->set_default_dot_style( $def );
254 if ($isBP) {
255 //set up the other blood pressure line
256 $s_alt = new scatter_line( '#0000FF', 2 );
257 $s_alt->set_default_dot_style( $def );
260 // Prepare and insert data
261 $data = array();
262 while ($row = sqlFetchArray($values)) {
263 if ($row["$name"]) {
264 $x=$row['unix_date'];
265 if ($multiplier) {
266 // apply unit conversion multiplier
267 $y=$row["$name"]*$multiplier;
269 else if ($isConvertFtoC ) {
270 // apply temp F to C conversion
271 $y=convertFtoC($row["$name"]);
273 else {
274 // no conversion, so use raw value
275 $y=$row["$name"];
277 $data[] = new scatter_value($x, $y);
280 $s->set_values( $data );
281 if ($isBP) {
282 //set up the other blood pressure line
283 $data = array();
284 while ($row = sqlFetchArray($values_alt)) {
285 if ($row["$name_alt"]) {
286 $x=$row['unix_date'];
287 if ($multiplier) {
288 // apply unit conversion multiplier
289 $y=$row["$name_alt"]*$multiplier;
291 else if ($isConvertFtoC ) {
292 // apply temp F to C conversion
293 $y=convertFtoC($row["$name_alt"]);
295 else {
296 // no conversion, so use raw value
297 $y=$row["$name_alt"];
299 $data[] = new scatter_value($x, $y);
302 $s_alt->set_values( $data );
305 // Prepare the x-axis
306 $x = new x_axis();
307 $x->set_range( $ranges['min_date'], $ranges['max_date'] );
308 // Calculate the steps and visible steps
309 $step=($ranges['max_date'] - $ranges['min_date'])/60;
310 $step_vis=2;
311 // do not allow steps to be less than 1 day
312 if ($step < 86400) {
313 $step = 86400;
314 $step_vis=1;
316 $x->set_steps($step);
317 $labels = new x_axis_labels();
318 $labels->text('#date:Y-m-d#');
319 $labels->set_steps($step);
320 $labels->visible_steps($step_vis);
321 $labels->rotate(90);
322 $x->set_labels($labels);
324 // Prepare the y-axis
325 $y = new y_axis();
326 if ($name == "bpd") {
327 // in this special case use the alternate ranges (the bps)
328 if ($multiplier) {
329 // apply unit conversion multiplier
330 $maximum = $ranges_alt["max_"."$name_alt"]*$multiplier;
332 else if ($isConvertFtoC ) {
333 // apply temp F to C conversion
334 $maximum = convertFtoC( $ranges_alt["max_"."$name_alt"] );
336 else {
337 // no conversion, so use raw value
338 $maximum = $ranges_alt["max_"."$name_alt"];
341 else {
342 if ($multiplier) {
343 // apply unit conversion multiplier
344 $maximum = $ranges["max_"."$name"]*$multiplier;
346 else if ($isConvertFtoC ) {
347 // apply temp F to C conversion
348 $maximum = convertFtoC( $ranges["max_"."$name"] );
350 else {
351 // no conversion, so use raw value
352 $maximum = $ranges["max_"."$name"];
355 // set the range and y-step
356 $y->set_range( 0 , $maximum + getIdealYSteps( $maximum ) );
357 $y->set_steps( getIdealYSteps( $maximum ) );
359 // Build and show the chart
360 $chart = new open_flash_chart();
361 $chart->set_title( new Title( $titleGraph ));
362 if ($isBP) {
363 // Set up both bp lines
364 $s -> set_key( $titleGraphLine1 , 10 );
365 $chart->add_element( $s );
366 $s_alt -> set_key( $titleGraphLine2 , 10 );
367 $chart->add_element( $s_alt );
369 else {
370 // Set up the line
371 $chart->add_element( $s );
373 $chart->set_x_axis( $x );
374 $chart->add_y_axis( $y );
376 //error_log("Chart: ".$chart->toPrettyString(),0);
378 echo $chart->toPrettyString();