spyglass icon indicating copy to clipboard operation
spyglass copied to clipboard

delete from `SpikeSortingOutput` exceeds max attempts

Open sharon-chiang opened this issue 11 months ago • 11 comments

I get the below error when trying to delete from SortGroup.

Code:

import spyglass.spikesorting.v0.spikesorting_recording as sgss
(sgss.SortGroup & {'nwb_file_name': 'J1620210529_.nwb',
                 'sort_group_id': 100}).cautious_delete()
Error stack
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/classes/digraph.py:899, in DiGraph.successors(self, n)
    898 try:
--> 899     return iter(self._succ[n])
    900 except KeyError as err:

KeyError: '`spikesorting_merge`.`spike_sorting_output`'

The above exception was the direct cause of the following exception:

NetworkXError                             Traceback (most recent call last)
Cell In[8], line 2
      1 import spyglass.spikesorting.v0.spikesorting_recording as sgss
----> 2 (sgss.SortGroup & {'nwb_file_name': 'J1620210529_.nwb',
      3                  'sort_group_id': 100}).cautious_delete()

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:452, in SpyglassMixin.cautious_delete(self, force_permission, *args, **kwargs)
    449 if not force_permission:
    450     self._check_delete_permission()
--> 452 merge_deletes = self.delete_downstream_merge(
    453     dry_run=True,
    454     disable_warning=True,
    455     return_parts=False,
    456 )
    458 safemode = (
    459     dj.config.get("safemode", True)
    460     if kwargs.get("safemode") is None
    461     else kwargs["safemode"]
    462 )
    464 if merge_deletes:

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:248, in SpyglassMixin.delete_downstream_merge(self, restriction, dry_run, reload_cache, disable_warning, return_parts, **kwargs)
    245 restriction = restriction or self.restriction or True
    247 merge_join_dict = {}
--> 248 for name, chain in self._merge_chains.items():
    249     join = chain.join(restriction)
    250     if join:

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/functools.py:993, in cached_property.__get__(self, instance, owner)
    991 val = cache.get(self.attrname, _NOT_FOUND)
    992 if val is _NOT_FOUND:
--> 993     val = self.func(instance)
    994     try:
    995         cache[self.attrname] = val

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:172, in SpyglassMixin._merge_chains(self)
    161 """Dict of chains to merges downstream of self
    162 
    163 Format: {full_table_name: TableChains}.
   (...)
    169 delete_downstream_merge call.
    170 """
    171 merge_chains = {}
--> 172 for name, merge_table in self._merge_tables.items():
    173     chains = TableChains(self, merge_table, connection=self.connection)
    174     if len(chains):

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/functools.py:993, in cached_property.__get__(self, instance, owner)
    991 val = cache.get(self.attrname, _NOT_FOUND)
    992 if val is _NOT_FOUND:
--> 993     val = self.func(instance)
    994     try:
    995         cache[self.attrname] = val

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:150, in SpyglassMixin._merge_tables(self)
    147             merge_tables[master_name] = master
    148             search_descendants(master)
--> 150 _ = search_descendants(self)
    152 logger.info(
    153     f"Building merge cache for {self.table_name}.\n\t"
    154     + f"Found {len(merge_tables)} downstream merge tables"
    155 )
    157 return merge_tables

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:148, in SpyglassMixin._merge_tables.<locals>.search_descendants(parent)
    146 if MERGE_PK in master.heading.names:
    147     merge_tables[master_name] = master
--> 148     search_descendants(master)

File ~/src/spyglass/src/spyglass/utils/dj_mixin.py:138, in SpyglassMixin._merge_tables.<locals>.search_descendants(parent)
    137 def search_descendants(parent):
--> 138     for desc in parent.descendants(as_objects=True):
    139         if (
    140             MERGE_PK not in desc.heading.names
    141             or not (master_name := get_master(desc.full_table_name))
    142             or master_name in merge_tables
    143         ):
    144             continue

File ~/src/datajoint-python/datajoint/table.py:215, in Table.descendants(self, as_objects)
    207 def descendants(self, as_objects=False):
    208     """
    209 
    210     :param as_objects: False - a list of table names; True - a list of table objects.
    211     :return: list of tables descendants in topological order.
    212     """
    213     return [
    214         FreeTable(self.connection, node) if as_objects else node
--> 215         for node in self.connection.dependencies.descendants(self.full_table_name)
    216         if not node.isdigit()
    217     ]

File ~/src/datajoint-python/datajoint/dependencies.py:170, in Dependencies.descendants(self, full_table_name)
    165 """
    166 :param full_table_name:  In form `schema`.`table_name`
    167 :return: all dependent tables sorted in topological order.  Self is included.
    168 """
    169 self.load(force=False)
--> 170 nodes = self.subgraph(nx.algorithms.dag.descendants(self, full_table_name))
    171 return unite_master_parts(
    172     [full_table_name] + list(nx.algorithms.dag.topological_sort(nodes))
    173 )

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/utils/backends.py:412, in _dispatch.__call__(self, backend, *args, **kwargs)
    409 def __call__(self, /, *args, backend=None, **kwargs):
    410     if not backends:
    411         # Fast path if no backends are installed
--> 412         return self.orig_func(*args, **kwargs)
    414     # Use `backend_name` in this function instead of `backend`
    415     backend_name = backend

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/algorithms/dag.py:73, in descendants(G, source)
     39 @nx._dispatch
     40 def descendants(G, source):
     41     """Returns all nodes reachable from `source` in `G`.
     42 
     43     Parameters
   (...)
     71     ancestors
     72     """
---> 73     return {child for parent, child in nx.bfs_edges(G, source)}

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/algorithms/dag.py:73, in <setcomp>(.0)
     39 @nx._dispatch
     40 def descendants(G, source):
     41     """Returns all nodes reachable from `source` in `G`.
     42 
     43     Parameters
   (...)
     71     ancestors
     72     """
---> 73     return {child for parent, child in nx.bfs_edges(G, source)}

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/algorithms/traversal/breadth_first_search.py:203, in bfs_edges(G, source, reverse, depth_limit, sort_neighbors)
    199     yield from generic_bfs_edges(
    200         G, source, lambda node: iter(sort_neighbors(successors(node))), depth_limit
    201     )
    202 else:
--> 203     yield from generic_bfs_edges(G, source, successors, depth_limit)

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/algorithms/traversal/breadth_first_search.py:103, in generic_bfs_edges(G, source, neighbors, depth_limit, sort_neighbors)
    101 n = len(G)
    102 depth = 0
--> 103 next_parents_children = [(source, neighbors(source))]
    104 while next_parents_children and depth < depth_limit:
    105     this_parents_children = next_parents_children

File ~/Documents/anaconda3/envs/spyglass/lib/python3.9/site-packages/networkx/classes/digraph.py:901, in DiGraph.successors(self, n)
    899     return iter(self._succ[n])
    900 except KeyError as err:
--> 901     raise NetworkXError(f"The node {n} is not in the digraph.") from err

NetworkXError: The node `spikesorting_merge`.`spike_sorting_output` is not in the digraph.

@CBroz1

sharon-chiang avatar Mar 22 '24 06:03 sharon-chiang