cstrittmatter@0: """Ontology finder and visualizer""" cstrittmatter@0: cstrittmatter@0: import copy, json, logging, requests, time cstrittmatter@0: import pygraphviz as pgv cstrittmatter@0: cstrittmatter@0: logging.getLogger('urllib3').setLevel(logging.WARNING) cstrittmatter@0: cstrittmatter@0: cstrittmatter@0: # TODO: figure out what to do with root Thing:Thing cstrittmatter@0: class Ontology_accession: cstrittmatter@0: '''Base class for defining attributes and behavior of single ontology accesions; cstrittmatter@0: Assume format definition (whitespace and punctuation okay):ontology_id''' cstrittmatter@0: existing_ontologies = {} cstrittmatter@0: cstrittmatter@0: @staticmethod cstrittmatter@0: def make_instance(acc): cstrittmatter@0: '''Use instead of default __init__ to enforce one instance per ontology''' cstrittmatter@0: try: cstrittmatter@0: return(Ontology_accession.existing_ontologies[acc]) cstrittmatter@0: except(KeyError): cstrittmatter@0: Ontology_accession.existing_ontologies[acc] = Ontology_accession(acc) cstrittmatter@0: return(Ontology_accession.existing_ontologies[acc]) cstrittmatter@0: cstrittmatter@0: def __init__(self, acc): cstrittmatter@0: '''If ontology is not recognized, just use short form, ex THING''' cstrittmatter@0: def_split = acc.split(':') cstrittmatter@0: self.label = ':'.join(def_split[:-1]) cstrittmatter@0: self.id = def_split[-1].replace('_',':') cstrittmatter@0: self.parents = 'not assigned yet' cstrittmatter@0: self.children = 'not assigned yet' cstrittmatter@0: self.ancestors = 'not assigned yet' cstrittmatter@0: self.descendants = 'not assigned yet' cstrittmatter@0: self.graph_nodes = 'not assigned yet' cstrittmatter@0: self.graph_fill = False cstrittmatter@0: self.ontology = def_split[1].split('_')[0] cstrittmatter@0: if self.label == '': cstrittmatter@0: self._get_label() cstrittmatter@0: cstrittmatter@0: def _api_results(self, input_list, return_list): cstrittmatter@0: '''Ignore obsolete terms, not currently checking for \'term_replaced_by\'''' cstrittmatter@0: for x_term in input_list: cstrittmatter@0: if x_term['is_obsolete']: cstrittmatter@0: continue cstrittmatter@0: new_term = x_term['label'] + ':' + x_term['short_form'] cstrittmatter@0: return_list.append(Ontology_accession.make_instance(new_term)) cstrittmatter@0: return(return_list) cstrittmatter@0: cstrittmatter@0: def _add_edges(self, family_member, family_list, edge_set, round_num): cstrittmatter@0: '''Add edges to graph''' cstrittmatter@0: if edge_set == []: cstrittmatter@0: return(edge_set) cstrittmatter@0: elif round_num > 0: cstrittmatter@0: for x in family_list: cstrittmatter@0: x.get_family(family_member) cstrittmatter@0: if family_member == 'parents': # TODO: how get x.family_member to collapse code cstrittmatter@0: if x.parents == ['none found']: cstrittmatter@0: continue cstrittmatter@0: if len(x.parents) > 5: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: new_edges = [(y._graph_label(),x._graph_label()) for y in x.parents] cstrittmatter@0: edge_set = edge_set + [z for z in new_edges if z not in edge_set] cstrittmatter@0: edge_set = x._add_edges(family_member, x.parents, edge_set, round_num-1) cstrittmatter@0: elif family_member == 'children': cstrittmatter@0: if x.children == ['none found']: cstrittmatter@0: continue cstrittmatter@0: if len(x.children) > 5: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: new_edges = [(x._graph_label(),y._graph_label()) for y in x.children] cstrittmatter@0: edge_set = edge_set + [z for z in new_edges if z not in edge_set] cstrittmatter@0: edge_set = x._add_edges(family_member, x.children, edge_set, round_num-1) cstrittmatter@0: return(edge_set) cstrittmatter@0: cstrittmatter@0: def _draw_graph(self, o_file, node_color, edge_color): cstrittmatter@0: '''Draw and save the graph''' cstrittmatter@0: ontol_graph = pgv.AGraph(name='ontology_graph') cstrittmatter@0: ontol_graph.add_node(self._graph_label()) cstrittmatter@0: for x in self.graph_nodes: cstrittmatter@0: ontol_graph.add_edge(x[0], x[1]) cstrittmatter@0: ontol_graph.node_attr.update(shape='box', cstrittmatter@0: style='rounded,filled', cstrittmatter@0: fillcolor='lightgrey', cstrittmatter@0: color=node_color) cstrittmatter@0: ontol_graph.edge_attr.update(shape='normal', cstrittmatter@0: color=edge_color, cstrittmatter@0: dir='back') cstrittmatter@0: ontol_graph.get_node(self._graph_label()).attr.update(fillcolor='lightblue') cstrittmatter@0: # TODO: determine best algorithm: neato, fdp, nop, twopi; tried circo; not dot, sfdp cstrittmatter@0: ontol_graph.draw(o_file, prog='twopi') cstrittmatter@0: cstrittmatter@0: def _expand_edge(self, family_member, family_list, edge_set, old_set='', stop_terms=False): cstrittmatter@0: '''Add edges to graph''' cstrittmatter@0: while old_set != edge_set: cstrittmatter@0: old_set = copy.deepcopy(edge_set) cstrittmatter@0: for x in family_list: cstrittmatter@0: if x == 'none found': cstrittmatter@0: break cstrittmatter@0: if type(stop_terms) == list: cstrittmatter@0: if x in stop_terms: cstrittmatter@0: break cstrittmatter@0: x.get_family(family_member) cstrittmatter@0: if family_member == 'parents': # TODO: how get x.family_member to collapse code cstrittmatter@0: if x.parents == ['none found']: cstrittmatter@0: continue cstrittmatter@0: if len(x.parents) > 5: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: new_edges = [(y._graph_label(),x._graph_label()) for y in x.parents] cstrittmatter@0: edge_set = edge_set + [z for z in new_edges if z not in edge_set] cstrittmatter@0: edge_set = x._expand_edge(family_member,x.parents,edge_set,old_set,stop_terms) cstrittmatter@0: elif family_member == 'children': cstrittmatter@0: if x.children == ['none found']: cstrittmatter@0: continue cstrittmatter@0: if len(x.children) > 5: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: new_edges = [(x._graph_label(),y._graph_label()) for y in x.children] cstrittmatter@0: edge_set = edge_set + [z for z in new_edges if z not in edge_set] cstrittmatter@0: edge_set = x._expand_edge(family_member,x.children,edge_set,old_set,stop_terms) cstrittmatter@0: return(edge_set) cstrittmatter@0: cstrittmatter@0: def _get_label(self): cstrittmatter@0: '''Retrieve definition is correct for an id; updates instance''' cstrittmatter@0: query_url = 'http://www.ebi.ac.uk/ols/api/terms?obo_id={}'.format(self.id) cstrittmatter@0: ols_resp = self._get_request(query_url) cstrittmatter@0: if ols_resp is None: cstrittmatter@0: logging.warning(f'Did not retrieve PURL for {self.id}') cstrittmatter@0: self.label = 'unk' cstrittmatter@0: return cstrittmatter@0: try: cstrittmatter@0: self.label = ols_resp.json()['_embedded']['terms'][0]['label'] cstrittmatter@0: except(KeyError): cstrittmatter@0: logging.warning(f'Did not find label for {self.id} in OLS') cstrittmatter@0: self.label = 'unk' cstrittmatter@0: except json.decoder.JSONDecodeError as err: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: self._get_label() cstrittmatter@0: cstrittmatter@0: def _get_request(self, request_url, max_retries=5): cstrittmatter@0: '''Retrieve URL''' cstrittmatter@0: while max_retries > 0: cstrittmatter@0: try: cstrittmatter@0: return(requests.get(request_url)) cstrittmatter@0: except: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: max_retries -= 1 cstrittmatter@0: return(None) cstrittmatter@0: cstrittmatter@0: def _graph_label(self): cstrittmatter@0: '''Format a graph label''' cstrittmatter@0: return(self.id+'\\n'+self.label) cstrittmatter@0: cstrittmatter@0: def _next_page(self, url_link, return_list): cstrittmatter@0: '''Get next page of search results''' cstrittmatter@0: next_resp = self._get_request(url_link) cstrittmatter@0: if next_resp is None: cstrittmatter@0: logging.warning(f'Did not retrieve URL for {url_link} during API search') cstrittmatter@0: return(False, return_list) cstrittmatter@0: else: cstrittmatter@0: try: cstrittmatter@0: next_link = next_resp.json()['_links']['next']['href'] cstrittmatter@0: except(KeyError): cstrittmatter@0: next_link = False cstrittmatter@0: return_list = self._api_results(next_resp.json()['_embedded']['terms'], return_list) cstrittmatter@0: return(next_link, return_list) cstrittmatter@0: cstrittmatter@0: def check_label(self): cstrittmatter@0: '''Check if given definition is correct for an id; returns Boolean or str `unk`''' cstrittmatter@0: self._get_label() cstrittmatter@0: if self.label != 'unk': cstrittmatter@0: return(ols_resp.json()['_embedded']['terms'][0]['label'] == self.label) cstrittmatter@0: else: cstrittmatter@0: return(self.label) cstrittmatter@0: cstrittmatter@0: def get_family(self, family_member): cstrittmatter@0: '''Returns list of parents, ancestors, children or descendants''' cstrittmatter@0: if family_member == 'parents' and self.parents != 'not assigned yet': cstrittmatter@0: return(self.parents) cstrittmatter@0: elif family_member == 'children' and self.children != 'not assigned yet': cstrittmatter@0: return(self.children) cstrittmatter@0: elif family_member == 'ancestors' and self.ancestors != 'not assigned yet': cstrittmatter@0: return(self.ancestors) cstrittmatter@0: elif family_member == 'descendants' and self.descendants != 'not assigned yet': cstrittmatter@0: return(self.descendants) cstrittmatter@0: cstrittmatter@0: if self.id.split(':')[0].lower() == 'gaz': cstrittmatter@0: query_url = 'https://www.ebi.ac.uk/ols/api/ontologies/gaz/terms?iri=' cstrittmatter@0: query_url += 'http://purl.obolibrary.org/obo/' + self.id.replace(':','_') cstrittmatter@0: ols_resp = self._get_request(query_url) cstrittmatter@0: qry_url = ols_resp.json()['_embedded']['terms'][0]['_links']\ cstrittmatter@0: ['hierarchical'+family_member.title()]['href'] cstrittmatter@0: else: cstrittmatter@0: query_url = 'http://www.ebi.ac.uk/ols/api/ontologies/{}/{}?id={}' cstrittmatter@0: qry_url = query_url.format(self.id.split(':')[0].lower(),family_member,self.id) cstrittmatter@0: cstrittmatter@0: ols_resp = self._get_request(qry_url) cstrittmatter@0: if ols_resp is None: cstrittmatter@0: logging.warning(f'Did not get URL for {url_link} during search for {family_member}') cstrittmatter@0: result_list = ['none found'] cstrittmatter@0: elif ols_resp.status_code > 200: cstrittmatter@0: result_list = ['none found'] cstrittmatter@0: elif ols_resp.json()['page']['totalElements'] > 0: cstrittmatter@0: result_list = self._api_results(ols_resp.json()['_embedded']['terms'], []) cstrittmatter@0: if ols_resp.json()['page']['totalPages'] > 1: cstrittmatter@0: next_url = ols_resp.json()['_links']['next']['href'] cstrittmatter@0: while next_url: cstrittmatter@0: next_url,result_list = self._next_page(next_url,result_list) cstrittmatter@0: else: cstrittmatter@0: result_list = ['none found'] cstrittmatter@0: cstrittmatter@0: if family_member == 'parents': cstrittmatter@0: self.parents = list(set(result_list)) cstrittmatter@0: elif family_member == 'children': cstrittmatter@0: self.children = list(set(result_list)) cstrittmatter@0: elif family_member == 'ancestors': cstrittmatter@0: self.ancestors = list(set(result_list)) cstrittmatter@0: elif family_member == 'descendants': cstrittmatter@0: self.descendants = list(set(result_list)) cstrittmatter@0: return(result_list) cstrittmatter@0: cstrittmatter@0: def bin_term(self, bin_package): cstrittmatter@0: '''Categorize term into given bins as Ontology_package''' cstrittmatter@0: term_bins = [] cstrittmatter@0: self.get_family('ancestors') cstrittmatter@0: if self.ancestors == ['none found']: cstrittmatter@0: ancestor_labels = [x.label + ':' + x.id.replace(':','_') for x in [self]] cstrittmatter@0: else: cstrittmatter@0: ancestor_labels = [x.label+':'+x.id.replace(':','_') for x in [self]+self.ancestors] cstrittmatter@0: return([x for x in ancestor_labels if x in bin_package.ontologies]) cstrittmatter@0: cstrittmatter@0: def visualize_term(self, o_file, node_color='black', edge_color='black', cstrittmatter@0: fill_out=False, stop_terms=False, draw_graph=True): cstrittmatter@0: '''Visualize one term''' cstrittmatter@0: if self.graph_nodes!='not assigned yet' and self.graph_fill==fill_out: cstrittmatter@0: if draw_graph: cstrittmatter@0: self._draw_graph(o_file, node_color, edge_color) cstrittmatter@0: else: cstrittmatter@0: self.get_family('parents') cstrittmatter@0: self.get_family('children') cstrittmatter@0: edge_set1,edge_set2 = [],[] cstrittmatter@0: if self.parents != ['none found']: cstrittmatter@0: edge_set1 = [(x._graph_label(),self._graph_label()) for x in self.parents] cstrittmatter@0: if self.children != ['none found']: cstrittmatter@0: edge_set2 = [(self._graph_label(),x._graph_label()) for x in self.children] cstrittmatter@0: if type(fill_out) == int: cstrittmatter@0: edge_set1 = self._add_edges('parents', self.parents, edge_set1, fill_out-1) cstrittmatter@0: edge_set2 = self._add_edges('children', self.children, edge_set2, fill_out-1) cstrittmatter@0: elif fill_out==True: cstrittmatter@0: edge_set1 = self._expand_edge('parents',self.parents,edge_set1,'',stop_terms) cstrittmatter@0: edge_set2 = self._expand_edge('children',self.children,edge_set2,'',stop_terms) cstrittmatter@0: self.graph_nodes = list(set(edge_set1+edge_set2)) cstrittmatter@0: if draw_graph: cstrittmatter@0: self._draw_graph(o_file, node_color, edge_color) cstrittmatter@0: cstrittmatter@0: cstrittmatter@0: class Ontology_package: cstrittmatter@0: '''Associate or package Ontology_accession objects together''' cstrittmatter@0: def __init__(self, package_label, ontol_list): cstrittmatter@0: self.label = package_label cstrittmatter@0: self.ontologies = ontol_list cstrittmatter@0: self.bins = [] cstrittmatter@0: self.lcp = 'not assigned yet' cstrittmatter@0: self.hcc = 'not assigned yet' cstrittmatter@0: self._lcp_state = (True,[]) cstrittmatter@0: self._hcc_state = (True,[]) cstrittmatter@0: self._bin_state = [] cstrittmatter@0: self.graph_nodes = 'not assigned yet' cstrittmatter@0: self.graph_state = False cstrittmatter@0: cstrittmatter@0: def _common_family(self,family_member,incl_terms,excl_terms): cstrittmatter@0: '''Find common family members''' cstrittmatter@0: family_candidates = {} cstrittmatter@0: for ontol_term in [x for x in self.ontologies if x.id not in excl_terms]: cstrittmatter@0: family_candidates[ontol_term] = ontol_term.get_family(family_member) cstrittmatter@0: common_members = self._common_list(family_candidates, incl_terms) cstrittmatter@0: while common_members == []: cstrittmatter@0: for ontol_term in [x for x in self.ontologies if x.id not in excl_terms]: cstrittmatter@0: if len(self.ontologies) > 30: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: original_list = list(family_candidates[ontol_term]) cstrittmatter@0: for family_ontol in original_list: cstrittmatter@0: if len(original_list) > 30: cstrittmatter@0: time.sleep(0.05) cstrittmatter@0: try: cstrittmatter@0: family_candidates[ontol_term].extend(\ cstrittmatter@0: family_ontol.get_family(family_member)) cstrittmatter@0: except(AttributeError): cstrittmatter@0: family_candidates[ontol_term].extend(['none found']) cstrittmatter@0: return(common_members) cstrittmatter@0: cstrittmatter@0: def _common_list(self, input_dic, incl_terms): cstrittmatter@0: '''Compare input dictionary keys and list''' cstrittmatter@0: term_lists = [] cstrittmatter@0: for ontol_key in input_dic: cstrittmatter@0: append_list = [ontol_key] cstrittmatter@0: for ontol_val in input_dic[ontol_key]: cstrittmatter@0: append_list.append(ontol_val) cstrittmatter@0: term_lists.append(append_list) cstrittmatter@0: common_set = set.intersection(*map(set, term_lists)) cstrittmatter@0: if incl_terms: cstrittmatter@0: common_keys = [] cstrittmatter@0: for ontol_acc in common_set: cstrittmatter@0: if ontol_acc in input_dic.keys(): cstrittmatter@0: common_keys.append(ontol_acc) cstrittmatter@0: if common_keys != []: cstrittmatter@0: return(common_keys) cstrittmatter@0: return(list(common_set - set(input_dic.keys()))) cstrittmatter@0: cstrittmatter@0: def _draw_graph(self, o_file, node_color, edge_color, show_lcp, show_hcc): cstrittmatter@0: '''Draw and save graph''' cstrittmatter@0: ontol_graph = pgv.AGraph(name='ontology_graph') cstrittmatter@0: for x in self.ontologies: cstrittmatter@0: ontol_graph.add_node(x._graph_label()) cstrittmatter@0: for x in self.graph_nodes: cstrittmatter@0: ontol_graph.add_edge(x[0], x[1]) cstrittmatter@0: ontol_graph.node_attr.update(shape='box', style='rounded,filled', cstrittmatter@0: fillcolor='lightgrey', color=node_color) cstrittmatter@0: ontol_graph.edge_attr.update(shape='normal', color=edge_color, dir='back') cstrittmatter@0: if show_lcp: cstrittmatter@0: for x in self.lcp: cstrittmatter@0: ontol_graph.get_node(x._graph_label()).attr.update(fillcolor='beige') cstrittmatter@0: if show_hcc: cstrittmatter@0: for x in self.hcc: cstrittmatter@0: ontol_graph.get_node(x._graph_label()).attr.update(fillcolor='beige') cstrittmatter@0: for x in self.ontologies: cstrittmatter@0: ontol_graph.get_node(x._graph_label()).attr.update(fillcolor='lightblue') cstrittmatter@0: ontol_graph.draw(o_file,prog='dot') cstrittmatter@0: cstrittmatter@0: def _list_hierarchy(self, input_list, input_position): cstrittmatter@0: '''Get lowest or highest terms''' cstrittmatter@0: if input_list == ['none found']: cstrittmatter@0: return(input_list) cstrittmatter@0: family_lists = {} cstrittmatter@0: for input_term in input_list: cstrittmatter@0: if len(input_list) > 30: time.sleep(0.05) cstrittmatter@0: if input_position == 'lowest': cstrittmatter@0: if input_term == 'none found': cstrittmatter@0: family_list = 'none found' cstrittmatter@0: else: cstrittmatter@0: family_list = input_term.get_family('ancestors') cstrittmatter@0: elif input_position == 'highest': cstrittmatter@0: if input_term == 'none found': cstrittmatter@0: family_list = 'none found' cstrittmatter@0: else: cstrittmatter@0: family_list = input_term.get_family('descendants') cstrittmatter@0: family_lists[input_term] = family_list cstrittmatter@0: while True: cstrittmatter@0: remove_terms = [] cstrittmatter@0: for input_term in input_list: cstrittmatter@0: if [True for f_l in family_lists if input_term in family_lists[f_l]] != []: cstrittmatter@0: del family_lists[input_term] cstrittmatter@0: remove_terms.append(input_term) cstrittmatter@0: if remove_terms != []: cstrittmatter@0: for x_term in remove_terms: cstrittmatter@0: input_list.remove(x_term) cstrittmatter@0: else: cstrittmatter@0: break cstrittmatter@0: return(input_list) cstrittmatter@0: cstrittmatter@0: def _trim_tips(self): cstrittmatter@0: '''Remove descendants of self.ontologies and parents of self.lcp''' cstrittmatter@0: tip_nodes = [x._graph_label() for x in self.ontologies] +\ cstrittmatter@0: [x._graph_label() for x in self.lcp] cstrittmatter@0: old_nodes = [] cstrittmatter@0: while old_nodes != self.graph_nodes: cstrittmatter@0: old_nodes = self.graph_nodes cstrittmatter@0: right_nodes = set() cstrittmatter@0: left_nodes = set() cstrittmatter@0: for x in self.graph_nodes: cstrittmatter@0: left_nodes.add(x[0]) cstrittmatter@0: right_nodes.add(x[1]) cstrittmatter@0: top_nodes = [x for x in left_nodes.difference(right_nodes) if x not in tip_nodes] cstrittmatter@0: bot_nodes = [x for x in right_nodes.difference(left_nodes) if x not in tip_nodes] cstrittmatter@0: self.graph_nodes = [x for x in self.graph_nodes if x[0] not in top_nodes] cstrittmatter@0: self.graph_nodes = [x for x in self.graph_nodes if x[1] not in bot_nodes] cstrittmatter@0: cstrittmatter@0: def get_lcp(self, incl_terms=True, excl_terms=[]): # TODO: missing excl_terms cstrittmatter@0: '''Find lowest common parent(s); can include input terms as lcp, cstrittmatter@0: exclude terms by obo id; saves results in lcp attribute''' cstrittmatter@0: if self._lcp_state == (incl_terms, excl_terms): cstrittmatter@0: if self.lcp != 'not assigned yet': cstrittmatter@0: return cstrittmatter@0: common_members = self._common_family('parents',incl_terms, excl_terms) cstrittmatter@0: common_members = self._list_hierarchy(common_members, 'lowest') cstrittmatter@0: if common_members != []: cstrittmatter@0: self.lcp = common_members cstrittmatter@0: self._lcp_state = (incl_terms, excl_terms) cstrittmatter@0: cstrittmatter@0: def get_hcc(self, incl_terms=True, excl_terms=[]): cstrittmatter@0: '''Get highest common child(ren); can include input terms as hcc; cstrittmatter@0: exclude terms by obo id; saves results in hcc attribute''' cstrittmatter@0: if self._hcc_state == (incl_terms, excl_terms): cstrittmatter@0: if self.hcc != 'not assigned yet': cstrittmatter@0: return cstrittmatter@0: common_members = self._common_family('children', incl_terms, excl_terms) cstrittmatter@0: common_members = self._list_hierarchy(common_members, 'highest') cstrittmatter@0: if common_members != []: cstrittmatter@0: self.hcc = common_members cstrittmatter@0: self._hcc_state = (incl_terms, excl_terms) cstrittmatter@0: cstrittmatter@0: def set_lcp(self, lcp_acc, incl_terms=True, excl_terms=[]): cstrittmatter@0: self.lcp = lcp_acc cstrittmatter@0: self._lcp_state = (incl_terms, excl_terms) cstrittmatter@0: cstrittmatter@0: def set_hcc(self, hcc_acc, incl_terms=True, excl_terms=[]): cstrittmatter@0: self.hcc = hcc_acc cstrittmatter@0: self._hcc_state = (incl_terms, excl_terms) cstrittmatter@0: cstrittmatter@0: def bin_terms(self, bin_package): cstrittmatter@0: '''Categorize terms by those in Ontology_package; saves results in bins attribute''' cstrittmatter@0: if self._bin_state == bin_package: cstrittmatter@0: return cstrittmatter@0: package_bins = [] cstrittmatter@0: for x in self.ontologies: cstrittmatter@0: package_bins.extend(x.bin_term(bin_package)) cstrittmatter@0: self.bins = list(set(package_bins)) cstrittmatter@0: cstrittmatter@0: def visualize_terms(self, o_file, fill_out=False, show_lcp=False, show_hcc=False, cstrittmatter@0: node_color='black', edge_color='black', cstrittmatter@0: lcp_stop=False, hcc_stop=False, trim_nodes=False): cstrittmatter@0: '''Visualize terms''' cstrittmatter@0: if self.graph_nodes=='not assigned yet' or self.graph_fill!=fill_out: cstrittmatter@0: self.graph_nodes = [] cstrittmatter@0: for x in self.ontologies: cstrittmatter@0: if lcp_stop and not hcc_stop: cstrittmatter@0: if x in self.lcp: cstrittmatter@0: continue cstrittmatter@0: x.visualize_term(o_file, fill_out=fill_out, cstrittmatter@0: stop_terms=self.lcp, draw_graph=False) cstrittmatter@0: elif hcc_stop and not lcp_stop: cstrittmatter@0: if x in self.hcc: cstrittmatter@0: continue cstrittmatter@0: x.visualize_term(o_file, fill_out=fill_out, cstrittmatter@0: stop_terms=self.hcc, draw_graph=False) cstrittmatter@0: elif hcc_stop and lcp_stop: cstrittmatter@0: if x in self.lcp+self.hcc: cstrittmatter@0: continue cstrittmatter@0: x.visualize_term(o_file, fill_out=fill_out, cstrittmatter@0: stop_terms=self.lcp+self.hcc, draw_graph=False) cstrittmatter@0: else: cstrittmatter@0: x.visualize_term(o_file, fill_out=fill_out, draw_graph=False) cstrittmatter@0: self.graph_nodes.extend([z for z in x.graph_nodes if z not in self.graph_nodes]) cstrittmatter@0: if trim_nodes: cstrittmatter@0: self._trim_tips() cstrittmatter@0: if len(self.graph_nodes) > 150: cstrittmatter@0: edge_string = 'Parent node\tChild node' cstrittmatter@0: for edge_tuple in self.graph_nodes: cstrittmatter@0: edge_string += '\n'+'\t'.join(edge_tuple) cstrittmatter@0: logging.info(f'Not drawing graph with {len(self.graph_nodes)} edges:\ cstrittmatter@0: \n\n{edge_string}\n') cstrittmatter@0: else: cstrittmatter@0: self._draw_graph(o_file,node_color,edge_color,show_lcp,show_hcc)