Tuesday, December 4, 2012

"Expired" Bug: CGI-DRG, VB-DRG, Access-DRG

A customer recently reported a bug to us which we have tracked down and are in the process of fixing.

The bug is this: if one used "Expired" as a discharge status in VB-DRG, Access-DRG or CGI-DRG, with the case described below, a bogus error was returned: code 5, "invalid discharge status."

Test case: primary diagnosis of 41071 and a discharge status of Expired.

Obviously, Expired is a valid discharge status: we had a bug in handling it. For some reason our mapping of Expired was explicitly not done for versions higher than 25.

We have fixed the bug and expect a re-release of version 30 by February 4th, 2013.

In order to validate our product, we used a DRG assignment app from another organization:

http://cs1.claimshop.net/grouper_demo/grouper_main.aspx

Tuesday, October 23, 2012

New 32 Bit Windows Reference Platform (f30)

As part of fixing the v30 bug (see posts with "v30 bug" as a label) we tok the opportunity to change our 32 bit Windows reference platform. The previous platform was over a decade old, so we were probably due.

Our 32 bit Windows platform is now:

Microsoft Windows 7 Professional, version 6.1.7601

The new executables work on the old reference platform, and vice versa, so we are not expecting any compatibility issues to arise from this platform change.

New 32 bit Linux Reference Platform (f30)

As part of fixing the v30 bug (see posts with "v30 bug" as a label) we were forced to change our 32 bit Linux reference platform. The previous platform was over a decade old, so we were probably due.

Our 32 bit Linux platform is now:

Linux 2.6.32-42-generic-pae #96-Ubuntu SMP Wed Aug 15 19:12:17 UTC 2012 i686 GNU/Linux

Under 32 bit Linux, our shared Perl object is now built against v5.10.1 and our shared PHP object is now built against 5.3.2-1ubuntu4.18.

Note that this means that we no longer support ancient glibc installations, but we suspect that there are precious few such installations left. However, if you are a customer of ours and you cannot run the new 32 bit Linux executable, we will be able to provide the old 32 bit Linux executables for the remainder of v30's reign--ie until October 1st, 2013.

Sunday, October 14, 2012

V30 Bug Test Case

This post is intended to give users of our various products a test case to ensure the corrected version of our product is in use.

Use the "v30 bug" label to see all the posts about this issue.

TEST CASE
The basic test case is this, from our new testdb.txt (line 18,374): WRONG=DRG 194; CORRECT=DRG 178. Note the Present on Admission (POA) indicators at the end of the diagnosis codes.

----------INPUT REC 18374----------
 age@  0 for  3:018
 sex@  3 for  1:1
  ds@  4 for  2:51
  dx@ 23 for 96:4870   Y|85172  N|48284  Y|69556  Y|E8616  Y                                                        
surg@223 for 98:9503   |9946   |9904   |9144   |9231   |3372   |0016   |9971                                             
 drg@607 for  3:178
 mdc@610 for  2:04
  rc@612 for  2:00
dflg@614 for 15:101100000000000
sflg@629 for 15:000000000000000

TEST CASE IN C
Here is a C program which calls our mhdrg() function on the this test case:

/* tryit.c (c) 2002 M+H Consulting, LLC C-callable demo (BFH) */
/* Sun Oct 14 18:08:14 EDT 2012 BFH test case for v30 bug */
/* Sun Oct  3 11:57:46 EDT 2010 BFH support f28 */
/* 10/06/2008 made win32 and unix versions the same */
/* 10/11/2003 added bit-string of used dx's and used procedures */

#include 
#include 
#include 

#define DELIM "^"
#define RETURNED 10

#ifdef WIN32
/* DLL functions */
extern int mhicd();             /* mhicd.dll */
extern char * mhdrg();          /* mhdrg.dll */
extern char * mherrdesc();      /* mhdrg.dll */
#else
char * mhdrg();
extern char * errdesc();        /* mhdrg.dll */
#endif

int main() {
    char * retval;
    char * p;
    char * a[RETURNED];
    char * expected;
    int i;

    /* f30 test case: bug fix
----------INPUT REC 18374----------
 age@  0 for  3:018
 sex@  3 for  1:1
  ds@  4 for  2:51
  dx@ 23 for 96:4870   Y85172  N48284  Y69556  YE8616  Y                                                        
surg@223 for 98:9503   9946   9904   9144   9231   3372   0016   9971                                             
 drg@607 for  3:178
 mdc@610 for  2:04
  rc@612 for  2:00
dflg@614 for 15:101100000000000
sflg@629 for 15:000000000000000
     */
     expected = "RC: 0 MDC: 04 DRG: 178";

    /* call the grouper, store results in reval */
    retval = mhdrg(
        "f30p",                 /* which DRG version you want */
        "/drbd/mnh/src/SWIG",   /* path to masks files */
        "1",                    /* discharge status */
        "18",                   /* patient age on admission */
        "1",                    /* patient sex (1=male, 2=female) */
        /* ICD DX codes */
        "4870   Y85172  N48284  Y69556  YE8616  Y",
        /* ICD procedure codes */
        "9503   9946   9904   9144   9231   3372   0016   9971   ",
        8,                      /* length of each ICD DX code */
        7                       /* length of each ICD procedure code */
    );

    /* if there was an error, alert the user */
    if (retval == NULL) {
        printf("M+H grouper argument or environment error: %s\n", errdesc());
        exit(-1);
    }

    /* show the raw return value */
    printf("Raw return value from mhdrg:\n%s\n\n",retval);

    /* deconstruct return from mhdrg() */
    p = strtok(retval,DELIM);
    for (i = 0; i < RETURNED && p != NULL; i++) {
        a[i] = p;
        p = strtok(NULL,DELIM);
    }
    /* last two return values are bit-strings of which ICD codes were 
     * used in the grouping 
     */

    puts("Deconstructed return value from mhdrg:");
    printf("rc=%s, mdc=%s, drg=%s, ovn=%s, weight=",a[0],a[1],a[2],a[3]);
#ifdef OLD_WAY
    printf("%s, mean=%s, porm=%s\ndesc=%s\ndx flags:%ld, px flags: %ld\n",a[4],a[5],a[6],a[7],dxu,pxu);
#else
    printf("%s, mean=%s, porm=%s\ndesc=%s\ndx flags:%s, px flags: %s\n",a[4],a[5],a[6],a[7],a[8],a[9]);
#endif

    /* show what we should get */
    printf("\nExpected result: %s\n",expected);

    /* last two return values are bit-strings of which ICD codes were used in the grouping */
    puts("\nSignificant ICD codes:");
#ifdef OLD_WAY
    for (mask = 1L,i = 0; i < 32; i++, mask *= 2L) {
        if (mask & dxu) {
            printf(" * DX code %2d was used\n",(i+1));
        }
    }
    for (mask = 1L,i = 0; i < 32; i++, mask *= 2L) {
        if (mask & pxu) {
            printf(" * Proc code %2d was used\n",(i+1));
        }
    }
#else
    p = a[8];
    for (i = 0; i < 32 && p[i] != '\000'; i++) {
        if (p[i] == '1') {
            printf(" * DX code %2d was used\n",(i+1));
        }
    }
    p = a[9];
    for (i = 0; i < 32 && p[i] != '\000'; i++) {
        if (p[i] == '1') {
            printf(" * Proc code %2d was used\n",(i+1));
        }
    }
#endif
    exit(0);
}
/* eof */

TEST CASE IN CGI-DRG
Here is an example of how the DAE failure looked in our CGI-DRG product:

Before fix: incorrect DRG of 194

M+H CGI CMS (HCFA) DRG Grouper (3.0:f30)

Version:  POA:  Exempt:  Age:  Sex:  Discharge Status: 
	    Diagnoses 1-5: *     *   
	   Diagnoses 6-10:           
	  Diagnoses 11-15:           

	   Procedures 1-5:                
	  Procedures 6-10:                
	 Procedures 11-15:                

						

DRG: 194 SIMPLE PNEUMONIA & PLEURISY W CC                                      
MDC:  4  Weight: 0.9996 Mean LOS: 0.00 Version: f30

© 2002-2012 M+H Consulting LLC, all rights reserved

After fix: correct DRG of 178

M+H CGI CMS (HCFA) DRG Grouper (3.0:f30)

Version:  POA:  Exempt:  Age:  Sex:  Discharge Status: 
	    Diagnoses 1-5: *   * *   
	   Diagnoses 6-10:           
	  Diagnoses 11-15:           

	   Procedures 1-5:                
	  Procedures 6-10:                
	 Procedures 11-15:                

						

DRG: 178 RESPIRATORY INFECTIONS & INFLAMMATIONS W CC                           
MDC:  4  Weight: 1.4403 Mean LOS: 0.00 Version: f30

© 2002-2012 M+H Consulting LLC, all rights reserved

V30 Bug

This post is an overview of an issue with the v30 DRG Assignment Engine (DAE) and our response to it. Related posts will have the label "v30 bug" in order to make them easier to find. This post will be updated as the status changes.

Current status (Oct 24 2:27pm Eastern)
The issue in regression testing under 32 bit Linux was hard enough to resolve that we upgraded the 32 bit Linux reference platform instead (for details, go here). While we were upgrading reference platforms, we also upgraded the Windows reference platform (for details, go here).

We have finished the in-house rebuild and revalidation of our products. We are currently rebuilding the products built using  a porting lab, at which point we will be ready to update our web site and start sending out free updates to customers. We have already begun sending out free updates to customers with standing orders.

History of Bug Fix

On October 11 at about 10am
Customer Service received a bug report:

One of our customers asked about a change in V30 that maps a dx of 487.0 with one 1 of 11 secondary pneumonia dx's to DRGs 177-179. In previous versions this combo would map to DRGs 193-195. She claims this change is in the specs of the final release. Our grouper is mapping this combo to the old DRGs of 193-195.

October 11 at about 10:30am
Tech Support punted this issue to Development.

October 12 at about 6pm
Development delivers a fix to Tech Support:

The problem was in the CC exclusion logic, requiring a change to the DAE, so all DRG assigning products will have to be re-released.

When the DAE was delivered the first time, you noticed that the test file did not do a very good job of covering the DRGs, and we said we would look into finding the latest one with better cover. which we did. When we ran against the new test file, there were over 200 mismatches. These turned out to be cases with more than 15 diagnoses or procedures. So we upped our limit to 25 which required changes to DRGFilt and it control file, cntl.f30.

Note that drgmasks.f30 did NOT change so you only have to redeliver the DAE itself (drgfilt, dll, shared object, etc).

October 13, various
Tech Support drew up their roll-out plan:
  1. create this overview post
  2. document a test case or two so users can confirm DAE status
  3. revalidate product line with new DAE and new test DB
  4. update our manual's "What's New" to reflect this bug
  5. have Customer Service approve documentation changes
  6. update web site with new products
  7. send updates for standing orders
  8. send updates for orders from the web site
Plan approved; plan execution begins.

October 14, various
Tech Support  continues executing plan.

Thursday, October 4, 2012

V30 Open Issues

10/4/12 11:03 AM Eastern
We have completed our V30 release with two open issues:
  1. Our 64 Bit Linux Perl Shared Object is still built against Perl v5.8.8, which is on the old side of the pre-5.10 divide. We can (and do) build against 5.10, but still in a developmental mode: we have yet to add the 5.10+ product to our catalogue. We haven't figured out what to call it: any suggestions?
  2. We have a similar issue with our 64 Bit Linux PHP Shared Object: we still build against a rather old PHP and need to have our developers create a production environment in which to build a newer object. We also need to update our catalogue to reflect this.
If you are looking to run the newer version of either of this products in the near future, please buy the  older version and send email to techsupport@drggroupers.com so we can send you the newer version by hand.

10/23/12 3:12PM Eastern
As part of our f30 bug fix, we changed our 32 bit Linux platform, which changed the PHP and Perl versions against which our 32 Linux shared objects are created:

32 bit Linux Perl version: v5.10.1
32 bit Linux PHP version: 5.3.2-1ubuntu4.18

So even if you are running 64 bit Linux, you might want our 32 bit Linux shared object, because most 64 Linux systems can run 32 bit versions of software and these versions are across important divides from our 64 bit versions.

Wednesday, October 3, 2012

DRGFilt Control File Change for V30: dxc & sgc

The ancient and venerable DRGFilt control file syntax has changed slightly for v30, released in October of 2012. The change is the addition of two new keywords, "dxc" and "sgc" and they stand for "diagnosis count" and "surgery/procedure count" respectively.

The problem they solve are records with 15 dx or 15 procedures. Since drgfilt's cntl file mechanism only has a two-digit length, it cannot directly specify all 15 when they are spaced as on these test records.

When these values are present, they are multiplied in drgfilt by the dxl and/or sgl and override the lengths on the dx and sg cards.

For example, our internal control file to process the Federal test data now looks like this:

age  000 03
sex  003 01
ds   004 02
dxl  000 08
dxc  000 15
poa  000 07
dx   023 96
sgl  000 07
sgc  000 15
surg 223 98
#drg  603 03
#mdc  600 02
#rc   598 02
exmp 006 01
# these are written out by us
drg  607 03
mdc  610 02
rc   612 02
dflg 614 15
sflg 629 15

Monday, October 1, 2012

New in V30

The DRG definitions were finalized early this year, allowing us to ship products on September 28, 2012 instead of our usual target of the first week in October.

This is a quiet year for DRG version change. The only real DRG change we have to report is the addtion of two new HACs (see glossary), 13 and 14.

Probably also because of the impending switch from ICD9 to ICD10, there are no new or revised or deleted ICD-9-CM diagnosis codes for V30. There are also no revised or deleted ICD-9-CM procedure codes for V30 and only one new procedure code:

00.95    Injection or infusion of glucarpidase

For details, visit the CMS site:

https://www.cms.gov/Medicare/Coding/ICD9ProviderDiagnosticCodes/

Conversion from ICD9 codes for diagnoses and procedures to ICD10 codes is still coming, but it isn't here yet. We will continue to produce ICD10 versions of our products as an aid to cutting over.

Friday, September 28, 2012

V30 for ICD10

We have a pre-release of V30 for ICD10 codes in the works. We expect CMS to release a definitions manual in the next few weeks, at which point we can ensure that our implementation is correct.

We expect CMS to release their V30 ICD10 grouper early next year, 2013. We intend to release ours on or before February 1st, 2013.

Thursday, September 27, 2012

V30 Release Early

Since there were no changes to V30 in the past few weeks, our pre-release V30 is being promoted to a full release today. While the official release date will be October 1st this year, we expect to finish our internal validation and distribution today, at which point we will fill our standing orders. We will update our website and on-line store tomorrow.

Thanks for your patience.

Thursday, August 16, 2012

F30 Pre-Release

We have received a pre-release of F30 from our development group to accommodate a DRG Assignment Service (DAS) client who wanted to try out F30 ahead of its official release on October 1st, 2012.

We put the pre-release F30 through our basic validation process, upgraded our DAS system and have used it successfully.

We are in the process of finishing the internal F30 roll-out.

Barring changes from CMS or bug reports, this will become our official F30 release on October 1st, 2012.

Thursday, May 31, 2012

DRG Weights

QUESTION

How do I check the DRG weights in your software?

ANSWER

You can confirm our weights by cross-checking against the source:

http://www.herc.research.va.gov/resources/faq_f03.asp

Wednesday, May 2, 2012

Calling mhicd()

There is some confusion, partly caused by bad documentation on our part, about calling mhicd(), the function which gives you the short description of the specified ICD9cm code.


ORIGINAL EMAIL

I get the following error message when I try to compile the examples in DRGMAN.pdf.
        'mhicd' : function does not take 4 arguments...
Can it be that the version differs?



ANSWER


You are right, the example is wrong, it is missing the final argument. We will fix that as soon as we can.

The mhicd() function takes 5 arguments:

(1) which kind of code: D=diagnosis, P or S=procedure
(2) the file name to use as the ICD9 look up table
(3) the ICD9 code to be looked up
(4) the buffer into which to put the name
(5) the length of the buffer
 
So the examples should look like this:


Visual BASIC

Private Sub dx_Change(index As Integer)
    Dim retval As String * 24
   
    Call mhicd("d", _
        Command & "/icd9.tab", Me.dx(index).Text, retval, 23)
    Me.ddesc(index).Caption = retval
End Sub


C VERSION


    if ((i=mhicd("d","icd9.tab","56409",retval,23))) {
        printf("Error from mhicd(): %d\n",i);
    } else {
        printf("%s\n",retval);
    }

Tuesday, April 3, 2012

C-Callable Shared Object Version?

QUESTION

How do I figure out which version of the C-Callable Shared Object I am using?


ANSWER

There is no good way because as of this writing, April-2012, the C-Callable Shared Object's API is missing the usual method for retrieving this information.

Instead, to see if your shared object will support a given version, you have to use the errdesc() function, like so:

-------------------------sample code starts

/* declare the functions inside the shared object: */
char * mhdrg();
extern char * errdesc();

int main() {
    char * retval;
    char * p;
    char * a[RETURNED];
    char * expected;
    int i;

    /* call the grouper, store results in reval */
    retval = mhdrg(
        "f29",                  /* which DRG version you want */
        "/drbd/mnh/src/SWIG",   /* path to masks files */
        "1",                    /* discharge status */
        "49",                   /* patient age on admission */
        "2",                    /* patient sex (1=male, 2=female) */
        /* ICD DX codes */
        //"99679   25041   5859    2767    25051   36904   25061   3371    40290   2859                    ",
        "71500  Y",
        /* ICD procedure codes */
//       0123456012345601234560123456
//      "3942   3993   3995                                                                  ",
        "8134   8135   ",
        8,                      /* length of each ICD DX code */
        7                       /* length of each ICD procedure code */
    );

    /* if there was an error, alert the user */
    if (retval == NULL) {
        printf("M+H grouper argument or environment error: %s\n", errdesc());
        exit(-1);
    }

    /* show the raw return value */
    printf("Raw return value from mhdrg:\n%s\n\n",retval);

    /* deconstruct return from mhdrg() */
    p = strtok(retval,DELIM);
    for (i = 0; i < RETURNED && p != NULL; i++) {
        a[i] = p;
        p = strtok(NULL,DELIM);
    }

    puts("Deconstructed return value from mhdrg:");
    printf("rc=%s, mdc=%s, drg=%s, ovn=%s, weight=",a[0],a[1],a[2],a[3]);
    printf("%s, mean=%s, porm=%s\ndesc=%s\ndx flags:%s, px flags: %s\n",a[4],a[5],a[6],a[7],a[8],a[9]);

    /* last two return values are bit-strings of which ICD codes were
     * used in the grouping
     */

    puts("\nSignificant ICD codes:");
    p = a[8];
    for (i = 0; i < 32 && p[i] != '\000'; i++) {
        if (p[i] == '1') {
            printf(" * DX code %2d was used\n",(i+1));
        }
    }
    p = a[9];
    for (i = 0; i < 32 && p[i] != '\000'; i++) {
        if (p[i] == '1') {
            printf(" * Proc code %2d was used\n",(i+1));
        }
    }

    exit(0);
}

Saturday, March 3, 2012

Access-DRG Versions

In order to keep up with MS-Access, we have had to split our Access-DRG product into two different products:
  1. Access-DRG/2003, which should run under MS-Access 2000, 2002 and 2003. This is the good old ".mdb" version
  2. Access-DRG/2007, which should run under MS-Access 2007. This is the new-fangled ".accdb" version
We have updated our product catalog and our retail web site, so you should now be able to get the version you need.

Note that this product is more-or-less useless without the VB-callable DLL, but the current VB-callable DLL is included with your Access-DRG purchase.

In the normal course of events, we expect you to buy Access-DRG once and VB-DLL subsequent year. You only need to buy Access-DRG again if and when Microsoft changes MS-Access enough to require a new app.

Thursday, March 1, 2012

Re-release of Windows Installers

We received a bug report that our windows installer for our VB-callable DLL did not work properly under at least some Windows 7 installations.

We use the Nullsoft Scriptable Installer System (NSIS) to create all of our windows installers. So rather than try to debug someone else's rather complex system, we did the usual Windows thing: we upgraded and tried again. And now it all works, hurray.

Just to be sure, we recreated all of our windows installers (see below) so there should be no other problems, at least until Windows 8 is released.

File NameProduct CodeO/SEnvVerComment
mhdrg.exeCDLLwin32f29.1f29.1, new NSIS
mhi9tabf26.exeCICDwin32f29.1
mhdrgvb.exeVBDLLwin32f29.1
mhvbdrg.exeVBDRGwin32vb5f29.1
mhicdvb.exeVBICDwin32f29.1
cgi-drg.exeW32CGIDRGwin32f29.1
drgfilt.exeWINFILTwin32f29.1
mhmasksXX.exeWINMASKwin32all of them:
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, v3

Friday, January 13, 2012

Will There Be an X29? If So, When?

QUESTION

We are interested in an ICD-10 experimental grouper for version 29. We see that you have one for X28. Will you do one for X29? If so, when?

ANSWER

CMS hasn't released v29 for ICD-10 yet. It is built and we're trying to persuade them to post it on their site as early in January as they are back to work. 10 minutes after they've done that, we can be the first to offer X29, but we can't do so before.

Thursday, January 5, 2012

Estimated CMI?

Your query to DRGGroupers.com:
My Boss wants an estimated CaseMixIndex  within 24 hours of admission.  I know that we have to default some fields, i.e. discharge status.  He wants me to compare the CMI using the 24 hours of data with the final CMI assigned after discharge.  Is this possible?  Does it even make sense for us to try?  Look forward to your response. 

Our reply:

Technologically, this is not hard. However it is not clear that the results would be meaningful, but that is your boss's call.

To assign a DRG, you need the following data elements:

(a) sex
(b) age
(c) diagnoses
(d) procedures
(e) discharge status

In the first 24 hours of an inpatient encounter, you would know the sex and age of the patient. You could assume that the discharge status will be "home" which will be very wrong sometimes. You could use the notoriously inaccurate admitting diagnosis and whatever procedures were performed immediately for the diagnoses and procedures.