diff --git a/Marie/pathways.py b/Marie/pathways.py index fba9d64a590c55ef06c7f341f8a7d11f8a741dc9..f78f797b983e26230d232cfdfeb8122958d62476 100644 --- a/Marie/pathways.py +++ b/Marie/pathways.py @@ -1,3 +1,16 @@ +""" +Description of the VICAN pathways +""" + +import warnings +from datetime import date +from dateutil.relativedelta import relativedelta + +import numpy as np +import numpy.random as rd +import pandas as pd + + from SNDSGenerator.pathway_factory import pathwayInjector from SNDSGenerator.database_model import ( Patient, @@ -7,15 +20,15 @@ from SNDSGenerator.database_model import ( ) from SNDSGenerator.simulation import simulation -from datetime import date -from dateutil.relativedelta import relativedelta - -import warnings -import numpy as np -import numpy.random as rd +# pylint: disable=C0103 class Surgery(pathwayInjector): + """Surgery pathway + + This pathway includes only one specific surgery (short hospital stay). + """ + def __init__(self, sim: simulation): super().__init__(sim) # CCAM codes for breast cancer surgeries @@ -26,7 +39,6 @@ class Surgery(pathwayInjector): "QEFA016", "QEFA017", "QEFA018", - "QEFA003", "QEF005", "QEFA010", @@ -38,9 +50,8 @@ class Surgery(pathwayInjector): "QEFA019", ] - def pathdesc(self, patient: Patient, d: date): - hospit_reason = "Z51.1" + hospit_reason = "C50" # C50.9 Tumeur maligne du sein, sans précision surgery_code = rd.choice(self.code_chir) care = ShortHospStay(patient, self.sim.etablissements[0], hospit_reason) @@ -53,13 +64,12 @@ class Surgery(pathwayInjector): class ET_uni(pathwayInjector): - """Endocrino Therapy""" + """Endocrino Therapy pathway""" def __init__(self, sim: simulation): super().__init__(sim) code_ET_ATC_AI = ["L02BA01"] code_ET_ATC_Tamoxifen = ["L02BG03", "L02BG06", "L02BG04"] - # SELECT PHA_CIP_C13 from IR_PHA_r where PHA_ATC_C07 like "L02BA01" or PHA_ATC_C07 like "L02BG03" or PHA_ATC_C07 like "L02BG06" or PHA_ATC_C07 like "L02BG04" or PHA_ATC_C07 like "L02AE03" or PHA_ATC_C07 like "L02AE02" or PHA_ATC_C07 like "L02AE04"; self.code_ET_CIP_L02BA01 = [ @@ -228,7 +238,7 @@ class ET_uni(pathwayInjector): def pathdesc(self, patient: Patient, d: date): # tirage d'un sur les deux - if rd.choice([0, 1], p=[0.255,0.745]): + if rd.choice([0, 1], p=[0.255, 0.745]): ET_code = rd.choice(self.code_ET_CIP_L02BA01) else: ET_code = rd.choice(self.code_ET_CIP_Tamoxifen) @@ -251,7 +261,10 @@ class ET_bi(pathwayInjector): code_ET_ATC_AI = ["L02BA01"] code_ET_ATC_Tamoxifen = ["L02BG03", "L02BG06", "L02BG04"] - # SELECT PHA_CIP_C13 from IR_PHA_r where PHA_ATC_C07 like "L02BA01" or PHA_ATC_C07 like "L02BG03" or PHA_ATC_C07 like "L02BG06" or PHA_ATC_C07 like "L02BG04" or PHA_ATC_C07 like "L02AE03" or PHA_ATC_C07 like "L02AE02" or PHA_ATC_C07 like "L02AE04"; + # SELECT PHA_CIP_C13 from IR_PHA_r where PHA_ATC_C07 like "L02BA01" or PHA_ATC_C07 + # like "L02BG03" or PHA_ATC_C07 like "L02BG06" or PHA_ATC_C07 like "L02BG04" or + # PHA_ATC_C07 like "L02AE03" or PHA_ATC_C07 like "L02AE02" or + # PHA_ATC_C07 like "L02AE04"; self.code_ET_CIP_L02BA01 = [ "3400932059324", "3400932865284", @@ -415,18 +428,42 @@ class ET_bi(pathwayInjector): "3400949980994", "3400949982028", ] - self.code_ET_CIP_agonist = ["3400930020005", "3400930122112", "3400930122129", "3400932829217", "3400932850037", "3400932850266", "3400932932672", "3400933129125", "3400933943769", "3400933963811", "3400934125423", "3400934125652", "3400935844675", "3400936690868", "3400936690929", "3400937575256", "3400937575317", "3400938081459", "3400938263381", "3400938458381", "3400939262123", "3400939890173", "3400949002634", "3400949002818"] - + self.code_ET_CIP_agonist = [ + "3400930020005", + "3400930122112", + "3400930122129", + "3400932829217", + "3400932850037", + "3400932850266", + "3400932932672", + "3400933129125", + "3400933943769", + "3400933963811", + "3400934125423", + "3400934125652", + "3400935844675", + "3400936690868", + "3400936690929", + "3400937575256", + "3400937575317", + "3400938081459", + "3400938263381", + "3400938458381", + "3400939262123", + "3400939890173", + "3400949002634", + "3400949002818", + ] def pathdesc(self, patient: Patient, d: date): nb_tot = 12 - seq_type = rd.choice([1,2,3,4], p=[0.5167, 0.4, 0.05, 0.0333]) - if seq_type==1: + seq_type = rd.choice([1, 2, 3, 4], p=[0.5167, 0.4, 0.05, 0.0333]) + if seq_type == 1: ET_code_AI = rd.choice(self.code_ET_CIP_L02BA01) ET_code_Tamoxifen = rd.choice(self.code_ET_CIP_Tamoxifen) - nb=rd.randint(1,nb_tot-1) + nb = rd.randint(1, nb_tot - 1) for i in range(nb): care = DrugDelivery(ET_code_Tamoxifen, patient, self.sim.pharms[0]) care.date_debut = d @@ -434,7 +471,7 @@ class ET_bi(pathwayInjector): patient.append(care) if i != nb - 1: d = d + relativedelta(months=1) - for i in range(nb_tot-nb): + for i in range(nb_tot - nb): care = DrugDelivery(ET_code_AI, patient, self.sim.pharms[0]) care.date_debut = d care.date_fin = d @@ -442,11 +479,11 @@ class ET_bi(pathwayInjector): if i != nb - 1: d = d + relativedelta(months=1) - elif seq_type==2: + elif seq_type == 2: - ET_code_AI = rd.choice(self.code_ET_CIP_L02BA01) - ET_code_Tamoxifen = rd.choice(self.code_ET_CIP_Tamoxifen) - nb=rd.randint(1,nb_tot-1) + ET_code_AI = rd.choice(self.code_ET_CIP_L02BA01) + ET_code_Tamoxifen = rd.choice(self.code_ET_CIP_Tamoxifen) + nb = rd.randint(1, nb_tot - 1) for i in range(nb): care = DrugDelivery(ET_code_AI, patient, self.sim.pharms[0]) care.date_debut = d @@ -454,7 +491,7 @@ class ET_bi(pathwayInjector): patient.append(care) if i != nb - 1: d = d + relativedelta(months=1) - for i in range(nb_tot-nb): + for i in range(nb_tot - nb): care = DrugDelivery(ET_code_Tamoxifen, patient, self.sim.pharms[0]) care.date_debut = d care.date_fin = d @@ -462,7 +499,7 @@ class ET_bi(pathwayInjector): if i != nb - 1: d = d + relativedelta(months=1) - elif seq_type==3: + elif seq_type == 3: ET_code_Tamoxifen = rd.choice(self.code_ET_CIP_Tamoxifen) ET_code_AI = rd.choice(self.code_ET_CIP_agonist) for i in range(nb_tot): # combien de temps ?? @@ -477,7 +514,7 @@ class ET_bi(pathwayInjector): if i != nb - 1: d = d + relativedelta(months=1) - elif seq_type==4: + elif seq_type == 4: ET_code_L02BA01 = rd.choice(self.code_ET_CIP_L02BA01) ET_code_AI = rd.choice(self.code_ET_CIP_agonist) for i in range(nb_tot): # combien de temps ?? @@ -523,43 +560,45 @@ class RT_outHospital(pathwayInjector): def __init__(self, sim: simulation): super().__init__(sim) - codes = {"YYYY166":5326, - "YYYY047":4280, - "YYYY152":3758, - "YYYY128":2863, - "YYYY048":2299, - "YYYY323":2006, - "YYYY334":1562, - "YYYY050":837, - "YYYY049":829, - "YYYY109":779, - "YYYY244":756, - "YYYY197":732, - "YYYY387":412, - "YYYY356":354, - "YYYY347":353, - "YYYY345":314, - "YYYY469":308, - "YYYY081":298, - "YYYY080":246, - "YYYY380":246, - "YYYY307":228, - "YYYY337":218, - "YYYY151":212, - "YYYY304":205, - "YYYY458":186, - "YYYY460":185, - "YYYY369":168, - "YYYY331":154, - "YYYY225":148, - "YYYY370":138, - "YYYY377":133, - "YYYY491":129, - "YYYY398":122, - "YYYY391":115, - "YYYY299":111, - "YYYY459":108, - "YYYY358":104} + codes = { + "YYYY166": 5326, + "YYYY047": 4280, + "YYYY152": 3758, + "YYYY128": 2863, + "YYYY048": 2299, + "YYYY323": 2006, + "YYYY334": 1562, + "YYYY050": 837, + "YYYY049": 829, + "YYYY109": 779, + "YYYY244": 756, + "YYYY197": 732, + "YYYY387": 412, + "YYYY356": 354, + "YYYY347": 353, + "YYYY345": 314, + "YYYY469": 308, + "YYYY081": 298, + "YYYY080": 246, + "YYYY380": 246, + "YYYY307": 228, + "YYYY337": 218, + "YYYY151": 212, + "YYYY304": 205, + "YYYY458": 186, + "YYYY460": 185, + "YYYY369": 168, + "YYYY331": 154, + "YYYY225": 148, + "YYYY370": 138, + "YYYY377": 133, + "YYYY491": 129, + "YYYY398": 122, + "YYYY391": 115, + "YYYY299": 111, + "YYYY459": 108, + "YYYY358": 104, + } # draw the CCAM code used for this patient all along the RT p = np.array(list(codes.values())) @@ -587,52 +626,54 @@ class RT_inHospital(pathwayInjector): The RT is organised as one first visit and then a collection of sessions. Each session has its own RSS (MCO stay) - + """ def __init__(self, sim: simulation): super().__init__(sim) - codes = {"ZZNL065":34192, - "ZZNL063":14296, - "YYYY047":11402, - "ZZNL062":5858, - "ZZNL064":5207, - "YYYY152":4953, - "YYYY166":4639, - "ZZNL053":3001, - "YYYY307":2318, - "YYYY048":1992, - "ZZNL050":1739, - "ZZNL037":1507, - "YYYY049":1301, - "ZZNL040":1266, - "YYYY450":1144, - "YYYY128":1113, - "YYYY347":1012, - "ZZNL031":936, - "ZZNL048":833, - "ZZNL054":791, - "ZZNL039":753, - "ZZNL043":675, - "YYYY459":552, - "YYYY197":528, - "YYYY387":488, - "YYYY050":479, - "ZZNL036":478, - "ZZNL051":456, - "ZZNL061":363, - "YYYY046":343, - "ZZNL030":325, - "YYYY304":290, - "YYYY337":229, - "YYYY081":223, - "YYYY492":211, - "YYYY109":166, - "YYYY151":164, - "ZZNL042":156, - "YYYY080":118, - "YYYY136":114} + codes = { + "ZZNL065": 34192, + "ZZNL063": 14296, + "YYYY047": 11402, + "ZZNL062": 5858, + "ZZNL064": 5207, + "YYYY152": 4953, + "YYYY166": 4639, + "ZZNL053": 3001, + "YYYY307": 2318, + "YYYY048": 1992, + "ZZNL050": 1739, + "ZZNL037": 1507, + "YYYY049": 1301, + "ZZNL040": 1266, + "YYYY450": 1144, + "YYYY128": 1113, + "YYYY347": 1012, + "ZZNL031": 936, + "ZZNL048": 833, + "ZZNL054": 791, + "ZZNL039": 753, + "ZZNL043": 675, + "YYYY459": 552, + "YYYY197": 528, + "YYYY387": 488, + "YYYY050": 479, + "ZZNL036": 478, + "ZZNL051": 456, + "ZZNL061": 363, + "YYYY046": 343, + "ZZNL030": 325, + "YYYY304": 290, + "YYYY337": 229, + "YYYY081": 223, + "YYYY492": 211, + "YYYY109": 166, + "YYYY151": 164, + "ZZNL042": 156, + "YYYY080": 118, + "YYYY136": 114, + } # draw the CCAM code used for this patient all along the RT p = np.array(list(codes.values())) @@ -642,7 +683,7 @@ class RT_inHospital(pathwayInjector): def pathdesc(self, patient: Patient, d: date): # create the stay initiating the Radio therapy care = ShortHospStay(patient, self.sim.etablissements[0], "Z5100") - care.DRel = "Z50" + care.DRel = "C50" if date.weekday(d) == 5: # Saturday d += relativedelta(days=2) @@ -650,33 +691,36 @@ class RT_inHospital(pathwayInjector): d += relativedelta(days=1) care.start_date = d care.finish_date = d - - #add a RUM + + # add a RUM rum = ShortHospStay.hospRUM(42, "Z5101") - rum.length=1 - rum.DRel = "Z5100" - care.RUMs.append( rum ) + rum.length = 1 + rum.DRel = "C50" + care.RUMs.append(rum) patient.append(care) - #next event + # next event if date.weekday(d) == 4: # d was a Friday d += relativedelta(days=3) else: d += relativedelta(days=1) - nb = rd.randint(5,8) #5 to 7 week of treatment + nb = rd.randint(5, 8) # 5 to 7 week of treatment # create one MCO (RSS) per RT session (Z5101: irradiation session) # The first session in the same day - for _ in range(nb*5-1): + for _ in range(nb * 5 - 1): # session everyday, except the weekend care = ShortHospStay(patient, self.sim.etablissements[0], "Z5101") + care.DRel = "C50" care.start_date = d care.finish_date = d care.ccam.append(self.act_code) - care.RUMs.append(ShortHospStay.hospRUM(42, "Z5101")) # add the corresponding RUM in a ambulatory service + care.RUMs.append( + ShortHospStay.hospRUM(42, "Z5101") + ) # add the corresponding RUM in a ambulatory service patient.append(care) - + if date.weekday(d) == 6: # d was a Sunday, might never happen!! d += relativedelta(days=1) elif date.weekday(d) == 5: # d was a Saturday, might never happen!! @@ -725,64 +769,225 @@ class CT_uni(pathwayInjector): "HPLB003": 4, "HPLB007": 0, "ZZLF004": 10, - "ZZLF900": 0, } - - #UCD codes: obtained from the requests: "select PHA_CIP_UCD from IR_PHA_R where PHA_ATC_C07="L01AA01"" + + # UCD codes: obtained from the requests: "select PHA_CIP_UCD from IR_PHA_R where PHA_ATC_C07="L01AA01"" + # complemented with UCD codes deduced from the NU_UCD_R table (Reference table for UCD) using the drug name (ATC code) + # L01AA01: CYCLOPHOSPHAMIDE -> ?? + # L01CD02: TAXOTERE -> "9178082","9178099" + # L01DB03: EPIRUBICINE -> "9284306","9284312","9284329","9284335","9284341","9284358","9284364","9284370","9284387","9284393","9284401","9284418","9284424","9285257","9285263","9285286","9285292","9285300","9285317","9285323","9285346","9285352","9293357","9293363","9293386","9293392","9304457","9304463","9304486","9304492","9305095","9305103","9305126","9305132","9306605","9306611","9306628","9306634","9306640","9306657","9306663","9306686","9313137","9313143","9313166","9313172","9313189","9316058","9316064","9316070","9319708","9319714","9328481","9332637","9332643","9337913","9337936","9337942","9337959","9343724","9343730","9343747","9343753" + # L01BC02: Fluorouracile -> "9191527","9191533","9191556","9192107","9192113","9192136","9196163","9196186","9196192","9196200","9216925","9227685","9227691","9227716","9227722","9247191","9247216","9247222","9247239","9257315","9268276","9268282","9334866","9334872","9334889","9334895","9340950","9340967","9340973","9340996","9341004" + # L01CD01: paclitaxel -> "9278091","9278116","9278122","9282744","9282750","9282767","9282773","9284499","9284507","9284513","9284536","9285381","9285398","9285406","9285412","9290459","9290465","9290471","9296829","9296835","9296841","9296858","9299443","9299466","9299472","9299489","9305379","9305385","9305391","9308254","9308923","9308946","9308952","9308969","9319022","9327903","9327926","9327932","9327949","9332809","9332815","9332821","9363282","9363299","9363307","9366441","9366458","9401350","9401367", + self.code_CT_ATC = { - "L01AA01":["9031083","9031077","9031114"], - "L01CD02":[], - "L01DB03":["9145332", "9145361"], - "L01BC02":["9224505", "9030534", "9224505", "9303995"], - "L01CD01":[] - } - #NB: the UCD codes does not necessarily exist in the NU_UCD_R table (Reference table for UCD) - # pick up a random UCD code: - self.ucd = "9031083" + "L01AA01": ["9031083", "9031077", "9031114"], + "L01CD02": ["9178082", "9178099"], + "L01DB03": [ + "9145332", + "9145361", + "9284306", + "9284312", + "9284329", + "9284335", + "9284341", + "9284358", + "9284364", + "9284370", + "9284387", + "9284393", + "9284401", + "9284418", + "9284424", + "9285257", + "9285263", + "9285286", + "9285292", + "9285300", + "9285317", + "9285323", + "9285346", + "9285352", + "9293357", + "9293363", + "9293386", + "9293392", + "9304457", + "9304463", + "9304486", + "9304492", + "9305095", + "9305103", + "9305126", + "9305132", + "9306605", + "9306611", + "9306628", + "9306634", + "9306640", + "9306657", + "9306663", + "9306686", + "9313137", + "9313143", + "9313166", + "9313172", + "9313189", + "9316058", + "9316064", + "9316070", + "9319708", + "9319714", + "9328481", + "9332637", + "9332643", + "9337913", + "9337936", + "9337942", + "9337959", + "9343724", + "9343730", + "9343747", + "9343753", + ], + "L01BC02": [ + "9224505", + "9030534", + "9224505", + "9303995", + "9191527", + "9191533", + "9191556", + "9192107", + "9192113", + "9192136", + "9196163", + "9196186", + "9196192", + "9196200", + "9216925", + "9227685", + "9227691", + "9227716", + "9227722", + "9247191", + "9247216", + "9247222", + "9247239", + "9257315", + "9268276", + "9268282", + "9334866", + "9334872", + "9334889", + "9334895", + "9340950", + "9340967", + "9340973", + "9340996", + "9341004", + ], + "L01CD01": [ + "9278091", + "9278116", + "9278122", + "9282744", + "9282750", + "9282767", + "9282773", + "9284499", + "9284507", + "9284513", + "9284536", + "9285381", + "9285398", + "9285406", + "9285412", + "9290459", + "9290465", + "9290471", + "9296829", + "9296835", + "9296841", + "9296858", + "9299443", + "9299466", + "9299472", + "9299489", + "9305379", + "9305385", + "9305391", + "9308254", + "9308923", + "9308946", + "9308952", + "9308969", + "9319022", + "9327903", + "9327926", + "9327932", + "9327949", + "9332809", + "9332815", + "9332821", + "9363282", + "9363299", + "9363307", + "9366441", + "9366458", + "9401350", + "9401367", + ], + } # table T_MCOaaMED **not yet implemented** - if nb is None: + if nb is None or nb <= 0: self.nb = int(rd.uniform(3, 10)) else: self.nb = nb - + self.delay = delay self.CT_code = None + self.ucd_atc = None + self.ucd = None def pathdesc(self, patient: Patient, d: date): + # then, pick up a random UCD code, through the choice of an ATC code: + self.ucd_atc = rd.choice(list(self.code_CT_ATC.keys())) + self.ucd = rd.choice(self.code_CT_ATC[self.ucd_atc]) - care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") - care.DRel = "Z50" - if date.weekday(d) == 5: # Saturday - d += relativedelta(days=-1) - elif date.weekday(d) == 6: # Sunday - d += relativedelta(days=1) - care.start_date = d - care.finish_date = d - patient.append(care) - + # choose the type of medical act p = np.array(list(self.code_CT_CCAM.values())) p /= np.sum(p) if self.CT_code is None: self.CT_code = rd.choice(list(self.code_CT_CCAM.keys()), p=p) - + oldd = d for _ in range(self.nb): care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "Z50" care.ccam.append(self.CT_code) - care.UCDs.append( ShortHospStay.UCD(self.ucd) ) + care.UCDs.append(ShortHospStay.UCD(self.ucd)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d patient.append(care) + oldd = d d = d + relativedelta(days=self.delay) - d = d - relativedelta(days=self.delay) - return d + return oldd class CT_bi(pathwayInjector): - """Chimiotherapy pathway, bitherapy""" + """Chimiotherapy (CT) pathway, bitherapy + + In a bitherapy, the patient starts with one type of drugs for CT, and at some point + of the therapy, the injected drug is changed. + In our model, we change the ATC type of the drugs delivered to patient though CT sessions. + """ - def __init__(self, sim: simulation, nb:int = None, delays:int = (14,21)): + def __init__(self, sim: simulation, nb: int = None, delays: int = (14, 21)): super().__init__(sim) self.code_CT_CIM10 = ["Z511", "Z512"] self.code_CT_CCAM = { @@ -811,56 +1016,236 @@ class CT_bi(pathwayInjector): "HPLB003": 4, "HPLB007": 0, "ZZLF004": 10, - "ZZLF900": 0, } - self.code_CT_ATC = ["L01AA01", "L01CD02", "L01DB03", "L01BC02", "L01CD01"] + self.code_CT_ATC = { + "L01AA01": ["9031083", "9031077", "9031114"], + "L01CD02": ["9178082", "9178099"], + "L01DB03": [ + "9145332", + "9145361", + "9284306", + "9284312", + "9284329", + "9284335", + "9284341", + "9284358", + "9284364", + "9284370", + "9284387", + "9284393", + "9284401", + "9284418", + "9284424", + "9285257", + "9285263", + "9285286", + "9285292", + "9285300", + "9285317", + "9285323", + "9285346", + "9285352", + "9293357", + "9293363", + "9293386", + "9293392", + "9304457", + "9304463", + "9304486", + "9304492", + "9305095", + "9305103", + "9305126", + "9305132", + "9306605", + "9306611", + "9306628", + "9306634", + "9306640", + "9306657", + "9306663", + "9306686", + "9313137", + "9313143", + "9313166", + "9313172", + "9313189", + "9316058", + "9316064", + "9316070", + "9319708", + "9319714", + "9328481", + "9332637", + "9332643", + "9337913", + "9337936", + "9337942", + "9337959", + "9343724", + "9343730", + "9343747", + "9343753", + ], + "L01BC02": [ + "9224505", + "9030534", + "9224505", + "9303995", + "9191527", + "9191533", + "9191556", + "9192107", + "9192113", + "9192136", + "9196163", + "9196186", + "9196192", + "9196200", + "9216925", + "9227685", + "9227691", + "9227716", + "9227722", + "9247191", + "9247216", + "9247222", + "9247239", + "9257315", + "9268276", + "9268282", + "9334866", + "9334872", + "9334889", + "9334895", + "9340950", + "9340967", + "9340973", + "9340996", + "9341004", + ], + "L01CD01": [ + "9278091", + "9278116", + "9278122", + "9282744", + "9282750", + "9282767", + "9282773", + "9284499", + "9284507", + "9284513", + "9284536", + "9285381", + "9285398", + "9285406", + "9285412", + "9290459", + "9290465", + "9290471", + "9296829", + "9296835", + "9296841", + "9296858", + "9299443", + "9299466", + "9299472", + "9299489", + "9305379", + "9305385", + "9305391", + "9308254", + "9308923", + "9308946", + "9308952", + "9308969", + "9319022", + "9327903", + "9327926", + "9327932", + "9327949", + "9332809", + "9332815", + "9332821", + "9363282", + "9363299", + "9363307", + "9366441", + "9366458", + "9401350", + "9401367", + ], + } if nb is None: self.nb = int(rd.uniform(3, 6)) else: - self.nb=nb + self.nb = nb + + # pick up a random UCD code, through the choice of an ATC code: + self.ucd_atc = None + self.ucd = None self.delays = delays self.CT_code = None def pathdesc(self, patient: Patient, d: date): - care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") - care.DRel = "Z50" - care.start_date = d - care.finish_date = d - patient.append(care) + # start by choosing the type of medical act for the sessions p = np.array(list(self.code_CT_CCAM.values())) p /= np.sum(p) if self.CT_code is None: self.CT_code = rd.choice(list(self.code_CT_CCAM.keys()), p=p) + # then, pick up a random UCD code, through the choice of an ATC code: + self.ucd_atc = rd.choice(list(self.code_CT_ATC.keys())) + self.ucd = rd.choice(self.code_CT_ATC[self.ucd_atc]) + + oldd = d nb = int(rd.uniform(3, 5)) for _ in range(nb): care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "C50" care.ccam.append(self.CT_code) + care.UCDs.append(ShortHospStay.UCD(self.ucd)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d patient.append(care) + oldd = d d = d + relativedelta(days=self.delays[0]) + + # change the type of ATC drugs (bitherapy) + self.ucd_atc = rd.choice(list(self.code_CT_ATC.keys()).remove(self.ucd_atc)) + self.ucd = rd.choice(self.code_CT_ATC[self.ucd_atc]) nb = int(rd.uniform(2, 5)) for _ in range(nb): care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "C50" care.ccam.append(self.CT_code) + care.UCDs.append(ShortHospStay.UCD(self.ucd)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d patient.append(care) + oldd = d d = d + relativedelta(days=self.delays[1]) - d = d - relativedelta(days=self.delays[1]) - return d + + return oldd class TT(pathwayInjector): """Targeted Therapy pathway""" - def __init__(self, sim: simulation, nb:int = 3): + def __init__(self, sim: simulation, nb: int = 3): super().__init__(sim) - self.code_TT_ATC = ["L01XC03"] # L01XE07 L01XC13, L01XC03, L01XC14 ??? + self.code_TT_ATC = ["L01XC03"] # L01XE07 L01XC13, L01XC03, L01XC14 ??? self.code_TT_CIP13 = [ "3400938379457", "3400938379518", @@ -888,14 +1273,12 @@ class TT(pathwayInjector): # implementation of a breast cancer pathway (P1) class P1(pathwayInjector): - def __init__(self, sim: simulation): - super().__init__(sim) - - # The starting date of thiscare pathway is not triggered by an - # external event : it is randomly generated ! + """ + The starting date of this care pathway is not triggered by an + external event: it is randomly generated ! + """ def pathdesc(self, patient: Patient, d: date): - """""" if len(self.sim.etablissements) == 0: warnings.warn( @@ -903,31 +1286,27 @@ class P1(pathwayInjector): ) return - Surgery(self.sim).pathdesc(patient, d) + d = Surgery(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P1" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) class P2(pathwayInjector): - """Rmplementation of a breast cancer pathway (P2) + """Implementation of a breast cancer pathway (P2) This profil corresponds to patients having a treatment pathway with [S+ET]. The starting date of this care pathway is uniformly random generated within the simulation year. """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): - """""" - if len(self.sim.etablissements) == 0: warnings.warn( "Warning (Pathway): no etablissement available to create the pathway" @@ -940,12 +1319,13 @@ class P2(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # inject ET - ET_uni(self.sim).pathdesc(patient, d) + d = ET_uni(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P2" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -959,12 +1339,7 @@ class P3(pathwayInjector): The starting date of this care pathway is uniformly random generated within the simulation year. """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): - """""" - if len(self.sim.etablissements) == 0: warnings.warn( "Warning (Pathway): no etablissement available to create the pathway" @@ -977,12 +1352,13 @@ class P3(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # Radiotherapy - RT(self.sim).pathdesc(patient, d) + d = RT(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P3" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -996,12 +1372,7 @@ class P4(pathwayInjector): The starting date of this care pathway is uniformly random generated within the simulation year. """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): - """""" - if len(self.sim.etablissements) == 0: warnings.warn( "Warning (Pathway): no etablissement available to create the pathway" @@ -1020,12 +1391,13 @@ class P4(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # ET - ET_uni(self.sim).pathdesc(patient, d) + d = ET_uni(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P4" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1036,15 +1408,10 @@ class P5(pathwayInjector): This profil corresponds to patients having a treatment pathway with [CT+S+RT+ET]. - The starting date of this care pathway is uniformly random generated within the simulation year. + The starting date of this care path """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): - """""" - if len(self.sim.etablissements) == 0: warnings.warn( "Warning (Pathway): no etablissement available to create the pathway" @@ -1083,12 +1450,13 @@ class P5(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # ET - ET_uni(self.sim).pathdesc(patient, d) + d = ET_uni(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P5" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1102,12 +1470,7 @@ class P6(pathwayInjector): The starting date of this care pathway is uniformly random generated within the simulation year. """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): - """""" - if len(self.sim.etablissements) == 0: warnings.warn( "Warning (Pathway): no etablissement available to create the pathway" @@ -1141,12 +1504,13 @@ class P6(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(15, 61))) # Radiotherapy - RT(self.sim).pathdesc(patient, d) + d = RT(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P6" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1164,6 +1528,8 @@ class P7(pathwayInjector): def __init__(self, sim: simulation): super().__init__(sim) + # self.code_TT_ATC = ["L01XC03"] # code pour Herceptin + self.code_TT_UCD = ["9220097", "9400037"] # version UCD de l'Herceptin def pathdesc(self, patient: Patient, d: date): """ @@ -1191,42 +1557,76 @@ class P7(pathwayInjector): else: unict = rd.binomial(1, 1) - #init the treatment with 4 sessions - therapy_phase1= CT_uni(self.sim) - d = therapy_phase1.pathdesc(patient, d, nb=4, delay=15) + # init the treatment with 4 sessions of CT alone + therapy_phase1 = CT_uni(self.sim, nb=4, delay=15) + d = therapy_phase1.pathdesc(patient, d) - dcomb = d + relativedelta(days=15) - - #continue in association with TT + # CT continue in association with TT + TT_code = rd.choice(self.code_TT_UCD) if unict: # CT unitherapy therapy = CT_uni(self.sim) therapy.CT_code = therapy_phase1.CT_code - d = therapy.pathdesc(patient, dcomb, nb=8, delay=15) + + for i in range(12): + care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "Z50" + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) + care.start_date = d + care.finish_date = d + care.ccam.append(therapy_phase1.CT_code) # same codes as before for CT + care.UCDs.append(ShortHospStay.UCD(therapy_phase1.ucd)) + if i % 3 == 0: + care.UCDs.append(ShortHospStay.UCD(TT_code)) + patient.append(care) + d = d + relativedelta(days=7) + d = d - relativedelta(days=7) else: - d = dcomb + # bi-therapy nb = int(rd.uniform(1, 10)) - for _ in range(nb): + i = 0 + while i < nb: care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "C50" care.ccam.append(therapy_phase1.CT_code) + care.UCDs.append(ShortHospStay.UCD(therapy_phase1.ucd)) + if i % 3 == 0: # combinaison with TT + care.UCDs.append(ShortHospStay.UCD(TT_code)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d patient.append(care) - d = d + relativedelta(days=15) + d = d + relativedelta(days=7) + i += 1 - p = np.array(list(therapy_phase1.code_CT_CCAM.values())) - p /= np.sum(p) - CT_code = rd.choice(list(therapy_phase1.code_CT_CCAM.keys()), p=p) - for _ in range(12-nb): + # choose another drug code for CT (bitherapy) + ucd_atc = rd.choice( + list(therapy_phase1.code_CT_ATC.keys()).remove(therapy_phase1.ucd_atc) + ) + ucd = rd.choice(therapy_phase1.code_CT_ATC[ucd_atc]) + while i < 12: care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") - care.ccam.append(CT_code) + care.DRel = "C50" + care.ccam.append(therapy_phase1.CT_code) + care.UCDs.append(ShortHospStay.UCD(ucd)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d + if i % 3 == 0: + care.UCDs.append(ShortHospStay.UCD(TT_code)) patient.append(care) - d = d + relativedelta(days=15) - d = d - relativedelta(days=15) - - TT(self.sim, nb=4).pathdesc(patient, dcomb) + d = d + relativedelta(days=7) + i += 1 + d = d - relativedelta(days=7) # Surgery dch = d + relativedelta(days=int(rd.uniform(7, 21))) @@ -1238,7 +1638,7 @@ class P7(pathwayInjector): # TT d = TT(self.sim, nb=10).pathdesc(patient, d) - # restart from surgery, no synchronized + # restart from surgery, not synchronized d = dch + relativedelta(days=int(rd.uniform(3, 31))) # RT @@ -1248,12 +1648,13 @@ class P7(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # ET bitherapy - ET_bi(self.sim).pathdesc(patient, d) + d = ET_bi(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P7" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1270,6 +1671,16 @@ class P8(pathwayInjector): def __init__(self, sim: simulation): super().__init__(sim) + self.code_TT_ATC = ["L01XC03"] # L01XE07 L01XC13, L01XC03, L01XC14 ??? + self.code_TT_CIP13 = [ + "3400938379457", + "3400938379518", + "3400941701764", + "3400941701825", + "3400941701993", + "3400949164349", + ] + self.code_TT_UCD = ["9220097", "9400037"] # version UCD de l'Herceptin def pathdesc(self, patient: Patient, d: date): """ @@ -1303,59 +1714,95 @@ class P8(pathwayInjector): else: unict = 1 + # init the treatment with 4 sessions of CT alone + therapy_phase1 = CT_uni(self.sim, nb=4, delay=15) + d = therapy_phase1.pathdesc(patient, d) - #init the treatment with 4 sessions - therapy_phase1= CT_uni(self.sim) - d = therapy_phase1.pathdesc(patient, d, nb=4, delay=15) - - dcomb = d + relativedelta(days=15) - - #continue in association with TT + # CT continue in association with TT + TT_code = rd.choice(self.code_TT_UCD) if unict: # CT unitherapy therapy = CT_uni(self.sim) therapy.CT_code = therapy_phase1.CT_code - d = therapy.pathdesc(patient, dcomb, nb=8, delay=15) + + for i in range(12): + care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "Z50" + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) + care.start_date = d + care.finish_date = d + care.ccam.append(therapy_phase1.CT_code) # same codes as before for CT + care.UCDs.append(ShortHospStay.UCD(therapy_phase1.ucd)) + if i % 3 == 0: + care.UCDs.append(ShortHospStay.UCD(TT_code)) + patient.append(care) + d = d + relativedelta(days=7) + d = d - relativedelta(days=7) else: - d = dcomb + # bi-therapy nb = int(rd.uniform(1, 10)) - for _ in range(nb): + i = 0 + while i < nb: care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") + care.DRel = "C50" care.ccam.append(therapy_phase1.CT_code) + care.UCDs.append(ShortHospStay.UCD(therapy_phase1.ucd)) + if i % 3 == 0: # combinaison with TT + care.UCDs.append(ShortHospStay.UCD(TT_code)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d patient.append(care) - d = d + relativedelta(days=15) + d = d + relativedelta(days=7) + i += 1 - p = np.array(list(therapy_phase1.code_CT_CCAM.values())) - p /= np.sum(p) - CT_code = rd.choice(list(therapy_phase1.code_CT_CCAM.keys()), p=p) - for _ in range(12-nb): + # choose another drug code for CT (bitherapy) + ucd_atc = rd.choice( + list(therapy_phase1.code_CT_ATC.keys()).remove(therapy_phase1.ucd_atc) + ) + ucd = rd.choice(therapy_phase1.code_CT_ATC[ucd_atc]) + while i < 12: care = ShortHospStay(patient, self.sim.etablissements[0], "Z511") - care.ccam.append(CT_code) + care.DRel = "C50" + care.ccam.append(therapy_phase1.CT_code) + care.UCDs.append(ShortHospStay.UCD(ucd)) + if date.weekday(d) == 5: # Saturday + d += relativedelta(days=-1) + elif date.weekday(d) == 6: # Sunday + d += relativedelta(days=1) care.start_date = d care.finish_date = d + if i % 3 == 0: + care.UCDs.append(ShortHospStay.UCD(TT_code)) patient.append(care) - d = d + relativedelta(days=15) - - TT(self.sim, nb=10).pathdesc(patient, dcomb) + d = d + relativedelta(days=7) + i += 1 + d = d - relativedelta(days=7) # break - d = dcomb + relativedelta(days=int(rd.uniform(3, 31))) + d = d + relativedelta(days=int(rd.uniform(3, 31))) # RT - d= RT(self.sim).pathdesc(patient, d) + d = RT(self.sim).pathdesc(patient, d) # break d = d + relativedelta(days=int(rd.uniform(3, 31))) # ET bitherapy - ET_bi(self.sim).pathdesc(patient, d) + d = ET_bi(self.sim).pathdesc(patient, d) + + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P8" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1370,9 +1817,6 @@ class P9(pathwayInjector): """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): """ - d is the starting date of the pathway @@ -1416,12 +1860,13 @@ class P9(pathwayInjector): d = d + relativedelta(days=int(rd.uniform(3, 31))) # RT - RT(self.sim).pathdesc(patient, d) + d = RT(self.sim).pathdesc(patient, d) + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P9" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) ) @@ -1436,9 +1881,6 @@ class P10(pathwayInjector): """ - def __init__(self, sim: simulation): - super().__init__(sim) - def pathdesc(self, patient: Patient, d: date): """ - d is the starting date of the pathway @@ -1499,15 +1941,17 @@ class P10(pathwayInjector): if uniet: # ET unitherapy - ET_uni(self.sim).pathdesc(patient, d) + d = ET_uni(self.sim).pathdesc(patient, d) else: # ET bitherapy - ET_bi(self.sim).pathdesc(patient, d) + d = ET_bi(self.sim).pathdesc(patient, d) + + return d def __precondition__(self, patient: Patient) -> bool: return patient.raw_data["pathway"] == "P10" - def __index_date__(self, patient: Patient): + def __index_date__(self, patient: Patient, d: date = pd.NaT): return date(day=1, month=1, year=self.sim.year) + relativedelta( days=int(rd.uniform(0, 364)) )