RORX019A ;BPOIFO/ACS - LIVER SCORE BY RANGE (CONT.) ; 8/23/11 8:38am
 ;;1.5;CLINICAL CASE REGISTRIES;**10,13,14,16**;Feb 17, 2006;Build 3
 ;
 ;08/23/2011 BP/KAM ROR*1.5*16 Remedy Call 512757 Correct the Liver
 ;                             Score Calculation
 ;
 ; This routine uses the following IAs:
 ;
 ; #10105 $$LN^XLFMTH (supported)
 ; #3556  GCPR^LA7QRY (supported)
 ; #10061 DEM^VADPT   (supported)
 ;
 ;******************************************************************************
 ;******************************************************************************
 ;                 --- ROUTINE MODIFICATION LOG ---
 ;        
 ;PKG/PATCH    DATE        DEVELOPER    MODIFICATION
 ;-----------  ----------  -----------  ----------------------------------------
 ;ROR*1.5*10   MAR  2010   A SAUNDERS   Routine created
 ;ROR*1.5*13   DEC  2010   A SAUNDERS   Moved tag CALCMLD to this routine
 ;ROR*1.5*14   APR  2011   A SAUNDERS   Added logic to calculate the APRI and
 ;                                      FIB4 scores.
 ;                                      
 ;******************************************************************************
 ;******************************************************************************
 Q
 ;
 ;*****************************************************************************
 ;OUTPUT REPORT 'RANGE' PARAMETERS, SET UP REPORT ID LIST (EXTRINISIC FUNCTION)
 ;
 ; PARTAG        Reference (IEN) to the parent tag
 ;
 ; Return Values:
 ;        RORDATA("IDLST") - list of IDs for tests requested
 ;       <0  Error code
 ;        0  Ok
 ;*****************************************************************************
PARAMS(PARTAG,RORDATA,RORTSK) ;
 N PARAMS,DESC,TMP,RC S RC=0
 ;--- Lab test ranges
 S RORDATA("RANGE",1)=0 ;initialize MELD to 'no range passed in'
 S RORDATA("RANGE",2)=0 ;initialize MELD Na to 'no range passed in'
 S RORDATA("RANGE",3)=0 ;initialize APRI to 'no range passed in'
 S RORDATA("RANGE",4)=0 ;initialize FIB4 to 'no range passed in'
 I $D(RORTSK("PARAMS","LRGRANGES","C"))>1  D  Q:RC<0 RC
 . N GRC,ELEMENT,NODE,RTAG,RANGE
 . S NODE=$NA(RORTSK("PARAMS","LRGRANGES","C"))
 . S RTAG=$$ADDVAL^RORTSK11(RORTSK,"LRGRANGES",,PARTAG)
 . S (GRC,RC)=0
 . F  S GRC=$O(@NODE@(GRC))  Q:GRC'>0  D  Q:RC<0
 .. S RANGE=0,DESC=$$RTEXT(GRC,.RORDATA,.RORTSK) ;get range description
 .. S ELEMENT=$$ADDVAL^RORTSK11(RORTSK,"LRGRANGE",DESC,RTAG) ;add desc to output
 .. I ELEMENT<0 S RC=ELEMENT Q
 .. D ADDATTR^RORTSK11(RORTSK,ELEMENT,"ID",GRC)
 .. ;add test ID to the test ID 'list'
 .. S RORDATA("IDLST")=$G(RORDATA("IDLST"))_$S($G(RORDATA("IDLST"))'="":","_GRC,1:GRC)
 .. ;--- Process the range values
 .. S TMP=$G(@NODE@(GRC,"L"))
 .. I TMP'="" D  S RANGE=1
 ... D ADDATTR^RORTSK11(RORTSK,ELEMENT,"LOW",TMP) S RORDATA("RANGE",GRC)=1
 .. S TMP=$G(@NODE@(GRC,"H"))
 .. I TMP'="" D  S RANGE=1
 ... D ADDATTR^RORTSK11(RORTSK,ELEMENT,"HIGH",TMP) S RORDATA("RANGE",GRC)=1
 .. I RANGE D ADDATTR^RORTSK11(RORTSK,ELEMENT,"RANGE",1)
 ;if user didn't select any tests, default to both tests
 ;I $G(RORDATA("IDLST"))="" S RORDATA("IDLST")="1,2" ;user must select a report in PATCH 12
 ;--- Success
 Q RC
 ;
 ;*****************************************************************************
 ;RETURN RANGE TEXT, ADD RANGE VALUES TO RORDATA (EXTRINISIC FUNCTION)
 ;
 ;INPUT:
 ;  GRC   Test ID number
 ;        ID=1: MELD
 ;        ID=2: MELD-Na
 ;        ID=3: APRI
 ;        ID=4: FIB4
 ;  RORDATA - Array with ROR data
 ;  RORTSK  - Task parameters
 ;
 ;OUTPUT:
 ;  RORDATA(ID,"L") - test ID low range
 ;  RORDATA(ID,"H") - test ID high range
 ;  Description - <range>
 ;*****************************************************************************
RTEXT(GRC,RORDATA,RORTSK) ;
 N RANGE,TMP
 S RANGE=""
 ;--- Range
 I $D(RORTSK("PARAMS","LRGRANGES","C",GRC))>1 D
 . ;--- Low
 . S TMP=$G(RORTSK("PARAMS","LRGRANGES","C",GRC,"L"))
 . S RORDATA(GRC,"L")=$G(TMP)
 . S:TMP'="" RANGE=RANGE_" not less than "_TMP
 . ;--- High
 . S TMP=$G(RORTSK("PARAMS","LRGRANGES","C",GRC,"H"))
 . S RORDATA(GRC,"H")=$G(TMP)
 . I TMP'=""  D:RANGE'=""  S RANGE=RANGE_" not greater than "_TMP
 . . S RANGE=RANGE_" and"
 ;--- Description
 S TMP=$G(RORTSK("PARAMS","LRGRANGES","C",GRC))
 S:TMP="" TMP="Unknown ("_GRC_")"
 Q TMP_" - "_$S(RANGE'="":"numeric results"_RANGE,1:"all results")
 ;
 ;************************************************************************
 ;CALCULATE THE MELD SCORE(S) - MELD AND MELD-NA
 ;
 ;INPUT
 ;  DFN      Patient DFN in LAB DATA file (#63)
 ;  PTAG     Reference IEN to the 'body' parent XML tag
 ;  RORDATA  Array with ROR data
 ;           RORDATA("FIELDS") - Field list for retrieving the test results
 ;  RORPTIEN Patient IEN in the ROR registry
 ;  RORLC    sub-file and LOINC codes to search for
 ;           
 ;OUTPUT
 ;  RORDATA  Array with ROR data
 ;           RORDATA("BILI")=RESULT^DATE   - Bilirubin result and date
 ;           RORDATA("CR")=RESULT^DATE     - Creatinine result and date
 ;           RORDATA("INR")=RESULT^DATE    - INR result and date
 ;           RORDATA("NA")=RESULT^DATE     - Sodium result and date
 ;           RORDATA("SCORE",1)            - MELD score
 ;           RORDATA("SCORE",2)            - MELD-Na score
 ;
 ;    1      Patient should appear on report
 ;   -1      Patient should NOT appear on report
 ;   
 ;   NOTE: the 'invalid' results will be stored as 'backup' results, in
 ;   case no valid result is found for Creatinine or Sodium.  An invalid
 ;   creatinine result is >12.  An invalid Sodium result is <100 or >180.
 ;   These results will be displayed on the report if no MELD range was 
 ;   specifically requested by the user, but the score will not be calculated.
 ;   They will not be displayed on the report if the user requested a MELD
 ;   range.
 ;************************************************************************
CALCMLD(DFN,PTAG,RORDATA,RORPTIEN,RORLC) ;
 N RORID,RORST,ROREND,RORLAB,RORMSG,RC
 S RORDATA("CALC")=0,RORDATA("CALCNA")=0 ;don't automatically calculate scores
 K RORDATA("SCORE",1),RORDATA("SCORE",2) ;calculated test scores
 K RORDATA("BVAL"),RORDATA("CVAL"),RORDATA("IVAL"),RORDATA("SVAL") ;test results
 K RORDATA("CINV"),RORDATA("SINV") ;test results
 K RORDATA("BILI"),RORDATA("CR"),RORDATA("INR"),RORDATA("NA") ;test result&date
 ;get patient ICN or SSN
 S RORID=$$PTID^RORUTL02(DFN)
 Q:'$G(RORID) -1
 ;---SET UP LAB API INPUT/OUTPUT PARMS---
 S RORST="2000101^CD" ;start date 1/1/1900
 S ROREND=$G(RORDATA("DATE"))\1 ;end date
 ;add 1 to the end date so the Lab API INCLUDES the end date correctly
 N X1,X2,X3 S X1=ROREND,X2=1 D C^%DTC S ROREND=X K X,X1,X2
 S ROREND=ROREND_"^CD"
 S RORLAB=$NA(^TMP("ROROUT",$J)) ;lab API output global
 K RORMSG,@RORLAB ;initialize prior to call
 ;---CALL LAB API---
 S RC=$$GCPR^LA7QRY(RORID,RORST,ROREND,.RORLC,"*",.RORMSG,RORLAB)
 I RC="",$D(RORMSG)>1  D  ;quit if error returned
 . N ERR,I,LST,TMP
 . S (ERR,LST)=""
 . F I=1:1  S ERR=$O(RORMSG(ERR))  Q:ERR=""  D
 . . S LST=LST_","_ERR,TMP=RORMSG(ERR)
 . . K RORMSG(ERR)  S RORMSG(I)=TMP
 . S LST=$P(LST,",",2,999)  Q:(LST=3)!(LST=99)
 . S RC=$$ERROR^RORERR(-27,,.RORMSG,RORPTIEN)
 I RC<0 Q -1
 ;Note: the Lab API returns data in the form of HL7 segments
 N TMP,RORSPEC,RORVAL,RORNODE,RORSEG,SEGTYPE,RORLOINC,RORDONE,RORDATE,RORTEST
 N RORCR,RORBIL,RORSOD,RORINR,FS
 S FS="|" ;HL7 field separator for lab data
 S (RORCR,RORBIL,RORSOD,RORINR,RORDONE,RORNODE)=0
 F  S RORNODE=$O(^TMP("ROROUT",$J,RORNODE)) Q:((RORNODE="")!(RORDONE))  D
 . S RORSEG=$G(^TMP("ROROUT",$J,RORNODE)) ;get entire HL7 segment
 . S SEGTYPE=$P(RORSEG,FS,1) ;get segment type (PID,OBR,OBX,etc.)
 . Q:SEGTYPE'="OBX"  ;we want OBX segments only
 . S RORSPEC=$P($P(RORSEG,FS,4),U,2) ;specimen type string (urine, serum, etc.)
 . S RORSPEC=":"_RORSPEC_":" ;append ":" as prefix and suffix
 . I ((RORSPEC[":UA:")!(RORSPEC[":UR:")) Q  ;quit if specimen type is urine
 . S RORLOINC=$P($P(RORSEG,FS,4),U,1) ;get LOINC code for test
 . S RORVAL=$P(RORSEG,FS,6) ;test result value
 . S RORVAL=$TR(RORVAL,"""","") ;get rid of double quotes around values
 . Q:($G(RORVAL)'>0)  ;quit if no value
 . S RORDATE=$$HL7TFM^XLFDT($P(RORSEG,FS,15)) ;get date collected
 . S RORDATE=RORDATE\1
 . ;---check for Creatinine match on LOINC---
 . I 'RORCR,RORDATA("CR_LOINC")[(";"_RORLOINC_";") D  Q
 .. ;store 'valid' value (12 or less) if no 'valid' value has been stored yet
 .. I RORVAL'>12,$O(RORDATA("CVAL",0))="" S RORDATA("CVAL",RORDATE)=RORVAL,RORCR=1 Q
 .. ;store 'invalid' value (>12) if no other value has been stored
 .. I RORVAL>12,$O(RORDATA("CVAL",0))="",$O(RORDATA("CINV",0))="" D
 ... S RORDATA("CINV",RORDATE)=$G(RORVAL)_"*" ;mark as 'invalid' value
 . ;---check for Sodium match on LOINC---
 . I 'RORSOD,RORDATA("SOD_LOINC")[(";"_RORLOINC_";") D  Q
 .. ;store 'valid' value (100 to 180) if no other 'valid' value has been stored
 .. I RORVAL'<100,RORVAL'>180,$O(RORDATA("SVAL",0))="" D  Q
 ... S RORDATA("SVAL",RORDATE)=$G(RORVAL),RORSOD=1
 .. ;store 'invalid' value (<100 or >180) if no other value has been stored yet
 .. I ((RORVAL<100)!(RORVAL>180)),$O(RORDATA("SVAL",0))="",$O(RORDATA("SINV",0))="" D  Q
 ... S RORDATA("SINV",RORDATE)=RORVAL_"*" Q   ;mark as 'invalid' value
 . ;---check for Bilirubin match on LOINC---
 . I 'RORBIL,RORDATA("BIL_LOINC")[(";"_RORLOINC_";") D  Q
 .. ;store first Bilirubin value
 .. I $O(RORDATA("BVAL",0))="" S RORDATA("BVAL",RORDATE)=RORVAL,RORBIL=1
 . ;---check for INR match on LOINC---
 . I 'RORINR,RORDATA("INR_LOINC")[(";"_RORLOINC_";") D  Q
 .. ;store first INR value
 .. I $O(RORDATA("IVAL",0))="" S RORDATA("IVAL",RORDATE)=RORVAL,RORINR=1
 . ;set flags to indicate if MELD/MELD-NA scores are ready to be calculated for this patient
 . I RORCR,RORBIL,RORINR S RORDATA("CALC")=1 D
 .. I RORDATA("IDLST")=1 S RORDONE=1 Q
 .. I RORSOD S RORDATA("CALCNA")=1,RORDONE=1
 ;
 ;if patient doesn't have data for either score, don't put them on report
 I '$G(RORDATA("CALC")),'$G(RORDATA("CALCNA")) Q -1
 ;--- put test result and test date into RORDATA(<test_name>)=result^date
 N DATE
 S DATE=$O(RORDATA("BVAL",0)) ;Bilirubin
 S RORDATA("BILI")=$S($G(DATE)="":U,1:$G(RORDATA("BVAL",DATE))_U_$G(DATE))
 S DATE=$O(RORDATA("CVAL",0)) ;Creatinine
 I $G(DATE)="" D  ;if regular Creatinine value is null, take invalid value
 . S DATE=$O(RORDATA("CINV",0)) I $G(DATE)>0 S RORDATA("CVAL",DATE)=$G(RORDATA("CINV",DATE))
 S RORDATA("CR")=$S($G(DATE)="":U,1:$G(RORDATA("CVAL",DATE))_U_$G(DATE))
 S DATE=$O(RORDATA("IVAL",0)) ;INR
 S RORDATA("INR")=$S($G(DATE)="":U,1:$G(RORDATA("IVAL",DATE))_U_$G(DATE))
 S DATE=$O(RORDATA("SVAL",0)) ;Sodium
 I $G(DATE)="" D  ;if regular Sodium value is null, take invalid value
 . S DATE=$O(RORDATA("SINV",0)) I $G(DATE)>0 S RORDATA("SVAL",DATE)=$G(RORDATA("SINV",DATE))
 S RORDATA("NA")=$S($G(DATE)="":U,1:$G(RORDATA("SVAL",DATE))_U_$G(DATE))
 ;
 N TEST,BILI,CR,INR,NA
 ;set lower limits for Bili, Cr, and INR to 1 if there's a value in there
 F TEST="BILI","CR","INR" D
 . S @TEST=$P($G(RORDATA(TEST)),U,1) Q:$G(@TEST)["*"  I $G(@TEST),@TEST<1 S @TEST=1
 ;for valid creatinine, use max=4 for calculations
 I $G(CR)'["*" D
 . I $G(CR)>4 S CR=4
 S NA=$P($G(RORDATA("NA")),U,1)
 ;for valid sodium, use min=120, max=135 for calculations
 I $G(NA)'["*" D
 . I $G(NA)>135 S NA=135 Q
 . I $G(NA)'="" I NA<120 S NA=120
 ;
 N TMP1,TMP2
 ;RORDATA("SCORE",1) will hold the calculated MELD score
 ;RORDATA("SCORE",2) will hold the calculated MELD Na score
 S (RORDATA("SCORE",1),RORDATA("SCORE",2))="" ;init calculated scores to null
 D
 . Q:($G(CR)["*")  ;quit if no calculation should occur
 . I $G(BILI),$G(CR),$G(INR) D
 .. ;MELD forumula: (.957*lne(Cr) + .378*lne(Bili) + 1.120*lne(Inr) + .643) * 10
 .. S TMP1=(.957*($$LN^XLFMTH(CR))+(.378*($$LN^XLFMTH(BILI)))+(1.120*($$LN^XLFMTH(INR)))+.643)*10
 .. S RORDATA("SCORE",1)=$J($G(TMP1),0,0) ;round MELD to whole number
 .. Q:($G(NA)["*")  ;quit if no calculation should occur
 .. ;if meld NA requested, sodium test must have a valid value
 .. I $G(NA),RORDATA("SCORE",1),RORDATA("IDLST")[2 D
 ... ;MELD-Na forumula: MELD + (1.59 *(135-Na))
 ... S TMP2=$G(RORDATA("SCORE",1))+(1.59*(135-NA))
 ... S RORDATA("SCORE",2)=$J($G(TMP2),0,0)
 Q 1
 ;************************************************************************
 ;CALCULATE THE FIBROSIS SCORE(S) - APRI and FIB4
 ;
 ;INPUT
 ;  DFN      Patient DFN in LAB DATA file (#63)
 ;  PTAG     Reference IEN to the 'body' parent XML tag
 ;  RORDATA  Array with ROR data
 ;           RORDATA("FIELDS") - Field list for retrieving the test results
 ;  RORPTIEN Patient IEN in the ROR registry
 ;  RORLC    sub-file and LOINC codes to search for
 ;           
 ;OUTPUT
 ;  RORDATA  Array with ROR data
 ;           RORDATA("AST")=RESULT^DATE   - AST result and date
 ;           RORDATA("PLAT")=RESULT^DATE  - Platelet result and date
 ;           RORDATA("ALT")=RESULT^DATE   - ALT result and date
 ;           RORDATA("SCORE",3)           - calculated APRI score
 ;           RORDATA("SCORE",4)           - calculated FIB4 score
 ;    1      Patient should appear on report
 ;   -1      Patient should NOT appear on report
 ;   
 ;************************************************************************
CALCFIB(DFN,PTAG,RORDATA,RORPTIEN,RORLC) ;
 N RORID,RORST,ROREND,RORLAB,RORMSG,RC
 S RORDATA("CALCAPRI")=0,RORDATA("CALCFIB4")=0 ;don't automatically calculate scores
 K RORDATA("SCORE",3),RORDATA("SCORE",4) ;calculated test scores
 K RORDATA("SVAL"),RORDATA("PVAL"),RORDATA("LVAL") ;test results
 K RORDATA("ALT"),RORDATA("PLAT"),RORDATA("AST") ; tes result and date
 ;get patient ICN or SSN
 S RORID=$$PTID^RORUTL02(DFN)
 Q:'$G(RORID) -1
 ;---SET UP LAB API INPUT/OUTPUT PARMS---
 S RORST="2000101^CD" ;start date 1/1/1900
 S ROREND=$G(RORDATA("DATE"))\1 ;end date
 ;add 1 to the end date so the Lab API INCLUDES the end date correctly
 N X1,X2,X3 S X1=ROREND,X2=1 D C^%DTC S ROREND=X K X,X1,X2
 S ROREND=ROREND_"^CD"
 S RORLAB=$NA(^TMP("ROROUT",$J)) ;lab API output global
 K RORMSG,@RORLAB ;initialize prior to call
 ;---CALL LAB API TO GET TEST RESULTS---
 S RC=$$GCPR^LA7QRY(RORID,RORST,ROREND,.RORLC,"*",.RORMSG,RORLAB)
 I RC="",$D(RORMSG)>1  D  Q -1 ;quit if error returned
 . N ERR,I,LST,TMP
 . S (ERR,LST)=""
 . F I=1:1  S ERR=$O(RORMSG(ERR))  Q:ERR=""  D
 . . S LST=LST_","_ERR,TMP=RORMSG(ERR)
 . . K RORMSG(ERR)  S RORMSG(I)=TMP
 . S LST=$P(LST,",",2,999)  Q:(LST=3)!(LST=99)
 . S RC=$$ERROR^RORERR(-27,,.RORMSG,RORPTIEN)
 I RC<0 Q -1
 ;Note: the Lab API returns data in the form of HL7 segments
 N TMP,RORSPEC,RORVAL,RORNODE,RORSEG,SEGTYPE,RORLOINC,RORDONE,RORDATE,RORTEST
 N RORAST,RORPLAT,RORALT,FS
 S FS="|" ;HL7 field separator for lab data
 S (RORAST,RORPLAT,RORALT,RORDONE,RORNODE)=0
 F  S RORNODE=$O(^TMP("ROROUT",$J,RORNODE)) Q:((RORNODE="")!(RORDONE))  D
 . S RORSEG=$G(^TMP("ROROUT",$J,RORNODE)) ;entire HL7 segment
 . S SEGTYPE=$P(RORSEG,FS,1) ;segment type (PID,OBR,OBX,etc.)
 . Q:SEGTYPE'="OBX"  ;test results are in the OBX segment
 . S RORSPEC=$P($P(RORSEG,FS,4),U,2) ;specimen type (urine, serum, etc.)
 . S RORSPEC=":"_RORSPEC_":" ;append ":" as prefix and suffix
 . I ((RORSPEC[":UA:")!(RORSPEC[":UR:")) Q  ;quit if specimen type is urine
 . S RORLOINC=$P($P(RORSEG,FS,4),U,1) ;LOINC code for test
 . S RORVAL=$P(RORSEG,FS,6) ;test result value
 . S RORVAL=$TR(RORVAL,"""","") ;get rid of double quotes around values
 . Q:($G(RORVAL)'>0)  ;quit if no value
 . S RORDATE=$$HL7TFM^XLFDT($P(RORSEG,FS,15)) ;get date collected
 . S RORDATE=RORDATE\1
 . ;test results will be stored in RORDATA("SVAL"),RORDATA("PVAL"), and RORDATA("LVAL")
 . ;---check for AST match on LOINC if not yet found and store it---
 . I 'RORAST,RORDATA("AST_LOINC")[(";"_RORLOINC_";") D  Q
 .. S RORDATA("SVAL",RORDATE)=RORVAL,RORAST=1 Q
 . ;---check for Platelet match on LOINC if not yet found and store it---
 . I 'RORPLAT,RORDATA("PLAT_LOINC")[(";"_RORLOINC_";") D  Q
 .. S RORDATA("PVAL",RORDATE)=$G(RORVAL),RORPLAT=1
 . ;---check for ALT match on LOINC if not yet found and store it---
 . I 'RORALT,RORDATA("ALT_LOINC")[(";"_RORLOINC_";") D  Q
 .. S RORDATA("LVAL",RORDATE)=RORVAL,RORALT=1
 . ;set flags to indicate if APRI/FIB4 scores are ready to be calculated for this patient
 . I RORAST,RORPLAT S RORDATA("CALCAPRI")=1 D
 .. I RORDATA("IDLST")=3 S RORDONE=1 ;done if APRI is the only score requested
 .. I RORALT S RORDATA("CALCFIB4")=1,RORDONE=1
 ;
 ;if patient doesn't have data for either score, then they shouldn't show up on report
 I '$G(RORDATA("CALCAPRI")),'$G(RORDATA("CALCFIB4")) Q -1
 ;--- put test result and test date into RORDATA(<test_name>)=result^date
 N DATE
 S DATE=$O(RORDATA("SVAL",0)) ;AST
 S RORDATA("AST")=$S($G(DATE)="":U,1:$G(RORDATA("SVAL",DATE))_U_$G(DATE))
 S DATE=$O(RORDATA("PVAL",0)) ;Platelet
 S RORDATA("PLAT")=$S($G(DATE)="":U,1:$G(RORDATA("PVAL",DATE))_U_$G(DATE))
 S DATE=$O(RORDATA("LVAL",0)) ;ALT
 S RORDATA("ALT")=$S($G(DATE)="":U,1:$G(RORDATA("LVAL",DATE))_U_$G(DATE))
 ;--- get just the test result values from array
 N TEST,AST,PLAT,ALT
 F TEST="AST","PLAT","ALT" S @TEST=$P($G(RORDATA(TEST)),U,1)
 ;--- calculate APRI/FIB4 scores
 N TMP1,TMP2
 ;RORDATA("SCORE",3) will hold the calculated APRI score
 ;RORDATA("SCORE",4) will hold the calculated FIB4 score
 S (RORDATA("SCORE",3),RORDATA("SCORE",4))="" ;init calculated scores to null
 S RC=1
 I $G(AST),$G(PLAT) D
 . I RORDATA("IDLST")[3 D  ;calculate APRI score: [AST/ULNAST/PLAT] * 100
 .. S TMP1=(AST/RORDATA("ULNAST")/PLAT)*100
 .. S RORDATA("SCORE",3)=$J($G(TMP1),0,2) ;round to 2 decimal points
 . I $G(ALT),RORDATA("IDLST")[4 D  ;calculate FIB4 score: (AGE*AST)/[(PLAT*ALT) to 1/2 power]
 .. N AGE S AGE=$$AGE(DFN,RORDATA("DATE")) ;get patient age
 .. I '$G(AGE) S RC=-1 Q  ;quit if age can't be calculated
 .. ;
 .. ; ROR*1.5*16 remedy ticket 512757 changed next two lines
 .. ;S TMP2=(AGE*AST)/$$PWR^XLFMTH((PLAT*ALT),.5)
 .. ;S RORDATA("SCORE",4)=$J($G(TMP2),0,0) ;round to whole number
 .. S TMP2=(AGE*AST)/(PLAT*($$PWR^XLFMTH((ALT),.5)))
 .. S RORDATA("SCORE",4)=$J($G(TMP2),0,2) ;round to 2 decimal places
 .. ;
 Q RC
 ;
 ;************************************************************************
 ;CALCULATE PATIENT AGE - EXTRINSIC FUNCTION
 ;
 ;INPUT
 ;  DFN      Patient DFN in PATIENT file (#2)
 ;  DATE     user-selected date for report calculations
 ;
 ;OUTPUT
 ;  Patient age is returned
 ;************************************************************************
AGE(DFN,DATE) ;
 ;--- get patient dob and dod using DEM^VADPT
 N RORDEM,RORDOB,RORDOD,RORAGE,VAROOT
 S VAROOT="RORDEM" D DEM^VADPT
 S RORDOB=$P($G(RORDEM(3)),U,1) ;date of birth
 S RORAGE=$P($G(RORDEM(4)),U,1) ;age as of today (DT)
 S RORDOD=$P($G(RORDEM(6)),U,1) ;date of death
 I DATE=DT Q $G(RORAGE)  ;if 'most recent' date, return age in API results
 ;compare DOD and user-selected 'as of' DATE
 I $G(RORDOD),$G(RORDOD)<DATE S DATE=RORDOD\1 ;use DOD if earlier than DATE
 S RORAGE=DATE-RORDOB ;calculate age
 S RORAGE=$S($L(RORAGE)=6:$E($G(RORAGE),1,2),1:$E($G(RORAGE),1,3))
 Q $G(RORAGE)
 
--- Routine Detail   --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HRORX019A   19318     printed  Sep 23, 2025@19:20:51                                                                                                                                                                                                   Page 2
RORX019A  ;BPOIFO/ACS - LIVER SCORE BY RANGE (CONT.) ; 8/23/11 8:38am
 +1       ;;1.5;CLINICAL CASE REGISTRIES;**10,13,14,16**;Feb 17, 2006;Build 3
 +2       ;
 +3       ;08/23/2011 BP/KAM ROR*1.5*16 Remedy Call 512757 Correct the Liver
 +4       ;                             Score Calculation
 +5       ;
 +6       ; This routine uses the following IAs:
 +7       ;
 +8       ; #10105 $$LN^XLFMTH (supported)
 +9       ; #3556  GCPR^LA7QRY (supported)
 +10      ; #10061 DEM^VADPT   (supported)
 +11      ;
 +12      ;******************************************************************************
 +13      ;******************************************************************************
 +14      ;                 --- ROUTINE MODIFICATION LOG ---
 +15      ;        
 +16      ;PKG/PATCH    DATE        DEVELOPER    MODIFICATION
 +17      ;-----------  ----------  -----------  ----------------------------------------
 +18      ;ROR*1.5*10   MAR  2010   A SAUNDERS   Routine created
 +19      ;ROR*1.5*13   DEC  2010   A SAUNDERS   Moved tag CALCMLD to this routine
 +20      ;ROR*1.5*14   APR  2011   A SAUNDERS   Added logic to calculate the APRI and
 +21      ;                                      FIB4 scores.
 +22      ;                                      
 +23      ;******************************************************************************
 +24      ;******************************************************************************
 +25       QUIT 
 +26      ;
 +27      ;*****************************************************************************
 +28      ;OUTPUT REPORT 'RANGE' PARAMETERS, SET UP REPORT ID LIST (EXTRINISIC FUNCTION)
 +29      ;
 +30      ; PARTAG        Reference (IEN) to the parent tag
 +31      ;
 +32      ; Return Values:
 +33      ;        RORDATA("IDLST") - list of IDs for tests requested
 +34      ;       <0  Error code
 +35      ;        0  Ok
 +36      ;*****************************************************************************
PARAMS(PARTAG,RORDATA,RORTSK) ;
 +1        NEW PARAMS,DESC,TMP,RC
           SET RC=0
 +2       ;--- Lab test ranges
 +3       ;initialize MELD to 'no range passed in'
           SET RORDATA("RANGE",1)=0
 +4       ;initialize MELD Na to 'no range passed in'
           SET RORDATA("RANGE",2)=0
 +5       ;initialize APRI to 'no range passed in'
           SET RORDATA("RANGE",3)=0
 +6       ;initialize FIB4 to 'no range passed in'
           SET RORDATA("RANGE",4)=0
 +7        IF $DATA(RORTSK("PARAMS","LRGRANGES","C"))>1
               Begin DoDot:1
 +8                NEW GRC,ELEMENT,NODE,RTAG,RANGE
 +9                SET NODE=$NAME(RORTSK("PARAMS","LRGRANGES","C"))
 +10               SET RTAG=$$ADDVAL^RORTSK11(RORTSK,"LRGRANGES",,PARTAG)
 +11               SET (GRC,RC)=0
 +12               FOR 
                       SET GRC=$ORDER(@NODE@(GRC))
                       if GRC'>0
                           QUIT 
                       Begin DoDot:2
 +13      ;get range description
                           SET RANGE=0
                           SET DESC=$$RTEXT(GRC,.RORDATA,.RORTSK)
 +14      ;add desc to output
                           SET ELEMENT=$$ADDVAL^RORTSK11(RORTSK,"LRGRANGE",DESC,RTAG)
 +15                       IF ELEMENT<0
                               SET RC=ELEMENT
                               QUIT 
 +16                       DO ADDATTR^RORTSK11(RORTSK,ELEMENT,"ID",GRC)
 +17      ;add test ID to the test ID 'list'
 +18                       SET RORDATA("IDLST")=$GET(RORDATA("IDLST"))_$SELECT($GET(RORDATA("IDLST"))'="":","_GRC,1:GRC)
 +19      ;--- Process the range values
 +20                       SET TMP=$GET(@NODE@(GRC,"L"))
 +21                       IF TMP'=""
                               Begin DoDot:3
 +22                               DO ADDATTR^RORTSK11(RORTSK,ELEMENT,"LOW",TMP)
                                   SET RORDATA("RANGE",GRC)=1
                               End DoDot:3
                               SET RANGE=1
 +23                       SET TMP=$GET(@NODE@(GRC,"H"))
 +24                       IF TMP'=""
                               Begin DoDot:3
 +25                               DO ADDATTR^RORTSK11(RORTSK,ELEMENT,"HIGH",TMP)
                                   SET RORDATA("RANGE",GRC)=1
                               End DoDot:3
                               SET RANGE=1
 +26                       IF RANGE
                               DO ADDATTR^RORTSK11(RORTSK,ELEMENT,"RANGE",1)
                       End DoDot:2
                       if RC<0
                           QUIT 
               End DoDot:1
               if RC<0
                   QUIT RC
 +27      ;if user didn't select any tests, default to both tests
 +28      ;I $G(RORDATA("IDLST"))="" S RORDATA("IDLST")="1,2" ;user must select a report in PATCH 12
 +29      ;--- Success
 +30       QUIT RC
 +31      ;
 +32      ;*****************************************************************************
 +33      ;RETURN RANGE TEXT, ADD RANGE VALUES TO RORDATA (EXTRINISIC FUNCTION)
 +34      ;
 +35      ;INPUT:
 +36      ;  GRC   Test ID number
 +37      ;        ID=1: MELD
 +38      ;        ID=2: MELD-Na
 +39      ;        ID=3: APRI
 +40      ;        ID=4: FIB4
 +41      ;  RORDATA - Array with ROR data
 +42      ;  RORTSK  - Task parameters
 +43      ;
 +44      ;OUTPUT:
 +45      ;  RORDATA(ID,"L") - test ID low range
 +46      ;  RORDATA(ID,"H") - test ID high range
 +47      ;  Description - <range>
 +48      ;*****************************************************************************
RTEXT(GRC,RORDATA,RORTSK) ;
 +1        NEW RANGE,TMP
 +2        SET RANGE=""
 +3       ;--- Range
 +4        IF $DATA(RORTSK("PARAMS","LRGRANGES","C",GRC))>1
               Begin DoDot:1
 +5       ;--- Low
 +6                SET TMP=$GET(RORTSK("PARAMS","LRGRANGES","C",GRC,"L"))
 +7                SET RORDATA(GRC,"L")=$GET(TMP)
 +8                if TMP'=""
                       SET RANGE=RANGE_" not less than "_TMP
 +9       ;--- High
 +10               SET TMP=$GET(RORTSK("PARAMS","LRGRANGES","C",GRC,"H"))
 +11               SET RORDATA(GRC,"H")=$GET(TMP)
 +12               IF TMP'=""
                       if RANGE'=""
                           Begin DoDot:2
 +13                           SET RANGE=RANGE_" and"
                           End DoDot:2
                       SET RANGE=RANGE_" not greater than "_TMP
               End DoDot:1
 +14      ;--- Description
 +15       SET TMP=$GET(RORTSK("PARAMS","LRGRANGES","C",GRC))
 +16       if TMP=""
               SET TMP="Unknown ("_GRC_")"
 +17       QUIT TMP_" - "_$SELECT(RANGE'="":"numeric results"_RANGE,1:"all results")
 +18      ;
 +19      ;************************************************************************
 +20      ;CALCULATE THE MELD SCORE(S) - MELD AND MELD-NA
 +21      ;
 +22      ;INPUT
 +23      ;  DFN      Patient DFN in LAB DATA file (#63)
 +24      ;  PTAG     Reference IEN to the 'body' parent XML tag
 +25      ;  RORDATA  Array with ROR data
 +26      ;           RORDATA("FIELDS") - Field list for retrieving the test results
 +27      ;  RORPTIEN Patient IEN in the ROR registry
 +28      ;  RORLC    sub-file and LOINC codes to search for
 +29      ;           
 +30      ;OUTPUT
 +31      ;  RORDATA  Array with ROR data
 +32      ;           RORDATA("BILI")=RESULT^DATE   - Bilirubin result and date
 +33      ;           RORDATA("CR")=RESULT^DATE     - Creatinine result and date
 +34      ;           RORDATA("INR")=RESULT^DATE    - INR result and date
 +35      ;           RORDATA("NA")=RESULT^DATE     - Sodium result and date
 +36      ;           RORDATA("SCORE",1)            - MELD score
 +37      ;           RORDATA("SCORE",2)            - MELD-Na score
 +38      ;
 +39      ;    1      Patient should appear on report
 +40      ;   -1      Patient should NOT appear on report
 +41      ;   
 +42      ;   NOTE: the 'invalid' results will be stored as 'backup' results, in
 +43      ;   case no valid result is found for Creatinine or Sodium.  An invalid
 +44      ;   creatinine result is >12.  An invalid Sodium result is <100 or >180.
 +45      ;   These results will be displayed on the report if no MELD range was 
 +46      ;   specifically requested by the user, but the score will not be calculated.
 +47      ;   They will not be displayed on the report if the user requested a MELD
 +48      ;   range.
 +49      ;************************************************************************
CALCMLD(DFN,PTAG,RORDATA,RORPTIEN,RORLC) ;
 +1        NEW RORID,RORST,ROREND,RORLAB,RORMSG,RC
 +2       ;don't automatically calculate scores
           SET RORDATA("CALC")=0
           SET RORDATA("CALCNA")=0
 +3       ;calculated test scores
           KILL RORDATA("SCORE",1),RORDATA("SCORE",2)
 +4       ;test results
           KILL RORDATA("BVAL"),RORDATA("CVAL"),RORDATA("IVAL"),RORDATA("SVAL")
 +5       ;test results
           KILL RORDATA("CINV"),RORDATA("SINV")
 +6       ;test result&date
           KILL RORDATA("BILI"),RORDATA("CR"),RORDATA("INR"),RORDATA("NA")
 +7       ;get patient ICN or SSN
 +8        SET RORID=$$PTID^RORUTL02(DFN)
 +9        if '$GET(RORID)
               QUIT -1
 +10      ;---SET UP LAB API INPUT/OUTPUT PARMS---
 +11      ;start date 1/1/1900
           SET RORST="2000101^CD"
 +12      ;end date
           SET ROREND=$GET(RORDATA("DATE"))\1
 +13      ;add 1 to the end date so the Lab API INCLUDES the end date correctly
 +14       NEW X1,X2,X3
           SET X1=ROREND
           SET X2=1
           DO C^%DTC
           SET ROREND=X
           KILL X,X1,X2
 +15       SET ROREND=ROREND_"^CD"
 +16      ;lab API output global
           SET RORLAB=$NAME(^TMP("ROROUT",$JOB))
 +17      ;initialize prior to call
           KILL RORMSG,@RORLAB
 +18      ;---CALL LAB API---
 +19       SET RC=$$GCPR^LA7QRY(RORID,RORST,ROREND,.RORLC,"*",.RORMSG,RORLAB)
 +20      ;quit if error returned
           IF RC=""
               IF $DATA(RORMSG)>1
                   Begin DoDot:1
 +21                   NEW ERR,I,LST,TMP
 +22                   SET (ERR,LST)=""
 +23                   FOR I=1:1
                           SET ERR=$ORDER(RORMSG(ERR))
                           if ERR=""
                               QUIT 
                           Begin DoDot:2
 +24                           SET LST=LST_","_ERR
                               SET TMP=RORMSG(ERR)
 +25                           KILL RORMSG(ERR)
                               SET RORMSG(I)=TMP
                           End DoDot:2
 +26                   SET LST=$PIECE(LST,",",2,999)
                       if (LST=3)!(LST=99)
                           QUIT 
 +27                   SET RC=$$ERROR^RORERR(-27,,.RORMSG,RORPTIEN)
                   End DoDot:1
 +28       IF RC<0
               QUIT -1
 +29      ;Note: the Lab API returns data in the form of HL7 segments
 +30       NEW TMP,RORSPEC,RORVAL,RORNODE,RORSEG,SEGTYPE,RORLOINC,RORDONE,RORDATE,RORTEST
 +31       NEW RORCR,RORBIL,RORSOD,RORINR,FS
 +32      ;HL7 field separator for lab data
           SET FS="|"
 +33       SET (RORCR,RORBIL,RORSOD,RORINR,RORDONE,RORNODE)=0
 +34       FOR 
               SET RORNODE=$ORDER(^TMP("ROROUT",$JOB,RORNODE))
               if ((RORNODE="")!(RORDONE))
                   QUIT 
               Begin DoDot:1
 +35      ;get entire HL7 segment
                   SET RORSEG=$GET(^TMP("ROROUT",$JOB,RORNODE))
 +36      ;get segment type (PID,OBR,OBX,etc.)
                   SET SEGTYPE=$PIECE(RORSEG,FS,1)
 +37      ;we want OBX segments only
                   if SEGTYPE'="OBX"
                       QUIT 
 +38      ;specimen type string (urine, serum, etc.)
                   SET RORSPEC=$PIECE($PIECE(RORSEG,FS,4),U,2)
 +39      ;append ":" as prefix and suffix
                   SET RORSPEC=":"_RORSPEC_":"
 +40      ;quit if specimen type is urine
                   IF ((RORSPEC[":UA:")!(RORSPEC[":UR:"))
                       QUIT 
 +41      ;get LOINC code for test
                   SET RORLOINC=$PIECE($PIECE(RORSEG,FS,4),U,1)
 +42      ;test result value
                   SET RORVAL=$PIECE(RORSEG,FS,6)
 +43      ;get rid of double quotes around values
                   SET RORVAL=$TRANSLATE(RORVAL,"""","")
 +44      ;quit if no value
                   if ($GET(RORVAL)'>0)
                       QUIT 
 +45      ;get date collected
                   SET RORDATE=$$HL7TFM^XLFDT($PIECE(RORSEG,FS,15))
 +46               SET RORDATE=RORDATE\1
 +47      ;---check for Creatinine match on LOINC---
 +48               IF 'RORCR
                       IF RORDATA("CR_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +49      ;store 'valid' value (12 or less) if no 'valid' value has been stored yet
 +50                           IF RORVAL'>12
                                   IF $ORDER(RORDATA("CVAL",0))=""
                                       SET RORDATA("CVAL",RORDATE)=RORVAL
                                       SET RORCR=1
                                       QUIT 
 +51      ;store 'invalid' value (>12) if no other value has been stored
 +52                           IF RORVAL>12
                                   IF $ORDER(RORDATA("CVAL",0))=""
                                       IF $ORDER(RORDATA("CINV",0))=""
                                           Begin DoDot:3
 +53      ;mark as 'invalid' value
                                               SET RORDATA("CINV",RORDATE)=$GET(RORVAL)_"*"
                                           End DoDot:3
                           End DoDot:2
                           QUIT 
 +54      ;---check for Sodium match on LOINC---
 +55               IF 'RORSOD
                       IF RORDATA("SOD_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +56      ;store 'valid' value (100 to 180) if no other 'valid' value has been stored
 +57                           IF RORVAL'<100
                                   IF RORVAL'>180
                                       IF $ORDER(RORDATA("SVAL",0))=""
                                           Begin DoDot:3
 +58                                           SET RORDATA("SVAL",RORDATE)=$GET(RORVAL)
                                               SET RORSOD=1
                                           End DoDot:3
                                           QUIT 
 +59      ;store 'invalid' value (<100 or >180) if no other value has been stored yet
 +60                           IF ((RORVAL<100)!(RORVAL>180))
                                   IF $ORDER(RORDATA("SVAL",0))=""
                                       IF $ORDER(RORDATA("SINV",0))=""
                                           Begin DoDot:3
 +61      ;mark as 'invalid' value
                                               SET RORDATA("SINV",RORDATE)=RORVAL_"*"
                                               QUIT 
                                           End DoDot:3
                                           QUIT 
                           End DoDot:2
                           QUIT 
 +62      ;---check for Bilirubin match on LOINC---
 +63               IF 'RORBIL
                       IF RORDATA("BIL_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +64      ;store first Bilirubin value
 +65                           IF $ORDER(RORDATA("BVAL",0))=""
                                   SET RORDATA("BVAL",RORDATE)=RORVAL
                                   SET RORBIL=1
                           End DoDot:2
                           QUIT 
 +66      ;---check for INR match on LOINC---
 +67               IF 'RORINR
                       IF RORDATA("INR_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +68      ;store first INR value
 +69                           IF $ORDER(RORDATA("IVAL",0))=""
                                   SET RORDATA("IVAL",RORDATE)=RORVAL
                                   SET RORINR=1
                           End DoDot:2
                           QUIT 
 +70      ;set flags to indicate if MELD/MELD-NA scores are ready to be calculated for this patient
 +71               IF RORCR
                       IF RORBIL
                           IF RORINR
                               SET RORDATA("CALC")=1
                               Begin DoDot:2
 +72                               IF RORDATA("IDLST")=1
                                       SET RORDONE=1
                                       QUIT 
 +73                               IF RORSOD
                                       SET RORDATA("CALCNA")=1
                                       SET RORDONE=1
                               End DoDot:2
               End DoDot:1
 +74      ;
 +75      ;if patient doesn't have data for either score, don't put them on report
 +76       IF '$GET(RORDATA("CALC"))
               IF '$GET(RORDATA("CALCNA"))
                   QUIT -1
 +77      ;--- put test result and test date into RORDATA(<test_name>)=result^date
 +78       NEW DATE
 +79      ;Bilirubin
           SET DATE=$ORDER(RORDATA("BVAL",0))
 +80       SET RORDATA("BILI")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("BVAL",DATE))_U_$GET(DATE))
 +81      ;Creatinine
           SET DATE=$ORDER(RORDATA("CVAL",0))
 +82      ;if regular Creatinine value is null, take invalid value
           IF $GET(DATE)=""
               Begin DoDot:1
 +83               SET DATE=$ORDER(RORDATA("CINV",0))
                   IF $GET(DATE)>0
                       SET RORDATA("CVAL",DATE)=$GET(RORDATA("CINV",DATE))
               End DoDot:1
 +84       SET RORDATA("CR")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("CVAL",DATE))_U_$GET(DATE))
 +85      ;INR
           SET DATE=$ORDER(RORDATA("IVAL",0))
 +86       SET RORDATA("INR")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("IVAL",DATE))_U_$GET(DATE))
 +87      ;Sodium
           SET DATE=$ORDER(RORDATA("SVAL",0))
 +88      ;if regular Sodium value is null, take invalid value
           IF $GET(DATE)=""
               Begin DoDot:1
 +89               SET DATE=$ORDER(RORDATA("SINV",0))
                   IF $GET(DATE)>0
                       SET RORDATA("SVAL",DATE)=$GET(RORDATA("SINV",DATE))
               End DoDot:1
 +90       SET RORDATA("NA")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("SVAL",DATE))_U_$GET(DATE))
 +91      ;
 +92       NEW TEST,BILI,CR,INR,NA
 +93      ;set lower limits for Bili, Cr, and INR to 1 if there's a value in there
 +94       FOR TEST="BILI","CR","INR"
               Begin DoDot:1
 +95               SET @TEST=$PIECE($GET(RORDATA(TEST)),U,1)
                   if $GET(@TEST)["*"
                       QUIT 
                   IF $GET(@TEST)
                       IF @TEST<1
                           SET @TEST=1
               End DoDot:1
 +96      ;for valid creatinine, use max=4 for calculations
 +97       IF $GET(CR)'["*"
               Begin DoDot:1
 +98               IF $GET(CR)>4
                       SET CR=4
               End DoDot:1
 +99       SET NA=$PIECE($GET(RORDATA("NA")),U,1)
 +100     ;for valid sodium, use min=120, max=135 for calculations
 +101      IF $GET(NA)'["*"
               Begin DoDot:1
 +102              IF $GET(NA)>135
                       SET NA=135
                       QUIT 
 +103              IF $GET(NA)'=""
                       IF NA<120
                           SET NA=120
               End DoDot:1
 +104     ;
 +105      NEW TMP1,TMP2
 +106     ;RORDATA("SCORE",1) will hold the calculated MELD score
 +107     ;RORDATA("SCORE",2) will hold the calculated MELD Na score
 +108     ;init calculated scores to null
           SET (RORDATA("SCORE",1),RORDATA("SCORE",2))=""
 +109      Begin DoDot:1
 +110     ;quit if no calculation should occur
               if ($GET(CR)["*")
                   QUIT 
 +111          IF $GET(BILI)
                   IF $GET(CR)
                       IF $GET(INR)
                           Begin DoDot:2
 +112     ;MELD forumula: (.957*lne(Cr) + .378*lne(Bili) + 1.120*lne(Inr) + .643) * 10
 +113                          SET TMP1=(.957*($$LN^XLFMTH(CR))+(.378*($$LN^XLFMTH(BILI)))+(1.120*($$LN^XLFMTH(INR)))+.643)*10
 +114     ;round MELD to whole number
                               SET RORDATA("SCORE",1)=$JUSTIFY($GET(TMP1),0,0)
 +115     ;quit if no calculation should occur
                               if ($GET(NA)["*")
                                   QUIT 
 +116     ;if meld NA requested, sodium test must have a valid value
 +117                          IF $GET(NA)
                                   IF RORDATA("SCORE",1)
                                       IF RORDATA("IDLST")[2
                                           Begin DoDot:3
 +118     ;MELD-Na forumula: MELD + (1.59 *(135-Na))
 +119                                          SET TMP2=$GET(RORDATA("SCORE",1))+(1.59*(135-NA))
 +120                                          SET RORDATA("SCORE",2)=$JUSTIFY($GET(TMP2),0,0)
                                           End DoDot:3
                           End DoDot:2
           End DoDot:1
 +121      QUIT 1
 +122     ;************************************************************************
 +123     ;CALCULATE THE FIBROSIS SCORE(S) - APRI and FIB4
 +124     ;
 +125     ;INPUT
 +126     ;  DFN      Patient DFN in LAB DATA file (#63)
 +127     ;  PTAG     Reference IEN to the 'body' parent XML tag
 +128     ;  RORDATA  Array with ROR data
 +129     ;           RORDATA("FIELDS") - Field list for retrieving the test results
 +130     ;  RORPTIEN Patient IEN in the ROR registry
 +131     ;  RORLC    sub-file and LOINC codes to search for
 +132     ;           
 +133     ;OUTPUT
 +134     ;  RORDATA  Array with ROR data
 +135     ;           RORDATA("AST")=RESULT^DATE   - AST result and date
 +136     ;           RORDATA("PLAT")=RESULT^DATE  - Platelet result and date
 +137     ;           RORDATA("ALT")=RESULT^DATE   - ALT result and date
 +138     ;           RORDATA("SCORE",3)           - calculated APRI score
 +139     ;           RORDATA("SCORE",4)           - calculated FIB4 score
 +140     ;    1      Patient should appear on report
 +141     ;   -1      Patient should NOT appear on report
 +142     ;   
 +143     ;************************************************************************
CALCFIB(DFN,PTAG,RORDATA,RORPTIEN,RORLC) ;
 +1        NEW RORID,RORST,ROREND,RORLAB,RORMSG,RC
 +2       ;don't automatically calculate scores
           SET RORDATA("CALCAPRI")=0
           SET RORDATA("CALCFIB4")=0
 +3       ;calculated test scores
           KILL RORDATA("SCORE",3),RORDATA("SCORE",4)
 +4       ;test results
           KILL RORDATA("SVAL"),RORDATA("PVAL"),RORDATA("LVAL")
 +5       ; tes result and date
           KILL RORDATA("ALT"),RORDATA("PLAT"),RORDATA("AST")
 +6       ;get patient ICN or SSN
 +7        SET RORID=$$PTID^RORUTL02(DFN)
 +8        if '$GET(RORID)
               QUIT -1
 +9       ;---SET UP LAB API INPUT/OUTPUT PARMS---
 +10      ;start date 1/1/1900
           SET RORST="2000101^CD"
 +11      ;end date
           SET ROREND=$GET(RORDATA("DATE"))\1
 +12      ;add 1 to the end date so the Lab API INCLUDES the end date correctly
 +13       NEW X1,X2,X3
           SET X1=ROREND
           SET X2=1
           DO C^%DTC
           SET ROREND=X
           KILL X,X1,X2
 +14       SET ROREND=ROREND_"^CD"
 +15      ;lab API output global
           SET RORLAB=$NAME(^TMP("ROROUT",$JOB))
 +16      ;initialize prior to call
           KILL RORMSG,@RORLAB
 +17      ;---CALL LAB API TO GET TEST RESULTS---
 +18       SET RC=$$GCPR^LA7QRY(RORID,RORST,ROREND,.RORLC,"*",.RORMSG,RORLAB)
 +19      ;quit if error returned
           IF RC=""
               IF $DATA(RORMSG)>1
                   Begin DoDot:1
 +20                   NEW ERR,I,LST,TMP
 +21                   SET (ERR,LST)=""
 +22                   FOR I=1:1
                           SET ERR=$ORDER(RORMSG(ERR))
                           if ERR=""
                               QUIT 
                           Begin DoDot:2
 +23                           SET LST=LST_","_ERR
                               SET TMP=RORMSG(ERR)
 +24                           KILL RORMSG(ERR)
                               SET RORMSG(I)=TMP
                           End DoDot:2
 +25                   SET LST=$PIECE(LST,",",2,999)
                       if (LST=3)!(LST=99)
                           QUIT 
 +26                   SET RC=$$ERROR^RORERR(-27,,.RORMSG,RORPTIEN)
                   End DoDot:1
                   QUIT -1
 +27       IF RC<0
               QUIT -1
 +28      ;Note: the Lab API returns data in the form of HL7 segments
 +29       NEW TMP,RORSPEC,RORVAL,RORNODE,RORSEG,SEGTYPE,RORLOINC,RORDONE,RORDATE,RORTEST
 +30       NEW RORAST,RORPLAT,RORALT,FS
 +31      ;HL7 field separator for lab data
           SET FS="|"
 +32       SET (RORAST,RORPLAT,RORALT,RORDONE,RORNODE)=0
 +33       FOR 
               SET RORNODE=$ORDER(^TMP("ROROUT",$JOB,RORNODE))
               if ((RORNODE="")!(RORDONE))
                   QUIT 
               Begin DoDot:1
 +34      ;entire HL7 segment
                   SET RORSEG=$GET(^TMP("ROROUT",$JOB,RORNODE))
 +35      ;segment type (PID,OBR,OBX,etc.)
                   SET SEGTYPE=$PIECE(RORSEG,FS,1)
 +36      ;test results are in the OBX segment
                   if SEGTYPE'="OBX"
                       QUIT 
 +37      ;specimen type (urine, serum, etc.)
                   SET RORSPEC=$PIECE($PIECE(RORSEG,FS,4),U,2)
 +38      ;append ":" as prefix and suffix
                   SET RORSPEC=":"_RORSPEC_":"
 +39      ;quit if specimen type is urine
                   IF ((RORSPEC[":UA:")!(RORSPEC[":UR:"))
                       QUIT 
 +40      ;LOINC code for test
                   SET RORLOINC=$PIECE($PIECE(RORSEG,FS,4),U,1)
 +41      ;test result value
                   SET RORVAL=$PIECE(RORSEG,FS,6)
 +42      ;get rid of double quotes around values
                   SET RORVAL=$TRANSLATE(RORVAL,"""","")
 +43      ;quit if no value
                   if ($GET(RORVAL)'>0)
                       QUIT 
 +44      ;get date collected
                   SET RORDATE=$$HL7TFM^XLFDT($PIECE(RORSEG,FS,15))
 +45               SET RORDATE=RORDATE\1
 +46      ;test results will be stored in RORDATA("SVAL"),RORDATA("PVAL"), and RORDATA("LVAL")
 +47      ;---check for AST match on LOINC if not yet found and store it---
 +48               IF 'RORAST
                       IF RORDATA("AST_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +49                           SET RORDATA("SVAL",RORDATE)=RORVAL
                               SET RORAST=1
                               QUIT 
                           End DoDot:2
                           QUIT 
 +50      ;---check for Platelet match on LOINC if not yet found and store it---
 +51               IF 'RORPLAT
                       IF RORDATA("PLAT_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +52                           SET RORDATA("PVAL",RORDATE)=$GET(RORVAL)
                               SET RORPLAT=1
                           End DoDot:2
                           QUIT 
 +53      ;---check for ALT match on LOINC if not yet found and store it---
 +54               IF 'RORALT
                       IF RORDATA("ALT_LOINC")[(";"_RORLOINC_";")
                           Begin DoDot:2
 +55                           SET RORDATA("LVAL",RORDATE)=RORVAL
                               SET RORALT=1
                           End DoDot:2
                           QUIT 
 +56      ;set flags to indicate if APRI/FIB4 scores are ready to be calculated for this patient
 +57               IF RORAST
                       IF RORPLAT
                           SET RORDATA("CALCAPRI")=1
                           Begin DoDot:2
 +58      ;done if APRI is the only score requested
                               IF RORDATA("IDLST")=3
                                   SET RORDONE=1
 +59                           IF RORALT
                                   SET RORDATA("CALCFIB4")=1
                                   SET RORDONE=1
                           End DoDot:2
               End DoDot:1
 +60      ;
 +61      ;if patient doesn't have data for either score, then they shouldn't show up on report
 +62       IF '$GET(RORDATA("CALCAPRI"))
               IF '$GET(RORDATA("CALCFIB4"))
                   QUIT -1
 +63      ;--- put test result and test date into RORDATA(<test_name>)=result^date
 +64       NEW DATE
 +65      ;AST
           SET DATE=$ORDER(RORDATA("SVAL",0))
 +66       SET RORDATA("AST")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("SVAL",DATE))_U_$GET(DATE))
 +67      ;Platelet
           SET DATE=$ORDER(RORDATA("PVAL",0))
 +68       SET RORDATA("PLAT")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("PVAL",DATE))_U_$GET(DATE))
 +69      ;ALT
           SET DATE=$ORDER(RORDATA("LVAL",0))
 +70       SET RORDATA("ALT")=$SELECT($GET(DATE)="":U,1:$GET(RORDATA("LVAL",DATE))_U_$GET(DATE))
 +71      ;--- get just the test result values from array
 +72       NEW TEST,AST,PLAT,ALT
 +73       FOR TEST="AST","PLAT","ALT"
               SET @TEST=$PIECE($GET(RORDATA(TEST)),U,1)
 +74      ;--- calculate APRI/FIB4 scores
 +75       NEW TMP1,TMP2
 +76      ;RORDATA("SCORE",3) will hold the calculated APRI score
 +77      ;RORDATA("SCORE",4) will hold the calculated FIB4 score
 +78      ;init calculated scores to null
           SET (RORDATA("SCORE",3),RORDATA("SCORE",4))=""
 +79       SET RC=1
 +80       IF $GET(AST)
               IF $GET(PLAT)
                   Begin DoDot:1
 +81      ;calculate APRI score: [AST/ULNAST/PLAT] * 100
                       IF RORDATA("IDLST")[3
                           Begin DoDot:2
 +82                           SET TMP1=(AST/RORDATA("ULNAST")/PLAT)*100
 +83      ;round to 2 decimal points
                               SET RORDATA("SCORE",3)=$JUSTIFY($GET(TMP1),0,2)
                           End DoDot:2
 +84      ;calculate FIB4 score: (AGE*AST)/[(PLAT*ALT) to 1/2 power]
                       IF $GET(ALT)
                           IF RORDATA("IDLST")[4
                               Begin DoDot:2
 +85      ;get patient age
                                   NEW AGE
                                   SET AGE=$$AGE(DFN,RORDATA("DATE"))
 +86      ;quit if age can't be calculated
                                   IF '$GET(AGE)
                                       SET RC=-1
                                       QUIT 
 +87      ;
 +88      ; ROR*1.5*16 remedy ticket 512757 changed next two lines
 +89      ;S TMP2=(AGE*AST)/$$PWR^XLFMTH((PLAT*ALT),.5)
 +90      ;S RORDATA("SCORE",4)=$J($G(TMP2),0,0) ;round to whole number
 +91                               SET TMP2=(AGE*AST)/(PLAT*($$PWR^XLFMTH((ALT),.5)))
 +92      ;round to 2 decimal places
                                   SET RORDATA("SCORE",4)=$JUSTIFY($GET(TMP2),0,2)
 +93      ;
                               End DoDot:2
                   End DoDot:1
 +94       QUIT RC
 +95      ;
 +96      ;************************************************************************
 +97      ;CALCULATE PATIENT AGE - EXTRINSIC FUNCTION
 +98      ;
 +99      ;INPUT
 +100     ;  DFN      Patient DFN in PATIENT file (#2)
 +101     ;  DATE     user-selected date for report calculations
 +102     ;
 +103     ;OUTPUT
 +104     ;  Patient age is returned
 +105     ;************************************************************************
AGE(DFN,DATE) ;
 +1       ;--- get patient dob and dod using DEM^VADPT
 +2        NEW RORDEM,RORDOB,RORDOD,RORAGE,VAROOT
 +3        SET VAROOT="RORDEM"
           DO DEM^VADPT
 +4       ;date of birth
           SET RORDOB=$PIECE($GET(RORDEM(3)),U,1)
 +5       ;age as of today (DT)
           SET RORAGE=$PIECE($GET(RORDEM(4)),U,1)
 +6       ;date of death
           SET RORDOD=$PIECE($GET(RORDEM(6)),U,1)
 +7       ;if 'most recent' date, return age in API results
           IF DATE=DT
               QUIT $GET(RORAGE)
 +8       ;compare DOD and user-selected 'as of' DATE
 +9       ;use DOD if earlier than DATE
           IF $GET(RORDOD)
               IF $GET(RORDOD)<DATE
                   SET DATE=RORDOD\1
 +10      ;calculate age
           SET RORAGE=DATE-RORDOB
 +11       SET RORAGE=$SELECT($LENGTH(RORAGE)=6:$EXTRACT($GET(RORAGE),1,2),1:$EXTRACT($GET(RORAGE),1,3))
 +12       QUIT $GET(RORAGE)