Skip to content
Open
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
45 changes: 44 additions & 1 deletion docs/getting_started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,16 @@ this checked-out directory and run:
$ conda env create -n cedalion -f environment_dev.yml
```

Select a descriptive name for the environment. Keep in mind that over time you
may want to have multiple environments in parallel, for example when you are working
on two projects that use different versions of cedalion. A naming scheme that
includes the current date ('cedalion_YYMMDD') is practical but you are free to choose
whatever works best for you.

Afterwards activate the environment and add an editable install of `cedalion` to it:
```
$ conda activate cedalion
$ pip install -e .
$ pip install -e . --no-deps
```

This will also install Jupyter Notebook to run the example notebooks.
Expand Down Expand Up @@ -93,6 +99,43 @@ $ hatch run build_docs
The same procedure as above applies. However, make sure to use a released version
from the main branch.

## Updating

### Updating between releases

In the past, you cloned the git repository to a local directory using the last released
version on the main branch. During installation, you created a conda environment and
added cedalion from that directory to the environment.

Updating to a newer version is easiest done by cloning the git repository again to a
different folder and creating a new environment. This way, the installed version remains
usable. It also guarantees that the new environment contains any updated dependencies.

The following example uses the version suffix in the directory and environment name.

```
$ git clone [email protected]:ibs-lab/cedalion.git path/to/cedalion_v25.1.0
$ cd path/to/cedalion_v25.1.0
$ conda env create -n cedalion_v25.1.0 -f environment_dev.yml
$ conda activate cedalion_v25.1.0
$ pip install -e . --no-deps
```

Switching between the different cedalion versions is then possible by activating the
corresponding environment.

### During development

Cedalion's development happens in the dev branch. The cloned git repository contains the
complete development history and maintains the connection to our main repository at
GitHub. By pulling the recent changes from there or by checking out a commit from the past
the cedalion directory can be brought to any desired version. The conda environment
will then use the checked out version.

Keep in mind that the cedalion's dependencies changed over time. When pulling recent
changes from dev you might need to update or recreate the environment.



## Container Environments

Expand Down
7 changes: 6 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ dependencies = [
"pywavefront==1.3.*",
"setuptools-scm",
"snirf==0.8.*",
"pmcx==0.4.2",
"pmcx>=0.3.3",
"pmcxcl==0.3.1",
"pyxdf==1.17.0",
]
Expand All @@ -80,6 +80,11 @@ requires = [
"hatch-conda>=0.5.2",
]

[tool.hatch.build.targets.sdist]
exclude = [
"/.github",
"/docs",
]

[tool.hatch.envs.default]
type = "conda"
Expand Down
83 changes: 83 additions & 0 deletions src/cedalion/vis/plot_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.figure import Figure
import matplotlib.pyplot as plt

import cedalion
import cedalion.typing as cdt
Expand Down Expand Up @@ -669,3 +670,85 @@ def run_vis(
main_gui = _MAIN_GUI(snirfData=blockaverage, geo2d=geo2d, geo3d=geo3d)
main_gui.show()
sys.exit(app.exec())


def save_plot_probe_image(
blockaverage,
geo2d,
geo3d,
out_file="probe_plot.png",
xscale=1.0,
yscale=1.0,
title=None,
show_optode_labels=True,
show_meas_lines=False,
):

# Extract probe layout
sPos = geo2d.sel(label=["S" in str(l) for l in geo2d.label.values])
dPos = geo2d.sel(label=["D" in str(l) for l in geo2d.label.values])
sourcePos3D = geo3d.sel(label=["S" in str(l) for l in geo3d.label.values])
detectorPos3D = geo3d.sel(label=["D" in str(l) for l in geo3d.label.values])

sPosVal = sPos.values
dPosVal = dPos.values

src_idx = [np.where(sPos.label == s)[0][0] for s in blockaverage.source.values]
det_idx = [np.where(dPos.label == d)[0][0] for d in blockaverage.detector.values]

chan_dist = np.linalg.norm(sourcePos3D.values[src_idx] - detectorPos3D.values[det_idx], axis=1)

# Normalize positions for plotting
all_xy = np.vstack((sPosVal, dPosVal))
scale = max(all_xy[:, 0].ptp(), all_xy[:, 1].ptp())
sxy = (sPosVal - all_xy.mean(axis=0)) / scale
dxy = (dPosVal - all_xy.mean(axis=0)) / scale

sx, sy = sxy[:, 0], sxy[:, 1]
dx, dy = dxy[:, 0], dxy[:, 1]

# Midpoints of channels
mx = (sx[src_idx] + dx[det_idx]) / 2
my = (sy[src_idx] + dy[det_idx]) / 2

# Time and HRF
t = blockaverage.reltime.values
hrf = blockaverage.values
trial_idx = 0 # First condition only
chrom_colors = [[0.862, 0.078, 0.235], [0, 0, 0.8]] # HbO and HbR

fig, ax = plt.subplots(figsize=(12, 12))

for i_ch in range(len(mx)):
for i_col in range(hrf.shape[2]):
x = mx[i_ch] + xscale * 0.1 * (t - t[0]) / (t[-1] - t[0])
y = my[i_ch] + yscale * 0.1 * (hrf[trial_idx, i_ch, i_col, :] - hrf.min()) / (hrf.max() - hrf.min())
ax.plot(x, y, color=chrom_colors[i_col], lw=0.7)

# Optodes
ax.plot(sx, sy, 'ro', label='Sources', alpha=0.6)
ax.plot(dx, dy, 'bo', label='Detectors', alpha=0.6)

# # Measurement lines
# for si, di in zip(src_idx, det_idx):
# ax.plot([sx[si], dx[di]], [sy[si], dy[di]], linestyle='--', color='gray', alpha=0.3)

if show_optode_labels:
for i, label in enumerate(sPos.label.values):
ax.text(sx[i], sy[i], str(label), color="r", fontsize=8, ha="center", va="center")
for i, label in enumerate(dPos.label.values):
ax.text(dx[i], dy[i], str(label), color="b", fontsize=8, ha="center", va="center")

if show_meas_lines:
for si, di in zip(src_idx, det_idx):
ax.plot([sx[si], dx[di]], [sy[si], dy[di]], linestyle='--', color='gray', alpha=0.3)

if title:
ax.set_title(title)

ax.axis('off')
ax.set_aspect('equal')
plt.tight_layout()
plt.savefig(out_file, dpi=300)
plt.close()
print(f"Saved probe plot to: {out_file}")