コード例 #1
0
    def run_conversion(self,
                       nwbfile: NWBFile,
                       metadata: dict = None,
                       overwrite: bool = False):
        assert isinstance(nwbfile,
                          NWBFile), "'nwbfile' should be of type pynwb.NWBFile"
        metadata_default = self.get_metadata()
        metadata = dict_deep_update(metadata_default, metadata)
        # Subject:
        if nwbfile.subject is None:
            nwbfile.subject = Subject(**metadata['Subject'])
        # adding behavior:
        start_time = 0.0
        rate = 1 / self.data_frame.time.diff().mean()
        beh_ts = []
        for behdict in self.beh_args:
            if 'cm' in behdict['unit']:
                conv = 1e-2
                behdict.update(unit='m')
            else:
                conv = 1
            behdict.update(starting_time=start_time,
                           rate=rate,
                           data=self.data_frame[behdict['name']].to_numpy() *
                           conv)
            beh_ts.append(TimeSeries(**behdict))
        if 'behavior' not in nwbfile.processing:
            beh_mod = nwbfile.create_processing_module(
                'behavior', 'Container for behavior time series')
            beh_mod.add(
                BehavioralTimeSeries(time_series=beh_ts,
                                     name='BehavioralTimeSeries'))
        else:
            beh_mod = nwbfile.processing['behavior']
            if 'BehavioralTimeSeries' not in beh_mod.data_interfaces:
                beh_mod.add(
                    BehavioralTimeSeries(time_series=beh_ts,
                                         name='BehavioralTimeSeries'))

        # adding stimulus:
        for inp_kwargs in self.stimulus_args:
            if inp_kwargs['name'] not in nwbfile.stimulus:
                inp_kwargs.update(
                    starting_time=start_time,
                    rate=rate,
                    data=self.data_frame[inp_kwargs['name']].to_numpy())
                nwbfile.add_stimulus(TimeSeries(**inp_kwargs))
コード例 #2
0
    def test_init(self):
        ts = TimeSeries('test_ts',
                        np.ones((2, 2)),
                        'unit',
                        timestamps=[1., 2., 3.])

        bts = BehavioralTimeSeries(ts)
        self.assertEqual(bts.time_series['test_ts'], ts)
コード例 #3
0
ファイル: sebi2NWB.py プロジェクト: mpompolas/to_nwb
def add_behavior(nwbfile, expt):

    bd = expt.behaviorData(imageSync=True)

    fs = 1 / expt.frame_period()

    behavior_module = nwbfile.create_processing_module(
        name='Behavior', description='Data relevant to behavior')

    # Add Normalized Position

    pos = Position(name='Normalized Position')
    pos.create_spatial_series(name='Normalized Position',
                              rate=fs,
                              data=bd['treadmillPosition'][:, np.newaxis],
                              reference_frame='0 is belt start',
                              conversion=0.001 * bd['trackLength'])

    behavior_module.add_container(pos)

    # Add Licking

    licking = BehavioralTimeSeries(name='Licking')
    licking.create_timeseries(
        name='Licking',
        data=bd['licking'],
        rate=fs,
        unit='na',
        description='1 if mouse licked during this imaging frame')

    behavior_module.add_container(licking)

    # Add Water Reward Delivery

    water = BehavioralTimeSeries(name='Water')
    water.create_timeseries(
        name='Water',
        data=bd['water'],
        rate=fs,
        unit='na',
        description='1 if water was delivered during this imaging frame')

    behavior_module.add_container(water)

    # Add Lap Times
    laps = BehavioralEvents(name='Lap Starts')
    # TODO probably not best to have laps as data and timestamps here
    laps.create_timeseries(name='Lap Starts',
                           data=bd['lap'],
                           timestamps=bd['lap'],
                           description='Frames at which laps began',
                           unit='na')

    behavior_module.add_container(laps)
コード例 #4
0
    def test_init(self):
        ts = TimeSeries('test_ts',
                        'a hypothetical source',
                        list(),
                        'unit',
                        timestamps=list())

        bts = BehavioralTimeSeries('test_bts', ts)
        self.assertEqual(bts.source, 'test_bts')
        self.assertEqual(bts.time_series, ts)
コード例 #5
0
ファイル: nwb_convert.py プロジェクト: SteinmetzLab/dataToNWB
def face_nwb():
    """
    Adds Face Energy BehavioralTimeSeries to behavior processing module.
    Needs data from face.motionEnergy.npy and face.timestamps.npy.
    """
    face_motion_energy = read_npy_file('face.motionEnergy.npy')
    face_timestamps = read_npy_file('face.timestamps.npy')
    face_rate = get_rate(face_timestamps)
    face_energy = TimeSeries(
        name='face_motion_energy',
        data=np.ravel(face_motion_energy),
        unit='arb. unit',
        starting_time=face_timestamps[0, 1],
        rate=face_rate,
        description='Features extracted from the video of the frontal aspect of '
        'the subject, including the subject\'s face and forearms.',
        comments='The integrated motion energy across the whole frame, i.e. '
        'sum( (thisFrame-lastFrame)^2 ). Some smoothing is applied '
        'before this operation.')
    face_interface = BehavioralTimeSeries(face_energy)
    behavior_module.add_data_interface(face_interface)
コード例 #6
0
    def test_init(self):
        ts = TimeSeries('test_ts', list(), 'unit', timestamps=list())

        bts = BehavioralTimeSeries(ts)
        self.assertEqual(bts.time_series['test_ts'], ts)
コード例 #7
0
# NWB provides the concept of a *data interface*--an object for a standard
# storage location of specific types of data--through the :py:class:`~pynwb.base.NWBDataInterface` class.
# For example, :py:class:`~pynwb.behavior.BehavioralTimeSeries` provides a container for holding one or more
# :py:class:`~pynwb.base.TimeSeries` objects that store time series behavioral data. By putting
# your behavioral data into a :py:class:`~pynwb.behavior.BehavioralTimeSeries` container, downstream users and
# tools know where to look to retrieve behavioral data. For a comprehensive list of available data interfaces, see the
# :ref:`overview page <modules_overview>`
#
# :py:class:`~pynwb.base.NWBDataInterface` objects can be added as acquisition data, or as members
# of a :ref:`ProcessingModule <basic_procmod>`
#
# For the purposes of demonstration, we will use a :py:class:`~pynwb.ecephys.LFP` data interface.

from pynwb.behavior import BehavioralTimeSeries

bts = BehavioralTimeSeries()
nwbfile.add_acquisition(bts)

####################
# Each data interface stores its own type of data. We suggest you read the documentation for the
# data interface of interest in the :ref:`API documentation <api_docs>` to figure out what data the
# data interface allows and/or requires and what methods you will need to call to add this data.

####################
# .. _basic_procmod:
#
# Processing modules
# ------------------
#
# *Processing modules* are used for storing a set of data interfaces that are related to a particular
# processing workflow. For example, if you want to store the intermediate results of a spike sorting workflow,
コード例 #8
0
def AddTDTAnalogDataToNWB(tdt_block_dir,
                          nwb_file_name='',
                          signal_info=None,
                          module_name='behavior',
                          verbose=False):
    """
        Copies analog (continuous) data from the specified Blackrock file to Neurodata Without Borders (NWB) file.
        This is usually continuous signals about behavior (joystick position, screen refreshes, etc).
        User should provide information about the signals to help end users understand what is in each signal.
        Multiple calls can be used to load multiple data signals from multiple files.

        Typically, the NWB file will already be initialized by calling InitializeNWBFromBlackrock.

        :param tdt_block_dir: {str} full path of TDT files to convert to NWB. If empty, will open dialog.
        :param nwb_file_name: [optional] {str} full path of NWB file to export to. Default is to change blackrock extension to 'nwb'
        :param signal_info: [optional] {list} List of dictionaries with information about the signals to save.
        :param module_name: [optional] {str} Name of module to store data.  Usually 'behavior' but could also be 'ecephys' or 'misc'
        :param verbose: [optional] {bool} whether to print updates while converting. Default is false.
        :return: {str} filename of NWB file (empty if error)
        """
    # Check to see if user specified a TDT filename
    if not tdt_block_dir:  # no file name passed
        # Ask user to specify a file
        if 'app' not in locals():
            app = QApplication([])
        tdt_block_dir = QFileDialog.getExistingDirectory(
            QFileDialog(), 'Select Directory', getcwd())

    # Check to see if valid nwb_file_name is passed
    tdt_tsq_files = [
        f for f in listdir(tdt_block_dir) if path.splitext(f)[1] == '.tsq'
    ]
    if not nwb_file_name:
        nwb_file_name = path.splitext(tdt_tsq_files[0])[0] + '.nwb'
    if verbose: print("Writing to NWB data file %s" % (nwb_file_name))

    # Initialize the TDT file
    try:
        # Requires the raw data to be imported
        tdt_header = tdt.read_block(tdt_block_dir, headers=1)
    except:  # catch *all* exceptions
        e = sys.exc_info()[0]
        raise FileNotFoundError(
            "Couldn't open TDT file. Error: {:s}".format(e))

    # Initialize the NWB file
    nwb_io = []
    try:
        if not path.isfile(nwb_file_name):
            # Initialize NWB file
            if verbose:
                print("NWB file doesn't exist. Creating new one: %s..." %
                      (nwb_file_name))
            InitializeNWBFromTDT(tdt_block_dir, nwb_file_name, verbose=verbose)

        # Append to existing file
        if verbose: print("Opening NWB file %s..." % (nwb_file_name), end='')
        nwb_file_append = True
        nwb_io = NWBHDF5IO(nwb_file_name, mode='a')
        nwb_file = nwb_io.read()
        if verbose: print("done.")
    except:  # catch *all* exceptions
        e = sys.exc_info()[0]
        if nwb_io: nwb_io.close()
        raise FileExistsError("Couldn't open NWB file. Error: %s" % e)

    # Make sure module name is either behavior or misc
    module_name = module_name.lower()
    if (module_name != 'behavior') and (module_name != 'misc'):
        raise ValueError("Module type must either be 'behavior' or 'misc'.")

    # Parse the signal_info list
    if not signal_info:
        raise ValueError("Must specify signals to load.")
    elec_ids = []
    for cur_signal_ind, cur_signal_info in enumerate(signal_info):
        if 'label' not in cur_signal_info.keys():
            raise ValueError(
                "Signal information must have a label for each signal.")
        if 'name' not in cur_signal_info.keys():
            raise ValueError(
                "Signal information must have a name for each signal. (Should be user-understandable)"
            )
        if 'comments' not in cur_signal_info.keys():
            signal_info[cur_signal_ind]['comments'] = ''
        # Find electrode IDs for this signal
        if ('elec_id' not in cur_signal_info.keys()) or (
                not cur_signal_info['elec_id']):
            # Loop through and grab all signals of type 'streams' that aren't RAW data
            signal_info[cur_signal_ind]['elec_id'] = []
            for cur_store in tdt_header.stores.keys():
                # Grab all 'streams' but ignore RAWs
                if (tdt_header.stores[cur_store].type_str
                        == 'streams') and (cur_store[0:3] != 'RAW'):
                    signal_info[cur_signal_ind]['elec_id'].append(cur_store)

    # Create processing module for saving data
    if module_name not in nwb_file.processing.keys():
        if verbose:
            print(
                "Specified processing module (%s) does not exist. Creating." %
                (module_name))
        signal_module = ProcessingModule(
            name=module_name,
            description="Processing module for continuous signal data from %s."
            % (path.split(tdt_tsq_files[0])[1]))
        nwb_file.add_processing_module(signal_module)

    # Create data interface for the analog signals
    signal_info_str = signal_info[0]['name']
    for i in range(1, len(signal_info)):
        signal_info_str = signal_info_str + ", " + signal_info[i]['name']
    if verbose:
        print("Creating %s data interface for signals %s." %
              (module_name, signal_info_str))
    if module_name == 'behavior':
        cur_data_interface = BehavioralTimeSeries(name="Analog signals (" +
                                                  signal_info_str + ")")
    elif module_name == 'misc':
        cur_data_interface = AbstractFeatureSeries(name="Analog signals (" +
                                                   signal_info_str + ")")
    else:
        raise ValueError("Module type must either be 'behavior' or 'misc'.")

    if verbose: print("Adding signals...")
    for cur_signal_ind, cur_signal_info in enumerate(signal_info):
        # Get data from file
        analog_data = []
        analog_fs = []
        analog_start_time = []
        for cur_elec_id in cur_signal_info['elec_id']:
            cur_data = tdt.read_block(tdt_block_dir, store=cur_elec_id)
            cur_analog_data = cur_data.streams[cur_elec_id].data
            cur_analog_data = np.reshape(cur_analog_data,
                                         [len(cur_analog_data), 1])
            if len(analog_data) == 0:
                analog_fs = cur_data.streams[cur_elec_id].fs
                analog_start_time = cur_data.streams[cur_elec_id].start_time
                analog_data = cur_analog_data
            else:
                analog_fs.append(cur_data.streams[cur_elec_id].fs)
                analog_start_time.append(
                    cur_data.streams[cur_elec_id].start_time)
                analog_data = np.concatenate([analog_data, cur_analog_data],
                                             axis=1)

        # Make sure all of the fs and start_times are the same
        analog_start_time = np.unique(analog_start_time)
        analog_fs = np.unique(analog_fs)
        if len(analog_start_time) != 1 or len(analog_fs) != 1:
            raise ValueError(
                'Start time and sampling frequency need to be the same for signals to be combined.'
            )

        # Create time series
        cur_data_interface.create_timeseries(
            name=cur_signal_info['name'],
            data=analog_data,
            comments=cur_signal_info['comments'],
            unit="V",  #TODO: Check that this is correct for TDT
            resolution=1.0,  #TODO: Can we get this from TDT?
            conversion=
            0.001,  #TODO: Check what the correct conversion is for TDT
            starting_time=analog_start_time[0],
            rate=analog_fs[0],
            description="Signal %s from %s." %
            (cur_signal_info['label'], path.split(tdt_tsq_files[0])[1]))
        if verbose: print("\tAdded %s." % (cur_signal_info['label']))

    # Add data interface to module in NWB file
    if verbose: print("Adding data interface to module.")
    nwb_file.processing[module_name].add(cur_data_interface)

    # Write the file
    if verbose: print("Writing NWB file and closing.")
    nwb_io.write(nwb_file)
    nwb_io.close()

    return nwb_file_name
コード例 #9
0
def chang2nwb(blockpath,
              outpath=None,
              session_start_time=None,
              session_description=None,
              identifier=None,
              anin4=False,
              ecog_format='auto',
              external_subject=True,
              include_pitch=False,
              include_intensity=False,
              speakers=True,
              mic=False,
              mini=False,
              hilb=False,
              verbose=False,
              imaging_path=None,
              parse_transcript=False,
              include_cortical_surfaces=True,
              include_electrodes=True,
              include_ekg=True,
              subject_image_list=None,
              rest_period=None,
              load_warped=False,
              **kwargs):
    """

    Parameters
    ----------
    blockpath: str
    outpath: None | str
        if None, output = [blockpath]/[blockname].nwb
    session_start_time: datetime.datetime
        default: datetime(1900, 1, 1)
    session_description: str
        default: blockname
    identifier: str
        default: blockname
    anin4: False | str
        Whether or not to convert ANIN4. ANIN4 is used as an extra channel for
        things like button presses, and is usually unused. If a string is
        supplied, that is used as the name of the timeseries.
    ecog_format: str
        ({'htk'}, 'mat', 'raw')
    external_subject: bool (optional)
        True: (default) cortical mesh is saved in an external file and a link is
            provided to that file. This is useful if you have multiple sessions for a single subject.
        False: cortical mesh is saved normally
    include_pitch: bool (optional)
        add pitch data. Default: False
    include_intensity: bool (optional)
        add intensity data. Default: False
    speakers: bool (optional)
        Default: False
    mic: bool (optional)
        default: False
    mini: only save data stub. Used for testing
    hilb: bool
        include Hilbert Transform data. Default: False
    verbose: bool (optional)
    imaging_path: str (optional)
        None: use IMAGING_DIR
        'local': use subject_dir/Imaging/
        else: use supplied string
    parse_transcript: str (optional)
    include_cortical_surfaces: bool (optional)
    include_electrodes: bool (optional)
    include_ekg: bool (optional)
    subject_image_list: list (optional)
        List of paths of images to include
    rest_period: None | array-like
    kwargs: dict
        passed to pynwb.NWBFile

    Returns
    -------

    """

    behav_module = None

    basepath, blockname = os.path.split(blockpath)
    subject_id = get_subject_id(blockname)
    if identifier is None:
        identifier = blockname

    if session_description is None:
        session_description = blockname

    if outpath is None:
        outpath = blockpath + '.nwb'
    out_base_path = os.path.split(outpath)[0]

    if session_start_time is None:
        session_start_time = datetime(1900, 1, 1).astimezone(timezone('UTC'))

    if imaging_path is None:
        subj_imaging_path = path.join(IMAGING_PATH, subject_id)
    elif imaging_path == 'local':
        subj_imaging_path = path.join(basepath, 'imaging')
    else:
        subj_imaging_path = os.path.join(imaging_path, subject_id)

    # file paths
    bad_time_file = path.join(blockpath, 'Artifacts', 'badTimeSegments.mat')
    ecog_path = path.join(blockpath, 'RawHTK')
    ecog400_path = path.join(blockpath, 'ecog400', 'ecog.mat')
    elec_metadata_file = path.join(subj_imaging_path, 'elecs',
                                   'TDT_elecs_all.mat')
    mesh_path = path.join(subj_imaging_path, 'Meshes')
    pial_files = glob.glob(path.join(mesh_path, '*pial.mat'))

    # Create the NWB file object
    nwbfile = NWBFile(session_description,
                      identifier,
                      session_start_time,
                      datetime.now().astimezone(),
                      session_id=identifier,
                      institution='University of California, San Francisco',
                      lab='Chang Lab',
                      **kwargs)

    nwbfile.add_electrode_column('bad', 'electrode identified as too noisy')

    bad_elecs_inds = get_bad_elecs(blockpath)

    if include_electrodes:
        add_electrodes(nwbfile,
                       elec_metadata_file,
                       bad_elecs_inds,
                       load_warped=load_warped)
    else:
        device = nwbfile.create_device('256Grid')
        electrode_group = nwbfile.create_electrode_group(
            name='256Grid electrodes',
            description='auto_group',
            location='location',
            device=device)

        for elec_counter in range(256):
            bad = elec_counter in bad_elecs_inds
            nwbfile.add_electrode(id=elec_counter + 1,
                                  x=np.nan,
                                  y=np.nan,
                                  z=np.nan,
                                  imp=np.nan,
                                  location=' ',
                                  filtering='none',
                                  group=electrode_group,
                                  bad=bad)
    ecog_elecs = list(range(len(nwbfile.electrodes)))
    ecog_elecs_region = nwbfile.create_electrode_table_region(
        ecog_elecs, 'ECoG electrodes on brain')

    # Read electrophysiology data from HTK files and add them to NWB file
    if ecog_format == 'auto':
        ecog_rate, data, ecog_path = auto_ecog(blockpath,
                                               ecog_elecs,
                                               verbose=False)
    elif ecog_format == 'htk':
        if verbose:
            print('reading htk acquisition...', flush=True)
        ecog_rate, data = readhtks(ecog_path, ecog_elecs)
        data = data.squeeze()
        if verbose:
            print('done', flush=True)

    elif ecog_format == 'mat':
        with File(ecog400_path, 'r') as f:
            data = f['ecogDS']['data'][:, ecog_elecs]
            ecog_rate = f['ecogDS']['sampFreq'][:].ravel()[0]
        ecog_path = ecog400_path

    elif ecog_format == 'raw':
        ecog_path = os.path.join(tdt_data_path, subject_id, blockname,
                                 'raw.mat')
        ecog_rate, data = load_wavs(ecog_path)

    else:
        raise ValueError('unrecognized argument: ecog_format')

    ts_desc = "all Wav data"

    if mini:
        data = data[:2000]

    ecog_ts = ElectricalSeries(name='ElectricalSeries',
                               data=H5DataIO(data, compression='gzip'),
                               electrodes=ecog_elecs_region,
                               rate=ecog_rate,
                               description=ts_desc,
                               conversion=0.001)
    nwbfile.add_acquisition(ecog_ts)

    if include_ekg:
        ekg_elecs = find_ekg_elecs(elec_metadata_file)
        if len(ekg_elecs):
            add_ekg(nwbfile, ecog_path, ekg_elecs)

    if mic:
        # Add microphone recording from room
        fs, data = get_analog(blockpath, 1)
        nwbfile.add_acquisition(
            TimeSeries('microphone',
                       data,
                       'audio unit',
                       rate=fs,
                       description="audio recording from microphone in room"))
    if speakers:
        fs, data = get_analog(blockpath, 2)
        # Add audio stimulus 1
        nwbfile.add_stimulus(
            TimeSeries('speaker 1',
                       data,
                       'NA',
                       rate=fs,
                       description="audio stimulus 1"))

        # Add audio stimulus 2
        fs, data = get_analog(blockpath, 3)
        if fs is not None:
            nwbfile.add_stimulus(
                TimeSeries('speaker 2',
                           data,
                           'NA',
                           rate=fs,
                           description='the second stimulus source'))

    if anin4:
        fs, data = get_analog(blockpath, 4)
        nwbfile.add_acquisition(
            TimeSeries(anin4,
                       data,
                       'aux unit',
                       rate=fs,
                       description="aux analog recording"))

    # Add bad time segments
    if os.path.exists(bad_time_file) and os.stat(bad_time_file).st_size:
        bad_time = sio.loadmat(bad_time_file)['badTimeSegments']
        for row in bad_time:
            nwbfile.add_invalid_time_interval(start_time=row[0],
                                              stop_time=row[1],
                                              tags=('ECoG artifact', ),
                                              timeseries=ecog_ts)

    if rest_period is not None:
        nwbfile.add_epoch_column(name='label', description='label')
        nwbfile.add_epoch(start_time=rest_period[0],
                          stop_time=rest_period[1],
                          label='rest_period')

    if hilb:
        block_hilb_path = os.path.join(hilb_dir, subject_id, blockname,
                                       blockname + '_AA.h5')
        file = File(block_hilb_path, 'r')

        data = transpose_iter(
            file['X'])  # transposes data during iterative write
        filter_center = file['filter_center'][:]
        filter_sigma = file['filter_sigma'][:]

        data = H5DataIO(DataChunkIterator(tqdm(data,
                                               desc='writing hilbert data'),
                                          buffer_size=400 * 20),
                        compression='gzip')

        decomp_series = DecompositionSeries(
            name='LFPDecompositionSeries',
            description='Gaussian band Hilbert transform',
            data=data,
            rate=400.,
            source_timeseries=ecog_ts,
            metric='amplitude')

        for band_mean, band_stdev in zip(filter_center, filter_sigma):
            decomp_series.add_band(band_mean=band_mean, band_stdev=band_stdev)

        hilb_mod = nwbfile.create_processing_module(
            name='ecephys', description='holds hilbert analysis results')
        hilb_mod.add_container(decomp_series)

    if include_cortical_surfaces:
        subject = ECoGSubject(subject_id=subject_id)
        subject.cortical_surfaces = create_cortical_surfaces(
            pial_files, subject_id)
    else:
        subject = Subject(subject_id=subject_id, species='H**o sapiens')

    if subject_image_list is not None:
        subject = add_images_to_subject(subject, subject_image_list)

    if external_subject:
        subj_fpath = path.join(out_base_path, subject_id + '.nwb')
        if not os.path.isfile(subj_fpath):
            subj_nwbfile = NWBFile(session_description=subject_id,
                                   identifier=subject_id,
                                   subject=subject,
                                   session_start_time=datetime(
                                       1900, 1, 1).astimezone(timezone('UTC')))
            with NWBHDF5IO(subj_fpath, manager=manager, mode='w') as subj_io:
                subj_io.write(subj_nwbfile)
        subj_read_io = NWBHDF5IO(subj_fpath, manager=manager, mode='r')
        subj_nwbfile = subj_read_io.read()
        subject = subj_nwbfile.subject

    nwbfile.subject = subject

    if parse_transcript:
        if parse_transcript == 'CV':
            parseout = parse(blockpath, blockname)
            df = make_df(parseout, 0, subject_id, align_pos=1)
            nwbfile.add_trial_column('cv_transition_time',
                                     'time of CV transition in seconds')
            nwbfile.add_trial_column(
                'speak',
                'if True, subject is speaking. If False, subject is listening')
            nwbfile.add_trial_column('condition', 'syllable spoken')
            for _, row in df.iterrows():
                nwbfile.add_trial(start_time=row['start'],
                                  stop_time=row['stop'],
                                  cv_transition_time=row['align'],
                                  speak=row['mode'] == 'speak',
                                  condition=row['label'])
        elif parse_transcript == 'singing':
            parseout = parse(blockpath, blockname)
            df = make_df(parseout, 0, subject_id, align_pos=0)
            if not len(df):
                df = pd.DataFrame(parseout)
                df['mode'] = 'speak'

            df = df.loc[df['label'].astype('bool'), :]  # handle empty labels
            nwbfile.add_trial_column(
                'speak',
                'if True, subject is speaking. If False, subject is listening')
            nwbfile.add_trial_column('condition', 'syllable spoken')
            for _, row in df.iterrows():
                nwbfile.add_trial(start_time=row['start'],
                                  stop_time=row['stop'],
                                  speak=row['mode'] == 'speak',
                                  condition=row['label'])
        elif parse_transcript == 'emphasis':
            parseout = parse(blockpath, blockname)
            try:
                df = make_df(parseout, 0, subject_id, align_pos=0)
            except:
                df = pd.DataFrame(parseout)
            if not len(df):
                df = pd.DataFrame(parseout)
            df = df.loc[df['label'].astype('bool'), :]  # handle empty labels
            nwbfile.add_trial_column('condition', 'word emphasized')
            nwbfile.add_trial_column(
                'speak',
                'if True, subject is speaking. If False, subject is listening')
            for _, row in df.iterrows():
                nwbfile.add_trial(start_time=row['start'],
                                  stop_time=row['stop'],
                                  speak=True,
                                  condition=row['label'])
        elif parse_transcript == 'MOCHA':
            nwbfile = create_transcription(nwbfile, transcript_path, blockname)

    # behavior
    if include_pitch:
        if behav_module is None:
            behav_module = nwbfile.create_processing_module(
                'behavior', 'processing about behavior')
        if os.path.isfile(
                os.path.join(blockpath, 'pitch_' + blockname + '.mat')):
            fs, data = load_pitch(blockpath)
            pitch_ts = TimeSeries(
                data=data,
                rate=fs,
                unit='Hz',
                name='pitch',
                description=
                'Pitch as extracted from Praat. NaNs mark unvoiced regions.')
            behav_module.add_container(
                BehavioralTimeSeries(name='pitch', time_series=pitch_ts))
        else:
            print('No pitch file for ' + blockname)

    if include_intensity:
        if behav_module is None:
            behav_module = nwbfile.create_processing_module(
                'behavior', 'processing about behavior')
        if os.path.isfile(
                os.path.join(blockpath, 'intensity_' + blockname + '.mat')):
            fs, data = load_pitch(blockpath)
            intensity_ts = TimeSeries(
                data=data,
                rate=fs,
                unit='dB',
                name='intensity',
                description='Intensity of speech in dB extracted from Praat.')
            behav_module.add_container(
                BehavioralTimeSeries(name='intensity',
                                     time_series=intensity_ts))
        else:
            print('No intensity file for ' + blockname)

    # Export the NWB file
    with NWBHDF5IO(outpath, manager=manager, mode='w') as io:
        io.write(nwbfile)

    if external_subject:
        subj_read_io.close()

    if hilb:
        file.close()

    # read check
    with NWBHDF5IO(outpath, manager=manager, mode='r') as io:
        io.read()