Skip to content
Merged
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
22 changes: 11 additions & 11 deletions bmtk/simulator/bionet/modules/ecp.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@
from dateutil.tz import tzlocal
from uuid import uuid4


from bmtk.simulator.bionet.modules.sim_module import SimulatorMod
from bmtk.utils.sonata.utils import add_hdf5_magic, add_hdf5_version

from bmtk.simulator.bionet.io_tools import io

pc = h.ParallelContext()
MPI_RANK = int(pc.id())
Expand Down Expand Up @@ -83,8 +84,12 @@ def __init__(self, tmp_dir, file_name, electrode_positions, file_name_nwb=None,

self._nwb_path = None
if file_name_nwb:
self._nwb_path = file_name_nwb if os.path.isabs(file_name_nwb) else os.path.join(tmp_dir, file_name_nwb)

try:
import pynwb
self._nwb_path = file_name_nwb if os.path.isabs(file_name_nwb) else os.path.join(tmp_dir, file_name_nwb)

except ImportError as ie:
io.log_warning('pynwb library is not installed, simulation cannot be saved to {file_name_nwb}.')

self._local_gids = []

Expand Down Expand Up @@ -246,26 +251,26 @@ def finalize(self, sim):
self._delete_tmp_files()
pc.barrier()

if self._nwb_path:
if self._nwb_path and MPI_RANK == 0:
convert2nwb(self._nwb_path, self._ecp_output, self._positions_file)

pc.barrier()


def convert2nwb(nwb_path, orig_hdf5_lfp, electrodes_file):
import pynwb

# io.log_debug('Writing to NWB format in {nwb_path}')
if os.path.exists(nwb_path):
io = pynwb.NWBHDF5IO(nwb_path, 'a')
nwbfile = io.read()
print('appending lfp')
else:
io = pynwb.NWBHDF5IO(nwb_path, "w")
nwbfile = pynwb.NWBFile(
session_start_time=datetime.now(tzlocal()),
session_description="test time",
identifier=str(uuid4()),
)
print('new nwb file')

electrodes_metdata_df = pd.read_csv(electrodes_file, sep=' ').set_index('channel')

Expand All @@ -281,14 +286,11 @@ def convert2nwb(nwb_path, orig_hdf5_lfp, electrodes_file):
)

# electrodes_file

nwbfile.add_electrode_column(name="channel_id", description="label of electrode")
with h5py.File(orig_hdf5_lfp, 'r') as orig_h5:
channels = orig_h5['ecp/channel_id'][()]
for chan in channels:
chan_data = electrodes_metdata_df.loc[chan]
# print(chan_data.get('location', 'None'))
# print(chan_data.get('x_pos', 'Not Avail'))
nwbfile.add_electrode(
group=electrode_group,
channel_id=chan,
Expand Down Expand Up @@ -327,8 +329,6 @@ def convert2nwb(nwb_path, orig_hdf5_lfp, electrodes_file):

io.write(nwbfile)

# print(nwb_path)


class RecXElectrode(object):
"""Extracellular electrode
Expand Down
29 changes: 15 additions & 14 deletions bmtk/utils/reports/spike_trains/spikes_file_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,11 @@ def write_nwb(path, spiketrain_reader, mode='a', include_population=True, units=
if MPI_rank == 0:
# Last checked pynwb doesn't support writing on multiple cores, must let first core do all the
# writing to NWB.

if os.path.exists(path) and mode != 'w':
io = pynwb.NWBHDF5IO(path, 'a')
nwbfile = io.read()
else:
io = pynwb.NWBHDF5IO(path, mode)
io = pynwb.NWBHDF5IO(path, 'w')
nwbfile = pynwb.NWBFile(
session_description='BMTK {} generated NWB spikes file'.format(bmtk.__version__),
identifier='Generated in-silico, no session id', # TODO: No idea what to put here?
Expand All @@ -180,20 +179,22 @@ def write_nwb(path, spiketrain_reader, mode='a', include_population=True, units=

nwbfile.add_unit_column(name="node_id", description="id of each node within a population")

for population in spiketrain_reader.populations:
for node_id in spiketrain_reader.node_ids(population=population):
spikes_times = spiketrain_reader.get_times(node_id=node_id, population=population)
if spikes_times is None or len(spikes_times) == 0:
# No spikes for given node, don't try to write to nwb
continue

# sometimes bmtk/sonata may default to use different 32 or unsigned data-types which will cause
# nwb to throw a fit. Need to explicity convert data-types just in case.
spikes_times = spikes_times.astype('float64')
node_id = int(node_id)
for population in spiketrain_reader.populations:
for node_id in spiketrain_reader.node_ids(population=population):
spikes_times = spiketrain_reader.get_times(node_id=node_id, population=population)
if spikes_times is None or len(spikes_times) == 0:
# No spikes for given node, don't try to write to nwb
continue

# sometimes bmtk/sonata may default to use different 32 or unsigned data-types which will cause
# nwb to throw a fit. Need to explicity convert data-types just in case.
spikes_times = np.array(spikes_times).astype('float64')
node_id = int(node_id)
if MPI_rank == 0:
add_unit(node_id, population, spikes_times)

# with pynwb.NWBHDF5IO(path, mode) as io:
# with pynwb.NWBHDF5IO(path, mode) as io:
if MPI_rank == 0:
io.write(nwbfile)

comm_barrier()
23 changes: 23 additions & 0 deletions docs/autodocs/source/bionet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,29 @@ And in the config
cell’s ECP.


**Saving ECP to NWB (Neurodata without Borders) format**

You can save the recorded extraceullar field to NWB format by specifying the "file_name_nwb" option.

.. code:: json

{
"ecp": {
"cells": "all",
"variable_name": "v",
"module": "extracellular",
"electrode_positions": "components/xelectrode/linear_probe.csv",
"file_name": "ecp.h5",
"file_name_nwb": "session_data.nwb"
}
}

In the above case will create an ElectricalSeries acquistion in the session_data.nwb file which can be analyzed
using pynwb, Matlab, pynapple, or other tools that support the reading of the NWB ecephys data. If the same session
nwb is also being used to write spikes or membrane properties, BMTK will attempt to append all data of the same
simulation "session" into a single file.


Synaptic Variables
++++++++++++++++++
Similar to recording from membrane potential, by setting the ``module`` parameter to ``netcon_report``, you can record the
Expand Down
Loading