Index: ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m
===================================================================
--- ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m	(revision 1665)
+++ ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m	(revision 1730)
@@ -1,5 +1,5 @@
 C0CRXNLK ; VEN/SMH - RxNorm Lookup Utilities ;2014-07-22  2:27 PM
- ;;2.3;RXNORM FOR VISTA;;Jul 22, 2014;Build 16
- ;(c) Sam Habiel 2013
+ ;;2.5;RXNORM FOR VISTA;;Apr 27, 2016;Build 16
+ ;(c) Sam Habiel 2016
  ; See accompanying license. Don't use otherwise.
  ;
@@ -7,5 +7,5 @@
  N DIQUIET S DIQUIET=1
  D DT^DICRW
- D EN^XTMUNIT($T(+0),1)
+ D EN^%ut($T(+0),2)
  QUIT
  ;
@@ -22,14 +22,13 @@
  Q ^(IEN)
  ;
-GCN2RXNT ; @TEST - Test Get RxNorm CUI using GCN
+GCN2RXNT ; @TEST Test Get RxNorm CUI using GCN
  Q:'$D(^C0CRXN(176.001,"STC","NDDF"))
  N L F L=1:1 N LN S LN=$T(GCN2RXND+L) Q:LN["<<END>>"  Q:LN=""  D
  . N GCN S GCN=$P(LN,";",3)
  . N RXN S RXN=$P(LN,";",4)
- . D CHKEQ^XTMUNIT($$GCN2RXN(GCN),RXN,"Translation from GCN to RXCUI failed")
+ . D CHKEQ^%ut($$GCN2RXN(GCN),RXN,"Translation from GCN to RXCUI failed")
  QUIT
  ;
 GCN2RXND ; @DATA - Data for Tests ;;GCN;EXPECTED RXNCUI
- ;;16033;991632
  ;;8208;310429
  ;;1275;628953
@@ -49,10 +48,10 @@
  Q GCNS
  ;
-RXN2GCNT ; @TEST - Test Get GCN from RXNCUI
+RXN2GCNT ; @TEST Test Get GCN from RXNCUI
  Q:'$D(^C0CRXN(176.001,"STX","NDDF"))
  N L F L=1:1 N LN S LN=$T(RXN2GCND+L) Q:LN["<<END>>"  Q:LN=""  D
  . N RXN S RXN=$P(LN,";",3)
  . N GCN S GCN=$P(LN,";",4)
- . D CHKEQ^XTMUNIT($$RXN2GCN(RXN),GCN,"Translation from RXCUI to GCN failed")
+ . D CHKEQ^%ut($$RXN2GCN(RXN),GCN,"Translation from RXCUI to GCN failed")
  QUIT
  ;
@@ -60,7 +59,7 @@
 RXN2GCND ; @DATA - Data for Tests ;;RXNORM CUI;Expected GCN; Human Readable Drug name for dear reader
  ;;998689;5145;Acetabulol 200mg tab
- ;;745679;5037;Albuterol Inhaler
+ ;;745679;28090;Albuterol Inhaler
  ;;197320;2536;Allopurinol 300mg tab
- ;;993691;3948^46236;Bupropion 75mg tab
+ ;;993691;46236;Bupropion 75mg tab
  ;;197591;3768;Diazepam 5mg tab
  ;;<<END>>
@@ -79,17 +78,16 @@
  Q C0PVUID
  ;
-RXN2VUIT ; @TEST - Get VUIDs given RxNorm values
+RXN2VUIT ; @TEST Get VUIDs given RxNorm values
  N L F L=1:1 N LN S LN=$T(RXN2VUID+L) Q:LN["<<END>>"  Q:LN=""  D
  . N RXN S RXN=$P(LN,";",3)
  . N VUIDS S VUIDS=$P(LN,";",4)
- . D CHKEQ^XTMUNIT($P($$RXN2VUI(RXN),U),$P(VUIDS,U),"Translation from RXNCUI to VUID failed")
+ . D CHKEQ^%ut($P($$RXN2VUI(RXN),U),$P(VUIDS,U),"Translation from RXNCUI to VUID failed")
  QUIT
  ;
 RXN2VUID ; @DATA - Data items for previous test
- ;;991632;4006455
  ;;310429;4002369^4013941
- ;;628953;4000874^4000856^4013966^4015798^4015799
+ ;;628953;4000856^4013966^4015798^4015799
  ;;197604;4003335^4015937
- ;;884173;4002469^4013919
+ ;;884173;4002469^4013919^4032795
  ;;<<END>>
  ;
@@ -105,9 +103,9 @@
  Q O
  ;
-VUI2VAPT ; @TEST - Get VA Product IEN from VUID
+VUI2VAPT ; @TEST Get VA Product IEN from VUID
  N L F L=1:1 N LN S LN=$T(VUI2VAPD+L) Q:LN["<<END>>"  Q:LN=""  D
  . N VUID S VUID=$P(LN,";",3)
  . N VAP S VAP=$P(LN,";",4)
- . D CHKEQ^XTMUNIT($$VUI2VAP(VUID),VAP,"Translation from VUID to VA PRODUCT failed")
+ . D CHKEQ^%ut($$VUI2VAP(VUID),VAP,"Translation from VUID to VA PRODUCT failed")
  QUIT
  ;
@@ -166,7 +164,7 @@
  N IEN S IEN=$O(^C0CRXN(176.001,"STC","NDDF","IN",BASE,"")) Q ^(IEN)
  ;
-FDI2RXNT ; @TEST - Test Get RxNorm CUI for FDB Ingredient/Base
+FDI2RXNT ; @TEST Test Get RxNorm CUI for FDB Ingredient/Base
  Q:'$D(^C0CRXN(176.001,"STC","NDDF"))
- D CHKEQ^XTMUNIT($$FDI2RXN(14739),1362160,"$$FDI2RXN failed")
+ D CHKEQ^%ut($$FDI2RXN(14739),1362160,"$$FDI2RXN failed")
  QUIT
  ;
@@ -177,8 +175,10 @@
  ; Input: RXNCUI By Value
  ; Output: VUID
- N IEN S IEN=$O(^C0CRXN(176.001,"STX","VANDF","IN",RXNCUI,"")) Q ^(IEN)
- ;
-RXN2VINT ; @TEST - Test Get VUID Ingredient for RxNorm CUI
- D CHKEQ^XTMUNIT($$RXN2VIN(1366467),4031768,"$$RXN2VIN failed")
+ N IEN S IEN=$O(^C0CRXN(176.001,"STX","VANDF","IN",RXNCUI,""))
+ I IEN Q ^(IEN)
+ E  Q ""
+ ;
+RXN2VINT ; @TEST Test Get VUID Ingredient for RxNorm CUI
+ D CHKEQ^%ut($$RXN2VIN(1366467),4031768,"$$RXN2VIN failed")
  QUIT
  ;
@@ -192,6 +192,6 @@
  Q C0PIEN_"^"_C0P01
  ;
-VIN2VAGT ; @TEST - Test Get VA Generic for VUID Ingredient
- D CHKEQ^XTMUNIT(+$$VIN2VAG(4023636),2832,"$$VIN2VAG failed")
+VIN2VAGT ; @TEST Test Get VA Generic for VUID Ingredient
+ D CHKEQ^%ut(+$$VIN2VAG(4023636),2832,"$$VIN2VAG failed")
  QUIT
  ;
@@ -218,17 +218,23 @@
  Q $$VIN2DIN($$RXN2VIN($$FDI2RXN(BASE)))
  ;
-VUI2RXN(VUID) ; $$ Public - Get RXNCUI for VUID (any VUID type)
- ; Input: VUID By Value
- ; Output: RXNCUIs delimited by ^
- ; Get all entries whose code is the VUID and are in the VA NDF which are clinical drugs
- D FIND^DIC(176.001,,"@;.01","PQX",VUID,,"CODE","I $P(^(0),U,12,13)=""VANDF^CD""")
- ; Deserialise it into a single string
- ; ^TMP("DILIST",4844,0)="1^*^0^"
- ; ^TMP("DILIST",4844,0,"MAP")="IEN^.01"
- ; ^TMP("DILIST",4844,1,0)="1006351^1364462"
- N RXNS S RXNS=""
- N I F I=0:0 S I=$O(^TMP("DILIST",$J,I)) Q:'I  S RXNS=RXNS_$P(^(I,0),U,2)_U
- S RXNS=$E(RXNS,1,$L(RXNS)-1)
- QUIT RXNS
+VUI2RXN(VUID,TTY) ; $$ Public Stephanie's Unified VUID searcher. Get RXNCUI given VUID
+ ;GIVEN A VUID IN ONE OF SEVERAL FILES RETURN THE ASSOCIATED RXNORM CODE IN 176.001
+ ; TTY="IN", "CD", or "PT"
+ ;        IN = DRUG INGRIDENT FILE & VA GENERIC file
+ ;        CD = VA PRODUCT FILE
+ ;        PT = VA DRUG CLASS
+ ;
+ ; SAB="VANDF"
+ ; CODE=VUID
+ ;
+ I $O(^C0CRXN(176.001,"STC","VANDF",TTY,VUID,"")) Q ^($O(^("")))
+ Q ""
+ ;
+VUI2RXNT ; @TEST VUID to RxNorm CUI tests
+ D CHKEQ^%ut($$VUI2RXN(4010151,"CD"),314231)
+ D CHKEQ^%ut($$VUI2RXN(4020940,"IN"),16681)
+ D CHKEQ^%ut($$VUI2RXN(4021568,"PT"),883)
+ D CHKEQ^%ut($$VUI2RXN(1234234,"CD"),"")
+ QUIT
  ;
 VUI2GCN(VUID) ; $$ Public - Get GCNs for a given VUID (any VUID type)
@@ -236,5 +242,5 @@
  ; Output: GCNs delimited by ^
  ; TODO: Unit Test
- N RXNS S RXNS=$$VUI2RXN(VUID)
+ N RXNS S RXNS=$$VUI2RXN(VUID,"AB")
  Q:RXNS="" ""  ; VUID not a drug or ingredient (can be food)
  N GCNS S GCNS=""
@@ -251,5 +257,5 @@
  N VUID S VUID=+^PSNDF(50.68,VAP,"VUID")  ; Get VUID
  I 'VUID S $EC=",U1," ; Must exist
- Q $$VUI2RXN(VUID)
+ Q $$VUI2RXN(VUID,"AB")
  ;
 MED2SCDN(DA) ; $$ Public - Medication to Semantic Clinical Drug Name
@@ -258,4 +264,7 @@
  N RXNCUI S RXNCUI=$$MED2RXN(DA)
  Q:'RXNCUI ""
+ Q $$SCDNAME(RXNCUI)
+ ;
+SCDNAME(RXNCUI) ; $$ Public - Semantic Clinical Drug Name for RxNorm CUI
  N IEN S IEN=$O(^C0CRXN(176.001,"STC","RXNORM","SCD",RXNCUI,""))  ; Let's try generic drug
  I 'IEN S IEN=$O(^C0CRXN(176.001,"STC","RXNORM","SBD",RXNCUI,""))  ; Let's try non-bioequivalent Brands then
@@ -265,4 +274,13 @@
  Q $P(^C0CRXN(176.001,IEN,0),U,15)
  ;
+ANYNAME(RXNCUI) ; $$ Public - Get the RxNorm name, no matter what it is
+ N RESULT S RESULT=""
+ N TTY S TTY=""
+ F  S TTY=$O(^C0CRXN(176.001,"STC","RXNORM",TTY)) Q:TTY=""  D  Q:RESULT]""
+ . N IEN S IEN=$O(^C0CRXN(176.001,"STC","RXNORM",TTY,RXNCUI,""))
+ . Q:'IEN
+ . S RESULT=$P(^C0CRXN(176.001,IEN,0),U,15)
+ QUIT RESULT
+ ;
 RXN2NDI(RXNCUI) ; $$ Public - Get NDDF Ingredient for RXNCUI
  ; Input: RXNCUI By Value
@@ -276,5 +294,5 @@
  ; Output: NDDF Base code
  ; TODO:Not tested...
- Q $$RXN2NDI($$VUI2RXN(VUID))
+ Q $$RXN2NDI($$VUI2RXN(VUID,"IN"))
  ;
  ; ---
@@ -287,7 +305,7 @@
  N IEN S IEN=$O(^C0CRXN(176.002,"ASAA","RXNORM","NDC",NDC,"")) Q ^(IEN)
  ;
-NDC2RXNT ; @TEST - Test Get RxCUI given the NDC & Get RxCUI given the 50.67 NDC
- D CHKEQ^XTMUNIT($$NDC2RXN("30142-0917-71"),198439,"$$NDC2RXN failed")
- D CHKEQ^XTMUNIT($$NDC2RXN2("000031868518","VANDF"),996520,"$$NDC2RXN2 failed")
+NDC2RXNT ; @TEST Test Get RxCUI given the NDC & Get RxCUI given the 50.67 NDC
+ D CHKEQ^%ut($$NDC2RXN("30142-0917-71"),198439,"$$NDC2RXN failed")
+ D CHKEQ^%ut($$NDC2RXN2("000031868518","VANDF"),996520,"$$NDC2RXN2 failed")
  QUIT
  ;
@@ -304,7 +322,7 @@
  ; Output: 0 or 1
  Q ''$D(^C0CRXN(176.001,"STC","RXNORM","SBD",RXN))
-ISBRANDT ; @TEST - Test Is this RxCUI for a brand drug?
- D CHKEQ^XTMUNIT($$ISBRAND(205535),1,"$$ISBRAND failed") ; Brand Prozac
- D CHKEQ^XTMUNIT($$ISBRAND(310384),0,"$$ISBRAND failed") ; Generic Fluoxetine
+ISBRANDT ; @TEST Test Is this RxCUI for a brand drug?
+ D CHKEQ^%ut($$ISBRAND(205535),1,"$$ISBRAND failed") ; Brand Prozac
+ D CHKEQ^%ut($$ISBRAND(310384),0,"$$ISBRAND failed") ; Generic Fluoxetine
  QUIT
  ;
@@ -315,6 +333,6 @@
  ; Output: RxCUI of Generic
  Q $O(^C0CRXN(176.005,"B",RXN,"has_tradename",""))
-BR2GENT ; @TEST - Test Convert Brand RxCUI to Generic RxCUI (many to 1)
- D CHKEQ^XTMUNIT($$BR2GEN(205535),310384,"$$BR2GEN failed")
+BR2GENT ; @TEST Test Convert Brand RxCUI to Generic RxCUI (many to 1)
+ D CHKEQ^%ut($$BR2GEN(205535),310384,"$$BR2GEN failed")
  QUIT
  ;
@@ -327,6 +345,6 @@
  Q RTN
  ;
-GEN2BRT ; @TEST - Test Convert Generic RxCUI to Brand RxCUIs (1 to many).
- D CHKTF^XTMUNIT($$GEN2BR(310384)[205535,"$$GEN2BR failed")
+GEN2BRT ; @TEST Test Convert Generic RxCUI to Brand RxCUIs (1 to many).
+ D CHKTF^%ut($$GEN2BR(310384)[205535,"$$GEN2BR failed")
  QUIT
  ;
@@ -345,16 +363,62 @@
  . S BNS=BNS_$P(^C0CRXN(176.001,BNIEN,0),U,15)_U
  QUIT $E(BNS,1,$L(BNS)-1)
-RXN2BNST ; @TEST - Test Get all Brand Names associated with an RXN
- D CHKTF^XTMUNIT($$RXN2BNS(205535)["Prozac","$$RXN2BNS failed")
- QUIT
- ;
- ; ---
- ;
-RXN2NDC(RXN) ; Get NDC codes for RxNorm code
+RXN2BNST ; @TEST Test Get all Brand Names associated with an RXN
+ D CHKTF^%ut($$RXN2BNS(205535)["Prozac","$$RXN2BNS failed")
+ QUIT
+ ;
+ ; ---
+ ;
+RXN2NDC(RXN) ; $$ Public - Get NDC codes for RxNorm code
  N NDCS S NDCS=""
  N I F I=0:0 S I=$O(^C0CRXN(176.002,"ASAR","RXNORM","NDC",RXN,I)) Q:'I  S NDCS=NDCS_^(I)_"^"
  S $E(NDCS,$L(NDCS))=""
  QUIT NDCS
-RXN2NDCT ; @TEST - Test Get NDC codes for RxNorm code
- D CHKTF^XTMUNIT($$RXN2NDC(197379)["^"_16714003309,"$$RXN2NDC failed")
- QUIT
+RXN2NDCT ; @TEST Test Get NDC codes for RxNorm code
+ D CHKTF^%ut($$RXN2NDC(197379)["^"_16714003309,"$$RXN2NDC failed")
+ QUIT
+ ;
+LVUID(RXN) ; $$ Public - Locate VUID, given RxNorm. Iterative Search
+ ; ^C0CRXN(176.001,"STC","RXNORM","IN",46239,IEN
+ N TTY S TTY=""
+ N intermediateRxCUI
+ N finalVUID
+ i '$$EXIST(RXN) q "0^not found in RxNorm"
+ ;
+ F  S TTY=$O(^C0CRXN(176.001,"STC","RXNORM",TTY)) Q:TTY=""  D  q:$g(intermediateRxCUI)  q:$g(finalVUID)
+ . N IEN S IEN=$O(^C0CRXN(176.001,"STC","RXNORM",TTY,RXN,""))
+ . I 'IEN quit  ; s err="0^not found in RxNorm" quit
+ . ; W ^C0CRXN(176.001,IEN,0),!
+ . I TTY="BN" s intermediateRxCUI=$$BR2GEN(RXN) quit  ; try searching with generic
+ . I TTY="IN"!(TTY="MIN") s finalVUID=$$RXN2VIN(RXN) quit         ; match VUID
+ . I TTY="PIN" s intermediateRxCUI=$$formOf(RXN) quit  ; try searching with ingredient
+ . I TTY="SCD" d
+ .. s finalVUID=$$RXN2VUI(RXN)
+ .. i finalVUID="" s finalVUID=$$containerOf(RXN)
+ .. I finalVUID="" s finalVUID=$$tradeName(RXN)
+ . I TTY="GPCK" d
+ .. s finalVUID=$$tradeName(RXN)
+ i $get(intermediateRxCUI) q $$LVUID(intermediateRxCUI) ; recurse
+ i $get(finalVUID) quit finalVUID
+ quit "0^no mapping found in RxNorm"
+ ;
+formOf(RXN) ; RXN is form of result
+ q $o(^C0CRXN(176.005,"B",RXN,"has_form",""))
+containerOf(RXN) ; loop through all contains and see if one hits it.
+ n container
+ n vuid s vuid=""
+ f container=0:0 s container=$o(^C0CRXN(176.005,"B",RXN,"contains",container)) q:'container  d  q:$g(vuid)
+ . s vuid=$$RXN2VUI(container)
+ quit vuid
+tradeName(RXN) ; loop through all tradenames and see if there's a match
+ n vuid s vuid=""
+ n tncui f tncui=0:0 s tncui=$o(^C0CRXN(176.005,"B",RXN,"tradename_of",tncui)) q:'tncui  d  q:$g(vuid)
+ . s vuid=$$RXN2VUI(tncui)
+ quit vuid
+ ;
+loopVUIDs ; [Public] Paste VUIDs to get the RxNorm Numbers
+ ; ZEXCEPT: DTIME
+ n rxn
+ f  r rxn:$g(DTIME,300) q:rxn=""  q:rxn=$c(4)  d
+ . w "|"
+ . w $$LVUID(rxn),"|",$$ANYNAME(rxn),!
+ quit
