PageRenderTime 37ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/library/openflashchart/graphs.php

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