def update_individual_handler(request, individual_guid): """Updates a single field in an Individual record. Args: request (object): Django HTTP Request object. individual_guid (string): GUID of the Individual. Request: body should be a json dictionary like: { 'value': xxx } Response: json dictionary representing the updated individual like: { <individualGuid> : { individualId: xxx, sex: xxx, affected: xxx, ... } } """ individual = Individual.objects.get(guid=individual_guid) project = individual.family.project check_permissions(project, request.user, CAN_EDIT) request_json = json.loads(request.body) update_individual_from_json(individual, request_json, user=request.user, allow_unknown_keys=True) return create_json_response({ individual.guid: _get_json_for_individual(individual, request.user) })
def update_individual_field_handler(request, individual_guid, field_name): """Updates an Individual record. Args: individual_guid (string): GUID of the individual. field_name (string): Name of Individual record field to update (eg. "affected"). """ individual = Individual.objects.get(guid=individual_guid) # check permission project = individual.family.project if not request.user.is_staff and not request.user.has_perm( CAN_EDIT, project): raise PermissionDenied("%s does not have EDIT permissions for %s" % (request.user, project)) request_json = json.loads(request.body) if "value" not in request_json: raise ValueError("Request is missing 'value' key") individual_json = {field_name: request_json['value']} update_individual_from_json(individual, individual_json) return create_json_response( {individual.guid: _get_json_for_individual(individual, request.user)})
def add_or_update_individuals_and_families(project, individual_records): """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 pedigree_info_utils#convert_fam_file_rows_to_json(..) """ families = {} for record in individual_records: family, created = Family.objects.get_or_create( project=project, family_id=record['familyId']) if created: if not family.display_name: family.display_name = family.family_id family.save() logger.info("Created family: %s" % (family, )) individual, created = Individual.objects.get_or_create( family=family, individual_id=record['individualId']) update_individual_from_json(individual, record, allow_unknown_keys=True) # apply additional json fields which don't directly map to Individual model fields individual.phenotips_eid = individual.guid # use this instead of individual_id to avoid chance of collisions if created: # create new PhenoTips patient record patient_record = create_patient(project, individual.phenotips_eid) individual.phenotips_patient_id = patient_record['id'] 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('hpoTerms'): # update phenotips hpo ids logger.info("Setting PhenoTips HPO Terms to: %s" % (record.get('hpoTerms'), )) set_patient_hpo_terms(project, individual.phenotips_eid, record.get('hpoTerms'), is_external_id=True) if not individual.display_name: individual.display_name = individual.individual_id individual.save() _deprecated_update_original_individual_data(project, individual) families[family.family_id] = family # update pedigree images for family in families.values(): update_pedigree_image(family)
def save_individuals_table(request, project_guid, token): """Handler for 'save' requests to apply Individual tables previously uploaded through receive_individuals_table(..) Args: request (object): Django request object project_guid (string): project GUID token (string): a token sent to the client by receive_individuals_table(..) """ project = _get_project_and_check_permissions(project_guid, request.user) serialized_file_path = _compute_serialized_file_path(token) with gzip.open(serialized_file_path) as f: records = json.load(f) families = {} for record in records: family, created = Family.objects.get_or_create(project=project, family_id=record['familyId']) if created: if not family.display_name: family.display_name = family.family_id family.save() logger.info("Created family: %s" % str(family)) individual, created = Individual.objects.get_or_create(family=family, individual_id=record['individualId']) update_individual_from_json(individual, record, allow_unknown_keys=True) individual.phenotips_eid = individual.guid # use this instead of individual_id to avoid chance of collisions if created: patient_record = create_patient(project, individual.phenotips_eid) individual.phenotips_patient_id = patient_record['id'] logger.info("Created phenotips record with patient id %s and external id %s" % ( str(individual.phenotips_patient_id), str(individual.phenotips_eid))) if not individual.case_review_status: individual.case_review_status = Individual.CASE_REVIEW_STATUS_IN_REVIEW if not individual.display_name: individual.display_name = individual.individual_id individual.save() _deprecated_update_original_individual_data(project, individual) families[family.family_id] = family # update pedigree images for family in families.values(): update_pedigree_image(family) # sync events os.remove(serialized_file_path) return create_json_response({})
def update_individual_field_handler(request, individual_guid, field_name): """Updates a single field in an Individual record. Args: request (object): Django HTTP Request object. individual_guid (string): GUID of the Individual. field_name (string): Name of the field to update (eg. "maternalId"). Request: body should be a json dictionary like: { 'value': xxx } Response: json dictionary representing the updated individual like: { <individualGuid> : { individualId: xxx, maternalId: xxx, affected: xxx, ... } } """ individual = Individual.objects.get(guid=individual_guid) project = individual.family.project check_permissions(project, request.user, CAN_EDIT) request_json = json.loads(request.body) if "value" not in request_json: raise ValueError("Request is missing 'value' key: %s" % (request.body, )) individual_json = {field_name: request_json['value']} update_individual_from_json(individual, individual_json) return create_json_response( {individual.guid: _get_json_for_individual(individual, request.user)})
def update_individual_field_handler(request, individual_guid, field_name): """Updates an Individual record. Args: individual_guid (string): GUID of the individual. field_name (string): Name of Individual record field to update (eg. "affected"). """ individual = Individual.objects.get(guid=individual_guid) project = individual.family.project check_permissions(project, request.user, CAN_EDIT) request_json = json.loads(request.body) if "value" not in request_json: raise ValueError("Request is missing 'value' key: %s" % (request.body, )) individual_json = {field_name: request_json['value']} update_individual_from_json(individual, individual_json) return create_json_response( {individual.guid: _get_json_for_individual(individual, request.user)})
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): """ 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 """ updated_families = set() updated_individuals = set() parent_updates = [] family_ids = {_get_record_family_id(record) for record in individual_records} families_by_id = {f.family_id: f for f in Family.objects.filter(project=project, family_id__in=family_ids)} missing_family_ids = family_ids - set(families_by_id.keys()) for family_id in missing_family_ids: family = create_model_from_json(Family, {'project': project, 'family_id': family_id}, user) families_by_id[family_id] = family updated_families.add(family) individual_models = Individual.objects.filter(family__project=project).prefetch_related( 'family', 'mother', 'father') has_individual_guid = any(record.get('individualGuid') for record in individual_records) if has_individual_guid: individual_lookup = { i.guid: i for i in individual_models.filter( guid__in=[record['individualGuid'] for record in individual_records]) } else: individual_lookup = defaultdict(dict) for i in individual_models.filter( individual_id__in=[_get_record_individual_id(record) for record in individual_records]): individual_lookup[i.individual_id][i.family] = i for record in individual_records: family_id = _get_record_family_id(record) family = families_by_id.get(family_id) if has_individual_guid: individual = individual_lookup[record.pop('individualGuid')] else: # uploaded files do not have unique guid's so fall back to a combination of family and individualId individual_id = _get_record_individual_id(record) individual = individual_lookup[individual_id].get(family) if not individual: individual = create_model_from_json( Individual, {'family': family, 'individual_id': individual_id, 'case_review_status': 'I'}, user) record['family'] = family record.pop('familyId', None) if individual.family != family: family = individual.family updated_families.add(family) previous_id = record.pop(JsonConstants.PREVIOUS_INDIVIDUAL_ID_COLUMN, None) if previous_id: 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), }) family_notes = record.pop(JsonConstants.FAMILY_NOTES_COLUMN, None) if family_notes: update_family_from_json(family, {'analysis_notes': family_notes}, user) updated_families.add(family) is_updated = update_individual_from_json(individual, record, user=user, allow_unknown_keys=True) if is_updated: updated_individuals.add(individual) updated_families.add(family) for update in parent_updates: individual = update.pop('individual') is_updated = update_individual_from_json(individual, update, user=user) if is_updated: updated_individuals.add(individual) updated_families.add(individual.family) # update pedigree images update_pedigree_images(updated_families, user, project_guid=project.guid) return list(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 add_or_update_individuals_and_families(project, individual_records): """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): if 'familyId' not in record: raise ValueError( "record #%s doesn't contain a 'familyId' key: %s" % (i, record)) if 'individualId' not in record: raise ValueError( "record #%s doesn't contain an 'individualId' key: %s" % (i, record)) family, created = Family.objects.get_or_create( project=project, family_id=record['familyId']) if created: logger.info("Created family: %s", family) if not family.display_name: family.display_name = family.family_id family.save() individual, created = Individual.objects.get_or_create( family=family, individual_id=record['individualId']) update_individual_from_json(individual, record, allow_unknown_keys=True) 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.phenotips_eid) individual.phenotips_patient_id = patient_record['id'] individual.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('hpoTerms'): # update phenotips hpo ids logger.info("Setting PhenoTips HPO Terms to: %s" % (record.get('hpoTerms'), )) set_patient_hpo_terms(project, individual.phenotips_eid, record.get('hpoTerms'), is_external_id=True) if not individual.display_name: individual.display_name = individual.individual_id individual.save() _deprecated_update_original_individual_data(project, individual) families[family.family_id] = family updated_families = list(families.values()) # update pedigree images update_pedigree_images(updated_families) return updated_families, updated_individuals