Examples#

The neuromorpho.org API reference provides examples for accessing neuron and publication data via the API using curl.

We repeat those examples here, showing how to use requests instead. There are four public API endpoints: neuron, literature, morphometry, and pvec which provide access to neuron metadata, publication metadata, neuron morphometry, and neuron persistence vectors, respectively.

Neuron#

import requests
neuron_endpoint = "https://neuromorpho.org/api/neuron"

All neurons#

Note

We won’t actually run this one, as it is an expensive query returning more than 80k neuron records.

r = requests.get(neuron_endpoint)

Neuron by id or name#

Neurons can be requested by id:

r = requests.get("/".join((neuron_endpoint, "id/1")))
r.raise_for_status()
r.json()
Hide code cell output
---------------------------------------------------------------------------
SSLError                                  Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connectionpool.py:466, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
    465 try:
--> 466     self._validate_conn(conn)
    467 except (SocketTimeout, BaseSSLError) as e:

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connectionpool.py:1095, in HTTPSConnectionPool._validate_conn(self, conn)
   1094 if conn.is_closed:
-> 1095     conn.connect()
   1097 # TODO revise this, see https://github.com/urllib3/urllib3/issues/2791

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connection.py:652, in HTTPSConnection.connect(self)
    650 server_hostname_rm_dot = server_hostname.rstrip(".")
--> 652 sock_and_verified = _ssl_wrap_socket_and_match_hostname(
    653     sock=sock,
    654     cert_reqs=self.cert_reqs,
    655     ssl_version=self.ssl_version,
    656     ssl_minimum_version=self.ssl_minimum_version,
    657     ssl_maximum_version=self.ssl_maximum_version,
    658     ca_certs=self.ca_certs,
    659     ca_cert_dir=self.ca_cert_dir,
    660     ca_cert_data=self.ca_cert_data,
    661     cert_file=self.cert_file,
    662     key_file=self.key_file,
    663     key_password=self.key_password,
    664     server_hostname=server_hostname_rm_dot,
    665     ssl_context=self.ssl_context,
    666     tls_in_tls=tls_in_tls,
    667     assert_hostname=self.assert_hostname,
    668     assert_fingerprint=self.assert_fingerprint,
    669 )
    670 self.sock = sock_and_verified.socket

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connection.py:805, in _ssl_wrap_socket_and_match_hostname(sock, cert_reqs, ssl_version, ssl_minimum_version, ssl_maximum_version, cert_file, key_file, key_password, ca_certs, ca_cert_dir, ca_cert_data, assert_hostname, assert_fingerprint, server_hostname, ssl_context, tls_in_tls)
    803         server_hostname = normalized
--> 805 ssl_sock = ssl_wrap_socket(
    806     sock=sock,
    807     keyfile=key_file,
    808     certfile=cert_file,
    809     key_password=key_password,
    810     ca_certs=ca_certs,
    811     ca_cert_dir=ca_cert_dir,
    812     ca_cert_data=ca_cert_data,
    813     server_hostname=server_hostname,
    814     ssl_context=context,
    815     tls_in_tls=tls_in_tls,
    816 )
    818 try:

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/util/ssl_.py:465, in ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context, ca_cert_dir, key_password, ca_cert_data, tls_in_tls)
    463     pass
--> 465 ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname)
    466 return ssl_sock

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/util/ssl_.py:509, in _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname)
    507     return SSLTransport(sock, ssl_context, server_hostname)
--> 509 return ssl_context.wrap_socket(sock, server_hostname=server_hostname)

File ~/.asdf/installs/python/3.11.9/lib/python3.11/ssl.py:517, in SSLContext.wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, session)
    511 def wrap_socket(self, sock, server_side=False,
    512                 do_handshake_on_connect=True,
    513                 suppress_ragged_eofs=True,
    514                 server_hostname=None, session=None):
    515     # SSLSocket class handles server_hostname encoding before it calls
    516     # ctx._wrap_socket()
--> 517     return self.sslsocket_class._create(
    518         sock=sock,
    519         server_side=server_side,
    520         do_handshake_on_connect=do_handshake_on_connect,
    521         suppress_ragged_eofs=suppress_ragged_eofs,
    522         server_hostname=server_hostname,
    523         context=self,
    524         session=session
    525     )

File ~/.asdf/installs/python/3.11.9/lib/python3.11/ssl.py:1104, in SSLSocket._create(cls, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, context, session)
   1103                 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
-> 1104             self.do_handshake()
   1105 except:

File ~/.asdf/installs/python/3.11.9/lib/python3.11/ssl.py:1382, in SSLSocket.do_handshake(self, block)
   1381         self.settimeout(None)
-> 1382     self._sslobj.do_handshake()
   1383 finally:

SSLError: [SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1006)

During handling of the above exception, another exception occurred:

SSLError                                  Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connectionpool.py:789, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
    788 # Make the request on the HTTPConnection object
--> 789 response = self._make_request(
    790     conn,
    791     method,
    792     url,
    793     timeout=timeout_obj,
    794     body=body,
    795     headers=headers,
    796     chunked=chunked,
    797     retries=retries,
    798     response_conn=response_conn,
    799     preload_content=preload_content,
    800     decode_content=decode_content,
    801     **response_kw,
    802 )
    804 # Everything went great!

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connectionpool.py:490, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
    489         new_e = _wrap_proxy_error(new_e, conn.proxy.scheme)
--> 490     raise new_e
    492 # conn.request() calls http.client.*.request, not the method in
    493 # urllib3.request. It also calls makefile (recv) on the socket.

SSLError: [SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1006)

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

MaxRetryError                             Traceback (most recent call last)
File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/adapters.py:667, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
    666 try:
--> 667     resp = conn.urlopen(
    668         method=request.method,
    669         url=url,
    670         body=request.body,
    671         headers=request.headers,
    672         redirect=False,
    673         assert_same_host=False,
    674         preload_content=False,
    675         decode_content=False,
    676         retries=self.max_retries,
    677         timeout=timeout,
    678         chunked=chunked,
    679     )
    681 except (ProtocolError, OSError) as err:

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/connectionpool.py:843, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
    841     new_e = ProtocolError("Connection aborted.", new_e)
--> 843 retries = retries.increment(
    844     method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
    845 )
    846 retries.sleep()

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/urllib3/util/retry.py:519, in Retry.increment(self, method, url, response, error, _pool, _stacktrace)
    518     reason = error or ResponseError(cause)
--> 519     raise MaxRetryError(_pool, url, reason) from reason  # type: ignore[arg-type]
    521 log.debug("Incremented Retry for (url='%s'): %r", url, new_retry)

MaxRetryError: HTTPSConnectionPool(host='neuromorpho.org', port=443): Max retries exceeded with url: /api/neuron/id/1 (Caused by SSLError(SSLError(1, '[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1006)')))

During handling of the above exception, another exception occurred:

SSLError                                  Traceback (most recent call last)
Cell In[2], line 1
----> 1 r = requests.get("/".join((neuron_endpoint, "id/1")))
      2 r.raise_for_status()
      3 r.json()

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/api.py:73, in get(url, params, **kwargs)
     62 def get(url, params=None, **kwargs):
     63     r"""Sends a GET request.
     64 
     65     :param url: URL for the new :class:`Request` object.
   (...)
     70     :rtype: requests.Response
     71     """
---> 73     return request("get", url, params=params, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/api.py:59, in request(method, url, **kwargs)
     55 # By using the 'with' statement we are sure the session is closed, thus we
     56 # avoid leaving sockets open which can trigger a ResourceWarning in some
     57 # cases, and look like a memory leak in others.
     58 with sessions.Session() as session:
---> 59     return session.request(method=method, url=url, **kwargs)

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/sessions.py:589, in Session.request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    584 send_kwargs = {
    585     "timeout": timeout,
    586     "allow_redirects": allow_redirects,
    587 }
    588 send_kwargs.update(settings)
--> 589 resp = self.send(prep, **send_kwargs)
    591 return resp

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/sessions.py:703, in Session.send(self, request, **kwargs)
    700 start = preferred_clock()
    702 # Send the request
--> 703 r = adapter.send(request, **kwargs)
    705 # Total elapsed time of the request (approximately)
    706 elapsed = preferred_clock() - start

File ~/checkouts/readthedocs.org/user_builds/neuromorpho-api/envs/latest/lib/python3.11/site-packages/requests/adapters.py:698, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
    694         raise ProxyError(e, request=request)
    696     if isinstance(e.reason, _SSLError):
    697         # This branch is for urllib3 v1.22 and later.
--> 698         raise SSLError(e, request=request)
    700     raise ConnectionError(e, request=request)
    702 except ClosedPoolError as e:

SSLError: HTTPSConnectionPool(host='neuromorpho.org', port=443): Max retries exceeded with url: /api/neuron/id/1 (Caused by SSLError(SSLError(1, '[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1006)')))

or by name:

r = requests.get("/".join((neuron_endpoint, "name/cnic_001")))
r.raise_for_status()
r.json()

Custom selection query#

Query strings are denoted by the q parameter. The general syntax for query parameters is: {neuron_field_name}:{comma-separated criteria}.

See the official API docs for details.

# Query all neurons from cats
params = {"q": "species:cat"}
r = requests.get("/".join((neuron_endpoint, "select")), params=params)
r.raise_for_status()

# Show only the pagination, for brevity's sake
r.json()

Filter queries#

Selection queries can include filters with the fq parameter. A query can included multiple filters:

params = {
    "q": "species:cat,rat,monkey",
    "fq": [  # Additional filters
        "stain:lucifer yellow",
        "brain_region:layer 3",
        "strain:Macaque",
    ],
}
r = requests.get("/".join((neuron_endpoint, "select")), params=params)
print(f"Target URL:\n  {r.url}")
r.raise_for_status()
r.json()

Neuron fields#

The listing of all neuron fields can be queried:

r = requests.get("/".join((neuron_endpoint, "fields")))
r.raise_for_status()
r.json()

Neuron field values#

Valid values for a given field:

r = requests.get("/".join((neuron_endpoint, "fields/species")))
r.raise_for_status()
r.json()

Neuron field partitioning#

Returns a listing of the number of neurons per each value in a given field. For instance, to view the total number of neurons by species:

r = requests.get("/".join((neuron_endpoint, "partition/species")))
r.raise_for_status()
r.json()

Literature#

pub_endpoint = "https://neuromorpho.org/api/literature"

All publications#

Note

We won’t actually run this one, as it is an expensive query returning nearly 32k records.

r = requests.get(pub_endpoint)

Publication select query#

# Query all publications involving neurons from cats
params = {"q": "species:mouse"}
r = requests.get("/".join((pub_endpoint, "select")), params=params)
r.raise_for_status()
r.json()

Literature fields#

Query all available literature fields

r = requests.get("/".join((pub_endpoint, "fields")))
r.raise_for_status()
r.json()

Literature field values#

Query valid values for a given field

r = requests.get("/".join((pub_endpoint, "fields/tracingSystem")))
r.raise_for_status()
r.json()

Literature field partitions#

The number of publications for each value in a literature field

r = requests.get("/".join((pub_endpoint, "partition/tracingSystem")))
r.raise_for_status()
r.json()

Morphometry#

morph_endpoint = "https://neuromorpho.org/api/morphometry"

Morphometry data for all neurons#

Note

We won’t actually run this one, as it is an expensive query returning over 80k records.

r = requests.get(morph_endpoint)

Morphometry by neuron id or name#

# By neuron id
r = requests.get("/".join((morph_endpoint, "id/1")))
r.raise_for_status()

# By neuron name
r = requests.get("/".join((morph_endpoint, "name/cnic_001")))
r.raise_for_status()
r.json()

Persistence vectors#

pvec_endpoint = "https://neuromorpho.org/api/pvec"

Persistence vectors for all neurons#

Note

We won’t actually run this one, as it is an expensive query returning over 100k records.

r = requests.get(pvec_endpoint)

By neuron id#

r = requests.get("/".join((pvec_endpoint, "id/1")))
r.raise_for_status()
r.content.decode()