Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

Friday, October 30, 2015

Support for 32-bit Linux in V33

In the Windows world we ship 32-bit DLLs because we count on "thunking" to allow this code to run in either 64-bit or 32-bit environments. But we do plan on upgrading our Windows development environment to 64-bit in the next four years.

In the Linux world we planned to drop 32-bit support with v33 (Oct-2015) but found that too many people still run 32-bit Linux, so we added 32-bit versions to all of our programmer tools:

  • our PHP module (phpdrgv33_32bit.so)
  • our Perl module (perldrgv33_32bit.so)
  • our C-callable object (libdrgv33_32bit.so)
  • DRGFilt (drgfiltv33_32bit)
We named the 32-bit versions by adding "_32bit" to the end of the file name and therefore before the extension. If you buy any of these modules, you get both the 32-bit and 64-bit versions. If you are in a 32-bit environment, you can either rename the object or call the 32-bit version explicitly.

Tuesday, October 23, 2012

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.

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.

Tuesday, October 11, 2011

F29 Release: Linux Validation

F29 Linux Product Validation Log

Masks for F29...Passed
DAE Regression Test...Passed
Linux DRGFilt for F29...Passed
Demo Linux version of DRGFilt...Passed
Linux C Shared Object for F29...Passed
Linux Perl Shared Object for F29...Passed
Linux PHP Shared Object for F29...Passed
Linux CGI-DRG for F29...Passed

Details

Masks for F29...Passed
Validated the masks file against official list, which we found here. Not that some MS-DRGs are not defined, such as 9, 18, 19, etc.

DAE Regression Test...Passed
Ran the latest DAE through our regression testing suite.

[Tue Oct 11 16:33:41 2011]     | --------SUMMARY-----------
[Tue Oct 11 16:33:41 2011]     |   v29: Ok
[Tue Oct 11 16:33:41 2011]     |   v28: Ok
[Tue Oct 11 16:33:41 2011]     |   v27(poa): Ok
[Tue Oct 11 16:33:41 2011]     |   v27: Ok
[Tue Oct 11 16:33:41 2011]     |   v26(poa): Ok
[Tue Oct 11 16:33:41 2011]     |   v26: Ok
[Tue Oct 11 16:33:41 2011]     |   v25: Ok
[Tue Oct 11 16:33:41 2011]     |   v24: Ok
[Tue Oct 11 16:33:41 2011]     |   v23: Ok
[Tue Oct 11 16:33:41 2011]     |   v22: Ok
[Tue Oct 11 16:33:41 2011]     |   v21: Ok
[Tue Oct 11 16:33:41 2011]     |   v20: Ok
[Tue Oct 11 16:33:41 2011]     |   v19: Ok
[Tue Oct 11 16:33:41 2011]     |   v18: Ok
[Tue Oct 11 16:33:41 2011]     |   v17: Ok
[Tue Oct 11 16:33:41 2011]     |   v16: Ok
[Tue Oct 11 16:33:41 2011]     |   v15: Ok
[Tue Oct 11 16:33:41 2011]     |   v14: Ok
[Tue Oct 11 16:33:41 2011]     |   v13: Ok
[Tue Oct 11 16:33:41 2011]     |   v12: Ok




Linux DRGFilt for F29...Passed
Validated the DAE with DRGFilt against the test data set with this control file:

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

Using our validation script, we compare the incoming DRG at offset 603 to our DRG at offset 607, the incoming MDC at 600 with ours at 610, the incoming RC at offset 598 with ours at 612.

Demo Linux version of DRGFilt...Passed
This free version only does F10. Validated it against our internal F10 dataset of 35,451 records.

Interactive Test Cases
We don't run the entire test dataset through our interactive UIs because it would be too much work for too little gain. Once we validate the core DAE, we validate the UIs with a sample of the official test dataset. This year that sample looks like this:

-------------------------------------------
   Age: 049
   Sex: F
  Disp: 01
   MDC: 21
   DRG: 908
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 99679 : :
  DX02: 25041 : :
  DX03: 5859  : :
  DX04: 2767  : :
  DX05: 25051 : :
  DX06: 36904 : :
  DX07: 25061 : :
  DX08: 3371  : :
  DX09: 40290 : :
  DX10: 2859::

Proc's:  Code
  SG01: 3942  
  SG02: 3993  
  SG03: 3995
-------------------------------------------
   Age: 059
   Sex: M
  Disp: 01
   MDC: 01
   DRG: 074
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 3564  : :
  DX02: 2639  : :
  DX03: 311   : :
  DX04: 2761  : :
  DX05: 5601  : :
  DX06: 5180::

Proc's:  Code
  SG01: 9383  
  SG02: 9339

-------------------------------------------
   Age: 050
   Sex: M
  Disp: 01
   MDC: 04
   DRG: 182
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 1628::

Proc's:  Code
  SG01: 324   
  SG02: 3409  
  SG03: 8965  
  SG04: 9396

-------------------------------------------
   Age: 077
   Sex: F
  Disp: 03
   MDC: 08
   DRG: 563
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 81611 : :
  DX02: 25081 : :
  DX03: 2512  : :
  DX04: E8849 : :
  DX05: 3319  : :
  DX06: 04110 : :
  DX07: 8831::

Proc's:  Code
  SG01: 7904  
  SG02: 9659  
  SG03: 8659

-------------------------------------------
   Age: 081
   Sex: F
  Disp: 01
   MDC: 02
   DRG: 117
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 3659::

Proc's:  Code
  SG01: 1279




Linux C Shared Object for F29...Passed
Validated the Linux C shared object with this test case, to also confirm that the used codes bit flag handling is now correct:

-------------------------------------------
   Age: 055
   Sex: F
  Disp: 01
   MDC: 08
   DRG: 455
  DX's:  Code :E:P where E=exempt flag P=present on admission flag
  DX01: 71500 : :Y

Proc's:  Code
  SG01: 8134  
  SG02: 8135



Raw return value from mhdrg:
0^8^455^29^5.6449^0.00^ ^COMBINED ANTERIOR/POSTERIOR SPINAL FUSION W/O CC/MCC                  ^1^11

Deconstructed return value from mhdrg:
rc=0, mdc=8, drg=455, ovn=29, weight=5.6449, mean=0.00, porm=
desc=COMBINED ANTERIOR/POSTERIOR SPINAL FUSION W/O CC/MCC                 
dx flags:1, px flags: 11

Expected result: RC: 0 MDC: 08 DRG: 455

Significant ICD codes:
 * DX code  1 was used
 * Proc code  1 was used
 * Proc code  2 was used


Linux Perl Shared Object for F29...Passed

Validated the Perl shared object against the same test case as C shared object.

THIS YEAR, WE WILL HAVE TO CHANGE OUR PROCESS TO HANDLE THE 5.8 VS POST-5.8 DIVIDE, AS WELL AS MULT-THREADED VS NOT-MULTI-THREADED.


Linux PHP Shared Object for F29...Passed
Validated the Perl shared object against the same test case as C shared object.

Linux CGI-DRG for F29...Passed
Validated the Linux CGI-DRG against same test case as C shared object.


Tuesday, October 4, 2011

Codes Used in DRG Assignment, Continued

QUESTION

This is a follow-up to an earlier question.
When I use this.......
---------------------------------------------
$retval = mhdrgc::mhdrg(
         #'f26p',                        # which DRG version you want
         'f28',                        # which DRG version you want
         '/home/programmer/grouper',        # path to masks files
         '1',                        # discharge status (home)
        '72',                        # patient age on admission
        '2',                        # patient sex (1=male, 2=female)
        # ICD DX codes
         '3313    3312    Y49320  Y5990   N7812   Y3051   Y73300  Y3004   Y3320   Y71598  Y412    ',
        # ICD procedure codes
        '0331            ',
        '8',                        # length of each ICD DX code
        '7',                       # length of each ICD procedure code
     );
------------------------------------------------------------------
I'm putting in 11 DX codes and 1 procedure code.

What I get back is this...
---------------------------------------------
0^1^57^28^0.9350^0.00^ ^DEGENERATIVE NERVOUS SYSTEM DISORDERS W/O MCC                         ^1^0


The blog states ...
"The strings are positional: 1001 means that the first code was used, codes two and three were not but code four was. "

Shouldn't the output be more like 
0^1^57^28^0.9350^0.00^ ^DEGENERATIVE NERVOUS SYSTEM DISORDERS W/O MCC                         ^10000000000^0

That is, 3313 was used, but the other ten weren't?

ANSWER

You are referring to the bitstrings of which diagnoses or procedures that were used in the DRG assignment. For the DRGFilt product, these are sflg and dflg keywords.

You are correct, there is a bug in the interface routine. What we see at the lowest level, when we run your example through our testbed, is this:

Diagnosis flags=(100000000000000000000000000000)
Procedure flags=(000000000000000)

So somewhere between the DAE and the Perl interface,the output is being stripped of trailing zeroes, which is not what we want in this case.

We have opened an internal bug and expect to have this fixed in the upcoming release.

Tuesday, August 30, 2011

Codes Used in DRG Assignment?

QUESTION

Hi Tech Support,

The PDF is very informative but it appears to be missing explanation of a couple of the output codes. I get ten bits of info but only first eight appear to be documented in the grouper's documentation PDF ("UNIX Embeddable Grouper API": pages 31-32). Those are .......

1. Grouper return code
2. Major Diagnostic category of assigned DRG
3. DRG assigned to patient encounter
4. DRG version number used to assign DRG
5. The weight of the DRG
6. Geometric mean length of stay for DRG
7. PorM flag
8. DRG description

The string I had returned to me by the grouper was....
0^1^57^28^0.9350^0.00^ ^DEGENERATIVE NERVOUS SYSTEM DISORDERS W/O MCC ^1^0

It's the last two fields of "1" and "0" that appear to be undocumented.

The last question I have is regarding the significance of diagnosis codes. When feeding a list of diagnosis codes into the grouper, is there a way to determine which of the diagnosis codes were significant in the grouper's decision making? I ran across something like that on page 22 (section labeled "Output") of the PDF that you folks package with the grouper.

Thanks so much for all of your assistance.

ANSWER

The lack of documentation for these fields is definitely an oversight, thank you for pointing this out. We will include these fields in the updated manual when we release it this coming October.

Those two fields are ASCII-ified bit strings of which codes were used in the DRG assignment. The first field is a string of diagnosis bits and the second string is a string of procedure bits. The strings consist of either an ASCII '1' or an ASCII '0'. A one means "this code was used" and a zero means "this code was not used."

The strings are positional: 1001 means that the first code was used, codes two and three were not but code four was.

Sunday, October 5, 2008

Validating a DRGFilt Control File

QUESTION

I find the DRGFilt control file format kind of hard to understand. How can I be sure that I got it right?

ANSWER

We hear you: the control file format is showing its age: it was derived from a format that originated on punch cards (!).

We use the following Perl script to validate our control files in-house:

Sample usage
In the examples below, replace "control-file" with the name of the control file you are validating, and "data-file" with the name of the data file you are running against. For extra credit, replace "pt-id" with the patient, claim or record ID you are looking for.

Unix
  • perl chkcntl.pl control-file < data-file | more
  • head -20 data-file | perl chkcntl.pl control-file | more
  • fgrep pt-id data-file | perl chkcntl.pl control-file
Windows
  • perl.exe chkcntl.pl control-file < data-file | more
  • perl.exe chkcntl.pl control-file < data-file > output.txt

Sample Perl Code

# chkcntl.pl - program to check a control file

my($sgl,$dxl,$recLen,%h) = Load(shift(@ARGV));

while (defined(my $l = <>)) {
    $l =~ s/\r|\n//g;
    # pad out input with astericks if too short
    while (length($l) < $recLen) { $l .= '*'; }

    my $output = "";
    foreach my $key (sort (keys %h)) {
    my $ref = $h{$key};
    my($name,$off,$len) = @$ref;

    my $val = substr($l,$off,$len);
    $output .= sprintf("%4.4s@%3d for %2d:",$name,$off,$len);

    if ($name =~ /^(dx|surg)$/i) {
        $output .= AddBar($val, ($name =~ /dx/i)? $dxl : $sgl);
    } else {
        $output .= $val;
    }

    $output .= "\n";
    }
    print $output,"\n";
}

exit(0);
#-----------------------------------------------------------------
sub AddBar {
    my $val = shift;
    my $len = shift;

    my $inLen = length($val);
    my @f = ();

    for (my $i = 0; $i < $inLen; $i += $len) {
    push(@f,substr($val,$i,$len));
    }

    return join('|',@f);
}

sub Load {
    my $fname = shift;

    my %h;  # keyed by offset, value is name
    my($dxl,$sgl) = (5,4);
    my $recLen = 0;
    my($poa,$exempt);

    open(FILE,$fname) || die "Could not open '$fname': $!";
    while (defined(my $l = <FILE>)) {
    next unless ($l =~ /^[a-zA-Z]/);
        #age  000 03
    my($name,$offset,$length) = unpack("a4xa3xa2",$l);

    if ($name =~ /sgl/i) {
        $sgl = $length;
        next;
    }
    if ($name =~ /dxl/i) {
        $dxl = $length;
        next;
    }
    if ($name =~ /poa/i) {
        $poa = $length;
        next;
    }
    if ($name =~ /exmp/i) {
        $exempt = $length;
        next;
    }

    my $key = sprintf("%03d",$offset);
    my $ref = [ $name, $offset, $length ];
    foreach my $el (@$ref) { $el =~ s/^\s+|\s+$//g; }
    $h{$key} = $ref;

    }
    close(FILE);

    # figure out end of record: max offset + length
    my ($max) = (reverse (sort keys %h));
    my $ref = $h{$max};
    my $recLen = $$ref[1] + $$ref[2];

    return ($sgl,$dxl,$recLen,%h);
}
# eof

Thursday, September 26, 2002

We Love SWIG

As we look to make our DAE more easily integrated with other people's software, we came across SWIG and it is our new best friend: easy to use, effect and Open Source. We use it for all of our Linux-based embeddable products and we love it.

Now we can provide DAE access for Perl scripts, PHP pages and C programs such as SAS.