def _update_locus_list_items(locus_list, genes_by_id, intervals, request_json, user): # Update genes for locus_list_gene in locus_list.locuslistgene_set.exclude( gene_id__in=genes_by_id.keys()): delete_seqr_model(locus_list_gene) for gene_id in genes_by_id.keys(): get_or_create_seqr_model( LocusListGene, locus_list=locus_list, gene_id=gene_id, created_by=user, ) # Update intervals genome_version = request_json.get( 'intervalGenomeVersion') or GENOME_VERSION_GRCh37 interval_guids = set() for interval in intervals: interval_model, _ = LocusListInterval.objects.get_or_create( locus_list=locus_list, chrom=interval['chrom'], start=interval['start'], end=interval['end'], genome_version=genome_version, ) interval_guids.add(interval_model.guid) locus_list.locuslistinterval_set.exclude(guid__in=interval_guids).delete()
def _update_locus_list_items(locus_list, genes_by_id, intervals, request_json, user): # Update genes for locus_list_gene in locus_list.locuslistgene_set.exclude(gene_id__in=genes_by_id.keys()): delete_seqr_model(locus_list_gene) for gene_id in genes_by_id.keys(): get_or_create_seqr_model( LocusListGene, locus_list=locus_list, gene_id=gene_id, created_by=user, ) # Update intervals genome_version = request_json.get('intervalGenomeVersion') or GENOME_VERSION_GRCh37 interval_guids = set() for interval in intervals: interval_model, _ = LocusListInterval.objects.get_or_create( locus_list=locus_list, chrom=interval['chrom'], start=interval['start'], end=interval['end'], genome_version=genome_version, ) interval_guids.add(interval_model.guid) locus_list.locuslistinterval_set.exclude(guid__in=interval_guids).delete()
def _create_project(name, description=None, genome_version=None, user=None): """Creates a new project. Args: name (string): Project name description (string): optional description user (object): Django user that is creating this project """ if not name: raise ValueError("Name not specified: %s" % (name,)) project_args = { 'name': name, 'description': description, 'created_by': user, 'deprecated_project_id': _slugify(name), } if genome_version: project_args['genome_version'] = genome_version project, _ = get_or_create_seqr_model(Project, **project_args) if PHENOTIPS_SERVER: try: _enable_phenotips_for_project(project) except Exception as e: logger.error("Unable to create patient in PhenoTips. Make sure PhenoTips is running: %s", e) raise return project
def edit_families_handler(request, project_guid): """Edit or one or more Family records. Args: project_guid (string): GUID of project that contains these individuals. """ request_json = json.loads(request.body) if request_json.get('uploadedFileId'): modified_families = load_uploaded_file( request_json.get('uploadedFileId')) else: modified_families = request_json.get('families') if modified_families is None: return create_json_response({}, status=400, reason="'families' not specified") project = get_project_and_check_permissions(project_guid, request.user, CAN_EDIT) updated_families = [] for fields in modified_families: if fields.get('familyGuid'): family = Family.objects.get(project=project, guid=fields['familyGuid']) elif fields.get(PREVIOUS_FAMILY_ID_FIELD): family = Family.objects.get( project=project, family_id=fields[PREVIOUS_FAMILY_ID_FIELD]) else: family, _ = get_or_create_seqr_model( Family, project=project, family_id=fields[FAMILY_ID_FIELD]) update_family_from_json(family, fields, user=request.user, allow_unknown_keys=True) updated_families.append(family) updated_families_by_guid = { 'familiesByGuid': { family.guid: _get_json_for_family(family, request.user, add_individual_guids_field=True) for family in updated_families } } return create_json_response(updated_families_by_guid)
def edit_families_handler(request, project_guid): """Edit or one or more Family records. Args: project_guid (string): GUID of project that contains these individuals. """ request_json = json.loads(request.body) if request_json.get('uploadedFileId'): modified_families = load_uploaded_file(request_json.get('uploadedFileId')) else: modified_families = request_json.get('families') if modified_families is None: return create_json_response( {}, status=400, reason="'families' not specified") project = get_project_and_check_permissions(project_guid, request.user, CAN_EDIT) updated_families = [] for fields in modified_families: if fields.get('familyGuid'): family = Family.objects.get(project=project, guid=fields['familyGuid']) elif fields.get(PREVIOUS_FAMILY_ID_FIELD): family = Family.objects.get(project=project, family_id=fields[PREVIOUS_FAMILY_ID_FIELD]) else: family, _ = get_or_create_seqr_model(Family, project=project, family_id=fields[FAMILY_ID_FIELD]) update_family_from_json(family, fields, user=request.user, allow_unknown_keys=True) updated_families.append(family) updated_families_by_guid = { 'familiesByGuid': { family.guid: _get_json_for_family(family, request.user, add_individual_guids_field=True) for family in updated_families } } return create_json_response(updated_families_by_guid)
def handle(self, *args, **options): from_project = Project.objects.get(guid=options['from_project']) to_project = Project.objects.get(guid=options['to_project']) family_ids = options['family_ids'] families = Family.objects.filter(project=from_project, family_id__in=family_ids) print('Found {} out of {} families. No match for: {}.'.format( len(families), len(set(family_ids)), set(family_ids) - set([f.family_id for f in families]))) for f in families: print("==> Moving phenotips for {}".format(f)) for seqr_individual in f.individual_set.all(): if phenotips_patient_exists(seqr_individual): # make sure phenotips_patient_id is up to date data_json = _get_patient_data( from_project, seqr_individual, ) seqr_individual.phenotips_patient_id = data_json["id"] seqr_individual.save() # update permissions phenotips_readonly_username, _ = get_phenotips_uname_and_pwd_for_project( to_project.phenotips_user_id, read_only=True) _add_user_to_patient(phenotips_readonly_username, seqr_individual.phenotips_patient_id, allow_edit=False) phenotips_readwrite_username, _ = get_phenotips_uname_and_pwd_for_project( to_project.phenotips_user_id, read_only=False) _add_user_to_patient(phenotips_readwrite_username, seqr_individual.phenotips_patient_id, allow_edit=True) for variant_tag_type in VariantTagType.objects.filter( project=from_project): variant_tags = VariantTag.objects.filter( saved_variant__family__in=families, variant_tag_type=variant_tag_type) if variant_tags: print('Updating "{}" tags'.format(variant_tag_type.name)) to_tag_type, created = get_or_create_seqr_model( VariantTagType, project=to_project, name=variant_tag_type.name) if created: update_seqr_model( to_tag_type, category=variant_tag_type.category, description=variant_tag_type.description, color=variant_tag_type.color, order=variant_tag_type.order, ) variant_tags.update(variant_tag_type=to_tag_type) print("Updating families") families.update(project=to_project) print("Done.")
def add_or_update_individuals_and_families(project, individual_records, user=None): """Add or update individual and family records in the given project. Args: project (object): Django ORM model for the project to add families to individual_records (list): A list of JSON records representing individuals. See the return value of pedigree_info_utils#convert_fam_file_rows_to_json(..) Return: 2-tuple: updated_families, updated_individuals containing Django ORM models """ families = {} updated_individuals = set() parent_updates = [] for i, record in enumerate(individual_records): # family id will be in different places in the json depending on whether it comes from a flat uploaded file or from the nested individual object family_id = record.get(JsonConstants.FAMILY_ID_COLUMN) or record.get('family', {}).get('familyId') if not family_id: raise ValueError("record #%s doesn't contain a 'familyId' key: %s" % (i, record)) if JsonConstants.INDIVIDUAL_ID_COLUMN not in record and 'individualGuid' not in record: raise ValueError("record #%s doesn't contain an 'individualId' key: %s" % (i, record)) family = families.get(family_id) if family: created = False else: family, created = get_or_create_seqr_model(Family, project=project, family_id=family_id) if created: logger.info("Created family: %s", family) # uploaded files do not have unique guid's so fall back to a combination of family and individualId if record.get('individualGuid'): individual_filters = {'guid': record['individualGuid']} else: individual_id = record.get(JsonConstants.PREVIOUS_INDIVIDUAL_ID_COLUMN) or record[JsonConstants.INDIVIDUAL_ID_COLUMN] individual_filters = {'family': family, 'individual_id': individual_id} individual, created = get_or_create_seqr_model(Individual, **individual_filters) if created: record.update({ 'caseReviewStatus': 'I', }) record['family'] = family record.pop('familyId', None) if individual.family != family: families[individual.family.family_id] = individual.family if record.get(JsonConstants.PREVIOUS_INDIVIDUAL_ID_COLUMN): updated_individuals.update(individual.maternal_children.all()) updated_individuals.update(individual.paternal_children.all()) record['displayName'] = '' # Update the parent ids last, so if they are referencing updated individuals they will check for the correct ID if record.get('maternalId') or record.get('paternalId'): parent_updates.append({ 'individual': individual, 'maternalId': record.pop('maternalId', None), 'paternalId': record.pop('paternalId', None), }) update_individual_from_json(individual, record, allow_unknown_keys=True, user=user) updated_individuals.add(individual) families[family.family_id] = family for update in parent_updates: individual = update.pop('individual') update_individual_from_json(individual, update, user=user) updated_families = list(families.values()) # update pedigree images update_pedigree_images(updated_families, project_guid=project.guid) return updated_families, list(updated_individuals)
def add_or_update_individuals_and_families(project, individual_records, user=None): """Add or update individual and family records in the given project. Args: project (object): Django ORM model for the project to add families to individual_records (list): A list of JSON records representing individuals. See the return value of pedigree_info_utils#convert_fam_file_rows_to_json(..) Return: 2-tuple: updated_families, updated_individuals containing Django ORM models """ families = {} updated_individuals = [] for i, record in enumerate(individual_records): # family id will be in different places in the json depending on whether it comes from a flat uploaded file or from the nested individual object family_id = record.get('familyId') or record.get('family', {}).get('familyId') if not family_id: raise ValueError( "record #%s doesn't contain a 'familyId' key: %s" % (i, record)) if 'individualId' not in record and 'individualGuid' not in record: raise ValueError( "record #%s doesn't contain an 'individualId' key: %s" % (i, record)) family, created = get_or_create_seqr_model(Family, project=project, family_id=family_id) if created: logger.info("Created family: %s", family) if not family.display_name: update_seqr_model(family, display_name=family.family_id) # uploaded files do not have unique guid's so fall back to a combination of family and individualId if record.get('individualGuid'): individual_filters = {'guid': record['individualGuid']} else: individual_filters = { 'family': family, 'individual_id': record['individualId'] } individual, created = get_or_create_seqr_model(Individual, **individual_filters) record['family'] = family record.pop('familyId', None) update_individual_from_json(individual, record, allow_unknown_keys=True, user=user) updated_individuals.append(individual) # apply additional json fields which don't directly map to Individual model fields individual.phenotips_eid = individual.guid # use guid instead of indiv_id to avoid collisions if created: # create new PhenoTips patient record patient_record = create_patient(project, individual) update_seqr_model(individual, phenotips_patient_id=patient_record['id'], case_review_status='I') logger.info( "Created PhenoTips record with patient id %s and external id %s" % (str(individual.phenotips_patient_id), str(individual.phenotips_eid))) if record.get(JsonConstants.HPO_TERMS_PRESENT_COLUMN) or record.get( JsonConstants.FINAL_DIAGNOSIS_OMIM_COLUMN): # update phenotips hpo ids logger.info("Setting PhenoTips HPO Terms to: %s" % (record.get(JsonConstants.HPO_TERMS_PRESENT_COLUMN), )) set_patient_hpo_terms( project, individual, hpo_terms_present=record.get( JsonConstants.HPO_TERMS_PRESENT_COLUMN, []), hpo_terms_absent=record.get( JsonConstants.HPO_TERMS_ABSENT_COLUMN, []), final_diagnosis_mim_ids=record.get( JsonConstants.FINAL_DIAGNOSIS_OMIM_COLUMN, [])) if not individual.display_name: update_seqr_model(individual, display_name=individual.individual_id) families[family.family_id] = family updated_families = list(families.values()) # update pedigree images update_pedigree_images(updated_families) return updated_families, updated_individuals
def handle(self, *args, **options): from_project = Project.objects.get(guid=options['from_project']) to_project = Project.objects.get(guid=options['to_project']) to_base_project = find_matching_xbrowse_model(to_project) family_ids = options['family_ids'] families = Family.objects.filter(project=from_project, family_id__in=family_ids) print('Found {} out of {} families. No match for: {}.'.format( len(families), len(set(family_ids)), set(family_ids) - set([f.family_id for f in families]))) for f in families: print("==> Moving {}".format(f)) for seqr_individual in f.individual_set.all(): base_individual = find_matching_xbrowse_model(seqr_individual) base_individual.project = to_base_project base_individual.save() # Update individuals in phenotips if _phenotips_patient_exists(seqr_individual): # make sure phenotips_patient_id is up to date data_json = _get_patient_data( from_project, seqr_individual, ) seqr_individual.phenotips_patient_id = data_json["id"] seqr_individual.save() # update permissions phenotips_readonly_username, _ = _get_phenotips_uname_and_pwd_for_project( to_project.phenotips_user_id, read_only=True) _add_user_to_patient(phenotips_readonly_username, seqr_individual.phenotips_patient_id, allow_edit=False) phenotips_readwrite_username, _ = _get_phenotips_uname_and_pwd_for_project( to_project.phenotips_user_id, read_only=False) _add_user_to_patient(phenotips_readwrite_username, seqr_individual.phenotips_patient_id, allow_edit=True) # Update individuals samples/ VCFs for from_vcf_file in base_individual.vcf_files.all(): to_vcf_file, _ = VCFFile.objects.get_or_create( project=to_base_project, elasticsearch_index=from_vcf_file.elasticsearch_index, file_path=from_vcf_file.file_path, dataset_type=from_vcf_file.dataset_type, sample_type=from_vcf_file.sample_type, loaded_date=from_vcf_file.loaded_date, ) base_individual.vcf_files.add(to_vcf_file) base_individual.vcf_files.remove(from_vcf_file) # Update variant tags/ notes saved_variants = SavedVariant.objects.filter(family=f) for variant_tag in VariantTag.objects.filter( saved_variant__in=saved_variants).select_related( 'variant_tag_type'): if variant_tag.variant_tag_type.project: to_tag_type, created = get_or_create_seqr_model( VariantTagType, project=to_project, name=variant_tag.variant_tag_type.name) if created: update_seqr_model( to_tag_type, category=variant_tag.variant_tag_type.category, description=variant_tag.variant_tag_type. description, color=variant_tag.variant_tag_type.color, order=variant_tag.variant_tag_type.order, ) update_seqr_model(variant_tag, variant_tag_type=to_tag_type) else: to_project_tag, created = ProjectTag.objects.get_or_create( project=to_base_project, tag=variant_tag.variant_tag_type.name) if created: to_project_tag.category = variant_tag.variant_tag_type.category to_project_tag.title = variant_tag.variant_tag_type.description to_project_tag.color = variant_tag.variant_tag_type.color to_project_tag.order = variant_tag.variant_tag_type.order to_project_tag.save() variant_tag.project_tag = to_project_tag variant_tag.save() base_family = find_matching_xbrowse_model(f) for note in BaseVariantNote.objects.filter(family=base_family): note.project = to_base_project note.save() # Update families update_seqr_model(f, project=to_project) print("Done.")