Compare commits

...

3 Commits

Author SHA1 Message Date
wendtalexander
a628359fe9 [pyproject] adding scipy to docs 2025-10-20 10:20:00 +02:00
wendtalexander
5bc7b31b28 [main] adding timeline command 2025-10-20 10:19:46 +02:00
wendtalexander
f3f5f916fb [doc] adding comparision between stimulus 2025-10-20 10:19:34 +02:00
4 changed files with 1037 additions and 921 deletions

View File

@@ -1,36 +1,45 @@
--- ---
title: Calibration title: Calibration
format:
html:
toc: true
toc-title: Contents
code-block-bg: true
code-block-border-left: "#31BAE9"
code-line-numbers: true
highlight-style: atom-one
link-external-icon: true
link-external-newwindow: true
eqn-number: true
--- ---
### Calibration of the Amplitude ### Calibration of the Amplitude
Lets look at the calibration and the first trial of the recording.
```{python} ```{python}
import pathlib
import rlxnix as rlx import rlxnix as rlx
import plotly.graph_objects as go import plotly.graph_objects as go
import numpy as np import numpy as np
import scipy.signal as signal
from plotly.subplots import make_subplots from plotly.subplots import make_subplots
dataset = rlx.Dataset("../oephys2nix/test/Test1/2025-10-08-aa-invivo-2-recording.nix") dataset_path = pathlib.Path("../oephys2nix/test/Test1/2025-10-08-aa-invivo-2-recording.nix")
relacs = rlx.Dataset("../oephys2nix/test/Test1/2025-10-08-aa-invivo-2_relacs/2025-10-08-aa-invivo-2.nix") relacs_path = pathlib.Path("../oephys2nix/test/Test1/2025-10-08-aa-invivo-2_relacs/2025-10-08-aa-invivo-2.nix")
repro_d = dataset.repro_runs("CalibEfield_1")[0]
repro_r = relacs.repro_runs("CalibEfield_1")[0]
fig = make_subplots( dataset = rlx.Dataset(str(dataset_path))
rows=4, relacs = rlx.Dataset(str(relacs_path))
cols=1,
shared_xaxes=True,
subplot_titles=(
"Stimulus Comparison",
"Local EOD Comparison",
"Global EOD Comparison",
"Sinus Comparison",
),)
#INFO: Select the first stimulus of the calibration repro
repro_d = dataset.repro_runs("CalibEfield_1")[0].stimuli[2]
repro_r = relacs.repro_runs("CalibEfield_1")[0].stimuli[2]
sinus, t = repro_d.trace_data("sinus") sinus, t = repro_d.trace_data("sinus")
sinus_r, t_r = repro_r.trace_data("V-1") sinus_r, t_r = repro_r.trace_data("V-1")
stimulus_oe, t = repro_d.trace_data("stimulus") stimulus_oe, t = repro_d.trace_data("stimulus")
stimulus_re, t_r = repro_r.trace_data("GlobalEFieldStimulus") stimulus_re, t_r = repro_r.trace_data("GlobalEFieldStimulus")
@@ -41,11 +50,27 @@ global_eod_oe, t = repro_d.trace_data("global-eod")
global_eod_re, t_r = repro_r.trace_data("EOD") global_eod_re, t_r = repro_r.trace_data("EOD")
ttl, t = repro_d.trace_data("ttl-line") ttl, t = repro_d.trace_data("ttl-line")
```
### Plotting the First trial
If you zoom in you can see a little delay between the different recording systems. It seems that open-ephys is before the relacs recording.
```{python}
#| echo: False
# 2. Add traces to the FIRST subplot (row=1, col=1) # 2. Add traces to the FIRST subplot (row=1, col=1)
# Note: Plotly rows and columns are 1-indexed # Note: Plotly rows and columns are 1-indexed
fig = make_subplots( rows=5, cols=1, shared_xaxes=True, subplot_titles=("TTL-Line",
"Stimulus Comparison", "Local EOD Comparison", "Global EOD Comparison",
"Sinus Comparison"))
fig.add_trace(
go.Scatter(x=t, y=ttl, name="ttl-line", line_color="magenta"),
row=1,
col=1,
)
fig.add_trace( fig.add_trace(
go.Scatter(x=t_r, y=stimulus_re, name="stimulus (relacs)", line_color="blue"), go.Scatter(x=t_r, y=stimulus_re, name="stimulus (relacs)", line_color="blue"),
row=1, row=2,
col=1, col=1,
) )
fig.add_trace( fig.add_trace(
@@ -55,12 +80,7 @@ fig.add_trace(
name="stimulus (open-ephys)", name="stimulus (open-ephys)",
line_color="red", line_color="red",
), ),
row=1, row=2,
col=1,
)
fig.add_trace(
go.Scatter(x=t, y=ttl, name="ttl-line", line_color="black"),
row=1,
col=1, col=1,
) )
@@ -68,12 +88,12 @@ fig.add_trace(
# 3. Add traces to the SECOND subplot (row=2, col=1) # 3. Add traces to the SECOND subplot (row=2, col=1)
fig.add_trace( fig.add_trace(
go.Scatter(x=t_r, y=local_eod_re, name="local EOD (relacs)", line_color="blue"), go.Scatter(x=t_r, y=local_eod_re, name="local EOD (relacs)", line_color="blue"),
row=2, row=3,
col=1, col=1,
) )
fig.add_trace( fig.add_trace(
go.Scatter(x=t, y=local_eod_oe, name="local EOD (open-ephys)", line_color="red"), go.Scatter(x=t, y=local_eod_oe, name="local EOD (open-ephys)", line_color="red"),
row=2, row=3,
col=1, col=1,
) )
@@ -81,42 +101,112 @@ fig.add_trace(
# 4. Add traces to the THIRD subplot (row=3, col=1) # 4. Add traces to the THIRD subplot (row=3, col=1)
fig.add_trace( fig.add_trace(
go.Scatter(x=t_r, y=global_eod_re, name="global EOD (relacs)", line_color="blue"), go.Scatter(x=t_r, y=global_eod_re, name="global EOD (relacs)", line_color="blue"),
row=3, row=4,
col=1, col=1,
) )
fig.add_trace( fig.add_trace(
go.Scatter( go.Scatter(
x=t, y=global_eod_oe, name="global EOD (open-ephys)", line_color="red" x=t, y=global_eod_oe, name="global EOD (open-ephys)", line_color="red"
), ),
row=3, row=4,
col=1, col=1,
) )
# 5. Add traces to the FOURTH subplot (row=4, col=1) # 5. Add traces to the FOURTH subplot (row=4, col=1)
fig.add_trace( fig.add_trace(
go.Scatter(x=t_r, y=sinus_r, name="sinus (relacs)", line_color="blue"), go.Scatter(x=t_r, y=sinus_r, name="sinus (relacs)", line_color="blue"),
row=4, row=5,
col=1, col=1,
) )
fig.add_trace( fig.add_trace(
go.Scatter(x=t, y=sinus, name="sinus (open-ephys)", line_color="red"), go.Scatter(x=t, y=sinus, name="sinus (open-ephys)", line_color="red"),
row=4, row=5,
col=1, col=1,
) )
# 6. Update the layout for a cleaner look # 6. Update the layout for a cleaner look
fig.update_layout( fig.update_layout(
title_text="Relacs vs. Open Ephys Data Alignment", template="plotly_dark",
height=800, # Set the figure height in pixels height=800, # Set the figure height in pixels
# Control the legend # Control the legend
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), #legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
legend=dict(
bgcolor="rgba(0,0,0,0)", # transparent dark (or use "#1f2630" to match bg)
bordercolor="#444",
borderwidth=0,
font=dict(color="#e5ecf6") # matches plotly_dark foreground
)
) )
# Add a label to the shared x-axis (targeting the last subplot) # Add a label to the shared x-axis (targeting the last subplot)
fig.update_xaxes(title_text="Time (s)", row=4, col=1) fig.update_xaxes(title_text="Time (s)", row=4, col=1)
# 7. Show the figure # 7. Show the figure
fig.show() fig.show()
``` ```
### Correlation between the Signals
```{python}
print(f"Duration of the dataset {repro_d.duration}")
print(f"Duration of the relacs {repro_r.duration}")
# Resample the open-ephys data
sinus_resampled = signal.resample(sinus, len(sinus_r))
```
```{python}
#| echo: False
fig = go.Figure()
fig.add_trace( go.Scatter(x=t_r, y=sinus_r, name="sinus (relacs)", line_color="blue", mode="lines+markers"))
fig.add_trace( go.Scatter(x=t_r, y=sinus_resampled, name="sinus-resampled (open-ephys)", line_color="red", mode="lines+markers"))
fig.update_layout(
template="plotly_dark",
height=500, # Set the figure height in pixels
# Control the legend
#legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
legend=dict(
bgcolor="rgba(0,0,0,0)", # transparent dark (or use "#1f2630" to match bg)
bordercolor="#444",
borderwidth=0,
font=dict(color="#e5ecf6") # matches plotly_dark foreground
)
)
fig.update_xaxes(range=[0, 0.01])
```
We need to scale the two signals
```{python}
oephys_lanes = [sinus, local_eod_oe, global_eod_oe, stimulus_oe]
relacs_lanes = [sinus_r, local_eod_re, global_eod_re, stimulus_re]
names_lanes = ["sinus", "local-eod", "global-eod", "stimulus"]
lags_lanes = []
for oephys_lane, relacs_lane, names_lane in zip(oephys_lanes, relacs_lanes, names_lanes, strict=True):
print(oephys_lane.shape)
print(relacs_lane.shape)
oephys_lane_resampled = signal.resample(oephys_lane, len(relacs_lane))
correlation = signal.correlate(oephys_lane_resampled, relacs_lane, mode="full")
lags = signal.correlation_lags(oephys_lane_resampled.size, relacs_lane.size, mode="full")
lag = lags[np.argmax(correlation)]
lags_lanes.append(lag)
print(f"{names_lane} has a lag of {lag}")
```
```{python}
#| echo: False
fig = go.Figure()
fig.add_trace( go.Scatter(x=t_r, y=sinus_r, name="sinus (relacs)", line_color="blue", mode="lines+markers"))
fig.add_trace( go.Scatter(x=t_r, y=np.roll(sinus_resampled, -lags_lanes[0]), name="sinus-resampled (open-ephys)", line_color="red", mode="lines+markers"))
fig.update_layout(
title="Sinus",
template="plotly_dark",
height=500, # Set the figure height in pixels
# Control the legend
#legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
legend=dict(
bgcolor="rgba(0,0,0,0)", # transparent dark (or use "#1f2630" to match bg)
bordercolor="#444",
borderwidth=0,
font=dict(color="#e5ecf6") # matches plotly_dark foreground
)
)
fig.update_xaxes(range=[0, 0.01])
```

View File

@@ -3,6 +3,7 @@ from pathlib import Path
from typing import Annotated from typing import Annotated
import nixio import nixio
import rlxnix as rlx
import typer import typer
from IPython import embed from IPython import embed
from rich.console import Console from rich.console import Console
@@ -37,11 +38,11 @@ def main(
setup_logging(logging.getLogger("oephys2nix"), verbosity=verbose) setup_logging(logging.getLogger("oephys2nix"), verbosity=verbose)
log.info(f"Selected data_path is {data_path}") log.info(f"Selected data_path is {data_path}")
open_ephys_data_paths = list(Path(data_path).rglob("*open-ephys")) open_ephys_data_paths = list(Path(data_path).rglob("*open-ephys"))
relacs_data_paths = list(Path(data_path).rglob("*relacs/*.nix"))
if not open_ephys_data_paths: if not open_ephys_data_paths:
log.error("Did not find any open-ephys data") log.error("Did not find any open-ephys data")
raise typer.Exit() raise typer.Exit()
relacs_data_paths = list(Path(data_path).rglob("*relacs/*.nix"))
if not relacs_data_paths: if not relacs_data_paths:
log.error("Did not find any relacs data") log.error("Did not find any relacs data")
raise typer.Exit() raise typer.Exit()
@@ -97,5 +98,27 @@ def main(
# stim.plot_stimulus() # stim.plot_stimulus()
@app.command()
def timeline(
data_path: Path = typer.Argument(
...,
help="The source directory containing the Open Ephys data.",
exists=True,
file_okay=False,
dir_okay=True,
readable=True,
resolve_path=True,
),
):
relacs_data_paths = list(Path(data_path).rglob("*relacs/*.nix"))
if not relacs_data_paths:
log.error("Did not find any relacs data")
raise typer.Exit()
dataset = rlx.Dataset(str(relacs_data_paths[0]))
dataset.plot_timeline()
dataset.close()
if __name__ == "__main__": if __name__ == "__main__":
app() app()

View File

@@ -22,6 +22,7 @@ docs = [
"jupyterlab>=4.4.9", "jupyterlab>=4.4.9",
"plotly>=6.3.1", "plotly>=6.3.1",
"quartodoc>=0.11.1", "quartodoc>=0.11.1",
"scipy>=1.16.2",
] ]
[tool.ruff] [tool.ruff]

1776
uv.lock generated

File diff suppressed because it is too large Load Diff