1 """This widgets lets you manage laboratory requests
2
3 - add requests
4 - keep track of pending requests
5 - see import errors
6 - review newly imported lab results
7 """
8
9
10 __version__ = "$Revision: 1.33 $"
11 __author__ = "Sebastian Hilbert <Sebastian.Hilbert@gmx.net>"
12
13 import os.path, sys, os, re as regex, random, logging
14
15
16
17 import wx
18 import wx.lib.mixins.listctrl as listmixins
19
20
21 from Gnumed.pycommon import gmI18N, gmPG2, gmCfg, gmExceptions, gmMatchProvider, gmDispatcher
22 from Gnumed.business import gmPerson, gmClinicalRecord, gmPathLab, gmStaff
23 from Gnumed.wxpython import gmGuiHelpers, gmPhraseWheel
24
25 _log = gmLog.gmDefLog
26 if __name__ == '__main__':
27 _log.SetAllLogLevels(gmLog.lData)
28 _log.Log(gmLog.lInfo, __version__)
29
30 [ wx.ID_LAB_GRID,
31 wx.ID_NB_LabJournal,
32 wx.ID_LBOX_pending_results,
33 wx.ID_PHRWH_labs,
34 wx.ID_TextCtrl_req_id,
35 wx.ID_BTN_save_request_ID,
36 wx.ID_BTN_select_all,
37 wx.ID_BTN_mark_reviewed,
38 wx.ID_pending_requests,
39 wx.ID_lbox_errors,
40 wx.ID_grid_unreviewed_results
41 ] = map(lambda _init_ctrls: wx.NewId(), range(11))
42
46
47 - def Draw(self, grid, attr, dc, rect, row, col, isSelected):
48 dc.SetBackgroundMode(wx.SOLID)
49 dc.SetBrush(wx.Brush(wx.BLACK, wx.SOLID))
50 dc.SetPen(wx.TRANSPARENT_PEN)
51 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
52
53 dc.SetBackgroundMode(wx.TRANSPARENT)
54 dc.SetFont(attr.GetFont())
55
56 text = grid.GetCellValue(row, col)
57 colors = [wxRED, wx.WHITE, wx.CYAN]
58 x = rect.x + 1
59 y = rect.y + 1
60 for ch in text:
61 dc.SetTextForeground(random.choice(colors))
62 dc.DrawText(ch, x, y)
63 w, h = dc.GetTextExtent(ch)
64 x = x + w
65 if x > rect.right - 5:
66 break
67
68
70 text = grid.GetCellValue(row, col)
71 dc.SetFont(attr.GetFont())
72 w, h = dc.GetTextExtent(text)
73 return wx.Size(w, h)
74
75
78
82
83 - def Draw(self, grid, attr, dc, rect, row, col, isSelected):
84 dc.SetBackgroundMode(wx.SOLID)
85 dc.SetBrush(wx.Brush(wx.BLACK, wx.SOLID))
86 dc.SetPen(wx.TRANSPARENT_PEN)
87 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
88 dc.SetBackgroundMode(wx.TRANSPARENT)
89 dc.SetFont(attr.GetFont())
90
91 text = grid.GetCellValue(row, col)
92 colors = [wxRED, wx.WHITE, wx.CYAN]
93 x = rect.x + 1
94 y = rect.y + 1
95 for ch in text:
96 dc.SetTextForeground(random.choice(colors))
97 dc.DrawText(ch, x, y)
98 w, h = dc.GetTextExtent(ch)
99 x = x + w
100 if x > rect.right - 5:
101 break
102
103
105 """This wx.Grid derivative displays lab data that has not yet been reviewed by a clinician.
106 """
108 """Set up our specialised grid.
109 """
110 wx.Grid.__init__(
111 self,
112 parent,
113 id,
114 pos = wx.DefaultPosition,
115 size = wx.DefaultSize,
116 style= wx.WANTS_CHARS
117 )
118
121 query = """
122 select pk, internal_OBSOLETE_name
123 from test_org
124 """
125 mp = gmMatchProvider.cMatchProvider_SQL2([query])
126 mp.setThresholds(aWord=2, aSubstring=4)
127
128 gmPhraseWheel.cPhraseWheel.__init__(
129 self,
130 parent = parent,
131 id = -1,
132 size = wx.DefaultSize,
133 pos = wx.DefaultPosition
134 )
135 self.SetToolTipString(_('choose which lab will process the probe with the specified ID'))
136 self.matcher = mp
137
138
140 - def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
141 wx.ListCtrl.__init__(self, parent, id, pos, size, style)
142 wx.ListCtrlAutoWidthMixin.__init__(self)
143
144
146 """This wx.Notebook derivative displays 'records still due' and lab-import related errors.
147 """
149 """Set up our specialised notebook.
150 """
151 wx.Notebook.__init__(
152 self,
153 parent,
154 id,
155 wx.DefaultPosition,
156 wx.DefaultSize,
157 0
158 )
159
160 self.__pat = gmPerson.gmCurrentPatient()
161
162 self.__do_layout_requests_page()
163 self.__do_layout_errors_page()
164 self.__do_layout_review_page()
165 self.__do_layout_config_page()
166
167 self.__register_events()
168
170 pnl_page = wx.Panel(self, -1)
171
172
173
174 szr_page = wx.BoxSizer(wx.VERTICAL)
175
176
177
178 pnl_page.SetAutoLayout(True)
179 pnl_page.SetSizer(szr_page)
180 szr_page.Fit(pnl_page)
181 szr_page.SetSizeHints(pnl_page)
182
183 self.AddPage(pnl_page, _("lab config"))
184
186
187 pnl_page = wx.Panel(self, -1)
188
189
190 hbszr = wx.StaticBoxSizer(
191 wx.StaticBox(
192 pnl_page,
193 -1,
194 _("add new request for current patient")
195 ),
196 wx.HORIZONTAL
197 )
198
199 lab_label = wx.StaticText(
200 name = 'lablabel',
201 parent = pnl_page,
202 id = -1,
203 label = _('Lab')
204 )
205
206 self.lab_wheel = cLabWheel(pnl_page)
207 self.lab_wheel.on_resize (None)
208 self.lab_wheel.add_callback_on_selection(self.on_lab_selected)
209
210 req_id_label = wx.StaticText(
211 name = 'req_id_label',
212 parent = pnl_page,
213 id = -1,
214 label = _("Specimen ID")
215 )
216
217 self.fld_request_id = wx.TextCtrl (
218 pnl_page,
219 wx.ID_TextCtrl_req_id,
220 "",
221 wx.DefaultPosition,
222 wx.Size(80,-1),
223 0
224 )
225
226 self.BTN_save_request_ID = wx.Button(
227 name = 'BTN_save_request_ID',
228 parent = pnl_page,
229 id = wx.ID_BTN_save_request_ID,
230 label = _("save lab request")
231 )
232 self.BTN_save_request_ID.SetToolTipString(_('associate chosen lab and ID with current patient'))
233
234 hbszr.Add(lab_label, 0, wx.ALIGN_CENTER | wx.ALL, 5)
235 hbszr.Add(self.lab_wheel, 0, wx.ALIGN_CENTER | wx.ALL, 5)
236 hbszr.Add(req_id_label, 0, wx.ALIGN_CENTER | wx.ALL, 5)
237 hbszr.Add(self.fld_request_id, 0, wx.ALIGN_CENTER| wx.ALL, 5)
238 hbszr.Add(self.BTN_save_request_ID, 0, wx.ALIGN_CENTER | wx.ALL, 5)
239
240
241 self.lbox_pending = cLabIDListCtrl(
242 pnl_page,
243 wx.ID_pending_requests,
244 size = wx.DefaultSize,
245 style = wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_VRULES
246 )
247
248 self.lbox_pending.InsertColumn(0, _("date"))
249 self.lbox_pending.InsertColumn(1, _("lab"))
250 self.lbox_pending.InsertColumn(2, _("sample id"))
251 self.lbox_pending.InsertColumn(3, _("patient"))
252 self.lbox_pending.InsertColumn(4, _("status"))
253
254 szr_page = wx.BoxSizer(wx.VERTICAL)
255 szr_page.Add(hbszr,0, wx.ALIGN_LEFT | wx.ALL, 5)
256 szr_page.Add(self.lbox_pending, 1, wxEXPAND | wx.ALIGN_CENTER | wx.ALL, 5)
257
258
259 pnl_page.SetAutoLayout(True)
260 pnl_page.SetSizer(szr_page)
261 szr_page.Fit(pnl_page)
262 szr_page.SetSizeHints(pnl_page)
263
264 self.AddPage(pnl_page, _("pending requests"))
265
267 pnl_page = wx.Panel( self, -1)
268
269 self.lbox_errors = cLabIDListCtrl (
270 parent = pnl_page,
271 id = wx.ID_lbox_errors,
272 size = wx.DefaultSize,
273 style = wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_VRULES
274 )
275 self.lbox_errors.InsertColumn(0, _("noticed when"))
276 self.lbox_errors.InsertColumn(1, _("problem"))
277 self.lbox_errors.InsertColumn(2, _("solution"))
278 self.lbox_errors.InsertColumn(3, _("context"))
279
280 szr_page = wx.BoxSizer(wx.VERTICAL)
281 szr_page.Add(self.lbox_errors, 1, wxEXPAND| wx.ALIGN_CENTER | wx.ALL, 5)
282
283
284 pnl_page.SetAutoLayout(True)
285 pnl_page.SetSizer(szr_page)
286 szr_page.Fit(pnl_page)
287 szr_page.SetSizeHints(pnl_page)
288
289 self.AddPage(pnl_page, _("lab errors"))
290
292 pnl_page = wx.Panel( self, -1)
293
294
295 self.__grid_unreviewed_results = cLabReviewGrid(
296 pnl_page,
297 wx.ID_grid_unreviewed_results
298 )
299 self.__grid_unreviewed_results.CreateGrid(0, 8, wx.Grid.wx.GridSelectCells)
300 self.__grid_unreviewed_results.SetDefaultCellAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
301
302 self.__grid_unreviewed_results.AutoSizeColumns(True)
303 self.__grid_unreviewed_results.AutoSizeRows(True)
304
305 renderer = apply(cLabJournalCellRenderer, ())
306 self.__grid_unreviewed_results.SetDefaultRenderer(renderer)
307
308
309
310
311
312
313
314
315
316
317
318 self.__grid_unreviewed_results.SetColLabelValue(0, _('reviewed'))
319 self.__grid_unreviewed_results.SetColLabelValue(1, _('relevant'))
320 self.__grid_unreviewed_results.SetColLabelValue(2, _('patient'))
321 self.__grid_unreviewed_results.SetColLabelValue(3, _('facility'))
322 self.__grid_unreviewed_results.SetColLabelValue(4, _('analysis'))
323 self.__grid_unreviewed_results.SetColLabelValue(5, _('result'))
324 self.__grid_unreviewed_results.SetColLabelValue(6, _('range'))
325 self.__grid_unreviewed_results.SetColLabelValue(7, _('info provided by lab'))
326
327 self.__grid_unreviewed_results.SetRowLabelSize(0)
328 self.__grid_unreviewed_results.AutoSize()
329
330
331
332 self.BTN_select_all = wx.Button(
333 name = 'BTN_select_all',
334 parent = pnl_page,
335 id = wx.ID_BTN_select_all,
336 label = _("select all requests")
337 )
338 self.BTN_select_all.SetToolTipString(_('select all requests'))
339
340 self.BTN_mark_reviewed = wx.Button(
341 name = 'BTN_mark_reviewed',
342 parent = pnl_page,
343 id = wx.ID_BTN_mark_reviewed,
344 label = _("mark selected requests as reviewed")
345 )
346 self.BTN_mark_reviewed.SetToolTipString(_('mark selected requests as reviewed'))
347
348 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
349 szr_buttons.Add(self.BTN_select_all, 0, wx.ALIGN_CENTER_VERTICAL, 1)
350 szr_buttons.Add(self.BTN_mark_reviewed, 0, wx.ALIGN_CENTER_VERTICAL, 1)
351
352
353 szr_page = wx.BoxSizer(wx.VERTICAL)
354 szr_page.Add(self.__grid_unreviewed_results, 1, wxEXPAND | wx.ALIGN_CENTER | wx.ALL, 5)
355 szr_page.Add(szr_buttons, 0, wxEXPAND | wx.ALIGN_CENTER | wx.ALL, 5)
356
357 pnl_page.SetAutoLayout(True)
358 pnl_page.SetSizer(szr_page)
359 szr_page.Fit(pnl_page)
360 szr_page.SetSizeHints(pnl_page)
361
362 self.AddPage(pnl_page, _("unreviewed results"))
363
365 wx.EVT_BUTTON(self.BTN_save_request_ID, wx.ID_BTN_save_request_ID, self.on_save_request_ID)
366 wx.EVT_BUTTON(self.BTN_select_all, wx.ID_BTN_select_all, self.on_select_all)
367 wx.EVT_BUTTON(self.BTN_mark_reviewed, wx.ID_BTN_mark_reviewed, self._on_mark_reviewed)
368
369 wx.EVT_GRID_CELL_LEFT_CLICK(self.__grid_unreviewed_results, self.OnLeftSClick)
370 wx.EVT_GRID_CELL_LEFT_DCLICK(self.__grid_unreviewed_results, self.OnLeftDClick)
371
372 wx.EVT_KEY_UP(self.__grid_unreviewed_results, self.OnKeyPressed)
373
375 if self.__pat['pk'] is None:
376 gmGuiHelpers.gm_show_error(
377 aMessage = _('Cannot load lab journal.\nYou first need to select a patient.'),
378 aTitle = _('loading lab journal')
379 )
380 return None
381
382 if self.__populate_notebook() is None:
383 return None
384 return 1
385
387
388 self.fld_request_id.Clear()
389 self.lab_wheel.Clear()
390
391
392
393 too_many, pending_requests = gmPathLab.get_pending_requests(limit=250)
394
395 self.lbox_pending.DeleteAllItems()
396
397 for request in pending_requests:
398 item_idx = self.lbox_pending.InsertItem(info=wx.ListItem())
399
400 self.lbox_pending.SetStringItem(index = item_idx, col=0, label=request['sampled_when'].date)
401
402 lab = self.__get_labname(request['pk_test_org'])
403 self.lbox_pending.SetStringItem(index = item_idx, col=1, label=lab[0][0])
404
405 self.lbox_pending.SetStringItem(index = item_idx, col=2, label=request['request_id'])
406
407 pat = request.get_patient()
408 self.lbox_pending.SetStringItem(index = item_idx, col=3, label="%s %s (%s)" % (pat[2], pat[3], pat[4].date))
409 self.lbox_pending.SetStringItem(index = item_idx, col=4, label=_('pending'))
410
411
412
413 lab_errors = self.__get_import_errors()
414
415 self.lbox_errors.DeleteAllItems()
416
417 for lab_error in lab_errors:
418 item_idx = self.lbox_errors.InsertItem(info=wx.ListItem())
419
420 self.lbox_errors.SetStringItem(index = item_idx, col=0, label=lab_error[1].date)
421
422 self.lbox_errors.SetStringItem(index = item_idx, col=1, label=lab_error[4])
423
424 self.lbox_errors.SetStringItem(index = item_idx, col=2, label=lab_error[5])
425
426 self.lbox_errors.SetStringItem(index = item_idx, col=3, label=lab_error[6])
427
428
429
430 more_avail, self.dict_unreviewed_results = gmPathLab.get_unreviewed_results(limit=50)
431
432
433
434
435 self.__grid_unreviewed_results.ClearGrid()
436
437 if self.__grid_unreviewed_results.GetNumberRows() == 0:
438 self.__grid_unreviewed_results.AppendRows(len(self.dict_unreviewed_results))
439
440 for item_idx in range(len(self.dict_unreviewed_results)):
441 result = self.dict_unreviewed_results[item_idx]
442
443
444 renderer = apply(wx.GridCellBoolRenderer, ())
445 self.__grid_unreviewed_results.SetCellRenderer(item_idx, 0 , renderer)
446 self.__grid_unreviewed_results.SetCellRenderer(item_idx, 1 , renderer)
447
448 self.__grid_unreviewed_results.SetReadOnly(item_idx, 0, 1)
449 self.__grid_unreviewed_results.SetReadOnly(item_idx, 1, 1)
450
451 self.__grid_unreviewed_results.EnableGridLines(0)
452
453 try:
454 self.__grid_unreviewed_results.SetColSize(0, self.__grid_unreviewed_results.GetColMinimalAcceptableWidth())
455 except AttributeError:
456 pass
457 self.__grid_unreviewed_results.SetCellValue(item_idx, 0, '0')
458
459 try:
460 self.__grid_unreviewed_results.SetColSize(1, self.__grid_unreviewed_results.GetColMinimalAcceptableWidth())
461 except AttributeError:
462 pass
463 self.__grid_unreviewed_results.SetCellValue(item_idx, 1, '0')
464
465 if (result['abnormal'] is not None) and (result['abnormal'].strip() != ''):
466 self.__grid_unreviewed_results.SetCellTextColour(item_idx,2,wx.RED)
467 self.__grid_unreviewed_results.SetCellTextColour(item_idx,3,wx.RED)
468 self.__grid_unreviewed_results.SetCellTextColour(item_idx,4,wx.RED)
469 self.__grid_unreviewed_results.SetCellTextColour(item_idx,5,wx.RED)
470 self.__grid_unreviewed_results.SetCellTextColour(item_idx,6,wx.RED)
471 self.__grid_unreviewed_results.SetCellTextColour(item_idx,7,wx.RED)
472
473 info = '(%s)' % result['abnormal']
474
475 self.__grid_unreviewed_results.SetCellValue(item_idx, 1, '1')
476 else:
477 info = ''
478
479 self.__grid_unreviewed_results.SetCellValue(item_idx, 1, '0')
480
481 pat = result.get_patient()
482 self.__grid_unreviewed_results.SetCellValue(item_idx, 2, "%s %s (%s)" % (pat[2], pat[3], pat[4].date))
483 self.__grid_unreviewed_results.SetColSize(2,200)
484
485 self.__grid_unreviewed_results.SetCellValue(item_idx, 3, result['lab_rxd_when'].date)
486 self.__grid_unreviewed_results.SetColSize(3,80)
487
488 self.__grid_unreviewed_results.SetCellValue(item_idx, 4, result['unified_name'])
489 self.__grid_unreviewed_results.SetColSize(4,100)
490
491
492 self.__grid_unreviewed_results.SetCellValue(item_idx, 5, '%s %s' % (result['unified_val'], info))
493 self.__grid_unreviewed_results.SetColSize(5,80)
494
495 if result['val_normal_range'] is None:
496 self.__grid_unreviewed_results.SetCellValue(item_idx, 6, '')
497 else:
498 self.__grid_unreviewed_results.SetCellValue(item_idx, 6, '%s %s' % (result['val_normal_range'], result['val_unit']))
499 self.__grid_unreviewed_results.SetColSize(6,80)
500
501
502 if result['note_provider'] is None:
503 self.__grid_unreviewed_results.SetCellValue(item_idx, 7, '')
504 else:
505 self.__grid_unreviewed_results.SetCellValue(item_idx, 7, result['note_provider'])
506
507
508 if more_avail:
509 gmDispatcher.send(signal = 'statustext', msg =_('More unreviewed results available. Review some to see more.'))
510
512 query = """select * from housekeeping_todo where category='lab'"""
513 import_errors = gmPG.run_ro_query('historica', query)
514 return import_errors
515
517
518 query= """select internal_OBSOLETE_name from test_org where pk=%s"""
519 labs = gmPG.run_ro_query('historica', query, None, data)
520 return labs
521
522
523
524
528
532
534
535
536
537 print "only stub for Crosscheck - please fix"
538
540 if selector is None:
541
542 return None
543
544 if selector in ['SelKEY', 'LDClick']:
545
546 col = self.__grid_unreviewed_results.GetGridCursorCol()
547 row = self.__grid_unreviewed_results.GetGridCursorRow()
548 if selector in ['LSClick']:
549
550 col = event.GetCol()
551 row = event.GetRow()
552
553 if col in [0,1]:
554 if self.__grid_unreviewed_results.GetCellValue(row,col) == '1':
555 self.__grid_unreviewed_results.SetCellValue(row,col, '0')
556 else:
557 self.__grid_unreviewed_results.SetCellValue(row,col,'1')
558 self.CrosscheckRelevant()
559 event.Skip()
560
562 """Is called when a key is pressed."""
563
564
565
566 if key.GetKeyCode() == WXK_DOWN:
567 key.Skip()
568
569 return
570
571 if key.GetKeyCode() == wx.WXK_UP:
572 key.Skip()
573
574 return
575
576
577
578
579 if key.GetKeyCode() == WXK_SPACE:
580 self.OnSelectCell(key,selector='SelKEY')
581 return
582
584 req_id = self.fld_request_id.GetValue()
585 if (req_id is None) or (req_id.strip() == ''):
586 gmGuiHelpers.gm_show_error (
587 _('You must type in a request ID !\n\nUsually you will find the request ID written on\nthe barcode sticker on your probe container.'),
588 _('saving request id')
589 )
590 return None
591 emr = self.__pat.get_emr()
592 request = emr.add_lab_request(lab=int(self.lab), req_id = req_id)
593 if request is None:
594 gmDispatcher.send(signal = 'statustext', msg =_('Cannot save lab request.'))
595 return None
596
597
598
599
600 self.__populate_notebook()
601
603 for item_idx in range(self.__grid_unreviewed_results.GetNumberRows()):
604 self.__grid_unreviewed_results.SetCellValue(item_idx, 0, '1')
605
607 reviewed_results = []
608 for row in range(self.__grid_unreviewed_results.GetNumberRows()):
609 if self.__grid_unreviewed_results.GetCellValue(row, 0) == '1':
610
611 result = self.dict_unreviewed_results[row]
612 reviewed_results.append(result)
613
614 relevant = self.__grid_unreviewed_results.GetCellValue(row, 1)
615 if relevant == '1':
616 result['relevant'] = 'true'
617 else:
618 result['relevant'] = 'false'
619
620 if len(reviewed_results) == 0:
621 gmGuiHelpers.beep_status_text(_('No results marked as reviewed.'))
622 event.Skip()
623 return None
624
625 for result in reviewed_results:
626 result['reviewed'] = 'true'
627 result['pk_reviewer'] = gmStaff.gmCurrentProvider()['pk_staff']
628 if not result['abnormal']:
629 result['abnormal'] = ''
630 successfull, error = result.save_payload()
631
632 if successfull:
633 self.__populate_notebook()
634 else:
635 _log.Log(gmLog.lErr, 'setting result status to reviewed failed %s' % error)
636 gmGuiHelpers.gm_show_error (
637 aMessage = _('Cannot mark results as "reviewed":\n%s') % error,
638 aTitle = _('update result status')
639 )
640 return None
641
642 event.Skip()
643
646
658
659
661 """This wx.Grid derivative displays a grid view of stored lab data.
662 """
664 """Set up our specialised grid.
665 """
666
667 self.__backend = gmPG.ConnectionPool()
668 self.__defconn = self.__backend.GetConnection('blobs')
669 if self.__defconn is None:
670 _log.Log(gmLog.lErr, "Cannot retrieve lab data without database connection !")
671 raise gmExceptions.ConstructorError, "cLabDataGrid.__init__(): need db conn"
672
673
674 self.__dbcfg = gmCfg.cCfgSQL(
675 aConn = self.__backend.GetConnection('default'),
676 aDBAPI = gmPG.dbapi
677 )
678
679 wx.Grid.__init__(
680 self,
681 parent,
682 id,
683 pos = wx.DefaultPosition,
684 size = wx.DefaultSize,
685 style= wx.WANTS_CHARS
686 )
687
688 self.__pat = gmPerson.gmCurrentPatient()
689
690
691
692
693 self.__grid_unreviewed_results = self.CreateGrid(0, 0, wx.Grid.wx.GridSelectCells )
694 self.SetDefaultCellAlignment(wx.ALIGN_RIGHT,wx.ALIGN_CENTRE)
695
696 renderer = apply(cLabDataGridCellRenderer, ())
697 self.SetDefaultRenderer(renderer)
698
699
700 self.AutoSizeColumns(True)
701 self.AutoSizeRows(True)
702
703
704 font = self.GetFont()
705
706 attr = wx.GridCellAttr()
707 attr.SetFont(font)
708
709 attr.SetReadOnly(True)
710
711
712
713
714
715
716
718 if self.CanEnableCellControl():
719 self.EnableCellEditControl()
720
721
723 if self.__pat['pk'] is None:
724 _log.Log(gmLog.lErr, 'need patient for update')
725 gmGuiHelpers.gm_show_error(
726 aMessage = _('Cannot load lab data.\nYou first need to select a patient.'),
727 aTitle = _('loading lab data')
728 )
729 return None
730
731 if self.__populate_grid() is None:
732 return None
733
734 return 1
735
736
738 """Fill grid with data.
739
740 sorting:
741 1) check user's preferred way of sorting
742 none defaults to smart sorting
743 2) check if user defined lab profiles
744 - add a notebook tab for each profile
745 - postpone profile dependent stats until tab is selected
746 sort modes :
747 1: no profiles -> smart sorting only
748 2: profile -> smart sorting first
749 3: profile -> user defined profile order
750 """
751 emr = self.__pat.get_emr()
752 results = None
753 if results is None:
754 name = self.__pat.get_names()
755 gmGuiHelpers.gm_show_error (
756 aMessage = _('Error loading lab data for patient\n[%s %s].') % (name['firstnames'], name['lastnames']),
757 aTitle = _('loading lab data')
758 )
759 return None
760 if len(results) == 0:
761 gmDispatcher.send(signal = 'statustext', msg =_('No lab data available.'))
762 return None
763
764 dates, test_names = self.__compile_stats(results)
765
766
767 sort_mode = 1
768
769 if sort_mode == 1:
770 """
771 2) look at the the most recent date a test was performed on
772 move these tests to the top
773 3) sort by runs starting with most recent date
774 a run is a series of consecutive dates a particular test was done on
775 sort by length of the runs
776 longest run will move to the top
777 """
778 pass
779
780
781 self.ClearGrid()
782
783 if self.GetNumberCols() == 0:
784 self.AppendCols(len(dates))
785
786 for i in range(len(dates)):
787 self.SetColLabelValue(i, dates[i])
788
789 if self.GetNumberRows() == 0:
790 self.AppendRows(len(test_names))
791
792 for i in range(len(test_names)):
793 self.SetRowLabelValue(i, test_names[i])
794
795 cells = []
796 for result in results:
797
798 x = dates.index(result['val_when'].date)
799 y = test_names.index(result['unified_name'])
800 cell_data = self.GetCellValue(x, y)
801 if cell_data == '':
802 self.SetCellValue(x, y, '%s %s' % (result['unified_val'], result['val_unit']))
803 else:
804 self.SetCellValue(x, y, '%s\n%s %s' % (cell_data, result['unified_val'], result['val_unit']))
805
806
807
808
809
810 self.AutoSize()
811 return 1
812
814
815 dates = []
816 test_names = []
817 for result in lab_results:
818 if result['val_when'].date not in dates:
819 dates.append(result['val_when'].date)
820 if result['unified_name'] not in test_names:
821 test_names.append(result['unified_name'])
822 dates.sort()
823
824 return dates, test_names
825
826
827
828
829
830
831
832
833
836
837
838
839
840
841 if __name__ == '__main__':
842 _log.Log (gmLog.lInfo, "starting lab journal")
843
844
845 try:
846 application = wxPyWidgetTester(size=(640,480))
847 application.SetWidget(cStandalonePanel,-1)
848 application.MainLoop()
849 except:
850 _log.LogException("unhandled exception caught !", sys.exc_info(), 1)
851
852 raise
853
854 _log.Log (gmLog.lInfo, "closing lab journal")
855
856