Skip to content

Commit 4e97d52

Browse files
authored
Merge pull request #20 from CINPLA/modernize
Modernize package and add actions
2 parents 2087206 + 30acbcc commit 4e97d52

21 files changed

+481
-424
lines changed

.github/workflows/full_tests.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Test on Ubuntu
2+
3+
on:
4+
pull_request:
5+
branches: [dev]
6+
types: [synchronize, opened, reopened]
7+
8+
9+
jobs:
10+
build-and-test:
11+
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v3
16+
- name: Set up Python
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: "3.10"
20+
- name: Install package
21+
run: |
22+
python -m pip install --upgrade pip
23+
pip install .[test]
24+
- name: Pytest
25+
run: |
26+
pytest -v
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Release to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
jobs:
8+
release:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Set up Python 3.10
14+
uses: actions/setup-python@v4
15+
with:
16+
python-version: "3.10"
17+
- name: Install Tools
18+
run: |
19+
python -m pip install --upgrade pip
20+
pip install setuptools wheel twine build
21+
- name: Package and Upload
22+
env:
23+
STACKMANAGER_VERSION: ${{ github.event.release.tag_name }}
24+
TWINE_USERNAME: __token__
25+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
26+
run: |
27+
python -m build --sdist --wheel
28+
twine upload dist/*

.pre-commit-config.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.5.0
4+
hooks:
5+
- id: fix-encoding-pragma
6+
exclude: tests/test_data
7+
- id: trailing-whitespace
8+
exclude: tests/test_data
9+
- id: end-of-file-fixer
10+
exclude: tests/test_data
11+
- id: check-docstring-first
12+
- id: debug-statements
13+
- id: check-toml
14+
- id: check-yaml
15+
exclude: tests/test_data
16+
- id: requirements-txt-fixer
17+
- id: detect-private-key
18+
- id: check-merge-conflict
19+
20+
- repo: https://github.com/psf/black
21+
rev: 24.4.2
22+
hooks:
23+
- id: black
24+
exclude: tests/test_data
25+
- id: black-jupyter
26+
27+
- repo: https://github.com/pycqa/isort
28+
rev: 5.13.2
29+
hooks:
30+
- id: isort
31+
args: ["--profile", "black"]
32+
33+
- repo: https://github.com/astral-sh/ruff-pre-commit
34+
rev: v0.4.4
35+
hooks:
36+
- id: ruff

examples/tracking_plot.py

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,21 @@
55
from scipy.ndimage.measurements import center_of_mass
66

77

8-
def plot_path(x, y, t, box_size, spike_times=None,
9-
color='grey', alpha=0.5, origin='upper',
10-
spike_color='r', rate_markersize=False, markersize=10.,
11-
animate=False, ax=None):
8+
def plot_path(
9+
x,
10+
y,
11+
t,
12+
box_size,
13+
spike_times=None,
14+
color="grey",
15+
alpha=0.5,
16+
origin="upper",
17+
spike_color="r",
18+
rate_markersize=False,
19+
markersize=10.0,
20+
animate=False,
21+
ax=None,
22+
):
1223
"""
1324
Plot path visited
1425
@@ -39,8 +50,7 @@ def plot_path(x, y, t, box_size, spike_times=None,
3950
"""
4051
if ax is None:
4152
fig = plt.figure()
42-
ax = fig.add_subplot(
43-
111, xlim=[0, box_size], ylim=[0, box_size], aspect=1)
53+
ax = fig.add_subplot(111, xlim=[0, box_size], ylim=[0, box_size], aspect=1)
4454

4555
ax.plot(x, y, c=color, alpha=alpha)
4656
if spike_times is not None:
@@ -49,20 +59,36 @@ def plot_path(x, y, t, box_size, spike_times=None,
4959

5060
if rate_markersize:
5161
markersize = spikes_in_bin[is_spikes_in_bin] * markersize
52-
ax.scatter(x[:-1][is_spikes_in_bin], y[:-1][is_spikes_in_bin],
53-
facecolor=spike_color, edgecolor=spike_color,
54-
s=markersize)
62+
ax.scatter(
63+
x[:-1][is_spikes_in_bin],
64+
y[:-1][is_spikes_in_bin],
65+
facecolor=spike_color,
66+
edgecolor=spike_color,
67+
s=markersize,
68+
)
5569

5670
ax.grid(False)
57-
if origin == 'upper':
71+
if origin == "upper":
5872
ax.invert_yaxis()
5973
return ax
6074

6175

62-
def animate_path(x, y, t, box_size, spike_times=None,
63-
color='grey', alpha=0.5, origin='upper',
64-
spike_color='r', rate_markersize=False, markersize=10.,
65-
animate=False, ax=None, title=''):
76+
def animate_path(
77+
x,
78+
y,
79+
t,
80+
box_size,
81+
spike_times=None,
82+
color="grey",
83+
alpha=0.5,
84+
origin="upper",
85+
spike_color="r",
86+
rate_markersize=False,
87+
markersize=10.0,
88+
animate=False,
89+
ax=None,
90+
title="",
91+
):
6692
"""
6793
Plot path visited
6894
@@ -93,35 +119,35 @@ def animate_path(x, y, t, box_size, spike_times=None,
93119
"""
94120
if ax is None:
95121
fig = plt.figure()
96-
ax = fig.add_subplot(
97-
111, xlim=[0, box_size], ylim=[0, box_size], aspect=1)
122+
ax = fig.add_subplot(111, xlim=[0, box_size], ylim=[0, box_size], aspect=1)
98123
if spike_times is not None:
99124
spikes_in_bin, _ = np.histogram(spike_times, t)
100125
is_spikes_in_bin = np.array(spikes_in_bin, dtype=bool)
101126

102127
if rate_markersize:
103-
markersizes = spikes_in_bin[is_spikes_in_bin]*markersize
128+
markersizes = spikes_in_bin[is_spikes_in_bin] * markersize
104129
else:
105-
markersizes = markersize*np.ones(is_spikes_in_bin.size)
130+
markersizes = markersize * np.ones(is_spikes_in_bin.size)
106131
ax.set_title(title)
107132
ax.grid(False)
108-
if origin == 'upper':
133+
if origin == "upper":
109134
ax.invert_yaxis()
110135
import time
136+
111137
plt.show()
112138
for idx, x, y, active, msize in zip(range(len(x)), x, y):
113139
ax.plot(x, y, c=color, alpha=alpha)
114140
if spike_times is not None:
115141
if is_spikes_in_bin[idx]:
116-
ax.scatter(x, y, facecolor=spike_color, edgecolor=spike_color,
117-
s=markersizes[idx])
142+
ax.scatter(x, y, facecolor=spike_color, edgecolor=spike_color, s=markersizes[idx])
118143
time.sleep(0.1) # plt.pause(0.0001)
119144
plt.draw()
120145
return ax
121146

122147

123-
def plot_head_direction_rate(spike_times, ang_bins, rate_in_ang, projection='polar',
124-
normalization=False, ax=None, color='k'):
148+
def plot_head_direction_rate(
149+
spike_times, ang_bins, rate_in_ang, projection="polar", normalization=False, ax=None, color="k"
150+
):
125151
"""
126152
127153
@@ -142,26 +168,38 @@ def plot_head_direction_rate(spike_times, ang_bins, rate_in_ang, projection='pol
142168
out : ax
143169
"""
144170
import math
171+
145172
if normalization:
146-
rate_in_ang = normalize(rate_in_ang, mode='minmax')
173+
rate_in_ang = normalize(rate_in_ang, mode="minmax")
147174
if ax is None:
148175
fig = plt.figure()
149176
ax = fig.add_subplot(111, projection=projection)
150177
bin_size = ang_bins[1] - ang_bins[0]
151178
if projection is None:
152179
ax.set_xticks(range(0, 360 + 60, 60))
153180
ax.set_xlim(0, 360)
154-
elif projection == 'polar':
181+
elif projection == "polar":
155182
ang_bins = [math.radians(deg) for deg in ang_bins]
156183
bin_size = math.radians(bin_size)
157184
ax.set_xticks([0, np.pi])
158185
ax.bar(ang_bins, rate_in_ang, width=bin_size, color=color)
159186
return ax
160187

161188

162-
def plot_ratemap(x, y, t, spike_times, bin_size=0.05, box_size=1,
163-
box_size=1, vmin=0, ax=None, smoothing=.05,
164-
origin='upper', cmap='viridis'):
189+
def plot_ratemap(
190+
x,
191+
y,
192+
t,
193+
spike_times,
194+
bin_size=0.05,
195+
box_size=1,
196+
box_size=1,
197+
vmin=0,
198+
ax=None,
199+
smoothing=0.05,
200+
origin="upper",
201+
cmap="viridis",
202+
):
165203
"""
166204
167205
@@ -184,19 +222,17 @@ def plot_ratemap(x, y, t, spike_times, bin_size=0.05, box_size=1,
184222
fig = plt.figure()
185223
ax = fig.add_subplot(111, xlim=[0, 1], ylim=[0, 1], aspect=1)
186224

187-
map = SpatialMap(
188-
x, y, t, spike_times, bin_size=bin_size, box_size=box_size)
225+
map = SpatialMap(x, y, t, spike_times, bin_size=bin_size, box_size=box_size)
189226
rate_map = map.rate_map(smoothing)
190-
ax.imshow(rate_map, interpolation='none', origin=origin,
191-
extent=(0, 1, 0, 1), vmin=vmin, cmap=cmap)
192-
ax.set_title('%.2f Hz' % np.nanmax(rate_map))
227+
ax.imshow(rate_map, interpolation="none", origin=origin, extent=(0, 1, 0, 1), vmin=vmin, cmap=cmap)
228+
ax.set_title("%.2f Hz" % np.nanmax(rate_map))
193229
ax.grid(False)
194230
return ax
195231

196232

197-
def plot_occupancy(x, y, t, bin_size=0.05, box_size=1, box_size=1,
198-
vmin=0, ax=None, convolve=True,
199-
origin='upper', cmap='jet'):
233+
def plot_occupancy(
234+
x, y, t, bin_size=0.05, box_size=1, box_size=1, vmin=0, ax=None, convolve=True, origin="upper", cmap="jet"
235+
):
200236
"""
201237
202238
@@ -219,10 +255,10 @@ def plot_occupancy(x, y, t, bin_size=0.05, box_size=1, box_size=1,
219255
fig = plt.figure()
220256
ax = fig.add_subplot(111, xlim=[0, 1], ylim=[0, 1], aspect=1)
221257

222-
occ_map = occupancy_map(x, y, t, bin_size=bin_size, box_size=box_size,
223-
box_size=box_size, convolve=convolve)
224-
cax = ax.imshow(occ_map, interpolation='none', origin=origin,
225-
extent=(0, 1, 0, 1), vmin=vmin, cmap=cmap, aspect='auto')
258+
occ_map = occupancy_map(x, y, t, bin_size=bin_size, box_size=box_size, box_size=box_size, convolve=convolve)
259+
cax = ax.imshow(
260+
occ_map, interpolation="none", origin=origin, extent=(0, 1, 0, 1), vmin=vmin, cmap=cmap, aspect="auto"
261+
)
226262
# ax.set_title('%.2f s' % np.nanmax(occ_map))
227263
ax.grid(False)
228264
return cax, np.nanmax(occ_map)

pyproject.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[project]
2+
name = "spatial_maps"
3+
version = "0.2.0"
4+
authors = [
5+
{ name = "Mikkel Lepperod", email = "[email protected]" },
6+
{ name = "Alessio Buccino", email = "[email protected]" },
7+
]
8+
9+
description = "Compute spatial maps for neural data."
10+
readme = "README.md"
11+
requires-python = ">=3.10"
12+
classifiers = [
13+
"Programming Language :: Python :: 3",
14+
"License :: OSI Approved :: MIT License",
15+
"Operating System :: OS Independent",
16+
]
17+
18+
dependencies = [
19+
"numpy<2",
20+
"scipy",
21+
"scikit-image",
22+
"astropy",
23+
"pandas",
24+
"elephant",
25+
"matplotlib"
26+
]
27+
28+
[project.urls]
29+
homepage = "https://github.com/CINPLA/spatial-maps"
30+
repository = "https://github.com/CINPLA/spatial-maps"
31+
32+
[build-system]
33+
requires = ["setuptools>=62.0"]
34+
build-backend = "setuptools.build_meta"
35+
36+
[tool.setuptools]
37+
include-package-data = true
38+
39+
[tool.setuptools.packages.find]
40+
where = ["src"]
41+
include = ["spatial_maps*"]
42+
namespaces = false
43+
44+
[project.optional-dependencies]
45+
dev = ["pre-commit", "black[jupyter]", "isort", "ruff"]
46+
test = ["pytest", "pytest-cov", "pytest-dependency", "mountainsort5"]
47+
docs = ["sphinx-gallery", "sphinx_rtd_theme"]
48+
full = [
49+
"spatial_maps[dev]",
50+
"spatial_maps[test]",
51+
"spatial_maps[docs]",
52+
]
53+
54+
[tool.coverage.run]
55+
omit = ["tests/*"]
56+
57+
[tool.black]
58+
line-length = 120

setup.py

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,6 @@
11
# -*- coding: utf-8 -*-
2-
from setuptools import setup
3-
import os
42

5-
from setuptools import setup, find_packages
3+
import setuptools
64

7-
long_description = open("README.md").read()
8-
9-
install_requires = [
10-
'numpy>=1.9',
11-
'scipy',
12-
'astropy',
13-
'pandas>=0.14.1',
14-
'elephant',
15-
'matplotlib']
16-
extras_require = {
17-
'testing': ['pytest'],
18-
'docs': ['numpydoc>=0.5',
19-
'sphinx>=1.2.2',
20-
'sphinx_rtd_theme']
21-
}
22-
23-
setup(
24-
name="spatial_maps",
25-
install_requires=install_requires,
26-
tests_require=install_requires,
27-
extras_require=extras_require,
28-
packages=find_packages(),
29-
include_package_data=True,
30-
version='0.1',
31-
)
5+
if __name__ == "__main__":
6+
setuptools.setup()

0 commit comments

Comments
 (0)