From 3bb44e4714b99805f668736eb5d3af5e376efc8e Mon Sep 17 00:00:00 2001 From: juhuntenburg Date: Tue, 7 Jun 2022 12:27:50 +0200 Subject: [PATCH] initial commit after cleanup --- .gitignore | 134 ++++++++++++++++++++++++++++++++++++ README.md | 45 ++++++++++++ brainwidemap/__init__.py | 3 + brainwidemap/bwm_loading.py | 73 ++++++++++++++++++++ requirements.txt | 5 ++ setup.py | 41 +++++++++++ 6 files changed, 301 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 brainwidemap/__init__.py create mode 100644 brainwidemap/bwm_loading.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8e56c8ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,134 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# PyCharm project settings +.idea + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Data folders diff --git a/README.md b/README.md new file mode 100644 index 00000000..de1767fa --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# paper-brain-wide-map +Code related to the brainwide map paper + + +# Installation +## Create a new python environment (optional) + +Install [Anaconda](https://www.anaconda.com/distribution/#download-section) and [git](https://git-scm.com/downloads), +and follow their installer instructions to add each to the system path + +Create new python environment +``` +conda create --name ibl_bwm python=3.9 +``` +Activate environment +``` +conda activate ibl_bwm +``` + +## Download and Install repository + +Clone the repo +``` +git clone https://github.com/int-brain-lab/paper-brain-wide-map.git +``` + +Navigate to repo +``` +cd paper-brain-wide-map +``` + +Install requirements and repo +``` +pip install -e . +``` + +## Query sessions for BWM analyses +You can now use the following in Python (note that ONE needs to be set up) +```python +from brainwidemap import bwm_query +from one.api import ONE + +one = ONE() +bwm_df = bwm_query(one) +``` \ No newline at end of file diff --git a/brainwidemap/__init__.py b/brainwidemap/__init__.py new file mode 100644 index 00000000..6a872231 --- /dev/null +++ b/brainwidemap/__init__.py @@ -0,0 +1,3 @@ +from brainwidemap.bwm_loading import bwm_query + +__version__ = "0.0.1" \ No newline at end of file diff --git a/brainwidemap/bwm_loading.py b/brainwidemap/bwm_loading.py new file mode 100644 index 00000000..dd2c35c9 --- /dev/null +++ b/brainwidemap/bwm_loading.py @@ -0,0 +1,73 @@ +from dateutil import parser +import numpy as np +import pandas as pd + + +def bwm_query(one, alignment_resolved=True, return_details=False): + """ + Function to query for brainwide map sessions that pass the most important quality controls. Returns a dataframe + with one row per insertions and columns ['pid', 'eid', 'probe_name', 'session_number', 'date', 'subject', 'lab'] + + Parameters + ---------- + one: ONE instance (can be remote or local) + alignment_resolved: bool, default is True. If True, only returns sessions with resolved alignment, + if False returns all sessions with at least one alignment + return_details: bool, default is False. If True returns a second output a list containing the full insertion + dictionary for all insertions returned by the query. Only needed if you need information that is + not contained in the output dataframe + + Returns + ------- + bwm_df: pd.DataFrame of BWM sessions to be included in analyses with columns + ['pid', 'eid', 'probe_name', 'session_number', 'date', 'subject', 'lab'] + """ + + base_query = ( + 'session__project__name__icontains,ibl_neuropixel_brainwide_01,' + 'session__json__IS_MOCK,False,' + 'session__qc__lt,50,' + '~json__qc,CRITICAL,' + 'session__extended_qc__behavior,1,' + 'json__extended_qc__tracing_exists,True,' + ) + + if alignment_resolved: + base_query += 'json__extended_qc__alignment_resolved,True,' + else: + base_query += 'json__extended_qc__alignment_count__gt,0,' + + qc_pass = ( + '~session__extended_qc___task_stimOn_goCue_delays__lt,0.9,' + '~session__extended_qc___task_response_feedback_delays__lt,0.9,' + '~session__extended_qc___task_wheel_move_before_feedback__lt,0.9,' + '~session__extended_qc___task_wheel_freeze_during_quiescence__lt,0.9,' + '~session__extended_qc___task_error_trial_event_sequence__lt,0.9,' + '~session__extended_qc___task_correct_trial_event_sequence__lt,0.9,' + '~session__extended_qc___task_reward_volumes__lt,0.9,' + '~session__extended_qc___task_reward_volume_set__lt,0.9,' + '~session__extended_qc___task_stimulus_move_before_goCue__lt,0.9,' + '~session__extended_qc___task_audio_pre_trial__lt,0.9') + + marked_pass = ( + 'session__extended_qc___experimenter_task,PASS') + + insertions = list(one.alyx.rest('insertions', 'list', django=base_query + qc_pass)) + insertions.extend(list(one.alyx.rest('insertions', 'list', django=base_query + marked_pass))) + + bwm_df = pd.DataFrame({ + 'pid': np.array([i['id'] for i in insertions]), + 'eid': np.array([i['session'] for i in insertions]), + 'probe_name': np.array([i['name'] for i in insertions]), + 'session_number': np.array([i['session_info']['number'] for i in insertions]), + 'date': np.array([parser.parse(i['session_info']['start_time']).date() for i in insertions]), + 'subject': np.array([i['session_info']['subject'] for i in insertions]), + 'lab': np.array([i['session_info']['lab'] for i in insertions]), + }).sort_values(by=['lab', 'subject', 'date', 'eid']) + bwm_df.drop_duplicates(inplace=True) + bwm_df.reset_index(inplace=True, drop=True) + + if return_details: + return bwm_df, insertions + else: + return bwm_df diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..1979f012 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +ONE-api +ibllib +numpy +pandas +python-dateutil \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..de8aeeb6 --- /dev/null +++ b/setup.py @@ -0,0 +1,41 @@ +from setuptools import setup, find_packages +import sys +from pathlib import Path + +CURRENT_DIRECTORY = Path(__file__).parent.absolute() + +CURRENT_PYTHON = sys.version_info[:2] +REQUIRED_PYTHON = (3, 8) +if CURRENT_PYTHON < REQUIRED_PYTHON: + sys.stderr.write(""" +========================== +Unsupported Python version +========================== +This version of iblutil requires Python {}.{}, but you're trying to +install it on Python {}.{}. +""".format(*(REQUIRED_PYTHON + CURRENT_PYTHON))) + sys.exit(1) + +with open("README.md", 'r') as f: + long_description = f.read() + +with open('requirements.txt') as f: + require = [x.strip() for x in f.readlines() if not x.startswith('git+')] + +setup( + name='brainwidemap', + version='0.1.0', + python_requires='>={}.{}'.format(*REQUIRED_PYTHON), + description='Github repo for code associated with IBL brainwide map paper', + license="MIT", + long_description=long_description, + long_description_content_type='text/markdown', + author='IBL', + url="https://www.internationalbrainlab.com/", + packages=find_packages(exclude=['scratch', 'tests']), # same as name + include_package_data=True, + # external packages as dependencies + install_requires=require, + entry_points={}, + scripts={} +)