def test_error_condition2(self): """Assert raises if randomization_list_model_cls not updated correctly. """ self.populate_list() site = Site.objects.get_current() randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() randomization_list_model_cls.objects.update(site_name=site.name) subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") rando = site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) rando.registered_subject.sid = None rando.registered_subject.save() with self.assertRaises(AlreadyRandomized) as cm: site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) self.assertEqual(cm.exception.code, randomization_list_model_cls._meta.label_lower)
def test_error_condition3(self): """Assert raises if randomization_list_model_cls not updated correctly. """ self.populate_list() site = Site.objects.get(name="gaborone") randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() randomization_list_model_cls.objects.update(site_name=site.name) subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) randomization_list_model_cls.objects.update(subject_identifier=None) with self.assertRaises(AlreadyRandomized) as cm: site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) self.assertEqual(cm.exception.code, "edc_registration.registeredsubject")
def test_for_sites(self): """Assert that allocates by site correctly. """ randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() randomization_list_model_cls.objects.all().delete() self.populate_list(site_names=self.site_names, per_site=5) site_names = [ obj.site_name for obj in randomization_list_model_cls.objects.all() ] shuffle(site_names) assert len(site_names) == len(self.site_names * 5) # consent and randomize 5 for each site for index, site_name in enumerate(site_names): site = Site.objects.get(name=site_name) subject_consent = SubjectConsent.objects.create( subject_identifier=f"12345{index}", site=site, user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) # assert consented subjects were allocated SIDs in the # correct order per site. for site_name in site_names: randomized_subjects = [ (obj.subject_identifier, str(obj.sid)) for obj in randomization_list_model_cls.objects.filter( allocated_site__name=site_name, subject_identifier__isnull=False).order_by("sid") ] for index, obj in enumerate( SubjectConsent.objects.filter( site__name=site_name).order_by("consent_datetime")): rs = RegisteredSubject.objects.get( subject_identifier=obj.subject_identifier) self.assertEqual(obj.subject_identifier, randomized_subjects[index][0]) self.assertEqual(rs.sid, randomized_subjects[index][1]) # clear out any unallocated randomization_list_model_cls.objects.filter( subject_identifier__isnull=True).delete() # assert raises on next attempt to randomize subject_consent = SubjectConsent.objects.create( subject_identifier=f"ABCDEF", site=site, user_created="erikvw") self.assertRaises( AllocationError, site_randomizers.get("ambition"), subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, )
def assignment(self): randomization_list_model_cls = site_randomizers.get( self.randomizer_name).model_cls() subject_identifier = self.cleaned_data.get("subject_identifier") obj = randomization_list_model_cls.objects.get( subject_identifier=subject_identifier) return site_randomizers.get(self.randomizer_name).get_assignment( {"assignment": obj.assignment})
def test_with_consent_ok(self): self.populate_list() site = Site.objects.get_current() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, )
def test_str(self): self.populate_list() site = Site.objects.get(name="gaborone") RandomizationList.objects.update(site_name=site.name) subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) obj = RandomizationList.objects.all().first() self.assertTrue(str(obj))
def test_with_list_selects_first(self): self.populate_list() randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() site = Site.objects.get_current() randomization_list_model_cls.objects.update(site_name=site.name) first_obj = randomization_list_model_cls.objects.all().first() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") rando = site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) self.assertEqual(rando.sid, first_obj.sid)
def test_with_gender_and_consent(self): class RandomizerWithGender(Randomizer): def __init__(self, gender=None, **kwargs): self.gender = gender super().__init__(**kwargs) @property def extra_required_attrs(self): return dict(gender=self.gender) randomizer = site_randomizers.get("default") randomizer.import_list() site = Site.objects.get_current() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, gender=FEMALE, user_created="erikvw") try: RandomizerWithGender( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, gender=FEMALE, user=subject_consent.user_created, ) except Exception as e: self.fail(f"Exception unexpectedly raised. Got {str(e)}.")
class CrfDfHandler(BaseCrfDfHandler): column_handler_cls = ColumnHandler na_value = "." visit_tbl = get_visit_tracking_model().replace(".", "_") enrollment_tbl = "ambition_screening_subjectscreening" rando_tbl = site_randomizers.get("default").model.replace(".", "_") sort_by = ["subject_identifier", "visit_datetime"]
def test_subject_does_not_exist(self): self.populate_list() site = Site.objects.get(name="gaborone") randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() randomization_list_model_cls.objects.update(site_name=site.name) subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, user_created="erikvw") RegisteredSubject.objects.all().delete() self.assertRaises( RandomizationError, site_randomizers.get("ambition"), subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, )
def save(self, *args, **kwargs): self.registered_subject = RegisteredSubject.objects.get( subject_identifier=self.subject_identifier) if self.randomizer_name: randomizer = site_randomizers.get(self.randomizer_name) self.rando_sid = (randomizer.model_cls().objects.get( subject_identifier=self.subject_identifier).sid) super().save(*args, **kwargs)
def test_updates_registered_subject(self): self.populate_list() site = Site.objects.get_current() RandomizationList.objects.update(site_name=site.name) subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) first_obj = RandomizationList.objects.all().first() rs = RegisteredSubject.objects.get(subject_identifier="12345") self.assertEqual(rs.subject_identifier, first_obj.subject_identifier) self.assertEqual(rs.sid, str(first_obj.sid)) self.assertEqual(rs.randomization_datetime, first_obj.allocated_datetime)
def populate_list(self, site_names=None, per_site=None): make_test_list( site_names=site_names or self.site_names, per_site=per_site, full_path=os.path.join( settings.EDC_RANDOMIZATION_LIST_PATH, site_randomizers.get("ambition").filename, ), ) RandomizationListImporter(name="ambition", overwrite=True)
def test_cannot_overwrite(self): site_randomizers._registry = {} site_randomizers.register(MyRandomizer) make_test_list( full_path=MyRandomizer.get_randomization_list_fullpath(), site_names=self.site_names, count=5, ) randomizer = site_randomizers.get(MyRandomizer.name) randomizer.import_list() self.assertRaises(RandomizationListImportError, randomizer.import_list)
def test_invalid_sid(self): # change to a different starting SID RandomizationListImporter(name="ambition") randomization_list_model_cls = site_randomizers.get( "ambition").model_cls() obj = randomization_list_model_cls.objects.all().order_by( "sid").first() obj.sid = 100 obj.save() with self.assertRaises(RandomizationListError) as cm: RandomizationListVerifier(randomizer_name="ambition") self.assertIn("Randomization list has invalid SIDs", str(cm.exception))
def test_with_consent_no_site(self): self.populate_list() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") self.assertRaises( RandomizationError, site_randomizers.get("ambition"), subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=None, user=subject_consent.user_created, )
def test_with_consent_insufficient_data(self): randomizer = site_randomizers.get("default") randomizer.import_list() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") self.assertRaises( RandomizationError, Randomizer, subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=None, )
def test_updates_list_obj_as_allocated(self): self.populate_list() site = Site.objects.get_current() RandomizationList.objects.update(site_name=site.name) RandomizationList.objects.all().first() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) first_obj = RandomizationList.objects.all().first() self.assertEqual(first_obj.subject_identifier, "12345") self.assertTrue(first_obj.allocated) self.assertIsNotNone(first_obj.allocated_user) self.assertEqual(first_obj.allocated_user, subject_consent.user_created) self.assertEqual(first_obj.allocated_datetime, subject_consent.consent_datetime) self.assertGreater(first_obj.modified, subject_consent.modified)
def test_cannot_rerandomize(self): self.populate_list() site = Site.objects.get_current() RandomizationList.objects.update(site_name=site.name) first_obj = RandomizationList.objects.all().first() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", user_created="erikvw") rando = site_randomizers.get("ambition")( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) self.assertEqual(rando.sid, first_obj.sid) self.assertRaises( AlreadyRandomized, site_randomizers.get("ambition"), subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, )
def test_can_overwrite_explicit(self): site_randomizers._registry = {} site_randomizers.register(MyRandomizer) make_test_list( full_path=MyRandomizer.get_randomization_list_fullpath(), site_names=self.site_names, count=5, ) randomizer = site_randomizers.get(MyRandomizer.name) try: randomizer.import_list(overwrite=True) except RandomizationListImportError: self.fail("RandomizationListImportError unexpectedly raised")
def get_subject_by_assignment(self, assignment): randomization_list_model_cls = site_randomizers.get( self.randomizer_name ).model_cls() for _ in range(0, 4): subject_identifier = self.create_subject() obj = randomization_list_model_cls.objects.get( subject_identifier=subject_identifier ) if Randomizer.get_assignment({"assignment": obj.assignment}) == assignment: return subject_identifier raise ValueError( f"Subject identifier cannot be None. Git assignment={assignment}" )
def subject_consent_on_post_save(sender, instance, raw, created, **kwargs): """Creates an onschedule instance for this consented subject, if it does not exist. """ if not raw: if not created: _, schedule = site_visit_schedules.get_by_onschedule_model( "ambition_prn.onschedule" ) schedule.refresh_schedule(subject_identifier=instance.subject_identifier) else: subject_screening = SubjectScreening.objects.get( screening_identifier=instance.screening_identifier ) subject_screening.subject_identifier = instance.subject_identifier subject_screening.consented = True subject_screening.save_base( update_fields=["subject_identifier", "consented"] ) # randomize Randomizer = site_randomizers.get("ambition") Randomizer( subject_identifier=instance.subject_identifier, report_datetime=instance.consent_datetime, site=instance.site, user=instance.user_created, ) # put subject on schedule _, schedule = site_visit_schedules.get_by_onschedule_model( "ambition_prn.onschedule" ) schedule.put_on_schedule( subject_identifier=instance.subject_identifier, onschedule_datetime=instance.consent_datetime, ) # create / delete action for reconsent if instance.completed_by_next_of_kin == YES: ReconsentAction(subject_identifier=instance.subject_identifier) else: try: delete_action_item( action_cls=ReconsentAction, subject_identifier=instance.subject_identifier, ) except ActionItemDeleteError: pass
def test_invalid_assignment(self): # change to a different assignments assignments = [100, 101] make_test_list( full_path=os.path.join( settings.EDC_RANDOMIZATION_LIST_PATH, site_randomizers.get("ambition").filename, ), site_names=self.site_names, assignments=assignments, count=5, ) self.assertRaises(InvalidAssignment, RandomizationListImporter, name="ambition")
def test_with_consent(self): randomizer = site_randomizers.get("default") randomizer.import_list() site = Site.objects.get_current() subject_consent = SubjectConsent.objects.create( subject_identifier="12345", site=site, user_created="erikvw") try: Randomizer( subject_identifier=subject_consent.subject_identifier, report_datetime=subject_consent.consent_datetime, site=subject_consent.site, user=subject_consent.user_created, ) except Exception as e: self.fail(f"Exception unexpectedly raised. Got {str(e)}.")
def populate_list(self, randomizer_name=None, site_names=None, per_site=None, overwrite_site=None): randomizer = site_randomizers.get(randomizer_name) make_test_list( full_path=randomizer.get_randomization_list_fullpath(), site_names=site_names or self.site_names, per_site=per_site, ) randomizer.import_list(overwrite=True) if overwrite_site: site = Site.objects.get_current() randomizer.model_cls().objects.update(site_name=site.name)
def assignment_description(self): Randomizer = site_randomizers.get(self.randomizer_name) subject_identifier = is_subject_identifier_or_raise( self.kwargs.get("subject_identifier")) try: obj = Randomizer.model_cls().objects.get( subject_identifier=subject_identifier) except ObjectDoesNotExist as e: current_site = Site.objects.get_current() total = (Randomizer.model_cls().objects.filter( site_name=current_site.name).count()) available = (Randomizer.model_cls().objects.filter( site_name=current_site.name, allocated=False).count()) raise RandomizationError( f"Subject {subject_identifier}. " f"Found {available}/{total} available records for {current_site}. Got {e}" ) return obj.assignment_description
def __init__(self, randomizer_name=None, fieldnames=None): self.messages = [] self.randomizer = site_randomizers.get(randomizer_name) if not self.randomizer: raise RandomizationListError( f"Randomizer not registered. Got `{randomizer_name}`") self.fieldnames = fieldnames or self.default_fieldnames try: self.count = self.randomizer.model_cls().objects.all().count() except (ProgrammingError, OperationalError) as e: self.messages.append(str(e)) else: if self.count == 0: self.messages.append( "Randomization list has not been loaded. " "Run the 'import_randomization_list' management command " "to load before using the system. " "Resolve this issue before using the system.") else: if not self.randomizer.get_randomization_list_path( ) or not os.path.exists( self.randomizer.get_randomization_list_path()): self.messages.append( f"Randomization list file does not exist but SIDs " f"have been loaded. Expected file " f"{self.randomizer.get_randomization_list_path()}. " f"Resolve this issue before using the system.") else: message = self.verify_list() if message: self.messages.append(message) if self.messages: if ("migrate" not in sys.argv and "makemigrations" not in sys.argv and "import_randomization_list" not in sys.argv): raise RandomizationListError(", ".join(self.messages))
class RandomizationList(RandomizationListModelMixin, BaseUuidModel): randomizer_cls = site_randomizers.get("ambition") assignment = EncryptedTextField(choices=((SINGLE_DOSE, SINGLE_DOSE_NAME), (CONTROL, CONTROL_NAME)), ) allocation = EncryptedTextField(verbose_name="Original integer allocation", null=True) @property def assignment_description(self): if self.assignment == CONTROL: assignment_description = CONTROL_NAME elif self.assignment == SINGLE_DOSE: assignment_description = SINGLE_DOSE_NAME else: raise RandomizationError( f"Invalid assignment. Expected one of [{CONTROL}, {SINGLE_DOSE}]. " f"Got `{self.assignment}`") return assignment_description class Meta(RandomizationListModelMixin.Meta): pass
def test_(self): randomizer = site_randomizers.get("default") randomizer.import_list()