Frustrated, Incorporated

Apparently the blog importer I was using is no longer supported by Facebook, so hopefully this one (NetworkedBlogs) will work. I decided to play around with the layout theme, and added a photo I took of the beautiful Flint Hills area around Emporia, Kansas.

Well, I started out the week attempting to update the rxkinetics.net web app. My plan is to add the ability to change and save settings and pk models, using the localStorage functionality in HTML5. But, localStorage is via JavaScript on the client side (web browser), whereas the web app is ASP.NET server side. And neither the twain shall meet.

Since this is a working site, I had to copy the abpk.aspx to a test page. Then I added a settings page for changing creatinine clearance options, and attempted to save and retrieve the settings and populate the screen.

I wanted to use JSON, because that is what I will need to use when I add local pk model storage. But, after screwing around with JSON for a day and failing, I gave up and put each setting into its’ own row.

Since I’m working in Visual studio 2005, there is no native support for JavaScript, no Intellisense, no syntax checking, no real time debugging. Just blind coding followed
by trial and error. The only debugging I could do was to put alerts at various points within the JavaScript to display the progress.

Then I had no idea where to put the JavaScript, and when to trigger it. Putting the code in head element and triggering the JavaScript on the page onload event did nothing because the page isn’t fully rendered yet. Placing the script in the body “sort of” worked, but the CheckBox.checked value didn’t change. I ended up adding some hidden elements to store the settings so the server side app could read them.

It took three days of beating my head against the wall to figure out this trivial stuff. So, having had enough of this frustration, I switched to working on the Nook Color version of the Android app.

The first problem I ran into was error after unexplained error in Eclipse. It kept showing errors from google tools, which aren’t even used in this app. I eventually figured out that these were red herrings, the real problem was the target platform was not set.

Next problem was the layout editor throwing an XML error on some of the layouts, for no reason whatsoever. Eventually discovered that this is a known bug in the Android layout editor.

Finally I was able to run the app in the emulator, but, as any developer knows there is no substitute for debugging the app on the actual target device.

And that’s when the real nightmare began.

B&N has the Nook Color totally locked down. It will not allow installation of “non-market” apps. Nor does it allow connection to the Android Debug Bridge, and there is no Development setting on the Nook as there is on a standard Android device.

I tried following the cryptic instructions on the Nook developer site to allow ADB access, to no avail.

Then I tried various methods from the internet to soft root it. One suggestion was to attempt to crash the browser by going to certain web site. It said to try it up to twelve times. Good grief, once upon a time google was useful for finding information, now it only brings up page after page of irrelevant useless crap.

Eventually I resorted to rooting the Nook, and, after uninstalling and reinstalling the ADB USB driver umpteen times, I was finally able to connect the Nook to Eclipse and debug the app. I started this at 5 AM and finally, at noon, got the app to run on the Nook.

Since I had copied the layouts from the Android phone version, I’ll need to change all of them, increasing the size and color of all the elements. But at least I can see some light at the end of the tunnel.

As for the web app, I’ll have to mull it over, my brain is just too tired now. I think I’m getting too old for all this switching between languages, my mind is not as agile as it used to be.

Misery

Update highlights

The update parade continues, adding new features to APK and Kinetics. Unfortunately I’ve had to spend a lot of time in the last two years learning and developing Android and web apps. But I’ve resolved to spend more time maintaining these traditional desktop apps, as a result there has been much catching up to do. Most of the new non-database functions were first implemented in Antibiotic Kinetics. It has a much smaller code base, making it easier to add and test new features without worrying about their impact on existing functionality. Although it takes more time to add new features to APK and Kinetics, the kinks have usually been worked out because of this “pre-testing” within the Antibiotic Kinetics code base.

APK 3.5.6 Features added/bugs fixed:

  • Added form position save to profile ini.
  • Added free text infusion time option.
  • Added real-time x,y graph scaling.
  • Added last used CrCl method saved.
  • Updated Bayesian routine.
  • Updated the updater stub.

Kinetics 2.3.3 – Features added/bugs fixed:

  • Added Adjust CL to LBW option on prospective clearance model.
  • Updated single point Bayesian analysis to allow level outside of dosing interval.
  • Fixed Clearance label on consult print-out.
  • Added max length to Sr Cr fields.
  • Fixed duplicate levels save.

Because there has been a fundamental change in how APK and Kinetics are accessed, I decided to make some screencasts demonstrating the changes, posting them to youtube.

Video highlights of APK update

Video highlights of Kinetics update

Video highlights of Antibiotic Kinetics update

Update week

Sheesh, what a week.

Spent the first day making some improvements to the RxInterventions program:

  1. Changed the export function to run independently of Excel
  2. Fixed a bug with the archive routine
  3. Added an info dialog to the input routine

Then spent the rest of the week simultaneously updating APK and Antibiotic Kinetics. Both programs use the same code base for the calculations, while APK adds database functionality.

For Antibiotic Kinetics and APK added the following calculation related changes:

  1. Adjust CL to LBW option to correct clearance for obesity.
  2. Changed single point Bayesian to allow analysis of level outside of dosing interval.
  3. Added SrCr adjustment settings for IDMS SrCr and for minium SrCr. Adjust settings are found on the Other CrCl methods screen.

APK received a complete makeover in version 3.5.4. The most apparent change is the patient database interface. The program now starts with a simple search box. Type in a patient name to find matching records, or press Enter to list all patients. The user cannot add a new patient until record search has been performed. The intent is to cut down on entry of duplicate records for the same patient.

Start screen:

APK start

APK start

Search results:

APK search list

APK search list

MRU drop down:

APK MRU list

APK MRU list

Complete APK 3.5.4 change listing:

  1. Added Overlay to patient tab with search as the default start up point.
  2. Added Most recent used patient list.
  3. Added Search listing.
  4. Updated SrCr fields to allow 2 decimal places.
  5. Added Print T90% and T95% to consult report.
  6. Added BMI to patient data tab.
  7. Added mouse hover to view dose in mg/kg.

P.S. this new version of WordPress is buggy, the picture upload feature is broken. When I click to add a pic, it blackens the screen and… nothing. Had to add pix via pain-in-the-ass HTML code. Also, the code formatting plug-in does the same thing, blacks out the screen completely without any functionality, so I could not post the Adjust CL to IBW code. Found this on the wordpress forums: I think we can confirm that it is a mistake of the last update of wordpress

Kinetics 2.3.1 update posted

I ran some final tests from a USB stick on Vista and Win7, everything worked great. But when I tested it on a virgin XP system, it threw error 713 “MSSTDFMT.DLL is not registered on this computer.” I looked in the project references and noticed that the data formatter dll was listed, so I unchecked it and recompiled. Same error. Closed the IDE, reloaded the project, made sure the dll was no longer referenced in the project. Recompiled, continued to error-out on the test machine.

I remembered playing around with the DataFormat property on one text box on the main form. I had wanted to see if this property could be used for a time formatter, instead of having to use that awful Microsoft date/time control. It wasn’t useful at all, so I deleted the DataFormat property from the text box. But the compiled exe is still looking for the dll. WTF was going on? I finally loaded the form into a text editor and found this:

1
      BeginProperty DataFormat 
2
         Type            =   1
3
         Format          =   "HH:MM"
4
         HaveTrueFalseNull=   0
5
         FirstDayOfWeek  =   0
6
         FirstWeekOfYear =   0
7
         LCID            =   1033
8
         SubFormatType   =   3
9
      EndProperty

Even though I had deleted all reference to this in the IDE, it was still showing up in the form code. I deleted this code block in the text editor, saved the file and recompiled. Finally, it ran without error on all 3 test platforms. Testing completed, I posted the update to the web site. So glad to get this over with, I hate VB and can’t wait to get back to working in Delphi.

Kinetics 2.3.1

Finished updating the help file today. I hadn’t given it a thorough review for 3 years.

Changes since my last blog post:

  • Added support for dual monitors.
  • Added error trap for corrupt database with recovery.
  • Added tips for levels date/time entry.
  • Added extrapolated peak/trough with Bayesian.
  • Improved EI nomogram graph.
  • Changed EI retrospective consult: print nomogram instead of SS plot.
  • Added MRU drop down list showing most recent patients accessed.
  • Added Copy consult to clipboard with right click on print icon.
  • Added direct print via icon (bypass preview), or preview via menu.
  • Added database cleanup (merge duplicate records).
  • Added T90% and T95% to consult printout.
  • Added MRN to tabulation reports.
  • Added Evaluate dose by weight tool.

Here is a screen shot of the MRU (most recently used) list:

MRU list

MRU list

And here is a screen shot of the improved EI nomogram:

Nomogram graph

Nomogram graph

Next up: more testing, then create installs: MSI for work (yuk) and EXE for others. I hope to update the video tutorials next time I’m off.

Kinetics 2.3

Decided to simplify screens even further. All other choices dithered out on patient search screen:

start up screen

Only 4 icon choices on the patient edit/entry tab:

patient display

Summary of changes accomplished so far:

  • Added new start screen with simplified patient list/retrieval
  • Added do not allow edit of MRN
  • Added MRN duplicate check
  • Added Do not allow complete name change
  • Added IDMS Srcr adjust & setting
  • Added IDMS for MDRD & adjust to BSA
  • Added Min Srcr setting
  • Added Levels scheduler
  • Added Word Doc template for Monitoring form printing
  • Added Realtime x,y graph scaling
  • Added draw both Trough and MIC (optional) lines
  • Added to Setup: Min Srcr setting, IDMS adjustment, Monitor template
  • Added Copy consult to Clipboard w/rt click on print icon or via menu
  • Added database cleanup: merge duplicate records
  • Added T90% and T95% to consult printout
  • Added MRN to consults report
  • Added view mg/kg/dose & mg/kg/day via menu
  • Fixed DOB save to be date only, not date & time

Yet to do:

  • Update help file
  • Update tutorial
  • Testing
  • Create and test new install

iOS saga continues

The Cannabis app looks fantastic on the Mac iOS emulator, but I’ve been doing this long enough to know that you can’t rely on an emulator for software testing. Installation on a physical device is required for a thorough test.

I thought my 2nd generation iPod touch would work for iOS testing, thinking that I would also be able to test the app’s backwards compatibility. But XCode would not connect to the iPod, throwing an error message that XCode did not support iOS v 3.

So, two weeks ago I bought a 4th generation iPod touch with a cracked screen on eBay for $75. It finally came in the mail, in a box without any padding, and miraculously it powered on. I connected it to the Mac, but XCode threw another error, this time saying that it did not support iOS v 5. You’ve got to be kidding me Apple.

One option was to upgrade XCode, but I didn’t want to go that route because I had read that Free Pascal on the Mac had issues with the newest version of XCode.

So, I have spent the last 2 days trying to downgrade the iPod to iOS 4.x. My first attempt to downgrade to 4.3.5 gave the cryptic message “the device isn’t eligible for the requested build”. I then tried to restore it to version 5, and it went into a text display with writing so tiny it was impossible to read. Thought for sure that I had bricked it. I tried multiple times yesterday (and into the night) to download iOS 5, but the storm moving through caused the electricity to shut off 8 times. What a cluster fuck, I eventually gave up.

This morning I was finally able to download iOS 5, but again iTunes gave the message “the device isn’t eligible for the requested build”. WTF Apple? This is the OS that this device came with, how could it be ineligible?

Searches of multiple web sites yielded different suggestions for editing the hosts file. Some said no hash marks, some said a hash mark with no spaces. I tried them all, this one finally worked:
# 74.208.105.171 gs.apple.com
# 74.208.10.249 gs.apple.com

After restoring to iOS 5 and backing up the SHSH blob, I downloaded 4.3.3, put the device into DFU mode, and finally was able to downgrade.

This walled garden approach is exactly why I hate Apple products, they control your device. Every time I use an Apple product I hear the control voice from the Outer Limits: “Do not attempt to adjust the picture. We are controlling transmission. If we wish to make it louder, we will bring up the volume. If we wish to make it softer, we will tune it to a whisper. We will control the horizontal. We will control the vertical. We can roll the image; make it flutter. We can change the focus to a soft blur or sharpen it to crystal clarity. For the next hour, sit quietly and we will control all that you see and hear.”

Anyway, here are a couple of screenshots of the app running on an actual iPod:
App icon on the home screen

App main screen

VB code snippets

One reason I’ve been avoiding working on Kinetics is because it was written in VB classic. At the time I started work on the Kinetics program (1995) I didn’t know any better. Not until I discovered Delphi did the limits of VB become apparent. Although I despise having to find workarounds for its’ shortcomings, I’m not translating 1,245,431 lines of code. No, that’s not a typo, 1,245,431 lines of code (including forms).

Below are some of the more interesting snippets of code that have been added to this version.


One of the first things on my to-do list was a function to prevent a user from completely changing the name in a patient record. The following code works perfectly. Setting the limit of change to 75% should allow one to correct misspellings without completely changing the name:

 Visual Basic |  copy code |? 
01
Public Function FuzzyMatch(Fstr As String, Sstr As String) As Single
02
'Purpose: Compare two strings and quantify the differences
03
 
04
    Dim L, L1, L2, M, SC, T, R As Integer
05
 
06
    L = 0
07
    M = 0
08
    SC = 1
09
 
10
    L1 = Len(Fstr)
11
    L2 = Len(Sstr)
12
 
13
    Do While L < L1
14
        L = L + 1
15
        For T = SC To L1
16
            If Mid$(Sstr, L, 1) = Mid$(Fstr, T, 1) Then
17
                M = M + 1
18
                SC = T
19
                T = L1 + 1
20
            End If
21
        Next T
22
    Loop
23
 
24
    If L1 = 0 Then
25
        FuzzyMatch = 0
26
    Else
27
        FuzzyMatch = M / L1
28
    End If
29
 
30
End Function

The calling code for the preceding FuzzyMatch function:

 Visual Basic |  copy code |? 
1
       sngFuzzy = FuzzyMatch(strPtName, .txtName.Text) * 100
2
 
3
       If sngFuzzy < 75 Then
4
         'Exit if change too great
5
          .txtName.SetFocus
6
          MsgBoxCenter .hwnd, "Name field has changed by " & Format(100 - sngFuzzy, "##0") & "%", vbExclamation + vbOKOnly, "Edit limit exceeded", .Width, .Height, .Left, .Top
7
          Exit Function
8
       End If
9



A new feature in this version is the option to use a Word template for printing the monitoring form. Instead of distributing yet another file, I embedded the default doc in the resource file as a binary, then used the following function to extract and save the Word doc from the resource. 

 Visual Basic |  copy code |? 
01
  If Not FileExists("\Blank.doc") Then
02
      Dim ba() As Byte
03
      Dim fh As Integer
04
      ba = LoadResData(101, "CUSTOM")
05
      fh = FreeFile
06
      Open gvDataPath & "\Blank.doc" For Binary As fh
07
      Put fh, , ba
08
      Close fh
09
  End If
10

The preceding code depends on a function missing in VB classic, to check whether a file already exists:

 Visual Basic |  copy code |? 
1
Public Function FileExists(Filename As String)
2
'Purpose: Check for file existence
3
   On Error Resume Next  
4
   FileExists = (Len(Dir(Filename)) > 0)  
5
End Function
6

Finally, there is this function for search and replacing text in a Word doc (have yet to figure out how to call the Printer dialog):

 Visual Basic |  copy code |? 
01
Public Sub PrintWordDoc(ModelName As String)
02
'Purpose: Word automation for monitoring form
03
 
04
On Error GoTo PrintWordDoc_Err
05
 
06
  'Open MS Word in background
07
   Dim WordApp As Object
08
   Set WordApp = CreateObject("Word.Application")
09
   WordApp.Visible = False
10
 
11
  'Open Template
12
   WordApp.Documents.Open (gvDataPath & "\BlankPK_monitor.doc")
13
 
14
  'Search and Replace loop
15
   Dim SearchString, ReplaceString As String
16
   Dim I As Integer
17
   For I = 1 To 3
18
      Select Case I
19
         Case 1
20
             SearchString = "C_PTNAME"
21
             ReplaceString = frmKinetics.txtName.Text
22
         Case 2
23
             SearchString = "C_ROOM"
24
             ReplaceString = frmKinetics.txtRmNumber.Text
25
         Case 3
26
             SearchString = "C_MD"
27
             ReplaceString = frmKinetics.txtPhysician.Text
28
         'Code truncated here
29
      End Select
30
 
31
      '? WordRange = WordApp.ActiveDocument.Content
32
 
33
      WordApp.Selection.Find.ClearFormatting
34
      WordApp.Selection.Find.Replacement.ClearFormatting
35
 
36
      With WordApp.Selection.Find
37
            .Text = SearchString
38
            .Replacement.Text = ReplaceString
39
            .Forward = True
40
            .Wrap = wdFindContinue
41
            .Format = False
42
            .MatchCase = False
43
            .MatchWholeWord = False
44
            .MatchWildcards = False
45
            .MatchSoundsLike = False
46
            .MatchAllWordForms = False
47
      End With
48
      WordApp.Selection.Find.Execute Replace:=wdReplaceAll
49
   Next
50
 
51
  'TODO
52
  'Set printer & NumCopies 
53
 
54
  'Print
55
  'for I = 1 to NumCopies 
56
   WordApp.ActiveDocument.PrintOut
57
 
58
  'Wait for print before closing Word
59
   While WordApp.BackgroundPrintingStatus > 0
60
       DoEvents
61
       DoEvents
62
       Sleep (100)
63
   Wend
64
 
65
  'Close the document without saving 
66
   WordApp.ActiveDocument.Close (0)
67
 
68
  'Quit Word
69
   WordApp.Quit
70
   WordApp = Nothing
71
 
72
'Exit before error trap
73
 Exit Sub
74
 
75
PrintWordDoc_Err:
76
   giTrapItCentralErrorProcessor = TrapItCentralErrorProcessor("ddoc.bas", "PrintWordDoc", CStr(Err), Error$)
77
   If giTrapItCentralErrorProcessor = 1 Then
78
      Resume
79
   ElseIf giTrapItCentralErrorProcessor = 2 Then
80
      Resume Next
81
   Else
82
      Call CleanExit
83
      End
84
   End If
85
 
86
End Sub

Kinetics update

Some history, a confession, and a re-dedication

Many years ago I designed the Kinetics program to keep a permanent record of patients and consults, realizing the importance of a patient’s history. The database is compact, individual records are very small in order to accommodate a large number of records in a small, easily accessible file. This was the fundamental concept I started with when I wrote the first DOS version 27 years ago.

When Windows 95 came out, text based programs became obsolete overnight. Suddenly everyone wanted icons to click, colorful 3-D dialogs, proportional fonts, and all the other features of a graphical user interface. So, I was asked to develop a Windows version of Kinetics. Work on the program has since consumed a large portion of my life.

Overall the experience has been satisfying, but I’ve never liked the visual database front-end. The data browser paradigm using a VCR style browser control may be visual, but it’s not intuitive. The concept took quite some time for me to understand.

Although I’ve always been dissatisfied with the data browser, I’ve come to accept it over the years, resigned to the fact that it was simply the standard way to create a Windows database front end. All the tutorials and examples in textbooks use the same clunky VCR-style browser control. I expected that all Windows database programs would function in this standard way (most do), and that people would eventually learn the paradigm. After corresponding with users, seeing how they fail to manage their database, it became obvious that most people don’t grasp the concept.

Because of this fundamental misunderstanding by users, Kinetics was never used correctly, people would use the temporary record for consults. They would add a patient without searching first, many patient records were duplicated, some patients (frequent flyers) were saved 6 times. There would even be multiple records for the same patient during the same admission. They used encounter number instead of medical record number, thus losing data integrity as the MRN is permanently associated with that patient.

Over the years I’ve added search features and list functions to give users the ability to navigate the data. I’ve created step-by-step tutorials and recorded demonstration videos for the web site to help users grasp the concept. But I was never able to address the fundamental problem, the counter-intuitive VCR database browser.

My priority is the science, I intended to concentrate on improving the algorithms and equations that analyze the data to give optimal results. But I’m always pulled away from the science in order to work on interface issues, Windows component problems, and workarounds to the clumsy, butt-ugly front-end.

I had all but given up on Kinetics, and focused more of my time on the Antibiotic Kinetics program. Of course, AbPK simply sidesteps the issue by totally eliminating the patient database. Another reason I stopped using Kinetics was because I became frustrated with handwriting monitoring forms and orders. So I programmed Antibiotic Kinetics to automate Word, filling-in and printing the paperwork, freeing me from the busy work so I could think the consult through.

However, karma does eventually catch up to you. I was burned by not having that all important consult history. I had abandoned my fundamental core principle. If I was still using Kinetics, and if it was being used properly, I would have known that we had consulted on this patient before, that he did not tolerate normal doses, and that he required an unusually low dose.

So, there is my confession, and my motivation for finally getting back to work on the Kinetics program. Oftentimes the best ideas come out of adversity.

Below is a peek at the old vs new starting screens.

First, the old way with the clunky VCR navigation, and the displayed temporary record.

The new start screen is yee-haw simple. Search is by MRN or patient name, toggle button to the left of the text box:

Type MRN (or name) and press enter to get a list of matching records. Only after a search is the “Add” button displayed.

Here is a look at the patient data tab after pulling up the record. There are only 5 database buttons to choose from (close, edit, save, cancel, list):

I would appreciate feedback from folks who are using the software, on the off chance that anyone actually reads this crap.

And I still need to work on the science, LOL.