fromcollectionsimportnamedtuplefromPyQt4.QtCoreimportQTimer,pyqtSlotasSlotimportOrange.dataimportOrange.networkimportOrange.featurefromOrange.OrangeWidgetsimportOWWidgetfromOrange.OrangeWidgetsimportOWGUIfromOrange.OrangeWidgetsimportOWItemModelsfromOrange.OrangeWidgets.OWConcurrentimportThreadExecutor,Futurefrom..importppi,taxonomy,geneNAME="Gene Network"DESCRIPTION="Extract a gene network for a set of genes."ICON="icons/GeneNetwork.svg"INPUTS=[("Data",Orange.data.Table,"set_data")]OUTPUTS=[("Network",Orange.network.Graph),("Items",Orange.data.Table)]Source=namedtuple("Source",["name","constructor","sf_domain","sf_filename"])SOURCES=[Source("BioGRID",ppi.BioGRID,"PPI",ppi.BioGRID.SERVER_FILE),# Source("STRING", ppi.STRING, "PPI", ppi.STRING.FILENAME)]classOWGeneNetwork(OWWidget.OWWidget):settingsList=["taxid","genes_in_row","network_source","include_neighborhood"]contextHandlers={"":OWWidget.DomainContextHandler("",["taxid","gene_var_index","genes_in_row"])}def__init__(self,parent=None,signalManager=None,title="Gene Network"):super(OWGeneNetwork,self).__init__(parent,signalManager,title,wantMainArea=False)self.taxid="9606"self.gene_var_index=-1self.genes_in_rows=Falseself.network_source=0self.include_neighborhood=Trueself.autocommit=Falseself.loadSettings()self.taxids=taxonomy.common_taxids()self.current_taxid_index=self.taxids.index(self.taxid)self.db=Noneself.data=Noneself.geneinfo=Noneself._invalidated=Falsebox=OWGUI.widgetBox(self.controlArea,"Info")self.info=OWGUI.widgetLabel(box,"No input\n")box=OWGUI.widgetBox(self.controlArea,"Network Source")OWGUI.comboBox(box,self,"network_source",items=[s.nameforsinSOURCES],callback=self._update_source_db)box=OWGUI.widgetBox(self.controlArea,"Organism")self.organism_cb=OWGUI.comboBox(box,self,"current_taxid_index",items=map(taxonomy.name,self.taxids),callback=self._update_organism)box=OWGUI.widgetBox(self.controlArea,"Genes")self.genes_cb=OWGUI.comboBox(box,self,"gene_var_index",callback=self._update_query_genes)self.varmodel=OWItemModels.VariableListModel()self.genes_cb.setModel(self.varmodel)OWGUI.checkBox(box,self,"genes_in_rows","Use attribute names",callback=self._update_query_genes)box=OWGUI.widgetBox(self.controlArea,"Neighborhood")OWGUI.checkBox(box,self,"include_neighborhood","Include immediate neighborers",callback=self.invalidate)box=OWGUI.widgetBox(self.controlArea,"Commit")# cb = OWGUI.checkBox(box, self, "autocommit")OWGUI.button(box,self,"Commit",callback=self.commit,default=True)self.executor=ThreadExecutor()# QTimer.singleShot(0, self.initialize)self._update_source_db()self._update_organism()@Slot()definitialize(self):ifself.dbisNone:self.db=ppi.BioGRID()defset_data(self,data):self.closeContext()self.data=dataifdataisnotNone:self.varmodel[:]=string_variables(data.domain)self.openContext("",data)# self._update_info()self.commit()else:self.varmodel[:]=[]defset_source_db(self,dbindex):self.network_source=dbindex# by taxid??self.db=SOURCES[self.network_source]()self.invalidate()defset_organism(self,index):self.current_taxid_index=indexself.taxid=self.taxids[index]self.invalidate()defset_gene_var(self,index):self.gene_var_index=indexself.invalidate()defquery_genes(self):ifself.gene_var_index>=0:var=self.varmodel[self.gene_var_index]genes=[unicode(inst[var])forinstinself.dataifnotinst[var].isSpecial()]returnlist(unique(genes))else:return[]definvalidate(self):self._invalidated=Trueifself.autocommit:QTimer.singleShot(0,self._maybe_commit)@Slot()def_maybe_commit(self):ifself._invalidated:self.commit()defcommit(self):gene_var=self.varmodel[self.gene_var_index]query_genes=self.query_genes()geneinfo=self.geneinfo.result()ppidb=self._dbtax_map=self._tax_mappingtaxid=tax_map.get(self.taxid,None)iftaxidisNone:raiseValueError# Normalize the names to ppidb primary keysmatcher=geneinfo.matcherquery_genes=zip(query_genes,map(matcher.umatch,query_genes))synonyms=ppidb_synonym_mapping(ppidb,taxid)query_genes=[(query_gene,geneid,synonyms.get(geneid,None))forquery_gene,geneidinquery_genes]query=[(syn[0],query_gene)forquery_gene,_,syninquery_genesifsyn]net=extract_network(ppidb,dict(query),geneinfo,self.include_neighborhood)# Items has the same domain as the input with query instances# corresponding to nodes where applicable (if include_neighborhood# then nodes not contained in the query will have instances with all# unknown valuesdata_by_query_name={str(inst[gene_var]):instforinstinself.data}items=Orange.data.Table(self.data.domain)fornodeid,nodeinsorted(net.nodes(data=True)):if"query_name"innode:items.append(data_by_query_name[node["query_name"]])else:items.append(Orange.data.Instance(self.data.domain))self.send("Network",net)self.send("Items",items)self._invalidated=Falsedeffetch_db(self,which):passdef_update_source_db(self):source=ppi.BioGRID()orgs=map(str,source.organisms())tax_mapping=taxonomy_match(orgs,self.taxids)tax_mapping={common_tax:db_taxfordb_tax,common_taxintax_mapping.items()ifcommon_taxisnotNone}# TODO: Disable the items in Organism combo box that are not# in this list.# model = self.organism_cb.model()# for i, taxid in self.taxids:# enabled = taxid in tax_mappingself._db=sourceself._tax_mapping=tax_mappingself.invalidate()def_update_organism(self):self.taxid=self.taxids[self.current_taxid_index]ifself.geneinfoisnotNone:self.geneinfo.cancel()self.geneinfo=self.executor.submit(lambda:gene.NCBIGeneInfo(self.taxid))self.invalidate()def_update_query_genes(self):self.invalidate()defunique(seq):seen=set()forelinseq:ifelnotinseen:seen.add(el)yieldeldefstring_variables(domain):variables=domain.variables+domain.getmetas().values()return[vforvinvariablesifisinstance(v,Orange.feature.String)]defmultimap_inverse(multimap):""" Return a multimap inverse relation. """d={}forkey,valuesinmultimap.iteritems():forvinvalues:d.setdefault(v,[]).append(key)returnddefppidb_synonym_mapping(ppidb,taxid):keys=ppidb.ids(taxid)mapping={key:ppidb.synonyms(key)forkeyinkeys}returnmultimap_inverse(mapping)deftaxonomy_match(query_taxids,target_taxids):taxid_mapping={}target_taxids=set(target_taxids)fortaxidinquery_taxids:mapped=taxid_map(taxid,target_taxids)taxid_mapping[taxid]=mappedreturntaxid_mappingdeftaxid_map(query,targets):ifqueryintargets:returnquerylineage=taxonomy.lineage(query)ifany(tidintargetsfortidinlineage):returnset(lineage).intersection(targets).pop()else:returnNonefromOrange.utilsimportserverfilesassfdeffetch_ppidb(ppidb,progress=None):sf.localpath_download(ppidb.DOMAIN,ppidb.SERVER_FILE,callback=progress,verbose=True)db=ppidb()mapping=taxonomy_match(db.organisms(),taxonomy.common_taxids())returndb,mappingdefextract_network(ppidb,query,geneinfo,include_neighborhood=True):""" include neighborhood """fromfunctoolsimportpartialfromcollectionsimportdefaultdictfromitertoolsimportcountifnotisinstance(query,dict):query={name:namefornameinquery}graph=Orange.network.Graph()# node ids in Orange.network.Graph need to be in [0 .. n-1]nodeids=defaultdict(partial(next,count()))forkey,query_nameinquery.items():nodeid=nodeids[key]graph.add_node(nodeid,key=key,synonyms=ppidb.synonyms(key),query_name=query_name)forkeyinquery:edges=ppidb.edges(key)forid1,id2,scoreinedges:ifinclude_neighborhoodorid1inqueryandid2inquery:nodeid1=nodeids[id1]nodeid2=nodeids[id2]ifnodeid1notingraph:graph.add_node(nodeid1,key=id1,synonyms=ppidb.synonyms(id1))ifnodeid2notingraph:graph.add_node(nodeid2,key=id1,synonyms=ppidb.synonyms(id2))ifscoreisnotNone:graph.add_edge(nodeid1,nodeid2,weight=score)else:graph.add_edge(nodeid1,nodeid2)# The "items" should table should contain the query name (ifnodedomain=Orange.data.Domain([Orange.feature.String("Query name"),# if applicableOrange.feature.String("id"),# ppidb primary keyOrange.feature.String("Synonyms"),# ppidb synonymsOrange.feature.String("Symbol"),# ncbi gene name ??Orange.feature.Discrete("source",values=["false","true"])],None)node_items=sorted(graph.node.items(),key=lambdat:nodeids[t[0]])nodeitems=Orange.data.Table(nodedomain,[[str(node.get("query_name","")),str(node.get("key","")),str(", ".join(node.get("synonyms",[]))),str(node.get("query_name",nodeid)),"true"if"query_name"innodeelse"false"]fornodeid,nodeinnode_items])graph.set_items(nodeitems)returngraphdefmain():fromPyQt4.QtGuiimportQApplicationapp=QApplication([])w=OWGeneNetwork()brown=Orange.data.Table("brown-selected")w.set_data(Orange.data.Table(brown[:5]))w.show()app.exec_()w.saveSettings()return0if__name__=="__main__":main()