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

Fix link types #248

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions pymaid/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@ def __copy__(self):
def __deepcopy__(self):
return self.copy()

def __hash__(self):
"""Hash based on server, api_token, http user, http password and project_id."""
return hash((self.server, self.api_token, self.http_user, self.http_password, self.project_id))

def copy(self):
"""Returns a copy of this CatmaidInstance. Does not copy cache."""
return CatmaidInstance(server=self.server,
Expand Down
81 changes: 6 additions & 75 deletions pymaid/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import numpy as np

from functools import lru_cache

logger = logging.getLogger('pymaid')

def default_logging():
Expand Down Expand Up @@ -116,82 +118,11 @@ def ipywidgets_installed():
tqdm = tqdm_classic
trange = trange_classic

# Hard-wired connector types. Use this to check for what's on the server:
# types = remote_instance.fetch(remote_instance._get_connector_types_url())
link_types = [{'name': 'Presynaptic',
'type': 'Synaptic',
'type_id': 'synaptic-connector',
'relation': 'presynaptic_to',
'isreciprocal': False,
'cardinality': 1,
'partner_reference': 'outgoing',
'partner_relation': 'postsynaptic_to',
'relation_id': 14},
{'name': 'Postsynaptic',
'type': 'Synaptic',
'type_id': 'synaptic-connector',
'relation': 'postsynaptic_to',
'isreciprocal': False,
'cardinality': None,
'partner_reference': 'incoming',
'partner_relation': 'presynaptic_to',
'relation_id': 8},
{'name': 'Abutting',
'type': 'Abutting',
'type_id': 'abutting-connector',
'relation': 'abutting',
'isreciprocal': True,
'cardinality': None,
'partner_reference': 'abutting',
'partner_relation': 'abutting',
'relation_id': 54650},
{'name': 'Gap junction',
'type': 'Gap junction',
'type_id': 'gapjunction-connector',
'relation': 'gapjunction_with',
'isreciprocal': True,
'cardinality': 2,
'partner_reference': 'gapjunction',
'partner_relation': 'gapjunction_with',
'relation_id': 686364},
{'name': 'Tight junction',
'type': 'Tight junction',
'type_id': 'tightjunction-connector',
'relation': 'tightjunction_with',
'isreciprocal': True,
'cardinality': 2,
'partner_reference': 'tightjunction',
'partner_relation': 'tightjunction_with',
'relation_id': 10686621},
{'name': 'Desmosome',
'type': 'Desmosome',
'type_id': 'desmosome-connector',
'relation': 'desmosome_with',
'isreciprocal': True,
'cardinality': 2,
'partner_reference': 'desmosome',
'partner_relation': 'desmosome_with',
'relation_id': 10686622},
{'name': 'Attachment',
'type': 'Attachment',
'type_id': 'attachment-connector',
'relation': 'attached_to',
'isreciprocal': False,
'cardinality': None,
'partner_reference': 'attachment',
'partner_relation': 'close_to',
'relation_id': 5989640},
{'name': 'Close to',
'type': 'Spatial',
'type_id': 'spatial-connector',
'relation': 'close_to',
'isreciprocal': True,
'cardinality': None,
'partner_reference': 'close_object',
'partner_relation': 'close_to',
'relation_id': 6216812}]

compact_skeleton_relations = {0: 'presynaptic_to',
1: 'postsynaptic_to',
2: 'gapjunction_with',
3: 'abutting'}

@lru_cache
def get_link_types(remote_instance):
return remote_instance.fetch(remote_instance._get_connector_types_url())
12 changes: 7 additions & 5 deletions pymaid/fetch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1225,14 +1225,16 @@ def get_connectors(x, relation_type=None, tags=None, remote_instance=None):

# Map hardwire connector type ID to their type name
# ATTENTION: "attachment" can be part of any connector type
rel_ids = {r['relation_id']: r for r in config.link_types}
rel_ids = {r['relation_id']: r for r in config.get_link_types(remote_instance)}

# Get connector type IDs
cn_ids = {k: v[0][3] for k, v in data['partners'].items()}

# Map type ID to relation (also note conversion of connector ID to integer)
cn_type = {int(k): rel_ids.get(v, {'type': 'unknown'})['type']
for k, v in cn_ids.items()}
# Map type ID to relation; also note:
# 1. Conversion of connector ID to integer)
# 2. We're using the "name" field of the relation - this used to be "type" but
# on VFB CATMAID "type" is always "Synaptic" while name can be "Presynaptic" or "Postsynaptic"
cn_type = {int(k): rel_ids.get(v, {}).get('name', 'unknown') for k, v in cn_ids.items()}

# Map connector ID to connector type
df['type'] = df.connector_id.map(cn_type)
Expand Down Expand Up @@ -1314,7 +1316,7 @@ def get_connector_links(x, with_tags=False, chunk_size=50,
df_collection = []
tags = {}

link_types = [l['relation'] for l in config.link_types]
link_types = [l['relation'] for l in config.get_link_types(remote_instance)]

with config.tqdm(desc='Fetching links', total=len(skids),
disable=config.pbar_hide,
Expand Down
4 changes: 2 additions & 2 deletions pymaid/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ def link_connector(links, remote_instance=None):
(node_id, connector_id, 'presynaptic_to') will make node presynaptic to connector
(node_id, connector_id, 'postsynaptic_to') will make node postsynaptic to connector

See ``pymaid.config.link_types`` for allowed `relation`.
See ``pymaid.config.get_link_types(remote_instance)`` for allowed `relation`.

remote_instance : CatmaidInstance, optional
If not passed directly, will try using global.
Expand Down Expand Up @@ -1368,7 +1368,7 @@ def link_connector(links, remote_instance=None):
'(node_id, connector_id, relation)')

# Make sure all relations are correct
ALLOWED_RELATIONS = [l['relation'] for l in config.link_types]
ALLOWED_RELATIONS = [l['relation'] for l in config.get_link_types(remote_instance)]
if any([l[2] not in ALLOWED_RELATIONS for l in links]):
raise ValueError('Tuple relationships must be either: {}'.format(', '.join(ALLOWED_RELATIONS)))

Expand Down
Loading