Skip to content

Commit

Permalink
Merge pull request #202 from kaeldai/release/v1.0.3
Browse files Browse the repository at this point in the history
Release/v1.0.3
  • Loading branch information
kaeldai committed Feb 16, 2022
2 parents 36d44aa + 66fe904 commit 8e470f5
Show file tree
Hide file tree
Showing 19 changed files with 150 additions and 97 deletions.
2 changes: 1 addition & 1 deletion bmtk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
__version__ = '1.0.2'
__version__ = '1.0.3'
7 changes: 5 additions & 2 deletions bmtk/analyzer/compartment.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def _find_nodes(population, config=None, nodes_file=None, node_types_file=None):
def plot_traces(config_file=None, report_name=None, population=None, report_path=None, group_by=None,
group_excludes=None, nodes_file=None, node_types_file=None,
node_ids=None, sections='origin', average=False, times=None, title=None,
show_legend=None, show=True):
show_legend=None, show=True, save_as=None):
"""Plot compartment variables (eg Membrane Voltage, Calcium conc.) traces from the output of simulation. Will
attempt to look in the SONATA simulation configuration json "reports" sections for any matching "membrane_report"
outputs with a matching report_name::
Expand Down Expand Up @@ -115,6 +115,8 @@ def plot_traces(config_file=None, report_name=None, population=None, report_path
:param show_legend: Set True or False to determine if legend should be displayed on the plot. The default (None)
function itself will guess if legend should be shown.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:return: matplotlib figure.Figure object
"""

Expand Down Expand Up @@ -176,5 +178,6 @@ def plot_traces(config_file=None, report_name=None, population=None, report_path
times=times,
title=title,
show_legend=show_legend,
show=show
show=show,
save_as=save_as
)
45 changes: 28 additions & 17 deletions bmtk/analyzer/spike_trains.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _find_nodes(population, config=None, nodes_file=None, node_types_file=None):
raise ValueError('Could not find nodes file with node population "{}".'.format(population))


def _plot_helper(plot_fnc, config_file=None, population=None, times=None, title=None, show=True,
def _plot_helper(plot_fnc, config_file=None, population=None, times=None, title=None, show=True, save_as=None,
group_by=None, group_excludes=None,
spikes_file=None, nodes_file=None, node_types_file=None):
sonata_config = SonataConfig.from_json(config_file) if config_file else None
Expand Down Expand Up @@ -136,11 +136,14 @@ def _plot_helper(plot_fnc, config_file=None, population=None, times=None, title=
else:
node_groups = None

return plot_fnc(spike_trains=spike_trains, node_groups=node_groups, population=pop, times=times, title=title, show=show)
return plot_fnc(
spike_trains=spike_trains, node_groups=node_groups, population=pop, times=times, title=title, show=show,
save_as=save_as
)


def plot_raster(config_file=None, population=None, with_histogram=True, times=None, title=None, show=True,
group_by=None, group_excludes=None,
save_as=None, group_by=None, group_excludes=None,
spikes_file=None, nodes_file=None, node_types_file=None):
"""Create a raster plot (plus optional histogram) from the results of the simulation.
Expand Down Expand Up @@ -170,6 +173,8 @@ def plot_raster(config_file=None, population=None, with_histogram=True, times=No
:param title: str, adds a title to the plot. If None (default) then name will be automatically generated using the
report_name.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:param group_by: Attribute of the "nodes" file used to group and average subsets of nodes.
:param group_excludes: list of strings or None. When using the "group_by", allows users to exclude certain groupings
based on the attribute value.
Expand All @@ -181,15 +186,17 @@ def plot_raster(config_file=None, population=None, with_histogram=True, times=No
:return: matplotlib figure.Figure object
"""
plot_fnc = partial(plotting.plot_raster, with_histogram=with_histogram)
return _plot_helper(plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show,
group_by=group_by, group_excludes=group_excludes,
spikes_file=spikes_file, nodes_file=nodes_file, node_types_file=node_types_file
return _plot_helper(
plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show, save_as=save_as,
group_by=group_by, group_excludes=group_excludes,
spikes_file=spikes_file, nodes_file=nodes_file, node_types_file=node_types_file
)


def plot_rates(config_file=None, population=None, smoothing=False, smoothing_params=None, times=None, title=None,
show=True, group_by=None, group_excludes=None, spikes_file=None, nodes_file=None, node_types_file=None):
show=True, save_as=None, group_by=None, group_excludes=None, spikes_file=None, nodes_file=None,
node_types_file=None):
"""Calculate and plot the rates of each node recorded during the simulation - averaged across the entirety of the
simulation.
Expand Down Expand Up @@ -221,6 +228,8 @@ def plot_rates(config_file=None, population=None, smoothing=False, smoothing_par
:param title: str, adds a title to the plot. If None (default) then name will be automatically generated using the
report_name.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:param group_by: Attribute of the "nodes" file used to group and average subsets of nodes.
:param group_excludes: list of strings or None. When using the "group_by", allows users to exclude certain groupings
based on the attribute value.
Expand All @@ -232,14 +241,15 @@ def plot_rates(config_file=None, population=None, smoothing=False, smoothing_par
:return: matplotlib figure.Figure object
"""
plot_fnc = partial(plotting.plot_rates, smoothing=smoothing, smoothing_params=smoothing_params)
return _plot_helper(plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show,
group_by=group_by, group_excludes=group_excludes,
spikes_file=spikes_file, nodes_file=nodes_file, node_types_file=node_types_file
return _plot_helper(
plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show, save_as=save_as,
group_by=group_by, group_excludes=group_excludes,
spikes_file=spikes_file, nodes_file=nodes_file, node_types_file=node_types_file
)


def plot_rates_boxplot(config_file=None, population=None, times=None, title=None, show=True,
def plot_rates_boxplot(config_file=None, population=None, times=None, title=None, show=True, save_as=None,
group_by=None, group_excludes=None,
spikes_file=None, nodes_file=None, node_types_file=None):
"""Creates a box plot of the firing rates taken from nodes recorded during the simulation.
Expand Down Expand Up @@ -268,6 +278,8 @@ def plot_rates_boxplot(config_file=None, population=None, times=None, title=None
:param title: str, adds a title to the plot. If None (default) then name will be automatically generated using the
report_name.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:param group_by: Attribute of the "nodes" file used to group and average subsets of nodes.
:param group_excludes: list of strings or None. When using the "group_by", allows users to exclude certain groupings
based on the attribute value.
Expand All @@ -279,8 +291,9 @@ def plot_rates_boxplot(config_file=None, population=None, times=None, title=None
:return: matplotlib figure.Figure object
"""
plot_fnc = partial(plotting.plot_rates_boxplot)
return _plot_helper(plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show,
return _plot_helper(
plot_fnc,
config_file=config_file, population=population, times=times, title=title, show=show, save_as=save_as,
group_by=group_by, group_excludes=group_excludes,
spikes_file=spikes_file, nodes_file=nodes_file, node_types_file=node_types_file
)
Expand Down Expand Up @@ -344,8 +357,6 @@ def to_dataframe(config_file, spikes_file=None, population=None):
:param population:
:return:
"""


# _, spike_trains = _find_spikes(config_file=config_file, spikes_file=spikes_file, population=population)
pop, spike_trains = _find_spikes(config_file=config_file, spikes_file=spikes_file, population=population)

Expand Down
50 changes: 28 additions & 22 deletions bmtk/simulator/bionet/modules/xstim.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ def __init__(self, positions_file, waveform, mesh_files_dir=None, cells=None, se
self._local_gids = []
self._fih = None

#def __set_extracellular_mechanism(self):
# for gid in self._local_gids:
# def __set_extracellular_mechanism(self):
# for gid in self._local_gids:

def initialize(self, sim):
if self._cells is None:
Expand All @@ -47,7 +47,7 @@ def initialize(self, sim):
def set_pointers():
for gid in self._local_gids:
cell = sim.net.get_cell_gid(gid)
#cell = sim.net.get_local_cell(gid)
# cell = sim.net.get_local_cell(gid)
cell.set_ptr2e_extracellular()

self._fih = sim.h.FInitializeHandler(0, set_pointers)
Expand All @@ -72,7 +72,10 @@ def __init__(self, positions_file, waveform, mesh_files_dir, dt):

stimelectrode_position_df = pd.read_csv(positions_file, sep=' ')

self.elmesh_files = stimelectrode_position_df['electrode_mesh_file']
if 'electrode_mesh_file' in stimelectrode_position_df.columns:
self.elmesh_files = stimelectrode_position_df['electrode_mesh_file']
else:
self.elmesh_files = None
self.elpos = stimelectrode_position_df[['pos_x', 'pos_y', 'pos_z']].T.values
self.elrot = stimelectrode_position_df[['rotation_x', 'rotation_y', 'rotation_z']].values
self.elnsites = self.elpos.shape[1] # Number of electrodes in electrode file
Expand All @@ -88,23 +91,30 @@ def __init__(self, positions_file, waveform, mesh_files_dir, dt):
self.place_the_electrodes()

def read_electrode_mesh(self):
el_counter = 0
for mesh_file in self.elmesh_files:
file_path = mesh_file if os.path.isabs(mesh_file) else os.path.join(self._mesh_files_dir, mesh_file)
mesh = pd.read_csv(file_path, sep=" ")
mesh_size = mesh.shape[0]
self.el_mesh_size.append(mesh_size)

self.el_mesh[el_counter] = np.zeros((3, mesh_size))
self.el_mesh[el_counter][0] = mesh['x_pos']
self.el_mesh[el_counter][1] = mesh['y_pos']
self.el_mesh[el_counter][2] = mesh['z_pos']
el_counter += 1
if self.elmesh_files is None:
# if electrode_mesh_file is missing then we still treat the electrode as a mesh on a grid of size 1 with
# single point at the (0, 0, 0) relative to electrode position
for el_counter in range(self.elnsites):
self.el_mesh_size.append(1)
self.el_mesh[el_counter] = np.zeros((3, 1))

def place_the_electrodes(self):
else:
# Each electrode has an associate mesh file
el_counter = 0
for mesh_file in self.elmesh_files:
file_path = mesh_file if os.path.isabs(mesh_file) else os.path.join(self._mesh_files_dir, mesh_file)
mesh = pd.read_csv(file_path, sep=" ")
mesh_size = mesh.shape[0]
self.el_mesh_size.append(mesh_size)

self.el_mesh[el_counter] = np.zeros((3, mesh_size))
self.el_mesh[el_counter][0] = mesh['x_pos']
self.el_mesh[el_counter][1] = mesh['y_pos']
self.el_mesh[el_counter][2] = mesh['z_pos']
el_counter += 1

def place_the_electrodes(self):
transfer_vector = np.zeros((self.elnsites, 3))

for el in range(self.elnsites):
mesh_mean = np.mean(self.el_mesh[el], axis=1)
transfer_vector[el] = self.elpos[:, el] - mesh_mean[:]
Expand All @@ -128,17 +138,13 @@ def rotate_the_electrodes(self):
self.el_mesh[el] = new_mesh

def set_transfer_resistance(self, gid, seg_coords):

rho = 300.0 # ohm cm
r05 = seg_coords['p05']
nseg = r05.shape[1]
cell_map = np.zeros((self.elnsites, nseg))
for el in six.moves.range(self.elnsites):

mesh_size = self.el_mesh_size[el]

for k in range(mesh_size):

rel = np.expand_dims(self.el_mesh[el][:, k], axis=1)
rel_05 = rel - r05
r2 = np.einsum('ij,ij->j', rel_05, rel_05)
Expand Down
29 changes: 20 additions & 9 deletions bmtk/utils/reports/compartment/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __get_node_groups(report, node_groups, population):


def plot_traces(report, population=None, node_ids=None, sections='origin', average=False, node_groups=None, times=None,
title=None, show_legend=None, show=True):
title=None, show_legend=None, show=True, save_as=None):
"""Displays the time trace of one or more nodes from a SONATA CompartmentReport file.
To plot a group of individual variable traces (based on their soma)::
Expand Down Expand Up @@ -79,6 +79,8 @@ def plot_traces(report, population=None, node_ids=None, sections='origin', avera
:param show_legend: Set True or False to determine if legend should be displayed on the plot. The default (None)
function itself will guess if legend should be shown.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:return: matplotlib figure.Figure object
"""
if node_groups is not None and node_ids is not None:
Expand All @@ -89,26 +91,26 @@ def plot_traces(report, population=None, node_ids=None, sections='origin', avera
node_groups = {'node_ids': node_ids, 'label': average}
return plot_traces_averaged(report=report, population=population, sections=sections,
node_groups=node_groups, times=times, title=title, show_legend=show_legend,
show=show)
show=show, save_as=save_as)

return plot_traces_individual(report=report, population=population, node_ids=node_ids, sections=sections,
times=times, title=title, show_legend=show_legend, show=show)
times=times, title=title, show_legend=show_legend, show=show, save_as=save_as)

elif node_groups is not None:
return plot_traces_averaged(report=report, population=population, sections=sections, node_groups=node_groups,
times=times, title=title, show_legend=show_legend, show=show)
times=times, title=title, show_legend=show_legend, show=show, save_as=save_as)

elif average is not None:
return plot_traces_averaged(report=report, population=population, sections=sections, times=times, title=title,
show_legend=show_legend, show=show)
show_legend=show_legend, show=show, save_as=save_as)

else:
return plot_traces_individual(report=report, population=population, sections=sections, times=times, title=title,
show_legend=show_legend, show=show)
show_legend=show_legend, show=show, save_as=save_as)


def plot_traces_individual(report, population=None, node_ids=None, sections='origin', times=None, title=None,
show_legend=None, show=True):
show_legend=None, show=True, save_as=None):
"""Used the plot time traces of individual nodes from a SONATA compartment report file.
Recommended use plot_traces instead, which will call this function if necessarcy.
Expand All @@ -124,6 +126,8 @@ def plot_traces_individual(report, population=None, node_ids=None, sections='ori
:param show_legend: Set True or False to determine if legend should be displayed on the plot. The default (None)
function itself will guess if legend should be shown.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:return: matplotlib figure.Figure object
"""

Expand Down Expand Up @@ -157,14 +161,17 @@ def plot_traces_individual(report, population=None, node_ids=None, sections='ori
if title:
axes.set_title(title)

if save_as:
plt.savefig(save_as)

if show:
plt.show()

return fig


def plot_traces_averaged(report, population=None, sections='origin', node_groups=None, times=None, title=None,
show_background=True, show_legend=None, show=True):
show_background=True, show_legend=None, show=True, save_as=None):
"""Used to plot averages across multiple nodes in a SONATA Compartment Report file.
Recommended that you use "plot_traces" function.
Expand Down Expand Up @@ -192,6 +199,8 @@ def plot_traces_averaged(report, population=None, sections='origin', node_groups
:param show_legend: Set True or False to determine if legend should be displayed on the plot. The default (None)
function itself will guess if legend should be shown.
:param show: bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
save plot.
:return: matplotlib figure.Figure object
"""
cr = CompartmentReport.load(report)
Expand Down Expand Up @@ -220,7 +229,6 @@ def plot_traces_averaged(report, population=None, sections='origin', node_groups
background_data = traces_data[:, nodes_indx]
axes.plot(trace_times, background_data, c='lightgray')


for node_grp in node_groups:
grp_ids = node_grp.pop('node_ids')
has_labels = has_labels or 'label' in node_grp
Expand Down Expand Up @@ -248,6 +256,9 @@ def plot_traces_averaged(report, population=None, sections='origin', node_groups
if (show_legend is None or show_legend) and has_labels:
axes.legend()

if save_as:
plt.savefig(save_as)

if show:
plt.show()

Expand Down
Loading

0 comments on commit 8e470f5

Please sign in to comment.