[docs]defvalidate(self,all_morphos):self._cache_patterns()repo_names={m.get_meta()["name"]forminall_morphos}missing=[nforn,patinself._patterns.items()ifnotany(pat.match(rn)forrninrepo_names)]ifmissing:err="Morphology repository misses the following morphologies"ifself._config_parentisnotNone:node=self._config_parent._config_parenterr+=f" required by {node.get_node_name()}"err+=f": {', '.join(missing)}"raiseMissingMorphologyError(err)
[docs]@config.nodeclassNeuroMorphoSelector(NameSelector,classmap_entry="from_neuromorpho"):_url="https://neuromorpho.org/"_meta="api/neuron/select?q=neuron_name:"_files="dableFiles/"def__boot__(self):withself.scaffold._comm.try_main():ifself.scaffold.is_main_process():morphos=self._scrape_nm(self.names)forname,morphoinmorphos.items():self.scaffold.morphologies.save(name,morpho,overwrite=True)def__unboot__(self):withself.scaffold._comm.try_main():ifself.scaffold.is_main_process():fornameinself.names:withcontextlib.suppress(MorphologyRepositoryError):# remove morphology if it was saved in the scaffold.self.scaffold.morphologies.remove(name)@classmethoddef_swc_url(cls,archive,name):return(f"{cls._url}{cls._files}{urllib.parse.quote(archive.lower())}/"f"CNG%20version/{name}.CNG.swc")@classmethoddef_scrape_nm(cls,names):withwarnings.catch_warnings():warnings.simplefilter("ignore")withThreadPoolExecutor()asexecutor:# Certificate issues with neuromorpho --> verify=Falsetry:res=requests.get(cls._url+cls._meta+",".join(names),verify=False,timeout=20)exceptrequests.exceptions.Timeout:# pragma: nocoverraiseSelectorError("NeuroMorpho API request timed out.")fromNoneifres.status_code==404:raiseSelectorError(f"'{names[0]}' is not a valid NeuroMorpho name.")elifres.status_code!=200:# pragma: nocoverraiseSelectorError("NeuroMorpho API error: "+res.message)metas={n:Noneforninnames}formetainres.json()["_embedded"]["neuronResources"]:delmeta["_links"]metas[meta["neuron_name"]]=metamissing=[nameforname,metainmetas.items()ifmetaisNone]ifmissing:raiseSelectorError(", ".join(f"'{n}'"forninmissing)+" are not valid NeuroMorpho names.")swc_urls={n:cls._swc_url(metas[n]["archive"],n)forninnames}defreq(n):returnrequests.get(swc_urls[n],verify=False,timeout=20)defsub(n):returnexecutor.submit(req,n),nfutures=dict(map(sub,names))morphos={n:Noneforninnames}withtempfile.TemporaryDirectory()astempdir:forfutureinconcurrent.futures.as_completed(futures.keys()):name=futures[future]path=tempdir+f"/{name}.swc"withopen(path,"w")asf:f.write(future.result().text)morphos[name]=parse_morphology_file(path)morphos[name].meta=metas[name]missing=[nameforname,minmorphos.items()ifmisNone]ifmissing:# pragma: nocoverraiseSelectorError("Downloading NeuroMorpho failed for "+", ".join(f"'{n}'"forninmissing)+".")returnmorphos