From f1876f8b9939a9b863dc88aab8d3fed3c16ad4e1 Mon Sep 17 00:00:00 2001 From: Muriithi Frederick Muriuki Date: Thu, 5 Aug 2021 13:08:57 +0300 Subject: Reorganise the database code Issue: https://github.com/genenetwork/gn-gemtext-threads/blob/main/topics/gn1-migration-to-gn2/clustering.gmi * Reorganise the code to separate the datasets from the traits, and to more closely conform to the same flow as that in GN1 --- gn3/db/traits.py | 171 ++++++++++++++++++++++++------------------------------- 1 file changed, 73 insertions(+), 98 deletions(-) (limited to 'gn3/db/traits.py') diff --git a/gn3/db/traits.py b/gn3/db/traits.py index 9f89510..85cccfa 100644 --- a/gn3/db/traits.py +++ b/gn3/db/traits.py @@ -1,6 +1,7 @@ """This class contains functions relating to trait data manipulation""" from typing import Any, Dict, Union from gn3.function_helpers import compose +from gn3.db.datasets import retrieve_trait_dataset def get_trait_csv_sample_data(conn: Any, @@ -77,41 +78,6 @@ def update_sample_data(conn: Any, return (updated_strains, updated_published_data, updated_se_data, updated_n_strains) -def retrieve_trait_dataset_name( - trait_type: str, threshold: int, name: str, connection: Any): - """ - Retrieve the name of a trait given the trait's name - - This is extracted from the `webqtlDataset.retrieveName` function as is - implemented at - https://github.com/genenetwork/genenetwork1/blob/master/web/webqtl/base/webqtlDataset.py#L140-L169 - """ - table_map = { - "ProbeSet": "ProbeSetFreeze", - "Publish": "PublishFreeze", - "Geno": "GenoFreeze", - "Temp": "TempFreeze"} - columns = "Id, Name, FullName, ShortName{}".format( - ", DataScale" if trait_type == "ProbeSet" else "") - query = ( - "SELECT %(columns)s " - "FROM %(table)s " - "WHERE " - "public > %(threshold)s " - "AND " - "(Name = %(name)s OR FullName = %(name)s OR ShortName = %(name)s)") - with connection.cursor() as cursor: - cursor.execute( - query, - { - "table": table_map[trait_type], - "columns": columns, - "threshold": threshold, - "name": name - }) - return cursor.fetchone() - - def retrieve_publish_trait_info(trait_data_source: Dict[str, Any], conn: Any): """Retrieve trait information for type `Publish` traits. @@ -156,11 +122,11 @@ def retrieve_publish_trait_info(trait_data_source: Dict[str, Any], conn: Any): }) return dict(zip([k.lower() for k in keys], cursor.fetchone())) -def set_confidential_field(trait_info): +def set_confidential_field(trait_type, trait_info): """Post processing function for 'Publish' trait types. It sets the value for the 'confidential' key.""" - if trait_info["type"] == "Publish": + if trait_type == "Publish": return { **trait_info, "confidential": 1 if ( @@ -271,7 +237,7 @@ def set_homologene_id_field_probeset(trait_info, conn): return {**trait_info, "homologeneid": res[0]} return {**trait_info, "homologeneid": None} -def set_homologene_id_field(trait_info, conn): +def set_homologene_id_field(trait_type, trait_info, conn): """ Common postprocessing function for all trait types. @@ -283,84 +249,83 @@ def set_homologene_id_field(trait_info, conn): "Publish": set_to_null, "ProbeSet": lambda ti: set_homologene_id_field_probeset(ti, conn) } - return functions_table[trait_info["type"]](trait_info) + return functions_table[trait_type](trait_info) -def set_geno_riset_fields(name, conn): - """ - Retrieve the RISet, and RISetID values for various Geno trait types. - """ +def load_publish_qtl_info(trait_info, conn): query = ( - "SELECT InbredSet.Name, InbredSet.Id " - "FROM InbredSet, GenoFreeze " - "WHERE GenoFreeze.InbredSetId = InbredSet.Id " - "AND GenoFreeze.Name = %(name)s") + "SELECT PublishXRef.Locus, PublishXRef.LRS, PublishXRef.additive " + "FROM PublishXRef, PublishFreeze " + "WHERE PublishXRef.Id = %(trait_name)s " + "AND PublishXRef.InbredSetId = PublishFreeze.InbredSetId " + "AND PublishFreeze.Id = %(dataset_id)s") with conn.cursor() as cursor: - return cursor.execute(query, {"name": name}) + cursor.execute() + return dict(zip(["locus", "lrs", "additive"], cursor.fetchone())) + return {"locus": "", "lrs": "", "additive": ""} -def set_publish_riset_fields(name, conn): - """ - Retrieve the RISet, and RISetID values for various Publish trait types. - """ +def load_probeset_qtl_info(trait_info, conn): query = ( - "SELECT InbredSet.Name, InbredSet.Id " - "FROM InbredSet, PublishFreeze " - "WHERE PublishFreeze.InbredSetId = InbredSet.Id " - "AND PublishFreeze.Name = %(name)s") + "SELECT ProbeSetXRef.Locus, ProbeSetXRef.LRS, ProbeSetXRef.pValue, " + "ProbeSetXRef.mean, ProbeSetXRef.additive " + "FROM ProbeSetXRef, ProbeSet " + "WHERE ProbeSetXRef.ProbeSetId = ProbeSet.Id " + " AND ProbeSet.Name = %(trait_name)s " + "AND ProbeSetXRef.ProbeSetFreezeId = %(dataset_id)s") with conn.cursor() as cursor: - return cursor.execute(query, {"name": name}) + cursor.execute() + return dict(zip( + ["locus", "lrs", "pvalue", "mean", "additive"], cursor.fetchone())) + return {"locus": "", "lrs": "", "pvalue": "", "mean": "", "additive": ""} -def set_probeset_riset_fields(name, conn): - """ - Retrieve the RISet, and RISetID values for various ProbeSet trait types. - """ - query = ( - "SELECT InbredSet.Name, InbredSet.Id " - "FROM InbredSet, ProbeSetFreeze, ProbeFreeze " - "WHERE ProbeFreeze.InbredSetId = InbredSet.Id " - "AND ProbeFreeze.Id = ProbeSetFreeze.ProbeFreezeId " - "AND ProbeSetFreeze.Name = %(name)s") - with conn.cursor() as cursor: - return cursor.execute(query, {"name": name}) - -def set_riset_fields(trait_info, conn): - """ - Retrieve the RISet, and RISetID values for various trait types. - """ - riset_functions_map = { - "Temp": lambda ti, con: (None, None), - "Geno": set_geno_riset_fields, - "Publish": set_publish_riset_fields, - "ProbeSet": set_probeset_riset_fields +def load_qtl_info(qtl, trait_type, trait_info, conn): + if not qtl: + return trait_info + qtl_info_functions = { + "Publish": load_publish_qtl_info, + "ProbeSet": load_probeset_qtl_info } - if not trait_info.get("haveinfo", None): + if trait_inf["name"] not in qtl_info_functions.keys(): return trait_info - riset, riid = riset_functions_map[trait_info["type"]]( - trait_info["name"], conn) - return { - **trait_info, "risetid": riid, - "riset": "BXD" if riset == "BXD300" else riset} + return qtl_info_functions[trait_type](trait_info, conn) def build_trait_name(trait_fullname): name_parts = trait_fullname.split("::") assert len(name_parts) >= 2, "Name format error" return { - "trait_db": name_parts[0], + "db": {"dataset_name": name_parts[0]}, "trait_fullname": trait_fullname, "trait_name": name_parts[1], "cellid": name_parts[2] if len(name_parts) == 3 else "" } +def retrieve_probeset_sequence(trait, conn): + query = ( + "SELECT ProbeSet.BlatSeq " + "FROM ProbeSet, ProbeSetFreeze, ProbeSetXRef " + "WHERE ProbeSet.Id=ProbeSetXRef.ProbeSetId " + "AND ProbeSetFreeze.Id = ProbeSetXRef.ProbeSetFreezeId " + "AND ProbeSet.Name = %(trait_name)s " + "AND ProbeSetFreeze.Name = %(dataset_name)s") + with conn.cursor() as cursor: + cursor.execute( + query, + { + "trait_name": trait["trait_name"], + "dataset_name": trait["db"]["dataset_name"] + }) + seq = cursor.fetchone() + return {**trait, "sequence": seq[0] if seq else ""} + def retrieve_trait_info( - trait_type: str, trait_full_name: str, trait_dataset_id: int, - trait_dataset_name: str, conn: Any, qtl=None): + trait_type: str, threshold: int, trait_full_name: str, conn: Any, + qtl=None): """Retrieves the trait information. https://github.com/genenetwork/genenetwork1/blob/master/web/webqtl/base/webqtlTrait.py#L397-L456 This function, or the dependent functions, might be incomplete as they are currently.""" - # pylint: disable=[R0913] trait = build_trait_name(trait_full_name) trait_info_function_table = { "Publish": retrieve_publish_trait_info, @@ -370,15 +335,19 @@ def retrieve_trait_info( } common_post_processing_fn = compose( - lambda ti: set_riset_fields(ti, conn), - lambda ti: set_homologene_id_field(ti, conn), - lambda ti: {"type": trait_type, **ti}, - lambda ti: {**ti, **trait}, + lambda ti: load_qtl_info(qtl, trait_type, ti, conn), + lambda ti: set_homologene_id_field(trait_type, ti, conn), + lambda ti: {"trait_type": trait_type, **ti}, + lambda ti: {**trait, **ti}, set_haveinfo_field) trait_post_processing_functions_table = { - "Publish": compose(set_confidential_field, common_post_processing_fn), - "ProbeSet": compose(common_post_processing_fn), + "Publish": compose( + lambda ti: set_confidential_field(trait_type, ti), + common_post_processing_fn), + "ProbeSet": compose( + lambda ti: retrieve_probeset_sequence(ti, conn), + common_post_processing_fn), "Geno": common_post_processing_fn, "Temp": common_post_processing_fn } @@ -387,10 +356,16 @@ def retrieve_trait_info( trait_post_processing_functions_table[trait_type], trait_info_function_table[trait_type]) - return retrieve_info( + trait_dataset = retrieve_trait_dataset(trait_type, trait, threshold, conn) + trait_info = retrieve_info( { "trait_name": trait["trait_name"], - "trait_dataset_id": trait_dataset_id, - "trait_dataset_name":trait_dataset_name + "trait_dataset_id": trait_dataset["dataset_id"], + "trait_dataset_name": trait_dataset["dataset_name"] }, conn) + return { + **trait_info, + "db": {**trait["db"], **trait_dataset}, + "riset": trait_dataset["riset"] + } -- cgit v1.2.3