saxoforn

SaxoForN data extraction tool
git clone git://arztpraxis-lohmann.de/saxoforn
Log | Files | Refs | LICENSE

saxofornQ12022.py (9698B)


      1 #!/usr/bin/env python
      2 # coding=utf-8
      3 #
      4 # © 2019-2022 Christoph Lohmann <20h@r-36.net>
      5 #
      6 # This file is published under the terms of the GPLv3.
      7 #
      8 
      9 import os
     10 import sys
     11 import getopt
     12 import codecs
     13 from datetime import datetime
     14 import operator
     15 
     16 topicno = 1
     17 
     18 # Return num of patients who have one occurence of some ebmcodes.
     19 def ebmcodeoccurence(container, ebmcodes):
     20 	occurence = 0
     21 	for sentence in container["sentences"]:
     22 		found = 0
     23 		for field in sentence["fields"]:
     24 			if field[0] == 5001:
     25 				if field[1] in ebmcodes:
     26 					if found == 0:
     27 						occurence += 1
     28 					found = 1
     29 	return occurence
     30 
     31 # Return sum of all occurences of some ebmcodes.
     32 def ebmcodesumoccurence(container, ebmcodes):
     33 	occurence = 0
     34 	for sentence in container["sentences"]:
     35 		for field in sentence["fields"]:
     36 			if field[0] == 5001:
     37 				if field[1] in ebmcodes:
     38 					occurence += 1
     39 	return occurence
     40 
     41 def expandcodes(codes):
     42 	newcodes = []
     43 	for code in codes:
     44 		if code.endswith(".-"):
     45 			for c in "012345678":
     46 				newcodes.append(code.replace("-", c))
     47 		else:
     48 			newcodes.append(code)
     49 	return newcodes
     50 
     51 def printcode(codesdb, code):
     52 	if code in codesdb:
     53 		print("%s = %d" % (code, codesdb[code]))
     54 	else:
     55 		print("%s = 0" % (code))
     56 
     57 def printcodes(codesdb, codes):
     58 	newcodes = expandcodes(codes)
     59 	for code in newcodes:
     60 		printcode(codesdb, code)
     61 
     62 def printcodessum(codesdb, codes):
     63 	codesum = 0
     64 	newcodes = expandcodes(codes)
     65 	for code in newcodes:
     66 		if code in codesdb:
     67 			codesum += codesdb[code]
     68 	print("%s = %d" % (newcodes, codesum))
     69 
     70 def sentence2dict(sentence):
     71 	rdict = {}
     72 
     73 	if not "fields" in sentence:
     74 		return rdict
     75 
     76 	for field in sentence["fields"]:
     77 		fstr = "%s" % (field[0])
     78 		if not fstr in rdict:
     79 			rdict[fstr] = []
     80 		rdict[fstr].append(field[1])
     81 
     82 	return rdict
     83 
     84 def parse_xdt(line):
     85 	length = int(line[:3])
     86 	fieldid = int(line[3:7])
     87 	fcontent = line[7:-2]
     88 
     89 	if length != len(line):
     90 		print("Invalid line: %s\n" % (line[:-2]))
     91 
     92 	return (length, fieldid, fcontent)
     93 
     94 def usage(app):
     95 	app = os.path.basename(app)
     96 	print("usage: %s [-h] adt.con" % (app), file=sys.stderr)
     97 	sys.exit(1)
     98 
     99 def main(args):
    100 	try:
    101 		opts, largs = getopt.getopt(args[1:], "h")
    102 	except getopt.GetoptError as err:
    103 		print(str(err))
    104 		usage(args[0])
    105 	
    106 	for o, a in opts:
    107 		if o == "-h":
    108 			usage(args[0])
    109 		else:
    110 			assert False, "unhandled option"
    111 
    112 	if len(largs) < 1:
    113 		usage(args[0])
    114 
    115 	# Aerzte
    116 	besa = {}
    117 	# Betriebsstaette
    118 	rvsa = {}
    119 	# PVS-Hersteller
    120 	adt0 = {}
    121 
    122 	begin = datetime.now()
    123 	lines = 0
    124 	containers = []
    125 	container = {}
    126 	sentence = {}
    127 	with codecs.open(largs[0], "r", "iso8859-15") as fd:
    128 		for line in fd:
    129 			(length, fieldid, fcontent) = parse_xdt(line)
    130 			lines += 1
    131 
    132 			#print((length, fieldid, fcontent))
    133 			if fieldid == 8000:
    134 				if fcontent == "con0":
    135 					container["name"] = fcontent
    136 					container["sentences"] = []
    137 					container["fields"] = []
    138 				elif fcontent == "con9":
    139 					if sentence != {}:
    140 						container["sentences"].append(sentence)
    141 					containers.append(container)
    142 					container = {}
    143 					sentence = {}
    144 				elif fcontent == "adt9":
    145 					if sentence != {}:
    146 						container["sentences"].append(sentence)
    147 					continue
    148 				elif fcontent == "kad9":
    149 					if sentence != {}:
    150 						container["sentences"].append(sentence)
    151 					continue
    152 				elif fcontent == "sad9":
    153 					if sentence != {}:
    154 						container["sentences"].append(sentence)
    155 					continue
    156 				else:
    157 					sentence = {}
    158 					sentence["name"] = fcontent
    159 					sentence["fields"] = []
    160 					container["sentences"].append(sentence)
    161 
    162 					# Filter out special data.
    163 					if sentence["name"] == "besa":
    164 						besa = sentence
    165 					elif sentence["name"] == "rvsa":
    166 						rvsa = sentence
    167 					elif sentence["name"] == "adt0":
    168 						adt0 = sentence
    169 				continue
    170 			else:
    171 				if "fields" in sentence:
    172 					sentence["fields"].append([fieldid,
    173 						fcontent])
    174 				else:
    175 					container["fields"].append([fieldid,
    176 						fcontent])
    177 
    178 	besa = sentence2dict(besa)
    179 	rvsa = sentence2dict(rvsa)
    180 	adt0 = sentence2dict(adt0)
    181 
    182 	ambscheine = 0
    183 	notfallscheine = 0
    184 	ueberweisungen = 0
    185 	belegarztscheine = 0
    186 	for sentence in containers[0]["sentences"]:
    187 		if sentence["name"] == "0101":
    188 			ambscheine += 1
    189 		elif sentence["name"] == "0104":
    190 			notfallscheine += 1
    191 		elif sentence["name"] == "0102":
    192 			ueberweisungen += 1
    193 		elif sentence["name"] == "0103":
    194 			belegarztscheine +=1
    195 
    196 	gesamtscheine = ambscheine + notfallscheine + ueberweisungen + \
    197 			belegarztscheine
    198 
    199 	# Anonymisation dictionaries.
    200 	# All ICD codes, multiple codes per patient.
    201 	icdcodes = {}
    202 	# ICD codes, one per patient.
    203 	icdcodespp = {}
    204 	# All EBM codes, multiple codes per patient.
    205 	ebmcodes = {}
    206 	# EBM codes, one per patient.
    207 	ebmcodespp = {}
    208 
    209 	for sentence in containers[0]["sentences"]:
    210 		icdcodefound = 0
    211 		ebmcodefound = 0
    212 		for field in sentence["fields"]:
    213 			if field[0] == 5001:
    214 				if field[1] in ebmcodes:
    215 					ebmcodes[field[1]] += 1
    216 				else:
    217 					ebmcodes[field[1]] = 1
    218 
    219 				if ebmcodefound == 0:
    220 					if field[1] in ebmcodespp:
    221 						ebmcodespp[field[1]] += 1
    222 					else:
    223 						ebmcodespp[field[1]] = 1
    224 				else:
    225 					ebmcodefound = 1
    226 			elif field[0] == 6001:
    227 				if field[1] in icdcodes:
    228 					icdcodes[field[1]] += 1
    229 				else:
    230 					icdcodes[field[1]] = 1
    231 
    232 				if icdcodefound == 0:
    233 					if field[1] in icdcodespp:
    234 						icdcodespp[field[1]] += 1
    235 					else:
    236 						icdcodespp[field[1]] = 1
    237 				else:
    238 					icdcodefound = 1
    239 
    240 	def sortdict(d):
    241 		return sorted(d.items(), key=lambda kv: kv[1])[::-1]
    242 
    243 	def printtopic(topic):
    244 		global topicno
    245 		print("%d.) %s" % (topicno, topic))
    246 		topicno += 1
    247 
    248 	oicdcodes = sortdict(icdcodes)
    249 	oebmcodes = sortdict(ebmcodes)
    250 
    251 	print("SaxoForN-Datenerhebung:")
    252 	print("")
    253 
    254 	printtopic("PVS")
    255 	pvshersteller = None
    256 	if "111" in adt0:
    257 		if "dv@data-vital.de" in adt0["111"][0]:
    258 			pvshersteller = "DATA VITAL"
    259 	print("PVS-Hersteller = %s" % (pvshersteller))
    260 	print("")
    261 
    262 	printtopic("Gesamtscheine")
    263 	# KBV_ITA_VGEX_Datensatzbeschreibung_KVDT.pdf#S27
    264 	print("amb. Scheine ..... %d" % (ambscheine))
    265 	print("Notfallscheine ... %d" % (notfallscheine))
    266 	print("Ueberweisungen ... %d" % (ueberweisungen))
    267 	print("Belegarztscheine . %d" % (belegarztscheine))
    268 	print("=========================")
    269 	print("Gesamtscheine .... %d" % (gesamtscheine))
    270 	print("")
    271 
    272 	printtopic("Grundpauschalen")
    273 	for grundpauschale in ["03001", "04001", "03002", "04002",\
    274 			"03003", "04003", "03004", "04004", "03005",\
    275 			"04005"]:
    276 		printcode(ebmcodespp, grundpauschale)
    277 	print("")
    278 
    279 	printtopic("AU-Anfragen")
    280 	#    Krankschreibung: "AU:"
    281 
    282 	#printtopic("Einweisungen")
    283 	# TODO: Parse BDT.
    284 	# In Bemerkungsfeld:
    285 	#    Einweisungen: "KH:"
    286 	#    Ueberweisungen: "UE:"
    287 	#    Krankschreibung: "AU:"
    288 	#    Transportschein: "TA:"
    289 	#    Laborbemerkung: "UL:" 
    290 	print("")
    291 
    292 	printtopic("COVID-19 Nachweise, PCR-Teste")
    293 	printcode(ebmcodespp, "88315")
    294 	sachsencovid19 = ["99136", "88240", "02402"]
    295 	print("Sachsen: %s = %d" % (sachsencovid19,\
    296 		ebmcodeoccurence(containers[0], sachsencovid19)))
    297 	hessencovid19 = ["88240", "02402"]
    298 	print("Hessen: %s = %d" % (hessencovid19,\
    299 		ebmcodeoccurence(containers[0], hessencovid19)))
    300 	print("")
    301 
    302 	printtopic("COVID-19 ICDs")
    303 	for covid19icd in ["U07.1", "U07.2", "U09.9", "U08.9", "U10.9", "U12.9"]:
    304 		printcode(icdcodes, covid19icd)
    305 	print("")
    306 
    307 	printtopic("Telefonsprechstunde")
    308 	printcode(ebmcodes, "01434")
    309 	print("")
    310 
    311 	printtopic("Videosprechstunde")
    312 	videosprechstunde = ["01450", "40129", "40128", "01444",\
    313 			"01442"]
    314 	print("EBM-Codes: %s = %d" % (videosprechstunde,\
    315 			ebmcodeoccurence(containers[0],\
    316 			videosprechstunde)))
    317 	print("Bitte Videosprechstundeanbieter heraussuchen.")
    318 	print("")
    319 
    320 	printtopic("App auf Rezept")
    321 	print("")
    322 
    323 	printtopic("Hausbesuche")
    324 	arzthausbesuche = ["01410", "01411", "01412", "01413", "01415"]
    325 	naepahausbesuche = ["03062", "03063", "38100"]
    326 	impfhausbesuche = ["88323", "88324"]
    327 
    328 	print("Arzthaubesuche: %s = %d" % (arzthausbesuche,
    329 		ebmcodesumoccurence(containers[0], arzthausbesuche)))
    330 	print("Naepahaubesuche: %s = %d" % (naepahausbesuche,
    331 		ebmcodesumoccurence(containers[0], naepahausbesuche)))
    332 	print("Impfhausbesuche: %s = %d" % (impfhausbesuche,
    333 		ebmcodesumoccurence(containers[0], impfhausbesuche)))
    334 	print("")
    335 
    336 	printtopic("Schilddrüsenerkrankungen")
    337 	printcodessum(icdcodes, ["E01.0", "E01.2", "E04.-"])
    338 	printcodessum(icdcodes, ["E02"])
    339 	printcodessum(icdcodes, ["E03.-", "E89.0"])
    340 	printcodessum(icdcodes, ["E05.-"])
    341 	printcodessum(icdcodes, ["E06.-"])
    342 	print("")
    343 
    344 	printtopic("ePA-Nutzung")
    345 	printcode(icdcodes, "88270")
    346 	print("TI-Anbindung? ja/nein")
    347 	print("Update auf ePA-Konnektor? ja/nein")
    348 	print("PVS-Modul ePA? ja/nein")
    349 	print("eHBA 2.0 bestellt? ja/nein")
    350 	print("Keine Anschaffung bisher? ja/nein")
    351 
    352 	printtopic("COVID-19-Impfungen")
    353 	biontech = ["88331A", "88331B", "88331R",\
    354 			"88331G", "88331H", "88331K",\
    355 			"88331V", "88331W", "88331X"]
    356 	printcodes(ebmcodes, biontech)
    357 	moderna = ["88332A", "88332B", "88332R",\
    358 			"88332G", "88332H", "88332K",\
    359 			"88332V", "88332W", "88332X"]
    360 	printcodes(ebmcodes, moderna)
    361 	astrazeneca = ["88333A", "88333B", "88333R",\
    362 			"88333G", "88333H", "88333K",\
    363 			"88333V", "88333W", "88333X"]
    364 	printcodes(ebmcodes, astrazeneca)
    365 	johnsonjohnson = ["88334", "88334R",\
    366 			"88334I", "88334K",\
    367 			"88334Y", "88334X"]
    368 	printcodes(ebmcodes, johnsonjohnson)
    369 	novavax = ["88335A", "88335B",\
    370 			"88335V", "88335W",\
    371 			"88335G", "88335H"]
    372 	printcodes(ebmcodes, novavax)
    373 	print("")
    374 
    375 	print("12.) Influenza-Impfungen")
    376 	influenza = ["89111", "89111S", "89112", "89112Y"]
    377 	printcodes(ebmcodes, influenza)
    378 	print("")
    379 
    380 	print("13.) Pneumokokken-Impfung")
    381 	pneumokokken = ["89119", "89119R",\
    382 			"89120", "89120R",\
    383 			"89120V", "89120X"]
    384 	printcodes(ebmcodes, pneumokokken)
    385 	print("")
    386 
    387 	return 0
    388 
    389 if __name__ == "__main__":
    390 	sys.exit(main(sys.argv))
    391