-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add iv-curve * add unit test * add calculate_rheobase function in tools + unit tests
- Loading branch information
Showing
6 changed files
with
305 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
"""Module for analyzing cell simulation results.""" | ||
try: | ||
import efel | ||
except ImportError: | ||
efel = None | ||
import numpy as np | ||
|
||
from bluecellulab.stimulus import StimulusFactory | ||
from bluecellulab.tools import calculate_rheobase | ||
from bluecellulab.analysis.inject_sequence import run_stimulus | ||
from bluecellulab.analysis.plotting import plot_iv_curve | ||
|
||
|
||
def compute_plot_iv_curve(cell, stim_start=100.0, duration=500.0, post_delay=100.0, threshold_voltage=-30, nb_bins=11): | ||
"""Compute and plot the IV curve from a given cell by injecting a | ||
predefined range of currents. | ||
Args: | ||
cell (bluecellulab.cell.Cell): The initialized cell model. | ||
stim_start (float): Start time for current injection (in ms). Default is 100.0 ms. | ||
duration (float): Duration of current injection (in ms). Default is 500.0 ms. | ||
post_delay (float): Delay after the stimulation ends (in ms). Default is 100.0 ms. | ||
nb_bins (int): Number of current injection levels. Default is 11. | ||
Returns: | ||
tuple: A tuple containing: | ||
- list_amp (np.ndarray): The predefined injected step current levels (nA). | ||
- steady_states (np.ndarray): The corresponding steady-state voltages (mV). | ||
""" | ||
rheobase = calculate_rheobase(cell) | ||
|
||
list_amp = np.linspace(rheobase - 2, rheobase - 0.1, nb_bins) # [nA] | ||
|
||
steps = [] | ||
times = [] | ||
voltages = [] | ||
# inject step current and record voltage response | ||
for amp in list_amp: | ||
stim_factory = StimulusFactory(dt=0.1) | ||
step_stimulus = stim_factory.step(pre_delay=stim_start, duration=duration, post_delay=post_delay, amplitude=amp) | ||
recording = run_stimulus(cell.template_params, step_stimulus, section="soma[0]", segment=0.5) | ||
steps.append(step_stimulus) | ||
times.append(recording.time) | ||
voltages.append(recording.voltage) | ||
|
||
steady_states = [] | ||
# compute steady state response | ||
efel.set_setting('Threshold', threshold_voltage) | ||
for voltage, t in zip(voltages, times): | ||
trace = { | ||
'T': t, | ||
'V': voltage, | ||
'stim_start': [stim_start], | ||
'stim_end': [stim_start + duration] | ||
} | ||
features_results = efel.get_feature_values([trace], ['steady_state_voltage_stimend']) | ||
steady_state = features_results[0]['steady_state_voltage_stimend'] | ||
steady_states.append(steady_state) | ||
|
||
# plot I-V curve | ||
plot_iv_curve(list_amp, steady_states) | ||
|
||
return np.array(list_amp), np.array(steady_states) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
"""Module for plotting analysis results of cell simulations.""" | ||
|
||
import matplotlib.pyplot as plt | ||
|
||
|
||
def plot_iv_curve(currents, voltages): | ||
"""Plots the IV curve. | ||
Args: | ||
currents (iterable): The injected current levels (nA). | ||
voltages (iterable): The corresponding steady-state voltages (mV). | ||
Raises: | ||
ValueError: If the lengths of currents and voltages do not match. | ||
""" | ||
if len(currents) != len(voltages): | ||
raise ValueError("currents and voltages must have the same length") | ||
|
||
# Plotting | ||
plt.figure(figsize=(10, 6)) | ||
plt.plot(voltages, currents, marker='o', linestyle='-', color='b') | ||
plt.title("I-V Curve") | ||
plt.ylabel("Injected current [nA]") | ||
plt.xlabel("Steady state voltage [mV]") | ||
plt.tight_layout() | ||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
"""Unit tests for the analysis module.""" | ||
|
||
from unittest.mock import MagicMock, patch | ||
import numpy as np | ||
import pytest | ||
from bluecellulab.analysis.analysis import compute_plot_iv_curve | ||
from pathlib import Path | ||
from bluecellulab.cell import Cell | ||
from bluecellulab.circuit.circuit_access import EmodelProperties | ||
|
||
|
||
parent_dir = Path(__file__).resolve().parent.parent | ||
|
||
|
||
class MockRecording: | ||
def __init__(self): | ||
self.time = [1, 2, 3] | ||
self.voltage = [-70, -55, -40] | ||
|
||
|
||
@pytest.fixture | ||
def mock_run_stimulus(): | ||
return MagicMock(return_value=MockRecording()) | ||
|
||
|
||
@pytest.fixture | ||
def mock_search_threshold_current(): | ||
return MagicMock(return_value=0.1) | ||
|
||
|
||
@pytest.fixture | ||
def mock_steady_state_voltage_stimend(): | ||
return MagicMock(return_value=-65) | ||
|
||
|
||
@pytest.fixture | ||
def mock_efel(): | ||
efel_mock = MagicMock() | ||
efel_mock.getFeatureValues.return_value = [{'steady_state_voltage_stimend': [-65]}] | ||
return efel_mock | ||
|
||
|
||
@pytest.fixture | ||
def mock_cell(): | ||
emodel_properties = EmodelProperties( | ||
threshold_current=1.1433533430099487, | ||
holding_current=1.4146618843078613, | ||
AIS_scaler=1.4561502933502197, | ||
soma_scaler=1.0 | ||
) | ||
cell = Cell( | ||
f"{parent_dir}/examples/circuit_sonata_quick_scx/components/hoc/cADpyr_L2TPC.hoc", | ||
f"{parent_dir}/examples/circuit_sonata_quick_scx/components/morphologies/asc/rr110330_C3_idA.asc", | ||
template_format="v6", | ||
emodel_properties=emodel_properties | ||
) | ||
return cell | ||
|
||
|
||
def test_plot_iv_curve(mock_cell, mock_run_stimulus, mock_search_threshold_current, mock_efel): | ||
"""Test the plot_iv_curve function.""" | ||
with patch('bluecellulab.cell.core', mock_cell), \ | ||
patch('bluecellulab.analysis.analysis.run_stimulus', mock_run_stimulus), \ | ||
patch('bluecellulab.tools.search_threshold_current', mock_search_threshold_current), \ | ||
patch('bluecellulab.analysis.analysis.efel', mock_efel): | ||
|
||
stim_start = 100.0 | ||
duration = 500.0 | ||
post_delay = 100.0 | ||
threshold_voltage = -30 | ||
nb_bins = 11 | ||
|
||
list_amp, steady_states = compute_plot_iv_curve(mock_cell, stim_start, duration, post_delay, threshold_voltage, nb_bins) | ||
|
||
assert isinstance(list_amp, np.ndarray) | ||
assert isinstance(steady_states, np.ndarray) | ||
assert len(list_amp) == nb_bins | ||
assert len(steady_states) == nb_bins |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters