def matchmaker_add(institute_id, case_name): """Add or update a case in MatchMaker""" # check that only authorized users can add patients to MME user_obj = store.user(current_user.email) if "mme_submitter" not in user_obj["roles"]: flash("unauthorized request", "warning") return redirect(request.referrer) institute_obj, case_obj = institute_and_case(store, institute_id, case_name) causatives = False features = False if case_obj.get("suspects") and len(case_obj.get("suspects")) > 3: flash( "At the moment it is not possible to save to MatchMaker more than 3 pinned variants", "warning", ) return redirect(request.referrer) elif case_obj.get("suspects"): causatives = True if case_obj.get("phenotype_terms"): features = True mme_save_options = ["sex", "features", "disorders"] for index, item in enumerate(mme_save_options): if item in request.form: LOG.info("item {} is in request form".format(item)) mme_save_options[index] = True else: mme_save_options[index] = False genomic_features = request.form.get("genomicfeatures") genes_only = True # upload to matchmaker only gene names if genomic_features == "variants": genes_only = False # upload to matchmaker both variants and gene names # If there are no genomic features nor HPO terms to share for this case, abort if (not case_obj.get("suspects") and not mme_save_options[1]) or (causatives is False and features is False): flash( "In order to upload a case to MatchMaker you need to pin a variant or at least assign a phenotype (HPO term)", "danger", ) return redirect(request.referrer) user_obj = store.user(current_user.email) # Required params for sending an add request to MME: mme_base_url = current_app.config.get("MME_URL") mme_accepts = current_app.config.get("MME_ACCEPTS") mme_token = current_app.config.get("MME_TOKEN") if not mme_base_url or not mme_accepts or not mme_token: flash( "An error occurred reading matchmaker connection parameters. Please check config file!", "danger", ) return redirect(request.referrer) add_result = controllers.mme_add( store=store, user_obj=user_obj, case_obj=case_obj, add_gender=mme_save_options[0], add_features=mme_save_options[1], add_disorders=mme_save_options[2], genes_only=genes_only, mme_base_url=mme_base_url, mme_accepts=mme_accepts, mme_token=mme_token, ) # flash MME responses (one for each patient posted) n_succes_response = 0 n_inserted = 0 n_updated = 0 category = "warning" for resp in add_result["server_responses"]: message = resp.get("message") if resp.get("status_code") == 200: n_succes_response += 1 else: flash( "an error occurred while adding patient to matchmaker: {}". format(message), "warning", ) if message == "Patient was successfully updated.": n_updated += 1 elif message == "Patient was successfully inserted into database.": n_inserted += 1 # if at least one patient was inserted or updated into matchmaker, save submission at the case level: if n_inserted or n_updated: category = "success" store.case_mme_update(case_obj=case_obj, user_obj=user_obj, mme_subm_obj=add_result) flash( "Number of new patients in matchmaker:{0}, number of updated records:{1}, number of failed requests:{2}" .format( n_inserted, n_updated, len(add_result.get("server_responses")) - n_succes_response, ), category, ) return redirect(request.referrer)
def matchmaker_add(request, institute_id, case_name): """Add all affected individuals from a case to a MatchMaker server Args: request(werkzeug.local.LocalProxy) institute_id(str): _id of an institute case_name(str): display name of a case """ # Check that general MME request requirements are fulfilled matchmaker_check_requirements(request) _, case_obj = institute_and_case(store, institute_id, case_name) candidate_vars = request.form.getlist("selected_var") if len(candidate_vars) > 3: flash( "At the moment it is not possible to save to MatchMaker more than 3 candidate variants / genes", "warning", ) return redirect(request.referrer) save_gender = "sex" in request.form features = ( hpo_terms(case_obj) if "features" in request.form and case_obj.get("phenotype_terms") else [] ) disorders = omim_terms(store, case_obj) if "disorders" in request.form else [] genes_only = request.form.get("genomicfeatures") == "genes" if not features and not candidate_vars: flash( "In order to upload a case to MatchMaker you need to pin a variant or at least assign a phenotype (HPO term)", "danger", ) return redirect(request.referrer) # create contact dictionary user_obj = store.user(current_user.email) contact_info = { "name": user_obj["name"], "href": "".join(["mailto:", user_obj["email"]]), "institution": "Scout software user, Science For Life Laboratory, Stockholm, Sweden", } submitted_info = { "contact": contact_info, "sex": save_gender, "features": features, "disorders": disorders, "genes_only": genes_only, "patient_id": [], "server_responses": [], } server_responses = [] n_updated = 0 for individual in case_obj.get("individuals"): if not individual["phenotype"] in [ 2, "affected", ]: # include only affected individuals continue patient = { "contact": contact_info, "id": ".".join( [case_obj["_id"], individual.get("individual_id")] ), # This is a required field form MME "label": ".".join([case_obj["display_name"], individual.get("display_name")]), "features": features, "disorders": disorders, } if save_gender: if individual["sex"] == "1": patient["sex"] = "MALE" else: patient["sex"] = "FEMALE" if candidate_vars: g_features = genomic_features( store, case_obj, individual.get("display_name"), candidate_vars, genes_only ) patient["genomicFeatures"] = g_features resp = matchmaker.patient_submit(patient) submitted_info["server_responses"].append( { "patient": patient, "message": resp.get("message"), "status_code": resp.get("status_code"), } ) if resp.get("status_code") != 200: flash( "an error occurred while adding patient to matchmaker: {}".format(resp), "warning", ) continue flash(f"Patient {individual.get('display_name')} saved to MatchMaker", "success") n_updated += 1 if n_updated > 0: store.case_mme_update(case_obj=case_obj, user_obj=user_obj, mme_subm_obj=submitted_info) return n_updated
def test_delete_user_mme_submitter( empty_mock_app, user_obj, case_obj, institute_obj, mme_submission, mme_patient ): """Test deleting a user that is a contact for a MatchMaker Exchange case""" runner = empty_mock_app.test_cli_runner() user_email = user_obj["email"] # GIVEN a user in the database store.user_collection.insert_one(user_obj) ## GIVEN a case with an affected individual saved in MatchMaker store.institute_collection.insert_one(institute_obj) case_obj["individuals"] = [ {"phenotype": 2, "individual_id": "ADM1059A2", "display_name": "NA12882"} ] mme_submission["patients"] = [mme_patient] case_obj["mme_submission"] = mme_submission store.case_collection.insert_one(case_obj) ## GIVEN that user_obj is the MME patient's contact updated_case = store.case_mme_update(case_obj, user_obj, mme_submission) # Submission contact should contain user's email assert updated_case["mme_submission"]["subm_user"] == user_email # And one associated event should be found in database assert store.event_collection.find_one({"verb": "mme_add", "user_id": user_email}) # WHEN using the CLI command to remove the user, then the function should ask to reassign MME case result = runner.invoke(cli, ["delete", "user", "-m", user_email], input="n") # AND user shouldn't be removed if answer is no assert "Aborted" in result.output assert store.user_collection.find_one({"email": user_email}) # User should also not be removed if answer provided is yes, but new contact doesn't exist non_existent_user = "******" result = runner.invoke( cli, ["delete", "user", "-m", user_email], input="\n".join(["y", non_existent_user]) ) assert f"User with email '{non_existent_user}' was not found" in result.output assert store.user_collection.find_one({"email": user_email}) # GIVEN another user with no right over the MME submission new_users_email = "*****@*****.**" result = runner.invoke( cli, [ "load", "user", "-i", institute_obj["_id"], "-u", "Diana Prince", "-m", new_users_email, ], ) assert result.exit_code == 0 # THEN if this user is provided as a new MME contact the remove command should fail again result = runner.invoke( cli, ["delete", "user", "-m", user_email], input="\n".join(["y", new_users_email]) ) assert ( f"Scout user with email '{new_users_email}' doesn't have a 'mme_submitter' role" in result.output ) assert store.user_collection.find_one({"email": user_email}) # GIVEN that the new user has a "mme_submitter" role store.user_collection.find_one_and_update( {"email": new_users_email}, {"$set": {"roles": ["mme_submitter"]}} ) # THEN the new user can be used as a new MME patient's contact result = runner.invoke( cli, ["delete", "user", "-m", user_email], input="\n".join(["y", new_users_email]) ) assert result.exit_code == 0 # AND the old user should be removed assert store.user_collection.find_one({"email": user_email}) is None
def matchmaker_add(institute_id, case_name): """Add or update a case in MatchMaker""" # check that only authorized users can add patients to MME user_obj = store.user(current_user.email) if 'mme_submitter' not in user_obj['roles']: flash('unauthorized request', 'warning') return redirect(request.referrer) institute_obj, case_obj = institute_and_case(store, institute_id, case_name) causatives = False features = False if case_obj.get('suspects') and len(case_obj.get('suspects'))>3: flash('At the moment it is not possible to save to MatchMaker more than 3 pinned variants', 'warning') return redirect(request.referrer) elif case_obj.get('suspects'): causatives = True if case_obj.get('phenotype_terms'): features = True mme_save_options = ['sex', 'features', 'disorders'] for index, item in enumerate(mme_save_options): if item in request.form: log.info('item {} is in request form'.format(item)) mme_save_options[index] = True else: mme_save_options[index] = False genomic_features = request.form.get('genomicfeatures') genes_only = True # upload to matchmaker only gene names if genomic_features == 'variants': genes_only = False # upload to matchmaker both variants and gene names # If there are no genomic features nor HPO terms to share for this case, abort if (not case_obj.get('suspects') and not mme_save_options[1]) or (causatives is False and features is False): flash('In order to upload a case to MatchMaker you need to pin a variant or at least assign a phenotype (HPO term)', 'danger') return redirect(request.referrer) user_obj = store.user(current_user.email) # Required params for sending an add request to MME: mme_base_url = current_app.config.get('MME_URL') mme_accepts = current_app.config.get('MME_ACCEPTS') mme_token = current_app.config.get('MME_TOKEN') if not mme_base_url or not mme_accepts or not mme_token: flash('An error occurred reading matchmaker connection parameters. Please check config file!', 'danger') return redirect(request.referrer) add_result = controllers.mme_add(store=store, user_obj=user_obj, case_obj=case_obj, add_gender=mme_save_options[0], add_features=mme_save_options[1], add_disorders=mme_save_options[2], genes_only=genes_only, mme_base_url = mme_base_url, mme_accepts=mme_accepts, mme_token=mme_token) # flash MME responses (one for each patient posted) n_succes_response = 0 n_inserted = 0 n_updated = 0 category = 'warning' for resp in add_result['server_responses']: message = resp.get('message') if resp.get('status_code') == 200: n_succes_response += 1 else: flash('an error occurred while adding patient to matchmaker: {}'.format(message), 'warning') if message == 'Patient was successfully updated.': n_updated +=1 elif message == 'Patient was successfully inserted into database.': n_inserted +=1 # if at least one patient was inserted or updated into matchmaker, save submission at the case level: if n_inserted or n_updated: category = 'success' store.case_mme_update(case_obj=case_obj, user_obj=user_obj, mme_subm_obj=add_result) flash('Number of new patients in matchmaker:{0}, number of updated records:{1}, number of failed requests:{2}'.format( n_inserted, n_updated, len(add_result.get('server_responses')) - n_succes_response), category) return redirect(request.referrer)