def test_get_names(self): names = pymaid.get_names(config_test.test_skids, remote_instance=self.rm) self.assertIsInstance(names, dict) self.assertIsInstance( pymaid.get_skids_by_name(list(names.values()), remote_instance=self.rm), pd.DataFrame)
def segments_to_skids(seg_ids, autoseg_instance, name_pattern="Google: {id}", merge_annotation_pattern="Merged: {name}", verbose=True): """Retrieve skeleton IDs of neurons corresponding to given segmentation ID(s). If a given segmentation ID has been merged into another fragment, will try retrieving by annotation. Parameters ---------- seg_ids : int | list of int Segmentation ID(s) of autoseg skeletons to retrieve. autoseg_instance : pymaid.CatmaidInstance Instance with autoseg skeletons. name_pattern : str, optional Segmentation IDs are encoded in the name. Use this parameter to define that pattern. merge_annotation_pattern : str, optional When neurons are merged, a reference to the loosing skeleton's name is kept as annotation. Use this parameter to define that pattern. Returns ------- Dict Dictionary mapping segmentation ID to skeleton ID. Will be ``None`` if no skeleton found. """ assert isinstance(autoseg_instance, pymaid.CatmaidInstance) assert isinstance(seg_ids, (list, np.ndarray, set, tuple, pd.Index, int, str)) seg_ids = navis.utils.make_iterable(seg_ids) # Prepare map seg ID -> skeleton ID seg2skid = {int(i): None for i in seg_ids} # First find neurons by name # Do NOT change the order of "names"! names = [name_pattern.format(id=i) for i in seg_ids] by_name = pymaid.get_skids_by_name(names, allow_partial=False, raise_not_found=False, remote_instance=autoseg_instance) by_name['skeleton_id'] = by_name.skeleton_id.astype(int) # Update map by those that could be found by name name2skid = by_name.set_index('name').skeleton_id.to_dict() seg2skid.update({ int(i): int(name2skid[n]) for i, n in zip(seg_ids, names) if n in by_name.name.values }) # Look for missing IDs not_found = [s for s in seg_ids if not seg2skid[int(s)]] # Try finding by annotation (temporarily raise logger level) if not_found: map = merge_annotation_pattern an = [map.format(name=name_pattern.format(id=n)) for n in not_found] old_lvl = pymaid.logger.level pymaid.set_loggers('ERROR') by_annotation = pymaid.get_skids_by_annotation( an, raise_not_found=False, allow_partial=False, intersect=False, remote_instance=autoseg_instance) pymaid.set_loggers(old_lvl) if by_annotation: annotations = pymaid.get_annotations( by_annotation, remote_instance=autoseg_instance) for seg, a in zip(not_found, an): for skid in annotations: if a in annotations[skid]: seg2skid[int(seg)] = int(skid) break # Figure out if we are still missing skeletons for any of the seg IDs if verbose: missing = [str(k) for k, v in seg2skid.items() if not v] if missing: # Check if skeleton ID has ever existed hist = pymaid.get_skeleton_change(missing, remote_instance=autoseg_instance) # Flatten the list of links (and convert to string) existed = set([str(e) for l in hist for e in l[0]]) still_missing = set(missing) & existed if still_missing: msg = "{} out of {} segmentation IDs could not be found: {}" msg = msg.format(len(still_missing), len(seg_ids), ", ".join(still_missing)) print(msg) return seg2skid