from urllib.parse import urlencode, urljoin from pymonad.maybe import Just, Maybe from pymonad.tools import curry import requests from gn3.monads import MonadicDict from gn2.utility.hmac import hmac_creation from gn2.utility.tools import GN3_LOCAL_URL from gn2.base import webqtlConfig # KLUDGE: Due to the lack of pagination, we hard-limit the maximum # number of search results. MAX_SEARCH_RESULTS = 10000 class GSearch: def __init__(self, kwargs): if ("type" not in kwargs) or ("terms" not in kwargs): raise ValueError self.type = kwargs["type"] self.terms = kwargs["terms"] # FIXME: Handle presentation (that is, formatting strings for # display) in the template rendering, not when retrieving # search results. chr_mb = curry(2, lambda chr, mb: f"Chr{chr}: {mb:.6f}") format3f = lambda x: f"{x:.3f}" hmac = curry(3, lambda trait_name, dataset, data_hmac: f"{trait_name}:{dataset}:{data_hmac}") convert_lod = lambda x: x / 4.61 self.trait_list = [] response = requests.get( urljoin(GN3_LOCAL_URL, "/api/search?" + urlencode({"query": self.terms, "type": self.type, "per_page": MAX_SEARCH_RESULTS}))) if response.status_code == 400 and "parsererror" in response.text.lower(): raise ValueError(f"Query `{self.terms}` has a problem: {response.json()}") response.raise_for_status() response_json = response.json() for i, trait in enumerate(response_json): trait = MonadicDict(trait) trait["index"] = Just(i) trait["location_repr"] = (Maybe.apply(chr_mb) .to_arguments(trait.pop("chr"), trait.pop("mb"))) trait["LRS_score_repr"] = trait.pop("lrs").map(convert_lod).map(format3f) trait["additive"] = trait["additive"].map(format3f) trait["mean"] = trait["mean"].map(format3f) trait["max_lrs_text"] = (Maybe.apply(chr_mb) .to_arguments(trait.pop("geno_chr"), trait.pop("geno_mb"))) if self.type == "gene": trait["hmac"] = (Maybe.apply(hmac) .to_arguments(trait['name'], trait['dataset'], Just(hmac_creation(f"{trait['name']}:{trait['dataset']}")))) elif self.type == "phenotype": trait["display_name"] = trait["name"] inbredsetcode = trait.pop("inbredsetcode") if inbredsetcode.map(len) == Just(3): trait["display_name"] = (Maybe.apply( curry(2, lambda inbredsetcode, name: f"{inbredsetcode}_{name}")) .to_arguments(inbredsetcode, trait["name"])) trait["hmac"] = (Maybe.apply(hmac) .to_arguments(trait['name'], trait['dataset'], Just(hmac_creation(f"{trait['name']}:{trait['dataset']}")))) trait["authors_display"] = (trait.pop("authors").map( lambda authors: ", ".join(authors[:2] + ["et al."] if len(authors) >=2 else authors))) trait["pubmed_text"] = trait["year"].map(str) self.trait_list.append(trait.data) self.trait_count = len(self.trait_list)