Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Long distance restrictions #949

Merged
merged 23 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- Create class `SpyglassGroupPart` to aid delete propagations #899
- Fix bug report template #955
- Add long-distance restrictions via `<<` and `>>` operators. #943
- Fix relative pathing for `mkdocstring-python=>1.9.1`. #967, #968

## [0.5.2] (April 22, 2024)
Expand Down
61 changes: 56 additions & 5 deletions docs/src/misc/mixin.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,22 @@ The Spyglass Mixin provides a way to centralize all Spyglass-specific
functionalities that have been added to DataJoint tables. This includes...

- Fetching NWB files
- Long-distance restrictions.
- Delete functionality, including permission checks and part/master pairs
- Export logging. See [export doc](export.md) for more information.

To add this functionality to your own tables, simply inherit from the mixin:

```python
import datajoint as dj

from spyglass.utils import SpyglassMixin

schema = dj.schema('my_schema')
schema = dj.schema("my_schema")

@schema
class MyOldTable(dj.Manual):
pass

@schema
class MyNewTable(SpyglassMixin, dj.Manual):)
class MyOldTable(dj.Manual):
pass
```

Expand All @@ -44,6 +43,58 @@ should be fetched from `Nwbfile` or an analysis file should be fetched from
`AnalysisNwbfile`. If neither is foreign-key-referenced, the function will refer
to a `_nwb_table` attribute.

## Long-Distance Restrictions

In complicated pipelines like Spyglass, there are often tables that 'bury' their
foreign keys as secondary keys. This is done to avoid having to pass a long list
of foreign keys through the pipeline, potentially hitting SQL limits (see also
[Merge Tables](./merge_tables.md)). This burrying makes it difficult to restrict
a given table by familiar attributes.

Spyglass provides a function, `restrict_by`, to handle this. The function takes
your restriction and checks parents/children until the restriction can be
applied. Spyglass introduces `<<` as a shorthand for `restrict_by` an upstream
key and `>>` as a shorthand for `restrict_by` a downstream key.

```python
from spyglass.example import AnyTable

AnyTable >> 'downsteam_attribute="value"'
AnyTable << 'upstream_attribute="value"'

# Equivalent to
AnyTable.restrict_by('upstream_attribute="value"', direction="up")
AnyTable.restrict_by('downsteam_attribute="value"', direction="down")
```

Some caveats to this function:

1. 'Peripheral' tables, like `IntervalList` and `AnalysisNwbfile` make it hard
to determine the correct parent/child relationship and have been removed
from this search.
2. This function will raise an error if it attempts to check a table that has
not been imported into the current namespace. It is best used for exploring
and debugging, not for production code.
3. It's hard to determine the attributes in a mixed dictionary/string
restriction. If you are having trouble, try using a pure string
restriction.
4. The most direct path to your restriction may not be the path took, especially
when using Merge Tables. When the result is empty see the warning about the
path used. Then, ban tables from the search to force a different path.

```python
my_table = MyTable() # must be instantced
my_table.ban_search_table(UnwantedTable1)
my_table.ban_search_table([UnwantedTable2, UnwantedTable3])
my_table.unban_search_table(UnwantedTable3)
my_table.see_banned_tables()

my_table << my_restriction
```

When providing a restriction of the parent, use 'up' direction. When providing a
restriction of the child, use 'down' direction.

## Delete Functionality

The mixin overrides the default `delete` function to provide two additional
Expand Down
Loading
Loading