def delete(self, dataset_uuid, study_id=None, user=None): """ Delete a dataset from a study given its unique identifier """ prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # Used for helper route using only dataset_uuid if study_id is None: study_id = find_study_id_from_lvl1_uuid("dataset", dataset_uuid, prop_name_to_id) if study_id is None: raise Exception( f"Dataset not found in any study (uuid = {dataset_uuid})") # 1. Get study data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) # 2. Delete specific dataset datasets_entry = study_converter.get_entry_by_name("datasets") datasets_entry.value.delete_nested_entry("uuid", dataset_uuid) if len(datasets_entry.value.value) == 0: study_converter.remove_entries(prop_names=["datasets"]) # 3. Update study state, data and ulpoad on DB message = f"Deleted dataset" update_study(study, study_converter, api.payload, message, user) return {"message": message}
def get(self, dataset_uuid, study_id=None, user=None): """ Fetch a specific dataset for a given study """ args = self._get_parser.parse_args() prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # Used for helper route using only dataset_uuid if study_id is None: study_id = find_study_id_from_lvl1_uuid("dataset", dataset_uuid, prop_name_to_id) if study_id is None: raise Exception( f"Dataset not found in any study (uuid = {dataset_uuid})") study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) # The converter is used for its get_entry_by_name() method study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) datasets_entry = study_converter.get_entry_by_name("datasets") dataset_nested_entry = datasets_entry.value.find_nested_entry( "uuid", dataset_uuid)[0] # The "dataset_nested_entry" entry is a NestedEntry (return list of dict) if args["entry_format"] == "api": return dataset_nested_entry.get_api_format() elif args["entry_format"] == "form": return dataset_nested_entry.get_form_format()
def test_reverse_map(self): input_data = { "key_1": "value_1", "key_2": "value_2", "key_3": "value_3" } expected_output = { "value_1": "key_1", "value_2": "key_2", "value_3": "key_3" } self.assertEqual(reverse_map(input_data), expected_output)
def put(self, dataset_uuid, study_id=None, user=None): """ Update a dataset for a given study """ prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # Used for helper route using only dataset_uuid if study_id is None: study_id = find_study_id_from_lvl1_uuid("dataset", dataset_uuid, prop_name_to_id) if study_id is None: raise Exception( f"Dataset not found in any study (uuid = {dataset_uuid})") payload = api.payload # 1. Split payload form_name = payload["form_name"] entries = payload["entries"] entry_format = payload.get("entry_format", "api") # 2. Get study data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) # 3. Get current dataset data datasets_entry = study_converter.get_entry_by_name("datasets") dataset_nested_entry = datasets_entry.value.find_nested_entry( "uuid", dataset_uuid)[0] dataset_converter = FormatConverter(mapper=prop_id_to_name) dataset_converter.entries = dataset_nested_entry.value # 4. Get new dataset data and get entries to remove new_dataset_converter, entries_to_remove = get_entity_converter( entries, entry_format, prop_id_to_name, prop_name_to_id) # 5. Update current dataset by adding, updating and deleting entries # Nested entries not present in the original form are ignored (example: dataset["samples"]) # won't be deleted if not present in the new data), it needs to be None or "" to be deleted dataset_converter.add_or_update_entries(new_dataset_converter.entries) dataset_converter.remove_entries(entries=entries_to_remove) dataset_nested_entry.value = dataset_converter.entries # 6. Validate dataset data against form validate_form_format_against_form(form_name, dataset_converter.get_form_format()) # 7. Update study state, data and ulpoad on DB message = "Updated dataset" update_study(study, study_converter, payload, message, user) return {"message": message}
def post(self, study_id, user=None): """ Add a new dataset for a given study """ payload = api.payload prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # 1. Split payload form_name = payload["form_name"] entries = payload["entries"] entry_format = payload.get("entry_format", "api") # 2. Get study data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) # 3. Create dataset entry and append it to "datasets" # Format and clean entity dataset_converter, _ = get_entity_converter(entries, entry_format, prop_id_to_name, prop_name_to_id) # Generate UUID dataset_converter, dataset_uuid = add_uuid_entry_if_missing( dataset_converter, prop_name_to_id) study_converter = add_entity_to_study_nested_list( study_converter=study_converter, entity_converter=dataset_converter, prop_name_to_id=prop_name_to_id, study_list_prop="datasets", ) # 4. Validate dataset data against form validate_form_format_against_form(form_name, dataset_converter.get_form_format()) # 5. Update study state, data and ulpoad on DB message = "Added dataset" update_study(study, study_converter, payload, message, user) return {"message": message, "uuid": dataset_uuid}, 201
def post(self, dataset_uuid, study_id=None, user=None): """ Add a new processing event for a given dataset """ prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # Used for helper route using only dataset_uuid if study_id is None: study_id = find_study_id_from_lvl1_uuid("dataset", dataset_uuid, prop_name_to_id) if study_id is None: raise Exception( f"Dataset not found in any study (uuid = {dataset_uuid})") payload = api.payload # 1. Split payload form_name = payload["form_name"] entries = payload["entries"] entry_format = payload.get("entry_format", "api") # 2. Get study and dataset data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) datasets_entry = study_converter.get_entry_by_name("datasets") dataset_nested_entry, dataset_position = datasets_entry.value.find_nested_entry( "uuid", dataset_uuid) # 3. Format and clean processing event data pe_converter, _ = get_entity_converter(entries, entry_format, prop_id_to_name, prop_name_to_id) # 4. Generate UUID pe_converter, pe_uuid = add_uuid_entry_if_missing(pe_converter, prop_name_to_id, replace=False) pe_nested_entry = NestedEntry(pe_converter) pe_nested_entry.value = pe_converter.entries # 5. Check if "process_events"" entry already exist study, creates it if it doesn't pes_entry = dataset_nested_entry.get_entry_by_name("process_events") if pes_entry is not None: pes_entry.value.value.append(pe_nested_entry) else: pes_entry = Entry( FormatConverter(prop_name_to_id)).add_form_format( "process_events", [pe_nested_entry.get_form_format()]) dataset_nested_entry.value.append(pes_entry) datasets_entry.value.value[dataset_position] = dataset_nested_entry # 6. Validate processing data against form validate_form_format_against_form(form_name, pe_converter.get_form_format()) # 7. Update study state, data and ulpoad on DB message = "Added processing event" update_study(study, study_converter, payload, message, user) return {"message": message, "uuid": pe_uuid}, 201
def put(self, sample_uuid, study_id=None, user=None): """ Update a sample for a given study """ prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # Used for helper route using only sample_uuid if study_id is None: study_id = find_study_id_from_lvl1_uuid("sample", sample_uuid, prop_name_to_id) if study_id is None: raise Exception( f"Sample not found in any study (uuid = {sample_uuid})") payload = api.payload # 1. Split payload validate_dict = payload.get("validate", None) form_names = payload.get("form_names", None) entries = payload["entries"] entry_format = payload.get("entry_format", "api") # 2. Get forms for validation forms = {} for key, validate in validate_dict.items(): if validate: forms[key] = app.form_manager.get_form_by_name( form_name=form_names[key]) # 3. Get study data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) # 3. Get current sample data samples_entry = study_converter.get_entry_by_name("samples") sample_nested_entry = samples_entry.value.find_nested_entry( "uuid", sample_uuid)[0] sample_converter = FormatConverter(mapper=prop_id_to_name) sample_converter.entries = sample_nested_entry.value # 4. Unify UUIDs with existing entities (including nested ones) # Format and clean entity new_sample_converter, _ = get_entity_converter(entries, entry_format, prop_id_to_name, prop_name_to_id) new_sample_form_format = new_sample_converter.get_form_format() [new_sample_form_format] = unify_sample_entities_uuids( existing_samples=study_converter.get_form_format().get( "samples", []), new_samples=[new_sample_form_format], ) # 5. Clean new data and get entries to remove # Format and clean entity new_sample_converter, entries_to_remove = get_entity_converter( entries=new_sample_form_format, entry_format="form", prop_id_to_name=None, prop_name_to_id=prop_name_to_id, ) # 6. Update current sample by adding, updating and deleting entries # Nested entries not present in the original form are ignored # won't be deleted if not present in the new data), it needs to be None or "" to be deleted sample_converter.add_or_update_entries(new_sample_converter.entries) sample_converter.remove_entries(entries=entries_to_remove) sample_nested_entry.value = sample_converter.entries # 7. Validate data against form validate_sample_against_form(sample_converter.get_form_format(), validate_dict, forms) # 8. Update study state, data and ulpoad on DB message = "Updated sample" update_study(study, study_converter, payload, message, user) return {"message": message}
def post(self, study_id, user=None): """ Add a new sample for a given study """ payload = api.payload prop_id_to_name = get_property_map(key="id", value="name") prop_name_to_id = reverse_map(prop_id_to_name) # 1. Split payload validate_dict = payload.get("validate", None) form_names = payload.get("form_names", None) entries = payload["entries"] entry_format = payload.get("entry_format", "api") # 2. Get forms for validation forms = {} for key, validate in validate_dict.items(): if validate: forms[key] = app.form_manager.get_form_by_name( form_name=form_names[key]) # 3. Get study data study = Study.objects().get(id=study_id) study_json = marshal(study, study_model) study_converter = FormatConverter(mapper=prop_id_to_name) study_converter.add_api_format(study_json["entries"]) # 4. Unify UUIDs with existing entities (including nested ones) # Format and clean entity sample_converter, _ = get_entity_converter(entries, entry_format, prop_id_to_name, prop_name_to_id) new_sample_form_format = sample_converter.get_form_format() [new_sample_form_format] = unify_sample_entities_uuids( existing_samples=study_converter.get_form_format().get( "samples", []), new_samples=[new_sample_form_format], ) # 5. Append new samples to "samples" in study # Format and clean entity sample_converter, _ = get_entity_converter( entries=new_sample_form_format, entry_format="form", prop_id_to_name=None, prop_name_to_id=prop_name_to_id, ) # Generate UUID (redundant, UUIDs already generated by unify_sample_entities_uuids) sample_converter, sample_uuid = add_uuid_entry_if_missing( sample_converter, prop_name_to_id) study_converter = add_entity_to_study_nested_list( study_converter=study_converter, entity_converter=sample_converter, prop_name_to_id=prop_name_to_id, study_list_prop="samples", ) # 6. Validate data against form validate_sample_against_form(sample_converter.get_form_format(), validate_dict, forms) # 7. Update study state, data and ulpoad on DB message = "Added sample" update_study(study, study_converter, payload, message, user) return {"message": message, "uuid": sample_uuid}, 201