saxofornQ42023.py (10505B)
1 #!/usr/bin/env python 2 # coding=utf-8 3 # 4 # © 2019-2024 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("Privatpatienten") 280 # Consart "P" 281 # Ziffer "1" 282 print("") 283 284 #printtopic("AU-Anfragen") 285 # Krankschreibung: "AU:" 286 287 printtopic("Anfragen Krankenkassen Muster 52") 288 printcode(ebmcodespp, "01622") 289 print("") 290 291 #printtopic("Einweisungen") 292 # TODO: Parse BDT. 293 # In Bemerkungsfeld: 294 # Einweisungen: "KH:" 295 # Ueberweisungen: "UE:" 296 # Krankschreibung: "AU:" 297 # Transportschein: "TA:" 298 # Laborbemerkung: "UL:" 299 #print("") 300 301 printtopic("COVID-19 Nachweise, PCR-Teste") 302 printcode(ebmcodespp, "88315") 303 304 sachsencovid19 = ["99136", "88240", "02402", "32006"] 305 print("Sachsen: %s = %d" % (sachsencovid19,\ 306 ebmcodeoccurence(containers[0], sachsencovid19))) 307 hessencovid19 = ["88240", "02402"] 308 print("Hessen: %s = %d" % (hessencovid19,\ 309 ebmcodeoccurence(containers[0], hessencovid19))) 310 print("") 311 312 printtopic("COVID-19 ICDs") 313 for covid19icd in ["U07.1", "U07.2", "U09.9", "U08.9", "U10.9", "U12.9"]: 314 printcode(icdcodes, covid19icd) 315 print("") 316 317 printtopic("Videosprechstunde") 318 videosprechstunde = ["01450", "40129", "40128", "01444",\ 319 "01442"] 320 print("EBM-Codes: %s = %d" % (videosprechstunde,\ 321 ebmcodeoccurence(containers[0],\ 322 videosprechstunde))) 323 print("Bitte Videosprechstundeanbieter heraussuchen.") 324 print("") 325 326 printtopic("Hausbesuche") 327 arzthausbesuche = ["01410", "01411", "01412", "01413", "01415"] 328 naepahausbesuche = ["03062", "03063", "38100"] 329 impfhausbesuche = ["88323", "88324"] 330 331 print("Arzthaubesuche: %s = %d" % (arzthausbesuche, 332 ebmcodesumoccurence(containers[0], arzthausbesuche))) 333 print("Naepahaubesuche: %s = %d" % (naepahausbesuche, 334 ebmcodesumoccurence(containers[0], naepahausbesuche))) 335 print("Impfhausbesuche: %s = %d" % (impfhausbesuche, 336 ebmcodesumoccurence(containers[0], impfhausbesuche))) 337 print("") 338 339 printtopic("App auf Rezept") 340 # Rezept "Digitale Gesundheitsanwendung" 341 print("") 342 343 printtopic("ePA-Nutzung") 344 printcode(icdcodes, "88270") 345 print("TI-Anbindung? ja/nein") 346 print("Update auf ePA-Konnektor? ja/nein") 347 print("PVS-Modul ePA? ja/nein") 348 print("eHBA 2.0 bestellt? ja/nein") 349 print("Keine Anschaffung bisher? ja/nein") 350 print("") 351 352 print("Influenza-Impfungen") 353 influenza = ["89111", "89111S", "89112", "89112Y"] 354 printcodes(ebmcodes, influenza) 355 print("") 356 357 print("Pneumokokken-Impfung") 358 pneumokokken = ["89119", "89119R",\ 359 "89120", "89120R",\ 360 "89120V", "89120X"] 361 printcodes(ebmcodes, pneumokokken) 362 print("") 363 364 printtopic("COVID-19-Impfungen") 365 biontech = ["88331A", "88331B", "88331R",\ 366 "88331G", "88331H", "88331K",\ 367 "88331V", "88331W", "88331X"] 368 printcodes(ebmcodes, biontech) 369 biontechneu = ["88337A", "88337B",\ 370 "88337V", "88337W",\ 371 "88337G", "88337H",\ 372 "88337K", "88337X"] 373 printcodes(ebmcodes, biontechneu) 374 moderna = ["88332A", "88332B", "88332R",\ 375 "88332G", "88332H", "88332K",\ 376 "88332V", "88332W", "88332X"] 377 printcodes(ebmcodes, moderna) 378 johnsonjohnson = ["88334", "88334R",\ 379 "88334I", "88334K",\ 380 "88334Y", "88334X"] 381 printcodes(ebmcodes, johnsonjohnson) 382 astrazeneca = ["88333A", "88333B", "88333R",\ 383 "88333G", "88333H", "88333K",\ 384 "88333V", "88333W", "88333X"] 385 printcodes(ebmcodes, astrazeneca) 386 novavax = ["88335A", "88335B",\ 387 "88335V", "88335W",\ 388 "88335G", "88335H", 389 "88335R", "88335K", 390 "88335X"] 391 printcodes(ebmcodes, novavax) 392 valneva = ["88336A", "88336B",\ 393 "88336V", "88336W",\ 394 "88336G", "88336H"] 395 printcodes(ebmcodes, valneva) 396 sanofi = ["88339A", "88339B",\ 397 "88339V", "88339W",\ 398 "88339G", "88339H", 399 "88339R", "88339K", 400 "88339X"] 401 printcodes(ebmcodes, valneva) 402 print("") 403 404 printcodes(ebmcodes, ["88125"]) 405 print("") 406 407 printtopic("Schilddrüsenerkrankungen") 408 printcodessum(icdcodes, ["E01.0", "E01.1", "E01.2"]) 409 printcodessum(icdcodes, ["E02"]) 410 printcodessum(icdcodes, ["E03.-"]) 411 printcodessum(icdcodes, ["E04.-"]) 412 printcodessum(icdcodes, ["E05.-"]) 413 printcodessum(icdcodes, ["E06.-"]) 414 printcodessum(icdcodes, ["E07.-"]) 415 printcodessum(icdcodes, ["D34.-"]) 416 print("") 417 418 printtopic("Schilddrüsensonographie") 419 printcodes(ebmcodes, ["33012"]) 420 print("") 421 422 return 0 423 424 if __name__ == "__main__": 425 sys.exit(main(sys.argv)) 426