*! version 1.1 13jan2015 /* mycd10 is an update of the Stata icd9 command Author: Joseph Canner Johns Hopkins University School of Medicine Department of Surgery Center for Surgical Trials and Outcomes Research jcanner1@jhmi.edu Version 1.0.0 May 19, 2014 * Original version Version 1.1 January 13, 2015 * Allows use of myicd10 and myicd10p as aliases * Removed some debugging steps * Add desciptions of chapters and block groups to generate and loookup subcommands (which requires extra prepares as well) * Reorganized help file */ program define mycd10 version 9 gettoken cmd 0 : 0, parse(" ,") local l = length("`cmd'") if "`cmd'"=="check" { Check `0' } else if "`cmd'"=="clean" { Clean `0' } else if "`cmd'" == substr("generate",1,max(3,`l')) { Gen `0' } else if "`cmd'" == substr("lookup",1,max(1,`l')) { gettoken subcmd 0 : 0 local ll = length("`subcmd'") if "`subcmd'" == substr("codes",1,max(2,`ll')) { Lookup `0' } else if "`subcmd'" == substr("blocks",1,max(1,`ll')) { Lookup_blocks `0' } else if "`subcmd'" == substr("chapters",1,max(2,`ll')) { // Since chapters are just integers, use Stata numlist option syntax Lookup_chapters , chapters(`0') } else { Lookup `subcmd' } } else if "`cmd'" == substr("search",1,max(3,`l')) { Search `0' } else if "`cmd'" == substr("tabulate",1,max(3,`l')) { Tabulate `0' } else if `"`cmd'"' == "table" { Table `0' } else if `"`cmd'"' == substr("query",1,max(1,`l')) { Query `0' } else if `"`cmd'"' == substr("prepare",1,max(1,`l')) { gettoken subcmd 0 : 0 local ll = length("`subcmd'") if "`subcmd'" == "using" { Prepare using `0' } else if "`subcmd'" == substr("codes",1,max(2,`ll')) { Prepare `0' } else if "`subcmd'" == substr("blocks",1,max(1,`ll')) { Prepare_blocks `0' } else if "`subcmd'" == substr("chapters",1,max(2,`ll')) { Prepare_chapters `0' } } else di in red "invalid mycd10 subcommand" end * --- * mycd10 prepare program define Prepare syntax using preserve qui insheet `using', delimiter(";") clear // In order to maintain compatibility back to Stata 9 can't use group rename //rename (v1-v14) (Level NodeType Terminal Chapter Block CodeNoDagger CodeNoAsterisk CodeNoDot Title SpecialMortality1 SpecialMortality2 SpecialMortality3 SpecialMortality4 SpecialMorbidity) local v=1 foreach var of newlist Level NodeType Terminal Chapter Block CodeNoDagger CodeNoAsterisk CodeNoDot Title SpecialMortality1 SpecialMortality2 SpecialMortality3 SpecialMortality4 SpecialMorbidity { rename v`v' `var' local ++v } label var Level "Level in the hierarchy of the classification" label var NodeType "Place in the classification tree" label var Terminal "Type of terminal node" label var Chapter "Chapter number" label var Block "First three character code of a block" label var CodeNoDagger "Code without possible dagger" label var CodeNoAsterisk "Code without possible asterisk" label var CodeNoDot "Code without dot" label var Title "Title" label var SpecialMortality1 "Reference to special tabulation list for mortality 1" label var SpecialMortality2 "Reference to special tabulation list for mortality 2" label var SpecialMortality3 "Reference to special tabulation list for mortality 3" label var SpecialMortality4 "Reference to special tabulation list for mortality 4" label var SpecialMorbidity "Reference to special tabulation list for morbidity" local adodir : sysdir PLUS local rawfile="`adodir'"+"m/mycd10_raw" save "`rawfile'", replace qui replace Title=Title+"*" if Level==3 keep Chapter Block CodeNoDot Title rename CodeNoDot __code10 rename Title __desc10 rename Chapter __chapter10 rename Block __block10 sort __code10 note: The mycd10 prepare command was based on data from ICD-10 2nd edition, downloaded from WHO in May, 2014. note: If you have problems with mycd10 attributable to changes in the file format from WHO, please contact the author of mycd10. local codfile="`adodir'"+"m/mycd10_cod" save "`codfile'", replace restore end * mycd10 prepare blocks * New with mycd10 (not in icd9): Define block groups program define Prepare_blocks syntax using preserve qui insheet `using', delimiter(";") clear // Find correct variable names local v=1 foreach var of newlist Block_Start Block_End Chapter Title { rename v`v' `var' local ++v } label var Block_Start "Starting block of block group" label var Block_End "Ending block of block group" label var Chapter "Chapter number" label var Title "Title" local adodir : sysdir PLUS local rawfile="`adodir'"+"m/mycd10_blocks_raw" save "`rawfile'", replace keep Block_Start Block_End Title rename Block_Start __block10 rename Block_End __lastblock10 rename Title __blockdesc10 sort __block10 note: The mycd10 prepare command was based on data from ICD-10 2nd edition, downloaded from WHO in May, 2014. note: If you have problems with mycd10 attributable to changes in the file format from WHO, please contact the author of mycd10. local codfile="`adodir'"+"m/mycd10_blk" save "`codfile'", replace restore end * mycd10 prepare chapters * New with mycd10 (not in icd9): Define chapter headings program define Prepare_chapters syntax using preserve qui insheet `using', delimiter(";") clear local v=1 foreach var of newlist Chapter Title { rename v`v' `var' local ++v } label var Chapter "Chapter number" label var Title "Title" local adodir : sysdir PLUS local rawfile="`adodir'"+"m/mycd10_chapters_raw" save "`rawfile'", replace rename Chapter __chapter10 rename Title __chapterdesc10 sort __chapter10 note: The mycd10 prepare command was based on data from ICD-10 2nd edition, downloaded from WHO in May, 2014. note: If you have problems with mycd10 attributable to changes in the file format from WHO, please contact the author of mycd10. local codfile="`adodir'"+"m/mycd10_chp" save "`codfile'", replace restore end * --- * mycd9 check program define Check, rclass syntax varname [, ANY List SYStem(string) Generate(string) ] local typ : type `varlist' if substr("`typ'",1,3)!="str" { di in red "`varlist' does not contain ICD-10 codes; " /* */ "ICD-10 codes must be stored as a string" exit 459 } if "`generate'"!="" { confirm new var `generate' } if "`system'"=="" { tempvar c } else local c "`system'" quietly { local typ : type `varlist' quietly gen `typ' `c' = upper(trim(`varlist')) compress `c' tempvar prob l /* 0. code may contain "", missing */ gen byte `prob' = cond(`c'=="", 0, .) /* 1. invalid placement of period */ /* 2. too many periods */ capture assert index(`c', ".") == 0 if _rc { gen byte `l' = index(`c', ".") replace `c' = (trim( /* */ substr(`c',1,`l'-1) + substr(`c',`l'+1,.) /* */ )) if `l' compress `c' replace `prob' = 1 if `l'>0 & `l' < 4 replace `prob' = 2 if index(`c', ".") drop `l' } /* 3. code too short */ /* 4. code too long */ gen byte `l' = length(`c') replace `prob'=3 if `l'<3 & `prob'==. replace `prob'=4 if `l'>5 & `prob'==. drop `l' /* 5. 1st char must be A-Z */ gen str1 `l' = substr(`c',1,1) replace `prob'=5 if (`l'<"A" | `l'>"Z") & `prob'==. /* 6. 2nd char must be 0-9 */ replace `l' = substr(`c',2,1) replace `prob' = 6 if (`l'<"0" | `l'>"9") & `prob'==. /* 7. 3rd char must be 0-9 */ replace `l' = substr(`c',3,1) replace `prob' = 7 if (`l'<"0" | `l'>"9") & `prob'==. /* 8. 4th char must be 0-9 or "" */ replace `l' = substr(`c',4,1) replace `prob' = 8 if (`l'<"0" | `l'>"9") & `l'!="" & `prob'==. /* 9. 5th char must be 0-9 or "" */ /* replace `l' = substr(`c',5,1) replace `prob' = 9 if (`l'<"0" | `l'>"9") & `l'!="" & `prob'==. drop `l' */ /* 3. code too short */ /* (if 1st char E, length is 4-5) */ /* gen byte `l' = length(`c') replace `prob' = 3 if substr(`c',1,1)=="E" & `l'<4 & `prob'==. */ /* clean up prob */ replace `prob' = 0 if `prob'==. } /* Early exit if system() option */ if "`system'"!="" { capture assert `prob'==0 if _rc==0 { exit } drop `c' di in red "`varlist' contains invalid ICD-10 codes" exit 459 } /* 9. invalid code */ qui count if `c'=="" local miss = r(N) preserve if `miss' != _N & "`any'"=="" { quietly { keep `varlist' `prob' `c' Merge `c' replace `prob' = 9 if _merge!=3 & `prob'==0 & `c'!="" } } qui count if `prob' local bad = r(N) return scalar esum = r(N) if `bad'==0 { if `miss'==_N { di in gr "(`varlist' contains all missing values)" } else if `miss'==0 { di in gr "(`varlist' contains valid ICD-10 codes; " /* */ "no missing values)" } else { local s = cond(`miss'==1, "", "s") di in gr "(`varlist' contains valid ICD-10 codes; " /* */ "`miss' missing value`s')" } ret scalar e1 = 0 ret scalar e2 = 0 ret scalar e3 = 0 ret scalar e4 = 0 ret scalar e5 = 0 ret scalar e6 = 0 ret scalar e7 = 0 ret scalar e8 = 0 //ret scalar e9 = 0 ret scalar e9 = . /* sic */ } else { di /* not in red, no extra line if output suppressed */ di in red "`varlist' contains invalid codes:" di /* not in red, no extra line if output suppressed */ qui count if `prob'==1 di in gr " 1. Invalid placement of period" /* */ _col(49) in ye %11.0gc r(N) ret scalar e1 = r(N) qui count if `prob'==2 di in gr " 2. Too many periods" /* */ _col(49) in ye %11.0gc r(N) ret scalar e2 = r(N) qui count if `prob'==3 di in gr " 3. Code too short" /* */ _col(49) in ye %11.0gc r(N) ret scalar e3 = r(N) qui count if `prob'==4 di in gr " 4. Code too long" /* */ _col(49) in ye %11.0gc r(N) ret scalar e4 = r(N) qui count if `prob'==5 di in gr " 5. Invalid 1st char (not A-Z)" /* */ _col(49) in ye %11.0gc r(N) ret scalar e5 = r(N) qui count if `prob'==6 di in gr " 6. Invalid 2nd char (not 0-9)" /* */ _col(49) in ye %11.0gc r(N) ret scalar e6 = r(N) qui count if `prob'==7 di in gr " 7. Invalid 3rd char (not 0-9)" /* */ _col(49) in ye %11.0gc r(N) ret scalar e7 = r(N) qui count if `prob'==8 di in gr " 8. Invalid 4th char (not 0-9)" /* */ _col(49) in ye %11.0gc r(N) ret scalar e8 = r(N) /* qui count if `prob'==9 di in gr " 9. Invalid 5th char (not 0-9)" /* */ _col(49) in ye %11.0gc r(N) ret scalar e9 = r(N) */ if "`any'"=="" { qui count if `prob'==9 di in gr " 9. Code not defined" /* */ _col(49) in ye %11.0gc r(N) ret scalar e9 = r(N) } else ret scalar e9 = . di in smcl in gr _col(49) "{hline 11}" di in gr _col(9) "Total" /* */ _col(49) in ye %11.0gc `bad' local s = cond(`bad'>1, "s", "") if "`list'" != "" { quietly { gen str27 __prob = "" replace __prob = /* */ "Invalid placement of period" /* */ if `prob'==1 replace __prob = "Too many periods" /* */ if `prob'==2 replace __prob = "Code too short" /* */ if `prob'==3 replace __prob = "Code too long" /* */ if `prob'==4 replace __prob = "Invalid 1st char" /* */ if `prob'==5 replace __prob = "Invalid 2nd char" /* */ if `prob'==6 replace __prob = "Invalid 3rd char" /* */ if `prob'==7 replace __prob = "Invalid 4th char" /* */ if `prob'==8 //replace __prob = "Invalid 5th char" if `prob'==9 replace __prob = "Code not defined" /* */ if `prob'==9 } di _n in gr "Listing of invalid codes" format __prob %-27s list `varlist' __prob if `prob'!=0 & `prob'!=. } } if "`generate'" != "" { quietly { keep `prob' rename `prob' `generate' tempfile one save `"`one'"' restore, preserve tempvar x merge using `"`one'"', _merge(`x') nonotes assert `x'==3 restore, not } } end program define Merge args c tempvar n quietly { gen long `n' = _n rename `c' __code10 } FindFile local fn `"`r(fn)'"' quietly { sort __code10 merge __code10 using `"`fn'"', nokeep keep(__code10) nonotes sort `n' rename __code10 `c' } end * --- * mycd10 clean program define Clean syntax varname [, Dots Pad] tempvar c l Check `varlist', system(`c') quietly { if "`dots'" != "" { replace `c' = substr(`c',1,3) + "." + substr(`c',4,.) if `c'!="" gen byte `l' = length(`c') replace `c' = substr(`c',1,`l'-1) if substr(`c',`l',1)=="." drop `l' local len 6 } else local len 5 if "`pad'"!="" { replace `c' = " " + `c' replace `c' = substr(`c' + " ",1,`len') replace `c' = trim(`c') if trim(`c')=="" } gen byte `l' = length(`c') summ `l', meanonly local len = max(7,cond(length("`varlist'")>r(max), length("`varlist'"), r(max)) + 1) count if `varlist' != `c' local ch = r(N) local s = cond(`ch'==1, "", "s") replace `varlist' = `c' compress `varlist' format `varlist' %-`len's } di in gr "(`ch' change`s' made)" end * --- * mycd10 generate * New with mycd10 (not in icd9): added support for chapters and blocks program define Gen gettoken newvar 0 : 0, parse(" =") gettoken eqsign 0 : 0, parse(" =") if `"`eqsign'"' != "=" { error 198 } syntax varname [, Main Description Chapter Block Range(string) Long End ] confirm new var `newvar' local nopt = ("`main'"!="") + ("`description'"!="") + (`"`range'"'!="") + (`"`chapter'"'!="") + (`"`block'"'!="") if `nopt'!=1 { di in red /* */ "must specify one of options -main-, -description-, -chapter-, -block-, or -range()-" exit 198 } if "`description'" == "" & "`chapter'" == "" & "`block'" == "" { if "`long'"!="" { di in red "option -long- not allowed" exit 198 } if "`end'"!="" { di in red "option -end- not allowed" exit 198 } } tempvar new c Check `varlist', system(`c') if "`main'"!="" { GenMain `new' `c' `varlist' } else if "`description'" != "" { GenDesc `new' `c' `varlist' "`long'" "`end'" } else if "`chapter'" != "" { GenChap `new' `c' `varlist' "`long'" "`end'" } else if "`block'" != "" { GenBlock `new' `c' `varlist' "`long'" "`end'" } else GenRange `new' `c' `varlist' `"`range'"' rename `new' `newvar' end program define GenMain args new c userv quietly { gen str3 `new' = substr(`c',1,3) if `c'!="" compress `new' label var `new' "main ICD10 from `userv'" } end program define GenDesc args new c userv long end if "`end'" != "" { local long "long" } FindFile local fn `"`r(fn)'"' tempname merge quietly { sort `c' rename `c' __code10 merge __code10 using `"`fn'"', nokeep _merge(`merge') nonotes rename __code10 `c' rename __desc10 `new' label var `new' "label for `userv'" count if `merge'!=3 & `c'!="" local unlab = r(N) drop `merge' __chapter10 __block10 if "`long'" != "" { mycd10 clean `c', dots replace `c' = " " + `c' replace `c' = substr(`c'+" ",1,7) if "`end'"=="" { replace `new' = `c' + " " + `new' } else { replace `new'= `new'+" "+`c' local f : format `new' if substr(`"`f'"',2,1)=="-" { local f = "%" + substr(`"`f'"',3,.) format `new' `f' } } replace `new' = "" if trim(`new')=="" } } if `unlab' { local s = cond(`unlab'==1, "", "s") di in gr "(`unlab' nonmissing values invalid and so could not be labeled)" } end program define GenChap version 10 args new c userv long end FindFile local fn `"`r(fn)'"' FindChapterFile local chpfn `"`r(fn)'"' tempname merge quietly { sort `c' rename `c' __code10 // First merge with code database to get chapter number merge m:1 __code10 using `"`fn'"', gen(`merge') nonotes drop if `merge'==2 drop `merge' drop __desc10 __block10 rename __code10 `c' // Then merge with chapter database to get chapter title merge m:1 __chapter10 using `"`chpfn'"', gen(`merge') nonotes drop if `merge'==2 if "`long'" != "" { if "`end'"=="" { replace __chapterdesc10=string(__chapter10)+") "+__chapterdesc10 if !mi(__chapter10) } else { replace __chapterdesc10=__chapterdesc10+" ("+string(__chapter10)+")" if !mi(__chapter10) } } drop __chapter10 rename __chapterdesc10 `new' label var `new' "Chapter for `userv'" count if `merge'!=3 & `c'!="" local unlab = r(N) drop `merge' } if `unlab' { local s = cond(`unlab'==1, "", "s") di in gr "(`unlab' nonmissing values invalid and so could not be labeled)" } end program define GenBlock version 10 args new c userv long end FindFile local fn `"`r(fn)'"' FindBlockFile local blkfn `"`r(fn)'"' tempname merge quietly { sort `c' rename `c' __code10 // First merge with code database to get code group merge m:1 __code10 using `"`fn'"', gen(`merge') nonotes drop if `merge'==2 drop `merge' drop __desc10 __chapter10 rename __code10 `c' // Then merge with block database to get block group title merge m:1 __block10 using `"`blkfn'"', gen(`merge') nonotes drop if `merge'==2 if "`long'" != "" { if "`end'"=="" { replace __blockdesc10=__block10+"-"+__lastblock10+") "+__blockdesc10 if !mi(__block10) } else { replace __blockdesc10=__blockdesc10+" ("+__block10+"-"+__lastblock10+")" if !mi(__block10) } } drop __block10 __lastblock10 rename __blockdesc10 `new' label var `new' "Block group for `userv'" count if `merge'!=3 & `c'!="" local unlab = r(N) drop `merge' } if `unlab' { local s = cond(`unlab'==1, "", "s") di in gr "(`unlab'" /* */ " nonmissing values invalid and so could not be labeled)" } end program define GenRange args new c userv range P_ilist `"`range'"' "," local list `"`s(list)'"' local rest = trim(`"`s(rest)'"') if `"`rest'"' != "" { error 198 } X_ilist `new' `c' `"`list'"' end * --- * mycd10 lookup program define Lookup P_ilist `"`0'"' "," local list `"`s(list)'"' local rest = trim(`"`s(rest)'"') if `"`rest'"' != "" { error 198 } FindFile local fn `"`r(fn)'"' tempvar use preserve quietly { use `"`fn'"', clear X_ilist `use' __code10 `"`list'"' keep if `use' } if _N == 0 { di in gr "(no matches found)" exit } local es = cond(_N==1, "", "es") qui mycd10 clean __code10, dots di _n in gr _N " match`es' found:" local i 1 while `i' <= _N { di in ye _col(5) __code10[`i'] _col(14) in gr __desc10[`i'] local i = `i' + 1 } end * --- * New with mycd10 (not in icd9): mycd10 lookup chapters program define Lookup_chapters syntax , chapters(numlist) FindChapterFile local fn `"`r(fn)'"' tempvar use preserve quietly { use `"`fn'"', clear tempvar use gen byte `use' = 0 foreach i of numlist `chapters' { replace `use' = 1 if __chapter10 == `i' } keep if `use' } if _N == 0 { di in gr "(no matches found)" exit } local es = cond(_N==1, "", "es") di _n in gr _N " match`es' found:" local i 1 while `i' <= _N { di in ye _col(5) __chapter10[`i'] _col(14) in gr __chapterdesc10[`i'] local i = `i' + 1 } end * --- * New with mycd10 (not in icd9): mycd10 lookup blocks program define Lookup_blocks P_ilist `"`0'"' "," local list `"`s(list)'"' local rest = trim(`"`s(rest)'"') if `"`rest'"' != "" { error 198 } FindBlockFile local fn `"`r(fn)'"' tempvar use preserve quietly { use `"`fn'"', clear X_blist `use' __block10 __lastblock10 `"`list'"' keep if `use' } if _N == 0 { di in gr "(no matches found)" exit } local es = cond(_N==1, "", "es") //qui mycd10 clean __code10, dots di _n in gr _N " match`es' found:" local i 1 while `i' <= _N { di in ye _col(5) __block10[`i'] "-" __lastblock10[`i'] _col(17) in gr __blockdesc10[`i'] local i = `i' + 1 } end * --- * mycd10 search program define Search local i 1 gettoken s1 0 : 0, parse(" ,") while `"`s`i''"' != "" & `"`s`i''"' != "," { local i = `i' + 1 gettoken s`i' 0 : 0, parse(" ,") } local n = `i' - 1 if `n'==0 { error 198 } local 0 `", `0'"' syntax [, OR ] FindFile local fn `"`r(fn)'"' tempvar use preserve quietly { use `"`fn'"', clear gen byte `use' = 0 local i 1 while `i' <= `n' { replace `use' = `use' + 1 if index(lower(__desc), lower(`"`s`i''"')) local i = `i' + 1 } } if "`or'" == "" { qui replace `use' = 0 if `use' != `n' } qui keep if `use' if _N == 0 { di in gr "(no matches found)" exit } local es = cond(_N==1, "", "es") qui mycd10 clean __code10, dots di _n in gr _N " match`es' found:" local i 1 while `i' <= _N { di in ye _col(5) __code10[`i'] _col(14) in gr __desc10[`i'] local i = `i' + 1 } end * --- * mycd10 tabulate program define Tabulate syntax varlist(min=1 max=2) [fw aw iw] [if] [in] [, /* */ Generate(string) SUBPOP(string) * ] if `"`subpop'"' != "" { di in red "option subpop() not allowed with mycd10 tabulate" exit 198 } if `"`generate'"' != "" { di in red "option generate() not allowed with mycd10 tabulate" exit 198 } tokenize `varlist' tempvar c desc Check `1', system(`c') preserve quietly { if `"`if'"'!="" | "`in'"!="" { keep `if' `in' } if "`weight'" != "" { tempname wgtv gen double wgtv = `exp' compress wgtv local w "[`weight'=`wgtv']" } local lbl : var label `1' if `"`lbl'"' == "" { local lbl "`1'" } keep `2' `wgtv' `c' mycd10 gen `desc' = `c', desc long end label var `desc' `"`lbl'"' } tabulate `desc' `2' `w', `options' end * --- * mycd10 table program define Table syntax varlist(min=1 max=3) [fw pw aw iw] [if] [in] [, /* */ Contents(string) BY(varlist) * ] tokenize `varlist' tempvar c desc Check `1', system(`c') if "`contents'" != "" { ConList `contents' local list `s(list)' local contopt contents(`contents') } if "`by'"!="" { local byopt by(`byopt') } preserve quietly { if `"`if'"'!="" | "`in'"!="" { keep `if' `in' } if "`weight'" != "" { tempname wgtv gen double wgtv = `exp' compress wgtv local w "[`weight'=`wgtv']" } local lbl : var label `1' if `"`lbl'"' == "" { local lbl "`1'" } keep `2' `wgtv' `c' `list' `by' mycd10 gen `desc' = `c', desc long end label var `desc' `"`lbl'"' } table `desc' `2' `3' `w', `contopt' `byopt' `options' end program define ConList, sclass sret clear while "`1'" != "" { if "`1'" != "freq" { mac shift sret local list `list' `1' } mac shift } end * --- * utility to parse and execute an icd10 rangelist (ilist) program define P_ilist, sclass args str term sret clear gettoken tok : str, parse(" *-/`term'") while `"`tok'"'!="" & `"`tok'"' != `"`term'"' { gettoken tok str : str, parse(" *-/`term'") IsEl `"`tok'"' local tok `"`s(tok)'"' gettoken nxttok : str, parse(" *-/`term'") if `"`nxttok'"' == "*" { gettoken nxttok str : str, parse(" *-/`term'") local list `"`list' `tok'*"' } else if `"`nxttok'"'=="-" | `"`nxttok'"'=="/" { gettoken nxttok str : str, parse(" *-/`term'") gettoken nxttok str : str, parse(" *-/`term'") IsEl `"`nxttok'"' local list `"`list' `tok'-`s(tok)'"' } else local list `"`list' `tok'"' gettoken tok : str, parse(" *-/`term'") } sret local list `"`list'"' sret local rest `"`str'"' end program define IsEl, sclass args c local c = upper(trim(`"`c'"')) if `"`c'"' == "" { di in red " invalid ICD-10 code" exit 198 } if index(`"`c'"', ".") { local l = index(`"`c'"', ".") local c = (trim( /* */ substr(`"`c'"',1,`l'-1) + substr(`"`c'"',`l'+1,.) /* */ )) if `l'>0 & `l'<4 { Invalid `"`c'"' "invalid placement of period" } if index(`"`c'"', ".") { Invalid `"`c'"' "too many periods" } } if length(`"`c'"') < 1 { Invalid `"`c'"' "code too short" } if length(`"`c'"') > 4 { Invalid `"`c'"' "code too long" } local l = substr(`"`c'"', 1, 1) if (`"`l'"'<"A" | `"`l'"'>"Z") { Invalid `"`c'"' "1st character must be A-Z" } local l = substr(`"`c'"', 2, 1) if (`"`l'"'<"0" | `"`l'"'>"9") & `"`l'"'!="" { Invalid `"`c'"' "2nd character must be 0-9" } local l = substr(`"`c'"', 3, 1) if (`"`l'"'<"0" | `"`l'"'>"9") & `"`l'"'!="" { Invalid `"`c'"' "3rd character must be 0-9" } local l = substr(`"`c'"', 4, 1) if (`"`l'"'<"0" | `"`l'"'>"9") & `"`l'"'!="" { Invalid `"`c'"' "4rd character must be 0-9" } /* local l = substr(`"`c'"', 5, 1) if (`"`l'"'<"0" | `"`l'"'>"9") & `"`l'"'!="" { Invalid `"`c'"' "5th character must be 0-9" } */ sret local tok `"`c'"' end program define Invalid args code msg di in red `""`code'" invalid: `msg'"' exit 198 end program define X_ilist args newvar vn list quietly { gen byte `newvar' = 0 tokenize `"`list'"' while "`1'" != "" { if index("`1'", "-") { local l = index("`1'", "-") local lb = substr("`1'",1,`l'-1) local ub = substr("`1'",`l'+1,.) replace `newvar' = 1 /* */ if `vn'>="`lb'" & `vn'<="`ub'" } else if index("`1'", "*") { local sub = substr("`1'",1,length("`1'")-1) local l = length("`sub'") replace `newvar' = 1 /* */ if substr(`vn',1,`l')=="`sub'" } else replace `newvar' = 1 if `vn' == "`1'" mac shift } } end // Variation of X_ilist to deal with block groups // Single blocks must be matched to a block group (range) in the block database // Blocks with * wildcard must be matched to a similar substring range in the block database // Block ranges (e.g., A00/A09) must only overlap a block group in the block database program define X_blist args newvar vn1 vn2 list quietly { gen byte `newvar' = 0 tokenize `"`list'"' while "`1'" != "" { if index("`1'", "-") { local l = index("`1'", "-") local lb = substr("`1'",1,`l'-1) local ub = substr("`1'",`l'+1,.) replace `newvar' = 1 if (`vn1'>="`lb'" & `vn1'<="`ub'") | (`vn2'>="`lb'" & `vn2'<="`ub'") } else if index("`1'", "*") { local sub = substr("`1'",1,length("`1'")-1) local l = length("`sub'") replace `newvar' = 1 if "`sub'">=substr(`vn1',1,`l') & "`sub'"<=substr(`vn2',1,`l') } else replace `newvar' = 1 if "`1'">=`vn1' & "`1'"<=`vn2' mac shift } } end program define FindFile capture noi quietly mycd10_ff mycd10_cod.dta, ado if _rc==0 { exit } local rc = _rc di di in gr "mycd10 needs a dataset that records the valid ICD-10 codes." di in gr "The procedure code dataset is stored with the mycd10 program." di in gr "The diagnosis code dataset needs to be downloaded from WHO first." di in gr `"Type "help mycd10" and see the installation instructions, "' di in gr "particulary the mycd10 prepare command." exit `rc' end program define FindChapterFile capture noi quietly mycd10_ff mycd10_chp.dta, ado if _rc==0 { exit } local rc = _rc di di in gr "mycd10 needs a dataset that records the valid ICD-10 chapters." di in gr "The procedure code dataset is stored with the mycd10 program." di in gr "The diagnosis code dataset needs to be downloaded from WHO first." di in gr `"Type "help mycd10" and see the installation instructions, "' di in gr "particulary the mycd10 prepare command." exit `rc' end program define FindBlockFile capture noi quietly mycd10_ff mycd10_blk.dta, ado if _rc==0 { exit } local rc = _rc di di in gr "mycd10 needs a dataset that records the valid ICD-10 block groups." di in gr "The procedure code dataset is stored with the mycd10 program." di in gr "The diagnosis code dataset needs to be downloaded from WHO first." di in gr `"Type "help mycd10" and see the installation instructions, "' di in gr "particulary the mycd10 prepare command." exit `rc' end program define Query syntax FindFile local fn `"`r(fn)'"' preserve quietly use `"`fn'"', clear notes end exit