1 """GnuMed pregnancy related dates caculcator.
2
3 Calculates from LMP:
4 - EDC
5 - 18th week ultrasound scan
6
7 Naegele's rule is easy for manual calculation, but a pain to code
8 Enter Haywood's rule ;-), human gestation is defined as 24192000 seconds.
9 (Ian, can you please explain a bit more ?)
10
11 TODO:
12 ideally, tool should query backend for parity, race, etc. for exact measurement
13 """
14
15
16
17 __version__ = "$Revision: 1.6 $"
18 __author__ = "M. Bonert, R. Terry, I. Haywood"
19 __licence__ = "GPL"
20
21 import math, zlib, cPickle, random, string, os.path
22
23 try:
24 import wxversion
25 import wx
26 except ImportError:
27 from wxPython import wx
28 from wxPython import calender
29 from wxPython.lib.rcsizer import RowColSizer
30
31 LMP_FIELD = 0
32 US_FIELD = 1
33
34 ID_LMP = wx.NewId()
35 ID_DUE = wx.NewId()
36 ID_DAY = wx.NewId()
37 ID_WEEK = wx.NewId()
38 ID_MENU = wx.NewId()
39
40 GESTATION = 24192000
41 WEEK = 604800
42 DAY = 86400
43 US18_52 = 10886400
44
45
47 """
48 The new pregnancy calculator.
49 """
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
67 myStyle = wxMINIMIZE_BOX | wx.CAPTION | wx.ALIGN_CENTER | \
68 wxALIGN_CENTER_VERTICAL | wx.TAB_TRAVERSAL | wx.STAY_ON_TOP
69 wx.Frame.__init__(self, parent, -1, _("Pregnancy Calculator"), style=myStyle)
70
71
72 self.xfer_cal_date_to=LMP_FIELD
73
74
75
76 self.ustxt=wx.DateTime_Today()
77
78
79
80
81
82 if __name__ == '__main__':
83 png_fname = os.path.join('..', 'bitmaps', 'preg_calculator.png')
84 else:
85 from Gnumed.pycommon import gmGuiBroker
86 gb = gmGuiBroker.GuiBroker()
87 png_fname = os.path.join(gb['gnumed_dir'], 'bitmaps', 'preg_calculator.png')
88 icon = wx.EmptyIcon()
89 icon.LoadFile(png_fname, wx.BITMAP_TYPE_PNG)
90 self.SetIcon(icon)
91
92 szr_rc = RowColSizer()
93
94
95
96
97 label = wx.StaticText(self,-1,_("LMP"),size = (50,20))
98 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
99 label.SetForegroundColour(wx.Colour(0,0,0))
100
101 self.txt_lmp = wx.TextCtrl(self,-1,"",size=(100,20))
102 self.txt_lmp.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
103 self.txt_lmp.SetToolTip(wx.ToolTip(_("Click on calendar to enter the last menstrual period date")))
104 tiplmp=self.txt_lmp.GetToolTip()
105
106 szr_row1 = wx.BoxSizer(wx.HORIZONTAL)
107 szr_row1.Add(self.txt_lmp,1,wx.EXPAND|wx.ALL,2)
108 wx.EVT_SET_FOCUS(self.txt_lmp, self.OnSetFocus_lmp)
109
110 szr_lmp = wx.BoxSizer(wx.HORIZONTAL)
111 szr_lmp.Add(label, 1, 0, 0)
112 szr_lmp.Add((10,1),0,0)
113 szr_rc.Add(szr_lmp, flag=wx.EXPAND, row=0, col=1)
114 szr_rc.Add(szr_row1, flag=wx.EXPAND, row=0, col=2, colspan=5)
115
116
117
118 label = wx.StaticText(self,-1,_("Gest."),size = (50,20))
119 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
120 label.SetForegroundColour(wx.Colour(0,0,0))
121
122 self.txtgest = wx.TextCtrl(self,-1,"",size=(100,20))
123 self.txtgest.Enable(False)
124 self.txtgest.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
125 self.txtgest_szr = wx.BoxSizer(wx.HORIZONTAL)
126 self.txtgest_szr.Add(self.txtgest,1,wx.EXPAND|wx.ALL,2)
127
128 szr_gest = wx.BoxSizer(wx.HORIZONTAL)
129 szr_gest.Add(label, 1, 0, 0)
130 szr_gest.Add((10,1),0,0)
131 szr_rc.Add(szr_gest, flag=wx.EXPAND, row=1, col=1)
132 szr_rc.Add(self.txtgest_szr, flag=wx.EXPAND, row=1, col=2, colspan=5)
133
134
135
136
137 label = wx.StaticText(self,-1,_("EDC"),size = (50,20))
138 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
139 label.SetForegroundColour(wx.Colour(0,0,0))
140
141 self.txtedc = wx.TextCtrl(self,-1,"",size=(100,20))
142 self.txtedc.Enable(False)
143 self.txtedc.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
144 szr_txtedc = wx.BoxSizer(wx.HORIZONTAL)
145 szr_txtedc.Add(self.txtedc,1,wx.EXPAND|wx.ALL,2)
146 szr_edc = wx.BoxSizer(wx.HORIZONTAL)
147 szr_edc.Add(label,1,0,0)
148 szr_edc.Add((10,1),0,0)
149 szr_rc.Add(szr_edc, flag=wx.EXPAND, row=2, col=1)
150 szr_rc.Add(szr_txtedc, flag=wx.EXPAND, row=2, col=2, colspan=5)
151
152
153
154
155 us_label = wx.StaticText(self,-1,_("18 Week Ultrasound Scan"),size = (200,20))
156 us_label.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.BOLD,False,''))
157 us_label.SetForegroundColour(wx.Colour(50,50,204))
158 szr_backgrnd_18WkScanDue = wx.BoxSizer(wx.VERTICAL)
159 szr_backgrnd_18WkScanDue.Add((1,3), 0)
160 szr_backgrnd_18WkScanDue.Add(us_label,1,wx.EXPAND,1)
161 szr_rc.Add(szr_backgrnd_18WkScanDue, flag=wx.ALIGN_CENTRE_HORIZONTAL, row=3, col=2, colspan=5)
162
163
164
165 label = wx.StaticText(self,-1,_("Due"),size = (100,20))
166 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
167 label.SetForegroundColour(wx.Colour(0,0,0))
168
169 self.txtdue = wx.TextCtrl(self,-1,"",size=(100,20))
170 self.txtdue.Enable(False)
171 self.txtdue.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
172 self.szr_txtdue = wx.BoxSizer(wx.HORIZONTAL)
173 self.szr_txtdue.Add(self.txtdue,1,wx.EXPAND|wx.ALL,2)
174 szr_due = wx.BoxSizer(wx.HORIZONTAL)
175 szr_due.Add(label,1,0,0)
176 szr_due.Add((10,1),0,0)
177 szr_rc.Add(szr_due, flag=wx.EXPAND, row=4, col=1)
178 szr_rc.Add(self.szr_txtdue, flag=wx.EXPAND, row=4, col=2, colspan=5)
179
180
181
182
183 rev_edc_label = wx.StaticText(self,-1,_("Ultrasound Scan - Revised EDC"),size = (300,20))
184 rev_edc_label.SetFont(wx.Font(10,wx.SWISS,wx.NORMAL,wx.BOLD,False,''))
185 rev_edc_label.SetForegroundColour(wx.Colour(50,50,204))
186 szr_backgrnd_RevEDCLabel = wx.BoxSizer(wx.VERTICAL)
187 szr_backgrnd_RevEDCLabel.Add((1,3), 0)
188 szr_backgrnd_RevEDCLabel.Add(rev_edc_label,1,wx.EXPAND,1)
189 szr_rc.Add(szr_backgrnd_RevEDCLabel, flag=wx.ALIGN_CENTRE_HORIZONTAL, row=5, col=2, colspan=5)
190
191
192
193
194 label1 = wx.StaticText(self,-1,_("Scan Date"),size = (25,20))
195 label1.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
196 label1.SetForegroundColour(wx.Colour(0,0,0))
197 self.txtdate = wx.TextCtrl(self,-1,"",size=(25,20))
198 self.txtdate.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
199 self.txtdate.SetToolTip(wx.ToolTip(_("Click on this field and then the ultrasound scan date on the calendar")))
200 tipdue=self.txtdate.GetToolTip()
201 wx.ToolTip_Enable(1)
202 self.szr_txtdate = wx.BoxSizer(wx.HORIZONTAL)
203 self.szr_txtdate.Add(self.txtdate,1,wx.EXPAND|wx.ALL,2)
204 wx.EVT_SET_FOCUS(self.txtdate, self.OnSetFocus_USDate)
205
206 szr_label1 = wx.BoxSizer(wx.HORIZONTAL)
207 szr_label1.Add(label1,1,0,0)
208 szr_label1.Add((10,1),0,0)
209 szr_rc.Add(szr_label1, flag=wx.EXPAND, row=6, col=1)
210 szr_rc.Add(self.szr_txtdate, flag=wx.EXPAND, row=6, col=2, colspan=5)
211
212
213
214 label2 = wx.StaticText(self,-1,_("Weeks"),size = (25,20))
215 label2.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
216 label2.SetForegroundColour(wx.Colour(0,0,0))
217 self.txtweeks = wx.SpinCtrl (self, -1, value = "0", min = 0, max = 42)
218 wx.EVT_SPINCTRL (self.txtweeks ,self.txtweeks.GetId(), self.EvtText_calcnewedc)
219 self.txtweeks.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
220 self.szr_txtweeks = wx.BoxSizer(wx.HORIZONTAL)
221 self.szr_txtweeks.Add(self.txtweeks,1,wx.EXPAND|wx.ALL,2)
222
223 label3 = wx.StaticText(self,-1,_("Days"),size = (25,20))
224 label3.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
225 label3.SetForegroundColour(wx.Colour(0,0,0))
226 self.txtdays = wx.SpinCtrl (self, -1, value = "0", min = 0, max = 6)
227 wx.EVT_SPINCTRL (self.txtdays ,self.txtdays.GetId(), self.EvtText_calcnewedc)
228 self.txtdays.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
229 self.szr_txtdays = wx.BoxSizer(wx.HORIZONTAL)
230 self.szr_txtdays.Add(self.txtdays,1,wx.EXPAND|wx.ALL,2)
231
232 szr_label2 = wx.BoxSizer(wx.HORIZONTAL)
233 szr_label2.Add(label2,1,wx.ALIGN_CENTRE_VERTICAL,0)
234 szr_label2.Add((10,1),0,0)
235 szr_label3 = wx.BoxSizer(wx.HORIZONTAL)
236 szr_label3.Add((10,1),0,0)
237 szr_label3.Add(label3,1,wx.ALIGN_CENTRE_VERTICAL,0)
238 szr_label3.Add((10,1),0,0)
239 szr_rc.Add(szr_label2, flag=wx.EXPAND, row=7, col=1)
240 szr_rc.Add(self.szr_txtweeks, flag=wx.EXPAND, row=7, col=2, colspan=2)
241 szr_rc.Add(szr_label3, flag=wx.EXPAND, row=7, col=4)
242 szr_rc.Add(self.szr_txtdays, flag=wx.EXPAND, row=7, col=5, colspan=2)
243
244
245
246
247 label = wx.StaticText(self,-1,_("Rev EDC"),size = (100,20))
248 label.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
249 label.SetForegroundColour(wx.Colour(0,0,0))
250
251 self.txtnewedc = wx.TextCtrl(self,-1,"",size=(100,20))
252 self.txtnewedc.Enable(False)
253 self.txtnewedc.SetFont(wx.Font(12,wx.SWISS,wx.NORMAL,wx.NORMAL,False,''))
254 self.szr_txtnewedc = wx.BoxSizer(wx.HORIZONTAL)
255 self.szr_txtnewedc.Add(self.txtnewedc,1,wx.EXPAND|wx.ALL,2)
256 szr_label=wx.BoxSizer(wx.HORIZONTAL)
257 szr_label.Add(label,1,0,0)
258 szr_label.Add((10,1),0,0)
259 szr_rc.Add(szr_label, flag=wx.EXPAND, row=8, col=1)
260 szr_rc.Add(self.szr_txtnewedc, flag=wx.EXPAND, row=8, col=2, colspan=5)
261 self.btnPrint = wx.Button(self,1011,_('&Print'))
262 self.btnSave = wx.Button(self,1011,_('&Save'))
263 szr_buttons = wx.BoxSizer(wx.HORIZONTAL)
264 szr_buttons.Add(self.btnPrint,0,wx.EXPAND)
265 szr_buttons.Add(self.btnSave,0,wx.EXPAND)
266 szr_rc.Add(szr_buttons, flag=wx.EXPAND,row=9, col=3, colspan=4)
267
268
269
270 szr_main_rt = wx.BoxSizer(wx.VERTICAL)
271 szr_main_rt.Add(szr_rc)
272 wx.EVT_BUTTON(self,1010,self.EvtReset)
273 wx.EVT_BUTTON(self,1011,self.EvtPrint)
274 wx.EVT_BUTTON(self,1012,self.EvtSave)
275
276
277
278 self.lmp_cal = wx.CalendarCtrl (self, ID_LMP,style = wx.RAISED_BORDER)
279 wx.EVT_CALENDAR_SEL_CHANGED(self.lmp_cal, ID_LMP, self.OnCalcByLMP)
280
281 szr_main_lf = wx.BoxSizer(wx.VERTICAL)
282 szr_main_lf.Add(self.lmp_cal,0,wx.ALIGN_CENTRE_HORIZONTAL)
283 btn_reset = wx.Button(self, 1010, _('&Reset'))
284
285 szr_main_lf.Add(btn_reset,0,wx.EXPAND)
286
287
288
289
290 szr_main_top= wx.BoxSizer(wx.HORIZONTAL)
291 szr_main_top.Add(szr_main_lf,0,0)
292 szr_main_top.Add((15,0),0,0)
293 szr_main_top.Add(szr_main_rt,0,0)
294
295
296
297
298
299 szr_main= wx.BoxSizer(wx.HORIZONTAL)
300 szr_main.Add(szr_main_top,1,wx.EXPAND|wx.ALL,10)
301 self.SetSizer (szr_main)
302 self.SetAutoLayout (1)
303 szr_main.Fit (self)
304
305 wx.EVT_CLOSE (self, self.OnClose )
306
307
309
310 if(self.xfer_cal_date_to==LMP_FIELD):
311
312
313
314
315
316
317
318
319 self.lmp = self.lmp_cal.GetDate ().GetTicks ()
320 today = wx.DateTime_Today().GetTicks()
321 due = self.lmp + GESTATION
322 gest = today - self.lmp
323 self.ultrasound18_52 = self.lmp + US18_52
324
325
326
327 lmp_txt = wx.DateTime()
328 lmp_txt.SetTimeT(self.lmp)
329 self.txt_lmp.SetValue(self.PurgeTime(lmp_txt))
330
331
332 gest_week = gest / WEEK
333 gest_day = (gest % WEEK) / DAY
334 if(gest_day==1):
335 days_label=_('day')
336 else:
337 days_label=_('days')
338 if(gest_week==1):
339 weeks_label=_('week')
340 else:
341 weeks_label=_('weeks')
342
343 txtgest_str=str(gest_week)+" "+weeks_label+", "+str(gest_day)+" "+days_label
344 self.txtgest.SetValue(txtgest_str)
345
346
347 edctxt = wx.DateTime()
348 edctxt.SetTimeT(due)
349 self.txtedc.SetValue(self.PurgeTime(edctxt))
350
351
352 self.ustxt = wx.DateTime()
353 self.ustxt.SetTimeT(self.ultrasound18_52)
354 self.txtdue.SetValue(self.PurgeTime(self.ustxt))
355
356 else:
357
358 self.usdate = self.lmp_cal.GetDate ().GetTicks ()
359 usdatetxt = wx.DateTime()
360 usdatetxt.SetTimeT(self.usdate)
361 self.txtdate.SetValue(self.PurgeTime(usdatetxt))
362
363
364 if( self.txtnewedc.GetValue() !=""):
365 self.EvtText_calcnewedc(self)
366
367
368 - def EvtText_calcnewedc (self, event):
369 try:
370 weeks=self.txtweeks.GetValue()
371 days=self.txtdays.GetValue()
372
373
374 newedc=self.usdate+GESTATION-WEEK*weeks-DAY*days
375
376 wx.D=wx.DateTime()
377 wx.D.SetTimeT(newedc)
378 self.txtnewedc.SetValue(self.PurgeTime(wx.D))
379 except:
380 pass
381
382
384
385 self.txt_lmp.SetValue("")
386 self.txtgest.SetValue("")
387 self.txtedc.SetValue("")
388 self.txtdue.SetValue("")
389
390 self.txtdate.SetValue("")
391 self.ustxt=wx.DateTime_Today()
392
393 self.txtweeks.SetValue(0)
394 self.txtdays.SetValue(0)
395 self.txtnewedc.SetValue("")
396
397 self.xfer_cal_date_to=LMP_FIELD
398 self.lmp_cal.SetDate(wx.DateTime_Today())
399
400
403
406
407
408
409
412
413
415 time_loc=string.find(str(date),":00:00")
416 date_str=str(date)
417 return date_str[:(time_loc-3)]
418
419
421 self.xfer_cal_date_to=LMP_FIELD
422 event.Skip()
423
424
426 self.lmp_cal.SetDate(self.ustxt)
427 self.xfer_cal_date_to=US_FIELD
428 event.Skip()
429
430
431
432
433
434
435 if __name__ == '__main__':
436 wx.InitAllImageHandlers()
437
443
444 import gettext
445 _ = gettext.gettext
446 gettext.textdomain ('gnumed')
447 app = TestApp()
448 app.MainLoop()
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533