Package: edc-randomization
edc-randomizationRandomization objects for clinicedc projectsOverviewTheRandomizerclass emulates the randomization of a clincial trial participant in
realtime. This module doesn’t actuallyrandomizein realtime. Instead, a CSV file is
prepared in advance by the statistician. This CSV file lists the order in which subjects
are to be randomized. TheRandomizerclass initially imports the entire list in order
into amodel. When a subject is to be randomized, theRandomizerclass selects
the next available row from the model.A very basicrandomization_list.csvprepared in advance might look like this:site_name,sid,assignment
temeke,1000,active
temeke,1001,active
temeke,1002,placebo
temeke,1003,active
temeke,1004,placebo
temeke,1005,placebo
...For large multisite trials this may be thousands of lines ordered using some type of block
randomization.This module will import (only once) all rows from the CSV file into a model. TheRandomizerclass selects and allocates in order by site_name one row per participant from the model.randomizer_cls=site_randomizers.get("default")randomizer_cls.randomize(subject_identifier=subject_identifier,...)# or just:site_randomizers.randomize("default",subject_identifier=subject_identifier,...)Usually, theRandomizerclass is instantiated in asignalonce the subject’s
eligibility is confirmed and the subject’s informed consent is submitted. Asignalattached to the subject’s informed consent is a good place to do this assuming the sequence
of events are 1) pass eligibility criteria, 2) complete informed consent, 3)randomizeand
issue study identifier 4) start baseline visit.@receiver(post_save,weak=False,sender=SubjectConsent,dispatch_uid="subject_consent_on_post_save",)defsubject_consent_on_post_save(sender,instance,raw,created,**kwargs):ifnotraw:ifcreated:...# randomizesite_randomizers.randomize("default",subject_identifier=instance.subject_identifier,report_datetime=instance.consent_datetime,site=instance.site,user=instance.user_created,)...Registering a randomizerThe defaultRandomizerclass isedc_randomization.randomizer.Randomizer. Unless you
indicate otherwise, it will be automatically registered with the site controller,site_randomizerswith the namedefault. It is recommended you access theRandomizerclass throughsite_randomizersinstead of directly importing.randomizer_cls=site_randomizers.get("default")Customizing the default randomizerSome attributes of the defaultRandomizerclass can be customized usingsettingsattributes:EDC_RANDOMIZATION_LIST_PATH='path/to/csv_file'EDC_RANDOMIZATION_ASSIGNMENT_MAP={"intervention":1,"control":2,}EDC_RANDOMIZATION_ASSIGNMENT_DESCRIPTION_MAP={"intervention":"Fluconazole plus flucytosine","control":"Fluconazole"}Creating a custom randomizerIf you need to customize further, create a customRandomizerclass.In the example below,genderis added for a trial stratified bygender.CustomRandomizerclasses live inrandomizers.pyin the root of your app. Thesite_randomizerscontroller willautodiscoverthem.# my_app/randomizers.py@register()classMyRandomizer(Randomizer):name="my_randomizer"model="edc_randomization.myrandomizationlist"randomization_list_path=tmpdirassignment_map={"Intervention":1,"Control":0}assignment_description_map={"Intervention":"Fluconazole plus flucytosine","Control":"Fluconazole"}extra_csv_fieldnames=["gender"]def__init__(self,gender=None,**kwargs):self.gender=gendersuper().__init__(**kwargs)@propertydefextra_required_instance_attrs(self):returndict(gender=self.gender)@propertydefextra_model_obj_options(self):returndict(gender=self.gender)@classmethoddefget_extra_list_display(cls):return[(4,"gender")]Theregister()decorator registers the custom class withsite_randomizers.With a custom randomizer, the defaultRandomizerclass is no longer needed,
update settings to prevent the default class from registering.Use the settings attribute:EDC_RANDOMIZATION_REGISTER_DEFAULT_RANDOMIZER=FalseConfirm this by checking thesite_randomizers:>>>randomizer_cls=site_randomizers.get("default")NotRegistered:ARandomizerclassbythisname...>>>randomizer_cls=site_randomizers.get("my_randomizer")>>>randomizer_cls.name"my_randomizer"Manually Importing from CSVARandomizerclass will callimport_listwhen it is instantiated
for the first time. If you want to load the CSV file manually,
import theRandomizerclass and callimport_list().>>>randomizer_cls=site_randomizers.get("my_randomizer")>>>randomizer_cls.import_list()ImportCSVdataRandomizer:-Name:my_randomizer-Assignments:{'active':1,'placebo':2}-Model:edc_randomization.myrandomizationlist-Path:/home/me/.etc/randomization_list.csv-Imported5SIDsforrandomizer`my_randomizer`intomodel`edc_randomization.myrandomizationlist`from/home/me/.etc/randomization_list.csv.-VerifiedOK.Manually Export to CSV>>>fromedc_randomization.utilsimportexport_randomization_list>>>export_randomization_list(randomizer_name="default",path="~/",username="erikvw")If the user does not have permissions to view the randomizationlist table, aRandomizationListExporterErrorwill be raised:RandomizationListExporterError:User`erikvw`doesnothavepermissiontoview'edc_randomization.randomizationlist'