- Timestamp:
- Dec 4, 2009, 12:11:15 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
WorldVistAEHR/trunk/r/PHARMACY_BENEFITS_MANAGEMENT-PSU/PSULRHL1.m
r613 r623 1 PSULRHL1 ;HCIOFO/BH/RDC - Process real time HL7 Lab messages ; 8/1/07 11:26am 2 ;;4.0;PHARMACY BENEFITS MANAGEMENT;**3,11**;MARCH, 2005;Build 8 3 ; 4 ; DBIA 3565 to subscribe to the LR7O ALL EVSEND RESULTS protocol 5 ; DBIA 998 to dig through ^DPT(i,"LR" go get the ien to file #63 6 ; DBIA 91-A to dig through ^LAB(60 to get the name of the test 7 ; DBIA 3630 to call the HL7 PID builder 8 ; DBIA 4727 to call EN^HLOCNRT 9 ; DBIA 3646 to call API: $$EMPL^DGSEC4 10 ; DBIA 4658 to call API: $$TSTRES^LRRPU 11 ; 12 ; This program is called when a lab test is verified. If it is for a 13 ; chemistry test, and not for an employee, an HL7 message will be 14 ; created and sent to the CMOP-NAT server. 15 ; 16 ; 17 HL7 ; Entry point for PBM processing - triggered by lab protocol 18 ; LR7O ALL EVSEND RESULTS. 19 ; 20 N ARR,FIRST,LRDFN,PSUEXT,PSUHLFS,PSUHLECH,PSUHLCS 21 ; 22 ; OREMSG is the pointer reference to the global that contains the 23 ; lab data and is passed in by the LR7O ALL EVSEND RESULTS protocol. 24 ; 25 I '$D(@OREMSG) Q 26 ; 27 ; Get Lab parameters 28 ; 29 D INIT^HLFNC2("PSU-SITE-DRIVER",.PSUHL) 30 ; 31 ; Set up CS delimeter for the Pharmacy message 32 ; 33 S PSUHL("CS")=$E(PSUHL("ECH"),1) 34 ; 35 ; Set up segment processing parameters 36 ; 37 S PSUEXT("PSUBUF")=$NA(^TMP("HLS",$J)) 38 S PSUEXT("PSUPTR")=0 39 ; 40 ; Get the delimiters that the passed in lab data is using 41 ; 42 D PARAMS 43 S PSUHLECH=$G(ARR("PSUHLECH"),"^~\&") 44 S PSUHLCS=$E(PSUHLECH,1) 45 ; 46 ; Quit if no DFN 47 ; 48 I '$D(ARR) Q 49 I ARR("DFN")=0!(ARR("DFN")="") Q 50 ; 51 ; Quit if patient is an employee 52 ; 53 I $$EMPL^DGSEC4(ARR("DFN"),"PS") Q 54 ; 55 ; Get Lab's equivalent of a DFN (LRDFN) 56 ; 57 S LRDFN=$P(^DPT(ARR("DFN"),"LR"),"^") ; DBIA 998 to get file #63 ien 58 ; 59 ; Loop through the lab data 60 ; 61 S FIRST=1 62 D LOOP 63 ; 64 ; Generate an HL7 if data exists to be sent 65 ; 66 I 'FIRST D GENERATE 67 ; 68 K PSUHL,ERR,OPTNS,ERR 69 ; 70 Q 71 ; 72 LOOP ; 73 N CNT,LRIDT,LRSS,PREV1,PREV2,QUIT1,QUIT2,REC,REC1,REC2,SEG,SEG1,SEG2,STR1 74 K ^TMP("HLS",$J) 75 S CNT=0 76 F Q:CNT="" S CNT=$O(@OREMSG@(CNT)) Q:'CNT D 77 . S REC=@OREMSG@(CNT) 78 . S REC=$$STRING(REC,CNT) 79 . S SEG=$P(REC,PSUHLFS,1) 80 . I SEG'="ORC" Q 81 . S STR1=$P(REC,PSUHLFS,4) 82 . S STR1=$P(STR1,PSUHLCS,1) 83 . S LRSS=$P(STR1,";",4) 84 . ; 85 . ; Quit if data is not for Chemistry 86 . ; 87 . I LRSS'="CH" Q 88 . S LRIDT=$P(STR1,";",5) 89 . S QUIT1=0 90 . F Q:QUIT1!(CNT="") S PREV1=CNT,CNT=$O(@OREMSG@(CNT)) Q:'CNT D 91 . . S REC1=@OREMSG@(CNT) 92 . . S REC1=$$STRING(REC1,CNT) 93 . . S SEG1=$P(REC1,PSUHLFS,1) 94 . . I SEG1="ORC" S CNT=PREV1,QUIT1=1 Q 95 . . I SEG1'="OBR" Q 96 . . ; If this is the first OBR being processed i.e. this is valid 97 . . ; chemistry data set the PID segment 98 . . I FIRST D PID S FIRST=0 99 . . D OBR(REC1) 100 . . S QUIT2=0 101 . . F Q:QUIT2 S PREV2=CNT,CNT=$O(@OREMSG@(CNT)) Q:'CNT D 102 . . . S REC2=@OREMSG@(CNT) 103 . . . S REC2=$$STRING(REC2,CNT) 104 . . . S SEG2=$P(REC2,PSUHLFS,1) 105 . . . I SEG2="OBR"!(SEG2="ORC") S CNT=PREV2,QUIT2=1 Q 106 . . . I SEG2'="OBX" Q 107 . . . D OBX(REC2) 108 Q 109 ; 110 PID ; Create the PID segment using the standard builder 111 ; 112 N K1,NEWSEG,SEG 113 S SEG="SEG" 114 D BLDPID^VAFCQRY(ARR("DFN"),1,"1,2,3",.SEG,.PSUHL,.ERR) 115 ; 116 ; Loop through the returned array just in case the data is spread over 117 ; more than one node 118 ; 119 S K1="",NEWSEG="" 120 F S K1=$O(SEG(K1)) Q:'K1 D 121 . S NEWSEG=NEWSEG_SEG(K1) 122 ; 123 ; Set the data string into the PBM HL7 array 124 ; 125 D SETSEG(NEWSEG) 126 ; 127 Q 128 ; 129 OBR(REC) ; Re-forms lab OBR to only send required data 130 ; 131 N OBRSEG,SITE,SPECDATE 132 S OBRSEG="OBR" 133 S SPECDATE=$P(REC,PSUHLFS,8) 134 S SITE=$P(REC,PSUHLFS,16) 135 S SITE=$TR(SITE,PSUHLCS,PSUHL("CS")) 136 ; 137 ; Create new OBR Segment and pass to SETSEG 138 ; 139 S $P(OBRSEG,PSUHL("FS"),8)=SPECDATE 140 S $P(OBRSEG,PSUHL("FS"),16)=SITE 141 ; 142 ; Set the data string into the PBM HL7 array 143 ; 144 D SETSEG(OBRSEG) 145 ; 146 Q 147 ; 148 OBX(REC) ; Reforms lab OBX to only send the data needed 149 N CODES,HRANGE,LABS,LNAME,LR60,LRANGE,LRDN,LOINC,LOINCS,P2,P3,P12,RANGE,RES,RESULTS,SEG,UNITS 150 ; 151 S P2=$P(REC,PSUHLFS,2) 152 S P3=$P(REC,PSUHLFS,3) 153 S P12=$P(REC,PSUHLFS,12) 154 S RESULTS=$P(REC,PSUHLFS,6) 155 S UNITS=$P(REC,PSUHLFS,7) 156 S LABS=$P(REC,PSUHLFS,4) 157 S LR60=$P(LABS,"^",4) 158 I LR60']"" Q 159 S LRDN=$G(^LAB(60,LR60,0)) 160 S LRDN=$P($P(LRDN,"^",5),";",2) ; DBIA 91 for data name 161 ; 162 ; Make the call to LRRPU to get the LOINC code for this test 163 ; 164 I LRDN']"" Q 165 S RES=$$TSTRES^LRRPU(LRDFN,LRSS,LRIDT,LRDN,LR60,1) 166 ; 167 S CODES=$P(RES,U,8),LOINCS=$P(CODES,"!",3) 168 S LOINC=$P(LOINCS,";",1),LNAME=$P(LOINCS,";",2) 169 S LRANGE=$P(RES,U,3),HRANGE=$P(RES,U,4) 170 S RANGE=LRANGE_"-"_HRANGE I RANGE="-" S RANGE="" 171 ; 172 ; Use the Pharmacy HL7 delimeters 173 ; 174 S LABS=$TR(LABS,PSUHLCS,PSUHL("CS")) 175 ; 176 ; Add LOINC to the list of Labs if it exists 177 ; 178 I LOINC'="" D 179 . ; 180 . ; Append the LOINC data using the pharmacy delimiters 181 . S LABS=LABS_PSUHL("CS")_LOINC_PSUHL("CS")_LNAME_PSUHL("CS")_"99LN" 182 ; 183 ; Put the data in the string 184 ; 185 S SEG="OBX" 186 S $P(SEG,PSUHL("FS"),2)=P2 187 S $P(SEG,PSUHL("FS"),3)=P3 188 S $P(SEG,PSUHL("FS"),4)=LABS 189 S $P(SEG,PSUHL("FS"),6)=RESULTS 190 S $P(SEG,PSUHL("FS"),7)=UNITS 191 S $P(SEG,PSUHL("FS"),8)=RANGE 192 S $P(SEG,PSUHL("FS"),12)=P12 193 ; 194 ; Put the string into the PBM HL7 global 195 ; 196 D SETSEG(SEG) 197 ; 198 Q 199 ; 200 STRING(HLSTR,CNT) ; Loops through sub nodes to create a full data string 201 N J 202 S J="" 203 F S J=$O(@OREMSG@(CNT,J)) Q:J="" S HLSTR=HLSTR_@OREMSG@(CNT,J) 204 Q HLSTR 205 ; 206 PARAMS ; Get the delimiters used in the lab data 207 ; 208 N CNT,ID,QUIT,REC,RES 209 K ARR 210 S (QUIT,CNT)=0,RES="" 211 F S CNT=$O(@OREMSG@(CNT)) Q:'CNT!(QUIT=2) D 212 . S REC=@OREMSG@(CNT) 213 . I $E(REC,1,3)="MSH" D Q 214 . . S PSUHLFS=$E(REC,4,4) 215 . . S ARR("PSUHLECH")=$P(REC,PSUHLFS,2),QUIT=QUIT+1 216 . I $P(REC,PSUHLFS,1)="PID" D Q 217 . . S ARR("DFN")=$P(REC,PSUHLFS,4) 218 . . S QUIT=QUIT+1 219 Q 220 ; 221 GENERATE ; Generate HL7 message 222 ; 223 ; D GENERATE^HLMA("PSU-SITE-DRIVER","GM",1,.RESULT,"",.OPTNS) 224 S OPTNS("QUEUE")="PBM LAB" 225 S RESULT=$$EN^HLOCNRT("PSU-SITE-DRIVER","GM",.OPTNS) 226 I +RESULT'=RESULT D 227 . S ^XTMP("PBM/HLO",DT,$J)=RESULT 228 K ^TMP("HLS",$J) 229 Q 230 ; 231 ; 232 SETSEG(SEG) ; 233 ; 234 ;***** STORES THE SEGMENT INTO THE ^TMP("HLS",$J) BUFFER 235 ; 236 ; SEG HL7 segment 237 ; 238 ; The SETSEG procedure stores the HL7 segment into the 239 ; standard HL7 buffer ^TMP("HLS",$J). The <TAB>, <CR> and <LF> 240 ; characters are replaced with spaces. Long segments are split among 241 ; sub-nodes of the main segment node. 242 ; 243 ; The PSUEXT array must be initialized before 244 ; calling this function. 245 ; 246 N I1,I2,MAXLEN,NODE,PTR,PTR1,SID,SL 247 S NODE=PSUEXT("PSUBUF"),PTR=$G(PSUEXT("PSUPTR"))+1 248 S SL=$L(SEG),MAXLEN=245 K @NODE@(PTR) 249 ;--- Store the segment 250 S @NODE@(PTR)=$TR($E(SEG,1,MAXLEN),$C(9,10,13)," ") 251 ; 252 ;--- Split the segment into sub-nodes if necessary 253 D:SL>MAXLEN 254 . S I2=MAXLEN 255 . F PTR1=1:1 S I1=I2+1,I2=I1+MAXLEN-1 Q:I1>SL D 256 . . S @NODE@(PTR,PTR1)=$TR($E(SEG,I1,I2),$C(9,10,13)," ") 257 ;--- Save the pointer 258 S PSUEXT("PSUPTR")=PTR 259 Q 1 PSULRHL1 ;HCIOFO/BH/RDC - Process real time HL7 Lab messages ; 5/15/04 3:10pm 2 ;;4.0;PHARMACY BENEFITS MANAGEMENT;**3**;MARCH, 2005 3 ; 4 ; DBIA 3565 to subscribe to the LR7O ALL EVSEND RESULTS protocol 5 ; DBIA 998 to dig through ^DPT(i,"LR" go get the ien to file #63 6 ; DBIA 91-A to dig through ^LAB(60 to get the name of the test 7 ; DBIA 3630 to call the HL7 PID builder 8 ; DBIA 4727 to call EN^HLOCNRT 9 ; DBIA 3646 to call API: $$EMPL^DGSEC4 10 ; DBIA 4658 to call API: $$TSTRES^LRRPU 11 ; 12 ; This program is called when a lab test is verified. If it is for a 13 ; chemistry test, and not for an employee, an HL7 message will be 14 ; created and sent to the CMOP-NAT server. 15 ; 16 ; 17 HL7 ; Entry point for PBM processing - triggered by lab protocol 18 ; LR7O ALL EVSEND RESULTS. 19 ; 20 N ARR,FIRST,LRDFN,PSUEXT,PSUHLFS,PSUHLECH,PSUHLCS 21 ; 22 ; OREMSG is the pointer reference to the global that contains the 23 ; lab data and is passed in by the LR7O ALL EVSEND RESULTS protocol. 24 ; 25 I '$D(@OREMSG) Q 26 ; 27 ; Get Lab parameters 28 ; 29 D INIT^HLFNC2("PSU-SITE-DRIVER",.PSUHL) 30 ; 31 ; Set up CS delimeter for the Pharmacy message 32 ; 33 S PSUHL("CS")=$E(PSUHL("ECH"),1) 34 ; 35 ; Set up segment processing parameters 36 ; 37 S PSUEXT("PSUBUF")=$NA(^TMP("HLS",$J)) 38 S PSUEXT("PSUPTR")=0 39 ; 40 ; Get the delimiters that the passed in lab data is using 41 ; 42 D PARAMS 43 S PSUHLECH=$G(ARR("PSUHLECH"),"^~\&") 44 S PSUHLCS=$E(PSUHLECH,1) 45 ; 46 ; Quit if no DFN 47 ; 48 I '$D(ARR) Q 49 I ARR("DFN")=0!(ARR("DFN")="") Q 50 ; 51 ; Quit if patient is an employee 52 ; 53 I $$EMPL^DGSEC4(ARR("DFN"),"PS") Q 54 ; 55 ; Get Lab's equivalent of a DFN (LRDFN) 56 ; 57 S LRDFN=$P(^DPT(ARR("DFN"),"LR"),"^") ; DBIA 998 to get file #63 ien 58 ; 59 ; Loop through the lab data 60 ; 61 S FIRST=1 62 D LOOP 63 ; 64 ; Generate an HL7 if data exists to be sent 65 ; 66 I 'FIRST D GENERATE 67 ; 68 K PSUHL,ERR,OPTNS,ERR 69 ; 70 Q 71 ; 72 LOOP ; 73 N CNT,LRIDT,LRSS,PREV1,PREV2,QUIT1,QUIT2,REC,REC1,REC2,SEG,SEG1,SEG2,STR1 74 K ^TMP("HLS",$J) 75 S CNT=0 76 F Q:CNT="" S CNT=$O(@OREMSG@(CNT)) Q:'CNT D 77 . S REC=@OREMSG@(CNT) 78 . S REC=$$STRING(REC,CNT) 79 . S SEG=$P(REC,PSUHLFS,1) 80 . I SEG'="ORC" Q 81 . S STR1=$P(REC,PSUHLFS,4) 82 . S STR1=$P(STR1,PSUHLCS,1) 83 . S LRSS=$P(STR1,";",4) 84 . ; 85 . ; Quit if data is not for Chemistry 86 . ; 87 . I LRSS'="CH" Q 88 . S LRIDT=$P(STR1,";",5) 89 . S QUIT1=0 90 . F Q:QUIT1!(CNT="") S PREV1=CNT,CNT=$O(@OREMSG@(CNT)) Q:'CNT D 91 . . S REC1=@OREMSG@(CNT) 92 . . S REC1=$$STRING(REC1,CNT) 93 . . S SEG1=$P(REC1,PSUHLFS,1) 94 . . I SEG1="ORC" S CNT=PREV1,QUIT1=1 Q 95 . . I SEG1'="OBR" Q 96 . . ; If this is the first OBR being processed i.e. this is valid 97 . . ; chemistry data set the PID segment 98 . . I FIRST D PID S FIRST=0 99 . . D OBR(REC1) 100 . . S QUIT2=0 101 . . F Q:QUIT2 S PREV2=CNT,CNT=$O(@OREMSG@(CNT)) Q:'CNT D 102 . . . S REC2=@OREMSG@(CNT) 103 . . . S REC2=$$STRING(REC2,CNT) 104 . . . S SEG2=$P(REC2,PSUHLFS,1) 105 . . . I SEG2="OBR"!(SEG2="ORC") S CNT=PREV2,QUIT2=1 Q 106 . . . I SEG2'="OBX" Q 107 . . . D OBX(REC2) 108 Q 109 ; 110 PID ; Create the PID segment using the standard builder 111 ; 112 N K1,NEWSEG,SEG 113 S SEG="SEG" 114 D BLDPID^VAFCQRY(ARR("DFN"),1,"1,2,3",.SEG,.PSUHL,.ERR) 115 ; 116 ; Loop through the returned array just in case the data is spread over 117 ; more than one node 118 ; 119 S K1="",NEWSEG="" 120 F S K1=$O(SEG(K1)) Q:'K1 D 121 . S NEWSEG=NEWSEG_SEG(K1) 122 ; 123 ; Set the data string into the PBM HL7 array 124 ; 125 D SETSEG(NEWSEG) 126 ; 127 Q 128 ; 129 OBR(REC) ; Re-forms lab OBR to only send required data 130 ; 131 N OBRSEG,SITE,SPECDATE 132 S OBRSEG="OBR" 133 S SPECDATE=$P(REC,PSUHLFS,8) 134 S SITE=$P(REC,PSUHLFS,16) 135 S SITE=$TR(SITE,PSUHLCS,PSUHL("CS")) 136 ; 137 ; Create new OBR Segment and pass to SETSEG 138 ; 139 S $P(OBRSEG,PSUHL("FS"),8)=SPECDATE 140 S $P(OBRSEG,PSUHL("FS"),16)=SITE 141 ; 142 ; Set the data string into the PBM HL7 array 143 ; 144 D SETSEG(OBRSEG) 145 ; 146 Q 147 ; 148 OBX(REC) ; Reforms lab OBX to only send the data needed 149 N CODES,HRANGE,LABS,LNAME,LR60,LRANGE,LRDN,LOINC,LOINCS,P2,P3,P12,RANGE,RES,RESULTS,SEG,UNITS 150 ; 151 S P2=$P(REC,PSUHLFS,2) 152 S P3=$P(REC,PSUHLFS,3) 153 S P12=$P(REC,PSUHLFS,12) 154 S RESULTS=$P(REC,PSUHLFS,6) 155 S UNITS=$P(REC,PSUHLFS,7) 156 S LABS=$P(REC,PSUHLFS,4) 157 S LR60=$P(LABS,"^",4) 158 S LRDN=$G(^LAB(60,LR60,0)) 159 S LRDN=$P($P(LRDN,"^",5),";",2) ; DBIA 91 for data name 160 ; 161 ; Make the call to LRRPU to get the LOINC code for this test 162 ; 163 S RES=$$TSTRES^LRRPU(LRDFN,LRSS,LRIDT,LRDN,LR60,1) 164 ; 165 S CODES=$P(RES,U,8),LOINCS=$P(CODES,"!",3) 166 S LOINC=$P(LOINCS,";",1),LNAME=$P(LOINCS,";",2) 167 S LRANGE=$P(RES,U,3),HRANGE=$P(RES,U,4) 168 S RANGE=LRANGE_"-"_HRANGE I RANGE="-" S RANGE="" 169 ; 170 ; Use the Pharmacy HL7 delimeters 171 ; 172 S LABS=$TR(LABS,PSUHLCS,PSUHL("CS")) 173 ; 174 ; Add LOINC to the list of Labs if it exists 175 ; 176 I LOINC'="" D 177 . ; 178 . ; Append the LOINC data using the pharmacy delimiters 179 . S LABS=LABS_PSUHL("CS")_LOINC_PSUHL("CS")_LNAME_PSUHL("CS")_"99LN" 180 ; 181 ; Put the data in the string 182 ; 183 S SEG="OBX" 184 S $P(SEG,PSUHL("FS"),2)=P2 185 S $P(SEG,PSUHL("FS"),3)=P3 186 S $P(SEG,PSUHL("FS"),4)=LABS 187 S $P(SEG,PSUHL("FS"),6)=RESULTS 188 S $P(SEG,PSUHL("FS"),7)=UNITS 189 S $P(SEG,PSUHL("FS"),8)=RANGE 190 S $P(SEG,PSUHL("FS"),12)=P12 191 ; 192 ; Put the string into the PBM HL7 global 193 ; 194 D SETSEG(SEG) 195 ; 196 Q 197 ; 198 STRING(HLSTR,CNT) ; Loops through sub nodes to create a full data string 199 N J 200 S J="" 201 F S J=$O(@OREMSG@(CNT,J)) Q:J="" S HLSTR=HLSTR_@OREMSG@(CNT,J) 202 Q HLSTR 203 ; 204 PARAMS ; Get the delimiters used in the lab data 205 ; 206 N CNT,ID,QUIT,REC,RES 207 K ARR 208 S (QUIT,CNT)=0,RES="" 209 F S CNT=$O(@OREMSG@(CNT)) Q:'CNT!(QUIT=2) D 210 . S REC=@OREMSG@(CNT) 211 . I $E(REC,1,3)="MSH" D Q 212 . . S PSUHLFS=$E(REC,4,4) 213 . . S ARR("PSUHLECH")=$P(REC,PSUHLFS,2),QUIT=QUIT+1 214 . I $P(REC,PSUHLFS,1)="PID" D Q 215 . . S ARR("DFN")=$P(REC,PSUHLFS,4) 216 . . S QUIT=QUIT+1 217 Q 218 ; 219 GENERATE ; Generate HL7 message 220 ; 221 ; D GENERATE^HLMA("PSU-SITE-DRIVER","GM",1,.RESULT,"",.OPTNS) 222 S OPTNS("QUEUE")="PBM LAB" 223 S RESULT=$$EN^HLOCNRT("PSU-SITE-DRIVER","GM",.OPTNS) 224 I +RESULT'=RESULT D 225 . S ^XTMP("PBM/HLO",DT,$J)=RESULT 226 K ^TMP("HLS",$J) 227 Q 228 ; 229 ; 230 SETSEG(SEG) ; 231 ; 232 ;***** STORES THE SEGMENT INTO THE ^TMP("HLS",$J) BUFFER 233 ; 234 ; SEG HL7 segment 235 ; 236 ; The SETSEG procedure stores the HL7 segment into the 237 ; standard HL7 buffer ^TMP("HLS",$J). The <TAB>, <CR> and <LF> 238 ; characters are replaced with spaces. Long segments are split among 239 ; sub-nodes of the main segment node. 240 ; 241 ; The PSUEXT array must be initialized before 242 ; calling this function. 243 ; 244 N I1,I2,MAXLEN,NODE,PTR,PTR1,SID,SL 245 S NODE=PSUEXT("PSUBUF"),PTR=$G(PSUEXT("PSUPTR"))+1 246 S SL=$L(SEG),MAXLEN=245 K @NODE@(PTR) 247 ;--- Store the segment 248 S @NODE@(PTR)=$TR($E(SEG,1,MAXLEN),$C(9,10,13)," ") 249 ; 250 ;--- Split the segment into sub-nodes if necessary 251 D:SL>MAXLEN 252 . S I2=MAXLEN 253 . F PTR1=1:1 S I1=I2+1,I2=I1+MAXLEN-1 Q:I1>SL D 254 . . S @NODE@(PTR,PTR1)=$TR($E(SEG,I1,I2),$C(9,10,13)," ") 255 ;--- Save the pointer 256 S PSUEXT("PSUPTR")=PTR 257 Q
Note:
See TracChangeset
for help on using the changeset viewer.