Index: /ccr/trunk/rxnorm/trunk/routines/C0CRXNAD.m
===================================================================
--- /ccr/trunk/rxnorm/trunk/routines/C0CRXNAD.m	(revision 1629)
+++ /ccr/trunk/rxnorm/trunk/routines/C0CRXNAD.m	(revision 1630)
@@ -1,132 +1,132 @@
-C0CRXNAD ; VEN/SMH - Add a drug to VISTA from RxNorm;2013-04-19  5:39 PM
- ;;1.0;RX NORM;;Apr 25, 2012;Build 99
- ; (C) 2013 Sam Habiel
- ; Proprietary Code. Don't use if license terms aren't supplied.
- ;
-ADDDRUG(RXN,NDC,BARCODE) ; Public Proc; Add Drug to Drug File
- ; Input: RXN - RxNorm Semantic Clinical Drug CUI by Value. Required.
- ; Input: NDC - Drug NDC by Value. Optional. Pass in 11 digit format without dashes.
- ; Input: BARCODE - Wand Barcode. Optional. Pass exactly as wand reads minus control characters.
- ; Output: Internal Entry Number
- ;
- ; Prelim Checks
- I '$G(RXN) S $EC=",U1," ; Required
- I $L($G(NDC)),$L(NDC)'=11 S $EC=",U1,"
- ;
- N PSSZ S PSSZ=1    ; Needed for the drug file to let me in!
- ;
- ; If RXN refers to a brand drug, get the generic instead.
- I $$ISBRAND^C0CRXNLK(RXN) S RXN=$$BR2GEN^C0CRXNLK(RXN)
- W !,"(debug) RxNorm is "_RXN,!
- ;
- ; Get first VUID for this RxNorm drug
- N VUID S VUID=+$$RXN2VUI^C0CRXNLK(RXN)
- Q:'VUID
- W "(debug) VUID for RxNorm CUI "_RXN_" is "_VUID,!
- ;
- ; IEN in 50.68
- N C0XVUID ; For Searching Compound Index
- S C0XVUID(1)=VUID
- S C0XVUID(2)=1
- N F5068IEN S F5068IEN=$$FIND1^DIC(50.68,"","XQ",.C0XVUID,"AMASTERVUID")
- Q:'F5068IEN
- W "F 50.68 IEN (debug): "_F5068IEN,!
- ;
- ; FDA Array
- N C0XFDA
- ;
- ; Name, shortened
- S C0XFDA(50,"+1,",.01)=$E($$GET1^DIQ(50.68,F5068IEN,.01),1,40)
- ;
- ; File BarCode as a Synonym for BCMA
- I $L($G(BARCODE)) D
- . S C0XFDA(50.1,"+2,+1,",.01)=BARCODE
- . S C0XFDA(50.1,"+2,+1,",1)="Q"
- ;
- ; Brand Names
- N BNS S BNS=$$RXN2BNS^C0CRXNLK(RXN) ; Brands
- I $L(BNS) N I F I=1:1:$L(BNS,U) D
- . N IENS S IENS=I+2
- . S C0XFDA(50.1,"+"_IENS_",+1,",.01)=$$UP^XLFSTR($E($P(BNS,U,I),1,40))
- . S C0XFDA(50.1,"+"_IENS_",+1,",1)="T"
- ;
- ; NDC (string)
- I $G(NDC) S C0XFDA(50,"+1,",31)=$E(NDC,1,5)_"-"_$E(NDC,6,9)_"-"_$E(NDC,10,11)
- ;
- ; Dispense Unit (string)
- S C0XFDA(50,"+1,",14.5)=$$GET1^DIQ(50.68,F5068IEN,"VA DISPENSE UNIT")
- ;
- ; National Drug File Entry (pointer to 50.6)
- S C0XFDA(50,"+1,",20)="`"_$$GET1^DIQ(50.68,F5068IEN,"VA GENERIC NAME","I")
- ;
- ; VA Product Name (string)
- S C0XFDA(50,"+1,",21)=$E($$GET1^DIQ(50.68,F5068IEN,.01),1,70)
- ;
- ; PSNDF VA PRODUCT NAME ENTRY (pointer to 50.68)
- S C0XFDA(50,"+1,",22)="`"_F5068IEN
- ;
- ; DEA, SPECIAL HDLG (string)
- D  ; From ^PSNMRG
- . N CS S CS=$$GET1^DIQ(50.68,F5068IEN,"CS FEDERAL SCHEDULE","I")
- . S CS=$S(CS?1(1"2n",1"3n"):+CS_"C",+CS=2!(+CS=3)&(CS'["C"):+CS_"A",1:CS)
- . S C0XFDA(50,"+1,",3)=CS
- ;
- ; NATIONAL DRUG CLASS (pointer to 50.605) (triggers VA Classification field)
- S C0XFDA(50,"+1,",25)="`"_$$GET1^DIQ(50.68,F5068IEN,"PRIMARY VA DRUG CLASS","I")
- ;
- ; Right Now, I don't file the following which ^PSNMRG does (cuz I don't need them)
- ; - Package Size (derived from NDC/UPN file)
- ; - Package Type (ditto)
- ; - CMOP ID (from $$PROD2^PSNAPIS)
- ; - National Formulary Indicator (from 50.68)
- ;
- ; Next Step is to kill Old OI if Dosage Form doesn't match
- ; Won't do that here as it's assumed any drugs that's added is new.
- ; This happens at ^PSNPSS
- ;
- ; Now add drug to drug file, as we need the IEN for the dosages call.
- N C0XERR,C0XIEN
- D UPDATE^DIE("E","C0XFDA","C0XIEN","C0XERR")
- S:$D(C0XERR) $EC=",U1,"
- ;
- ; Next Step: Kill off old doses and add new ones.
- D EN2^PSSUTIL(C0XIEN(1))
- ;
- ; Mark uses for the Drug; use the undocumented Silent call in PSSGIU
- N PSIUDA,PSIUX ; Expected Input variables
- S PSIUDA=C0XIEN(1),PSIUX="O^Outpatient Pharmacy" D ENS^PSSGIU
- S PSIUDA=C0XIEN(1),PSIUX="U^Unit Dose" D ENS^PSSGIU
- S PSIUDA=C0XIEN(1),PSIUX="X^Non-VA Med" D ENS^PSSGIU
- ;
- ; Get VA Generic text and VA Product pointer for Orderable Item creation plus dosage form information
- N VAGENP S VAGENP=$P(^PSDRUG(C0XIEN(1),"ND"),U) ; VA Generic Pointer
- N VAGEN S VAGEN=$$VAGN^PSNAPIS(VAGENP) ; VA Generic Full name
- N VAPRODP S VAPRODP=$P(^PSDRUG(C0XIEN(1),"ND"),U,3) ; VA Product Pointer
- N DOSAGE S DOSAGE=$$PSJDF^PSNAPIS(0,VAPRODP) ; IEN of dose form in 50.606 ^ Text
- N DOSEPTR S DOSEPTR=$P(DOSAGE,U) ; ditto
- N DOSEFORM S DOSEFORM=$P(DOSAGE,U,2) ;ditto
- ;
- ; Get the (possibly new) Orderable Item Text
- N VAG40 S VAG40=$E(VAGEN,1,40) ; Max length of .01 field
- ;
- ; See if there is an existing orderable item already. If so, populate the Pharmacy Orderable item on drug file.
- N OI S OI=$O(^PS(50.7,"ADF",VAG40,DOSEPTR,""))
- ;
- ; Otherwise, add a new one. (See MCHAN+12^PSSPOIMN)
- I 'OI D
- . N C0XFDA,C0XERR
- . S C0XFDA(50.7,"+1,",.01)=VAG40
- . S C0XFDA(50.7,"+1,",.02)=DOSEPTR
- . D UPDATE^DIE("",$NA(C0XFDA),$NA(OI),$NA(C0XERR))
- . I $D(C0XERR) S $EC=",U1,"
- . S OI=OI(1) ; For ease of use...
- . ; Next two statements: See FIN^PSSPOIM1 and MF^PSSDEE.
- . D EN^PSSPOIDT(OI) ; Update Indexes; activations, etc.
- . D EN2^PSSHL1(OI,"MUP") ; Send HL7 message to CPRS
- ;
- ; Finally, add the orderable Item to the drug file.
- N C0XFDA,C0XERR S C0XFDA(50,C0XIEN(1)_",",2.1)=OI ; Orderable Item
- D FILE^DIE("",$NA(C0XFDA),$NA(C0XERR))
- S:$D(C0XERR) $EC=",U1,"
- ;
-EX QUIT C0XIEN(1)
+C0CRXNAD	; VEN/SMH - Add a drug to VISTA from RxNorm;2013-04-19  5:39 PM
+	;;2.2;RXNORM FOR VISTA;;Nov 14, 2013;Build 8
+	; (C) 2013 Sam Habiel
+	; Proprietary Code. Don't use if license terms aren't supplied.
+	;
+ADDDRUG(RXN,NDC,BARCODE)	; Public Proc; Add Drug to Drug File
+	; Input: RXN - RxNorm Semantic Clinical Drug CUI by Value. Required.
+	; Input: NDC - Drug NDC by Value. Optional. Pass in 11 digit format without dashes.
+	; Input: BARCODE - Wand Barcode. Optional. Pass exactly as wand reads minus control characters.
+	; Output: Internal Entry Number
+	;
+	; Prelim Checks
+	I '$G(RXN) S $EC=",U1," ; Required
+	I $L($G(NDC)),$L(NDC)'=11 S $EC=",U1,"
+	;
+	N PSSZ S PSSZ=1    ; Needed for the drug file to let me in!
+	;
+	; If RXN refers to a brand drug, get the generic instead.
+	I $$ISBRAND^C0CRXNLK(RXN) S RXN=$$BR2GEN^C0CRXNLK(RXN)
+	W !,"(debug) RxNorm is "_RXN,!
+	;
+	; Get first VUID for this RxNorm drug
+	N VUID S VUID=+$$RXN2VUI^C0CRXNLK(RXN)
+	Q:'VUID
+	W "(debug) VUID for RxNorm CUI "_RXN_" is "_VUID,!
+	;
+	; IEN in 50.68
+	N C0XVUID ; For Searching Compound Index
+	S C0XVUID(1)=VUID
+	S C0XVUID(2)=1
+	N F5068IEN S F5068IEN=$$FIND1^DIC(50.68,"","XQ",.C0XVUID,"AMASTERVUID")
+	Q:'F5068IEN
+	W "F 50.68 IEN (debug): "_F5068IEN,!
+	;
+	; FDA Array
+	N C0XFDA
+	;
+	; Name, shortened
+	S C0XFDA(50,"+1,",.01)=$E($$GET1^DIQ(50.68,F5068IEN,.01),1,40)
+	;
+	; File BarCode as a Synonym for BCMA
+	I $L($G(BARCODE)) D
+	. S C0XFDA(50.1,"+2,+1,",.01)=BARCODE
+	. S C0XFDA(50.1,"+2,+1,",1)="Q"
+	;
+	; Brand Names
+	N BNS S BNS=$$RXN2BNS^C0CRXNLK(RXN) ; Brands
+	I $L(BNS) N I F I=1:1:$L(BNS,U) D
+	. N IENS S IENS=I+2
+	. S C0XFDA(50.1,"+"_IENS_",+1,",.01)=$$UP^XLFSTR($E($P(BNS,U,I),1,40))
+	. S C0XFDA(50.1,"+"_IENS_",+1,",1)="T"
+	;
+	; NDC (string)
+	I $G(NDC) S C0XFDA(50,"+1,",31)=$E(NDC,1,5)_"-"_$E(NDC,6,9)_"-"_$E(NDC,10,11)
+	;
+	; Dispense Unit (string)
+	S C0XFDA(50,"+1,",14.5)=$$GET1^DIQ(50.68,F5068IEN,"VA DISPENSE UNIT")
+	;
+	; National Drug File Entry (pointer to 50.6)
+	S C0XFDA(50,"+1,",20)="`"_$$GET1^DIQ(50.68,F5068IEN,"VA GENERIC NAME","I")
+	;
+	; VA Product Name (string)
+	S C0XFDA(50,"+1,",21)=$E($$GET1^DIQ(50.68,F5068IEN,.01),1,70)
+	;
+	; PSNDF VA PRODUCT NAME ENTRY (pointer to 50.68)
+	S C0XFDA(50,"+1,",22)="`"_F5068IEN
+	;
+	; DEA, SPECIAL HDLG (string)
+	D  ; From ^PSNMRG
+	. N CS S CS=$$GET1^DIQ(50.68,F5068IEN,"CS FEDERAL SCHEDULE","I")
+	. S CS=$S(CS?1(1"2n",1"3n"):+CS_"C",+CS=2!(+CS=3)&(CS'["C"):+CS_"A",1:CS)
+	. S C0XFDA(50,"+1,",3)=CS
+	;
+	; NATIONAL DRUG CLASS (pointer to 50.605) (triggers VA Classification field)
+	S C0XFDA(50,"+1,",25)="`"_$$GET1^DIQ(50.68,F5068IEN,"PRIMARY VA DRUG CLASS","I")
+	;
+	; Right Now, I don't file the following which ^PSNMRG does (cuz I don't need them)
+	; - Package Size (derived from NDC/UPN file)
+	; - Package Type (ditto)
+	; - CMOP ID (from $$PROD2^PSNAPIS)
+	; - National Formulary Indicator (from 50.68)
+	;
+	; Next Step is to kill Old OI if Dosage Form doesn't match
+	; Won't do that here as it's assumed any drugs that's added is new.
+	; This happens at ^PSNPSS
+	;
+	; Now add drug to drug file, as we need the IEN for the dosages call.
+	N C0XERR,C0XIEN
+	D UPDATE^DIE("E","C0XFDA","C0XIEN","C0XERR")
+	S:$D(C0XERR) $EC=",U1,"
+	;
+	; Next Step: Kill off old doses and add new ones.
+	D EN2^PSSUTIL(C0XIEN(1))
+	;
+	; Mark uses for the Drug; use the undocumented Silent call in PSSGIU
+	N PSIUDA,PSIUX ; Expected Input variables
+	S PSIUDA=C0XIEN(1),PSIUX="O^Outpatient Pharmacy" D ENS^PSSGIU
+	S PSIUDA=C0XIEN(1),PSIUX="U^Unit Dose" D ENS^PSSGIU
+	S PSIUDA=C0XIEN(1),PSIUX="X^Non-VA Med" D ENS^PSSGIU
+	;
+	; Get VA Generic text and VA Product pointer for Orderable Item creation plus dosage form information
+	N VAGENP S VAGENP=$P(^PSDRUG(C0XIEN(1),"ND"),U) ; VA Generic Pointer
+	N VAGEN S VAGEN=$$VAGN^PSNAPIS(VAGENP) ; VA Generic Full name
+	N VAPRODP S VAPRODP=$P(^PSDRUG(C0XIEN(1),"ND"),U,3) ; VA Product Pointer
+	N DOSAGE S DOSAGE=$$PSJDF^PSNAPIS(0,VAPRODP) ; IEN of dose form in 50.606 ^ Text
+	N DOSEPTR S DOSEPTR=$P(DOSAGE,U) ; ditto
+	N DOSEFORM S DOSEFORM=$P(DOSAGE,U,2) ;ditto
+	;
+	; Get the (possibly new) Orderable Item Text
+	N VAG40 S VAG40=$E(VAGEN,1,40) ; Max length of .01 field
+	;
+	; See if there is an existing orderable item already. If so, populate the Pharmacy Orderable item on drug file.
+	N OI S OI=$O(^PS(50.7,"ADF",VAG40,DOSEPTR,""))
+	;
+	; Otherwise, add a new one. (See MCHAN+12^PSSPOIMN)
+	I 'OI D
+	. N C0XFDA,C0XERR
+	. S C0XFDA(50.7,"+1,",.01)=VAG40
+	. S C0XFDA(50.7,"+1,",.02)=DOSEPTR
+	. D UPDATE^DIE("",$NA(C0XFDA),$NA(OI),$NA(C0XERR))
+	. I $D(C0XERR) S $EC=",U1,"
+	. S OI=OI(1) ; For ease of use...
+	. ; Next two statements: See FIN^PSSPOIM1 and MF^PSSDEE.
+	. D EN^PSSPOIDT(OI) ; Update Indexes; activations, etc.
+	. D EN2^PSSHL1(OI,"MUP") ; Send HL7 message to CPRS
+	;
+	; Finally, add the orderable Item to the drug file.
+	N C0XFDA,C0XERR S C0XFDA(50,C0XIEN(1)_",",2.1)=OI ; Orderable Item
+	D FILE^DIE("",$NA(C0XFDA),$NA(C0XERR))
+	S:$D(C0XERR) $EC=",U1,"
+	;
+EX	QUIT C0XIEN(1)
Index: /ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m
===================================================================
--- /ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m	(revision 1629)
+++ /ccr/trunk/rxnorm/trunk/routines/C0CRXNLK.m	(revision 1630)
@@ -1,4 +1,4 @@
-C0CRXNLK	; VEN/SMH - RxNorm Lookup Utilities ;2013-04-10  7:01 PM
-	;;1.0;RX NORM;;Apr 25, 2012;Build 99
+C0CRXNLK	; VEN/SMH - RxNorm Lookup Utilities ;2013-11-14  2:43 PM
+	;;2.2;RXNORM FOR VISTA;;Nov 14, 2013;Build 8
 	;(c) Sam Habiel 2013
 	; See accompanying license. Don't use otherwise.
@@ -10,5 +10,5 @@
 	QUIT
 	;
-EXIST(RXN) ; $$ Public - Does this RxNorm CUI exist?
+EXIST(RXN)	; $$ Public - Does this RxNorm CUI exist?
 	; Input: RxNorm CUI by value
 	; Output: Extrinsic
@@ -22,5 +22,6 @@
 	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)
@@ -29,5 +30,5 @@
 	QUIT
 	;
-GCN2RXND ; @DATA - Data for Tests ;;GCN;EXPECTED RXNCUI
+GCN2RXND	; @DATA - Data for Tests ;;GCN;EXPECTED RXNCUI
 	;;16033;991632
 	;;8208;310429
@@ -35,4 +36,32 @@
 	;;18;197604
 	;;346;884173
+	;;<<END>>
+	;
+	;
+	;
+RXN2GCN(RXNCUI)	; $$ Public - Get GCN(s) given an RxNorm Number
+	; Input: RXNCUI by Value
+	; Output: Caret delimited Extrinsic
+	N GCNS S GCNS=""
+	N I S I=""
+	F  S I=$O(^C0CRXN(176.001,"STX","NDDF","CDC",RXNCUI,I)) Q:I=""  S GCNS=GCNS_+^(I)_U ; + b/c we want the GCN w/o leading zeros
+	S GCNS=$E(GCNS,1,$L(GCNS)-1) ; remove trailing ^
+	Q GCNS
+	;
+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")
+	QUIT
+	;
+	;
+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
+	;;197320;2536;Allopurinol 300mg tab
+	;;993691;3948^46236;Bupropion 75mg tab
+	;;197591;3768;Diazepam 5mg tab
 	;;<<END>>
 	;
@@ -50,5 +79,5 @@
 	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)
@@ -57,5 +86,5 @@
 	QUIT
 	;
-RXN2VUID ; @DATA - Data items for previous test
+RXN2VUID	; @DATA - Data items for previous test
 	;;991632;4006455
 	;;310429;4002369^4013941
@@ -76,5 +105,5 @@
 	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)
@@ -83,5 +112,5 @@
 	QUIT
 	;
-VUI2VAPD ; @DATA - Data for above test
+VUI2VAPD	; @DATA - Data for above test
 	;;4006455;5932
 	;;4002369;1784
@@ -112,5 +141,5 @@
 	;
 	;
-RXN2MEDS(RXNCUI) ; $$ Public - Convert RxNorm value to currently existing drugs in File 50.
+RXN2MEDS(RXNCUI)	; $$ Public - Convert RxNorm value to currently existing drugs in File 50.
 	; Input: SCD RXNCUI
 	; Output; Caret delimited extrinsic
@@ -123,5 +152,5 @@
 	. N VUID S VUID=$P(VUIDS,U,I)
 	. N VAPRODS S VAPRODS=$$VUI2VAP(VUID) ; Get VA Product from VUID (multiple products per VUID)
-	. I '$L(VAPRODS) S ^SAM(RXNCUI)="TELL SAM",DONE=1 QUIT  ; MUST EXIST. Every VUID must have a product to go with it.
+	. I '$L(VAPRODS) S $ECODE=",U-NO-VA-PRODUCT-CORRUPT-NDF,"  ; MUST EXIST. Every VUID must have a product to go with it.
 	. N J F J=1:1:$L(VAPRODS,U) D  Q:DONE
 	. . N VAPROD S VAPROD=$P(VAPRODS,U,J)
@@ -138,4 +167,5 @@
 	;
 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")
 	QUIT
@@ -162,5 +192,5 @@
 	Q C0PIEN_"^"_C0P01
 	;
-VIN2VAGT ; @TEST - Test Get VA Generic for VUID Ingredient
+VIN2VAGT	; @TEST - Test Get VA Generic for VUID Ingredient
 	D CHKEQ^XTMUNIT(+$$VIN2VAG(4023636),2832,"$$VIN2VAG failed")
 	QUIT
@@ -202,5 +232,15 @@
 	QUIT RXNS
 	;
-MED2RXN(DA) ; $$ Public - Get RxNorm CUI for Drug
+VUI2GCN(VUID)	; $$ Public - Get GCNs for a given VUID (any VUID type)
+	; Input: VUID by Value
+	; Output: GCNs delimited by ^
+	; TODO: Unit Test
+	N RXNS S RXNS=$$VUI2RXN(VUID)
+	N GCNS S GCNS=""
+	N I F I=1:1:$L(RXNS,U) S GCNS=GCNS_$$RXN2GCN($P(RXNS,U,I))_U
+	S GCNS=$E(GCNS,1,$L(GCNS)-1)
+	QUIT GCNS
+	;
+MED2RXN(DA)	; $$ Public - Get RxNorm CUI for Drug
 	; Input: DA - Medication IEN
 	; Output: RXNCUIs delimited by ^
@@ -212,5 +252,5 @@
 	Q $$VUI2RXN(VUID)
 	;
-MED2SCDN(DA) ; $$ Public - Medication to Semantic Clinical Drug Name
+MED2SCDN(DA)	; $$ Public - Medication to Semantic Clinical Drug Name
 	; Input: DA - Medication IEN
 	; Output: The Canonical Semantic Clinical Drug name
@@ -239,5 +279,5 @@
 	; ---
 	;
-NDC2RXN(NDC) ; $$ Public - Get RxCUI given the NDC
+NDC2RXN(NDC)	; $$ Public - Get RxCUI given the NDC
 	; NB: Will only work if passed NDC is in 5-4-2 format.
 	; Input: NDC By Value in 5-4-2 Format
@@ -246,5 +286,5 @@
 	N IEN S IEN=$O(^C0CRXN(176.002,"ASAA","RXNORM","NDC",NDC,"")) Q ^(IEN)
 	;
-NDC2RXNT ; @TEST - Test Get RxCUI given the NDC
+NDC2RXNT	; @TEST - Test Get RxCUI given the NDC
 	D CHKEQ^XTMUNIT($$NDC2RXN("30142-0917-71"),198439,"$$NDC2RXN failed")
 	QUIT
@@ -252,9 +292,9 @@
 	; ---
 	;
-ISBRAND(RXN) ; $$ Public - Is this RxCUI for a brand drug?
+ISBRAND(RXN)	; $$ Public - Is this RxCUI for a brand drug?
 	; Input: RxCUI
 	; Output: 0 or 1
 	Q ''$D(^C0CRXN(176.001,"STC","RXNORM","SBD",RXN))
-ISBRANDT ; @TEST - Test Is this RxCUI for a brand drug?
+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
@@ -263,9 +303,9 @@
 	; ---
 	;
-BR2GEN(RXN) ; $$ Public - Convert Brand RxCUI to Generic RxCUI (many to 1)
+BR2GEN(RXN)	; $$ Public - Convert Brand RxCUI to Generic RxCUI (many to 1)
 	; Input: RxCUI of Brand
 	; 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)
+BR2GENT	; @TEST - Test Convert Brand RxCUI to Generic RxCUI (many to 1)
 	D CHKEQ^XTMUNIT($$BR2GEN(205535),310384,"$$BR2GEN failed")
 	QUIT
@@ -273,5 +313,5 @@
 	; ---
 	;
-GEN2BR(RXN) ; $$ Public - Convert Generic RxCUI to Brand RxCUIs (1 to many).
+GEN2BR(RXN)	; $$ Public - Convert Generic RxCUI to Brand RxCUIs (1 to many).
 	N RTN S RTN="" ; Return
 	N I S I="" F  S I=$O(^C0CRXN(176.005,"B",RXN,"tradename_of",I)) Q:'I  S RTN=RTN_I_U
@@ -279,5 +319,5 @@
 	Q RTN
 	;
-GEN2BRT ; @TEST - Test Convert Generic RxCUI to Brand RxCUIs (1 to many).
+GEN2BRT	; @TEST - Test Convert Generic RxCUI to Brand RxCUIs (1 to many).
 	D CHKTF^XTMUNIT($$GEN2BR(310384)[205535,"$$GEN2BR failed")
 	QUIT
@@ -285,5 +325,5 @@
 	; ---
 	;
-RXN2BNS(RXN) ; $$ Public - Get all Brand Names associated with an RXN
+RXN2BNS(RXN)	; $$ Public - Get all Brand Names associated with an RXN
 	N BNS S BNS=""
 	I $$ISBRAND(RXN) S RXN=$$BR2GEN(RXN)
@@ -297,5 +337,16 @@
 	. 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
+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
+	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
Index: /ccr/trunk/rxnorm/trunk/routines/C0CRXNRD.m
===================================================================
--- /ccr/trunk/rxnorm/trunk/routines/C0CRXNRD.m	(revision 1629)
+++ /ccr/trunk/rxnorm/trunk/routines/C0CRXNRD.m	(revision 1630)
@@ -1,13 +1,17 @@
-C0CRXNRD	; VEN/SMH - RxNorm Utilities: Routine to Read RxNorm files;2013-03-06  4:32 PM
-	;;2.0;RX NORM;;May 11, 2012;Build 50
+C0CRXNRD	; VEN/SMH - RxNorm Utilities: Routine to Read RxNorm files;2013-11-14  1:23 PM
+	;;2.2;RXNORM FOR VISTA;;Nov 14, 2013;Build 8
 	; (C) Sam Habiel 2013
 	; See license for terms of use.
 	;
 	W "No entry from top" Q
-IMPORT(PATH) ; PUBLIC ENTRY POINT. Rest are private
+IMPORT(PATH,RESTRICTED)	; PUBLIC ENTRY POINT. Rest are private
 	I PATH="" QUIT
+	S RESTRICTED=$G(RESTRICTED,0)
 	S U="^"
 	N STARTTIME S STARTTIME=$P($H,",")*24*60*60+$P($H,",",2)
-	D SAB(PATH),CONSO(PATH),SAT(PATH),STY(PATH),REL(PATH),DOC(PATH)
+	N SABS
+	D SAB(PATH,.SABS) ; Load restriction values into SAB.     ; 176.006
+	D CONSO(PATH,.SABS,RESTRICTED),SAT(PATH,.SABS,RESTRICTED) ; 176.001,176.002
+	D STY(PATH),REL(PATH),DOC(PATH)                           ; 176.003-5
 	N ENDTIME S ENDTIME=$P($H,",")*24*60*60+$P($H,",",2)
 	W !,(ENDTIME-STARTTIME)/60_" minutes elapsed"
@@ -25,5 +29,7 @@
 	QUIT
 GETLINES(PATH,FILENAME)	; Get number of lines in a file
+	N POP
 	D OPEN^%ZISH("FILE",PATH,FILENAME,"R")
+	Q:POP
 	U IO
 	N I,LINE
@@ -31,9 +37,9 @@
 	D CLOSE^%ZISH("FILE")
 	Q I-1
-CONSO(PATH,INCRES)	; Open and read concepts file: RXNCONSO.RRF
+CONSO(PATH,SABS,RESTRICTED)	; Open and read concepts file: RXNCONSO.RRF
 	; PATH ByVal, path of RxNorm files
-	; INCRES ByVal, include restricted sources. 1 for yes, 0 for no
+	; SABS ByRef, arrays of SABS(SAB)=restriction level
+	; RESTRICTED ByVal, include restricted sources. 1 for yes, 0 for no
 	I PATH="" QUIT
-	S INCRES=+$G(INCRES) ; if not passed, becomes zero.
 	N FILENAME S FILENAME="RXNCONSO.RRF"
 	D DELFILED(176.001) ; delete data
@@ -48,12 +54,11 @@
 	. IF $$STATUS^%ZISH QUIT
 	. I '(C0CCOUNT#1000) U $P W C0CCOUNT," of ",LINES," read ",! U IO ; update every 1000
+	. ;
+	. ; Deal with restriction level
+	. N SAB S SAB=$P(LINE,"|",12)
+	. I 'RESTRICTED,SABS(SAB) QUIT  ; If not include restricted, and SABS(SAB) is not zero, quit
+	. ;
+	. ; Save data
 	. S ^C0CRXN(176.001,C0CCOUNT,0)=$TR(LINE,"|^","^|")
-	. ; TODO Implement Filtering:
-	. ; If the source is a restricted source, decide what to do based on what's asked.
-	. ; N SRCIEN S SRCIEN=$$FIND1^DIC(176.003,"","QX",SAB,"B") ; SrcIEN in RXNORM SOURCES file
-	. ; N RESTRIC S RESTRIC=$$GET1^DIQ(176.003,SRCIEN,14,"I") ; 14 is restriction field; values 0-4
-	. ; If RESTRIC is zero, then it's unrestricted. Everything else is restricted.
-	. ; If user didn't ask to include restricted sources, and the source is restricted, then quit
-	. ; I 'INCRES,RESTRIC QUIT
 EX	D CLOSE^%ZISH("FILE")
 	N DIK S DIK="^C0CRXN(176.001," D IXALL^DIK
@@ -61,5 +66,8 @@
 	;
 	;
-SAT(PATH)	; Open and read Concept and Atom attributes: RXNSAT.RRF
+SAT(PATH,SABS,RESTRICTED)	; Open and read Concept and Atom attributes: RXNSAT.RRF
+	; PATH ByVal, path of RxNorm files
+	; SABS ByRef, arrays of SABS(SAB)=restriction level
+	; RESTRICTED ByVal, include restricted sources. 1 for yes, 0 for no
 	I PATH="" QUIT
 	N FILENAME S FILENAME="RXNSAT.RRF"
@@ -82,4 +90,8 @@
 	. S $P(LINE,"|",9)=RXCUI1
 	. ;
+	. ; Deal with restricted sources
+	. N SAB S SAB=$P(LINE,"|",10)
+	. I 'RESTRICTED,SABS(SAB) QUIT  ; If not include restricted, and SABS(SAB) is not zero, quit
+	. ;
 	. ; Save off
 	. S ^C0CRXN(176.002,C0CCOUNT,0)=$TR(LINE,"|^","^|")
@@ -89,5 +101,5 @@
 	;
 	;
-SAB(PATH)	; Open the read RxNorm Sources file: RXNSAB.RRF
+SAB(PATH,SABS)	; Open the read RxNorm Sources file: RXNSAB.RRF
 	I PATH="" QUIT
 	N FILENAME S FILENAME="RXNSAB.RRF"
@@ -109,4 +121,6 @@
 EX3	D CLOSE^%ZISH("FILE")
 	N DIK S DIK="^C0CRXN(176.003," D IXALL^DIK
+	N C0CI F C0CI=0:0 S C0CI=$O(^C0CRXN(176.003,C0CI)) Q:'C0CI  D
+	. S SABS($$GET1^DIQ(176.003,C0CI,.01))=$$GET1^DIQ(176.003,C0CI,"SRL")
 	QUIT
 STY(PATH)	; Open and read RxNorm Semantic types file: RXNSTY.RRF
