def __get_single_fl_task(self, task_name, task_description, camera_id,
                             task_epochs, task_environment):
        task_name_data = VectorData(name='task_name',
                                    description='the name of the task',
                                    data=[task_name])
        task_description_data = VectorData(
            name='task_description',
            description='a description of the task',
            data=[task_description])
        camera_id_data = VectorData(
            name='camera_id',
            description='the ID number of the camera used for video',
            data=[camera_id])
        task_epochs_data = VectorData(
            name='task_epochs',
            description=
            'the temporal epochs where the animal was exposed to this task',
            data=[task_epochs])
        environment_data = VectorData(
            name='task_environment',
            description=
            'the environment in which the animal performed the task',
            data=[task_environment])

        task = TaskBuilder.build(name='task_' + str(self.task_counter),
                                 description='',
                                 task_name=task_name_data,
                                 task_description=task_description_data,
                                 camera_id=camera_id_data,
                                 task_epochs=task_epochs_data,
                                 task_environment=environment_data)
        self.task_counter += 1

        return task
Exemple #2
0
 def test_DynamicTableRegion_shape_validation(self):
     # Create a test DynamicTable
     dt_spec = [
         {
             'name': 'foo',
             'description': 'foo column'
         },
         {
             'name': 'bar',
             'description': 'bar column'
         },
         {
             'name': 'baz',
             'description': 'baz column'
         },
     ]
     dt_data = [[1, 2, 3, 4, 5], [10.0, 20.0, 30.0, 40.0, 50.0],
                ['cat', 'dog', 'bird', 'fish', 'lizard']]
     columns = [
         VectorData(name=s['name'], description=s['description'], data=d)
         for s, d in zip(dt_spec, dt_data)
     ]
     dt = DynamicTable("with_columns_and_data",
                       "a test table",
                       columns=columns)
     # Create test DynamicTableRegion
     dtr = DynamicTableRegion('dtr', [1, 2, 2], 'desc', table=dt)
     # Confirm that the shapes match
     res = assertEqualShape(dtr, np.arange(9).reshape(3, 3))
     self.assertTrue(res.result)
Exemple #3
0
    def test_task_creator_create_task_and_write_to_nwb_successfully(self):
        nwb_content = NWBFile(session_description='demonstrate external files',
                              identifier='NWBE1',
                              session_start_time=datetime(2017,
                                                          4,
                                                          3,
                                                          11,
                                                          tzinfo=tzlocal()),
                              file_create_date=datetime(2017,
                                                        4,
                                                        15,
                                                        12,
                                                        tzinfo=tzlocal()))
        processing_module = ProcessingModule('pm', 'none')

        mock_fl_task_0 = Mock(spec=FlTask)
        mock_fl_task_0.name = 'task_0'
        mock_fl_task_0.description = ''
        mock_fl_task_0.columns = [
            VectorData(name='task_name', description='', data=['Sleep']),
            VectorData(name='task_description',
                       description='',
                       data=['The animal sleeps in a small empty box.']),
            VectorData(name='camera_id', description='', data=[[0]]),
            VectorData(name='task_epochs', description='', data=[[1, 3, 5]]),
        ]
        mock_fl_task_1 = Mock(spec=FlTask)
        mock_fl_task_1.name = 'task_1'
        mock_fl_task_1.description = ''
        mock_fl_task_1.columns = [
            VectorData(name='task_name', description='', data=['Stem+Leaf']),
            VectorData(name='task_description',
                       description='',
                       data=['Spatial Bandit']),
            VectorData(name='camera_id', description='', data=[[1, 2]]),
            VectorData(name='task_epochs', description='', data=[[2, 4]]),
        ]

        task_0 = TaskCreator.create(mock_fl_task_0)
        task_1 = TaskCreator.create(mock_fl_task_1)

        processing_module.add(task_0)
        processing_module.add(task_1)
        nwb_content.add_processing_module(processing_module)

        with NWBHDF5IO(path='task.nwb', mode='w') as nwb_file_io:
            nwb_file_io.write(nwb_content)
            nwb_file_io.close()

        with NWBHDF5IO(path='task.nwb', mode='r') as nwb_file_io:
            nwb_content = nwb_file_io.read()
            self.assertContainerEqual(
                nwb_content.processing['pm'].data_interfaces['task_0'], task_0)
            self.assertContainerEqual(
                nwb_content.processing['pm'].data_interfaces['task_1'], task_1)

        os.remove('task.nwb')
def test_infer_categorical_columns():
    data1 = np.array([1, 2, 2, 3, 1, 1, 3, 2, 3])
    data2 = np.array([3, 4, 2, 4, 3, 2, 2, 4, 4])

    vd1 = VectorData('Data1',
                     'vector data for creating a DynamicTable',
                     data=data1)
    vd2 = VectorData('Data2',
                     'vector data for creating a DynamicTable',
                     data=data2)
    vd = [vd1, vd2]

    dynamic_table = DynamicTable(name='test table',
                                 description='This is a test table',
                                 columns=vd,
                                 colnames=['Data1', 'Data2'])

    assert dicts_exact_equal(infer_categorical_columns(dynamic_table), {
        'Data1': np.array([1, 2, 3]),
        'Data2': np.array([2, 3, 4])
    })
Exemple #5
0
def test_surgery():
    nwbfile = NWBFile('session description',
                      'session id',
                      datetime.now(tzlocal()),
                      experimenter='experimenter name',
                      lab='lab name',
                      institution='institution name',
                      experiment_description=('experiment description'),
                      session_id='sessionid')
    surgery_tempo = Surgery(
        surgery_date='0000-0-0',
        implantation_device='my_implantationdevice',
        ophys_implant_name='myophysimplantname',
        virus_injection_id='virusID',
        virus_injection_opsin_l_r='R',
        virus_injection_coordinates='[1.0, 2.0, 3.0]',
        ophys_injection_date='000-00-00',
        ophys_injection_flr_protein_data=DynamicTable(
            name='name',
            description='ophys_data',
            columns=[
                VectorData(name='protein_name',
                           description='protein_name_column',
                           data=['protein1', 'protein2']),
                Measurement(name='protein_concentration',
                            description='protein_conc_column',
                            data=[2e12, 5e12],
                            unit='ml')
            ]))
    mouse_data_tempo = SubjectComplete(name='mouse_metadata',
                                       surgery_data=surgery_tempo,
                                       sacrificial_date='0000-00-00',
                                       strain='myanimalstrain')

    nwbfile.subject = mouse_data_tempo
    # testing nwbfile addition:
    assert_array_equal(
        nwbfile.subject.surgery_data.ophys_injection_flr_protein_data.
        columns[1].data, [2e12, 5e12])
    assert_array_equal(
        nwbfile.subject.surgery_data.virus_injection_coordinates,
        [1.0, 2.0, 3.0])
    with NWBHDF5IO('test_device_surgery.nwb', 'w') as io:
        io.write(nwbfile)
        del nwbfile
    with NWBHDF5IO('test_device_surgery.nwb', 'r', load_namespaces=True) as io:
        nwb = io.read()
        assert_array_equal(
            nwb.subject.surgery_data.ophys_injection_flr_protein_data.
            columns[1].data, [2e12, 5e12])
        assert_array_equal(
            nwb.subject.surgery_data.virus_injection_coordinates,
            [1.0, 2.0, 3.0])
Exemple #6
0
def create_ragged_array(name, values):
    """
    :param values: list of lists
    :return:
    """
    vector_data = VectorData(
        name, 'indicates which compartments the data refers to',
        [item for sublist in values for item in sublist])
    vector_index = VectorIndex(name + '_index',
                               np.cumsum([len(x) for x in values]),
                               target=vector_data)
    return vector_data, vector_index
Exemple #7
0
def test_infer_categorical_columns():
    data1 = np.array([1, 2, 2, 3, 1, 1, 3, 2, 3])
    data2 = np.array([3, 4, 2, 4, 3, 2, 2, 4, 4])
    device = Device(name="device")
    eg_1 = ElectrodeGroup(name="electrodegroup1",
                          description="desc",
                          location="brain",
                          device=device)
    eg_2 = ElectrodeGroup(name="electrodegroup2",
                          description="desc",
                          location="brain",
                          device=device)
    data3 = [eg_1, eg_2, eg_1, eg_1, eg_1, eg_1, eg_1, eg_1, eg_1]
    vd1 = VectorData("Data1",
                     "vector data for creating a DynamicTable",
                     data=data1)
    vd2 = VectorData("Data2",
                     "vector data for creating a DynamicTable",
                     data=data2)
    vd3 = VectorData("ElectrodeGroup",
                     "vector data for creating a DynamicTable",
                     data=data3)
    vd = [vd1, vd2, vd3]

    dynamic_table = DynamicTable(
        name="test table",
        description="This is a test table",
        columns=vd,
        colnames=["Data1", "Data2", "ElectrodeGroup"],
    )
    assert dicts_exact_equal(
        infer_categorical_columns(dynamic_table),
        {
            "Data1": data1,
            "Data2": data2,
            "ElectrodeGroup": [i.name for i in data3]
        },
    )
Exemple #8
0
    def write_segmentation(
        segext_obj: SegmentationExtractor,
        save_path: PathType = None,
        plane_num=0,
        metadata: dict = None,
        overwrite: bool = True,
        buffer_size: int = 10,
        nwbfile=None,
    ):
        assert (
            save_path is None or nwbfile is None
        ), "Either pass a save_path location, or nwbfile object, but not both!"

        # parse metadata correctly:
        if isinstance(segext_obj, MultiSegmentationExtractor):
            segext_objs = segext_obj.segmentations
            if metadata is not None:
                assert isinstance(metadata, list), (
                    "For MultiSegmentationExtractor enter 'metadata' as a list of "
                    "SegmentationExtractor metadata")
                assert len(metadata) == len(segext_objs), (
                    "The 'metadata' argument should be a list with the same "
                    "number of elements as the segmentations in the "
                    "MultiSegmentationExtractor")
        else:
            segext_objs = [segext_obj]
            if metadata is not None and not isinstance(metadata, list):
                metadata = [metadata]
        metadata_base_list = [
            NwbSegmentationExtractor.get_nwb_metadata(sgobj)
            for sgobj in segext_objs
        ]
        print(f"writing nwb for {segext_obj.extractor_name}\n")
        # updating base metadata with new:
        for num, data in enumerate(metadata_base_list):
            metadata_input = metadata[num] if metadata else {}
            metadata_base_list[num] = dict_recursive_update(
                metadata_base_list[num], metadata_input)
        metadata_base_common = metadata_base_list[0]

        # build/retrieve nwbfile:
        if nwbfile is not None:
            assert isinstance(
                nwbfile, NWBFile), "'nwbfile' should be of type pynwb.NWBFile"
            write = False
        else:
            write = True
            save_path = Path(save_path)
            assert save_path.suffix == ".nwb"
            if save_path.is_file() and not overwrite:
                nwbfile_exist = True
                file_mode = "r+"
            else:
                if save_path.is_file():
                    os.remove(save_path)
                if not save_path.parent.is_dir():
                    save_path.parent.mkdir(parents=True)
                nwbfile_exist = False
                file_mode = "w"
            io = NWBHDF5IO(str(save_path), file_mode)
            if nwbfile_exist:
                nwbfile = io.read()
            else:
                nwbfile = NWBFile(**metadata_base_common["NWBFile"])

        # Subject:
        if metadata_base_common.get("Subject") and nwbfile.subject is None:
            nwbfile.subject = Subject(**metadata_base_common["Subject"])

        # Processing Module:
        if "ophys" not in nwbfile.processing:
            ophys = nwbfile.create_processing_module(
                "ophys", "contains optical physiology processed data")
        else:
            ophys = nwbfile.get_processing_module("ophys")

        for plane_no_loop, (segext_obj, metadata) in enumerate(
                zip(segext_objs, metadata_base_list)):
            # Device:
            if metadata["Ophys"]["Device"][0]["name"] not in nwbfile.devices:
                nwbfile.create_device(**metadata["Ophys"]["Device"][0])

            # ImageSegmentation:
            image_segmentation_name = (
                "ImageSegmentation" if plane_no_loop == 0 else
                f"ImageSegmentation_Plane{plane_no_loop}")
            if image_segmentation_name not in ophys.data_interfaces:
                image_segmentation = ImageSegmentation(
                    name=image_segmentation_name)
                ophys.add(image_segmentation)
            else:
                image_segmentation = ophys.data_interfaces.get(
                    image_segmentation_name)

            # OpticalChannel:
            optical_channels = [
                OpticalChannel(**i) for i in metadata["Ophys"]["ImagingPlane"]
                [0]["optical_channel"]
            ]

            # ImagingPlane:
            image_plane_name = ("ImagingPlane" if plane_no_loop == 0 else
                                f"ImagePlane_{plane_no_loop}")
            if image_plane_name not in nwbfile.imaging_planes.keys():
                input_kwargs = dict(
                    name=image_plane_name,
                    device=nwbfile.get_device(
                        metadata_base_common["Ophys"]["Device"][0]["name"]),
                )
                metadata["Ophys"]["ImagingPlane"][0][
                    "optical_channel"] = optical_channels
                input_kwargs.update(**metadata["Ophys"]["ImagingPlane"][0])
                if "imaging_rate" in input_kwargs:
                    input_kwargs["imaging_rate"] = float(
                        input_kwargs["imaging_rate"])
                imaging_plane = nwbfile.create_imaging_plane(**input_kwargs)
            else:
                imaging_plane = nwbfile.imaging_planes[image_plane_name]

            # PlaneSegmentation:
            input_kwargs = dict(
                description="output from segmenting imaging plane",
                imaging_plane=imaging_plane,
            )
            ps_metadata = metadata["Ophys"]["ImageSegmentation"][
                "plane_segmentations"][0]
            if ps_metadata[
                    "name"] not in image_segmentation.plane_segmentations:
                ps_exist = False
            else:
                ps = image_segmentation.get_plane_segmentation(
                    ps_metadata["name"])
                ps_exist = True

            roi_ids = segext_obj.get_roi_ids()
            accepted_list = segext_obj.get_accepted_list()
            accepted_list = [] if accepted_list is None else accepted_list
            rejected_list = segext_obj.get_rejected_list()
            rejected_list = [] if rejected_list is None else rejected_list
            accepted_ids = [1 if k in accepted_list else 0 for k in roi_ids]
            rejected_ids = [1 if k in rejected_list else 0 for k in roi_ids]
            roi_locations = np.array(segext_obj.get_roi_locations()).T

            def image_mask_iterator():
                for id in segext_obj.get_roi_ids():
                    img_msks = segext_obj.get_roi_image_masks(
                        roi_ids=[id]).T.squeeze()
                    yield img_msks

            if not ps_exist:
                input_kwargs.update(
                    **ps_metadata,
                    columns=[
                        VectorData(
                            data=H5DataIO(
                                DataChunkIterator(image_mask_iterator(),
                                                  buffer_size=buffer_size),
                                compression=True,
                                compression_opts=9,
                            ),
                            name="image_mask",
                            description="image masks",
                        ),
                        VectorData(
                            data=roi_locations,
                            name="RoiCentroid",
                            description=
                            "x,y location of centroid of the roi in image_mask",
                        ),
                        VectorData(
                            data=accepted_ids,
                            name="Accepted",
                            description=
                            "1 if ROi was accepted or 0 if rejected as a cell during segmentation operation",
                        ),
                        VectorData(
                            data=rejected_ids,
                            name="Rejected",
                            description=
                            "1 if ROi was rejected or 0 if accepted as a cell during segmentation operation",
                        ),
                    ],
                    id=roi_ids,
                )

                ps = image_segmentation.create_plane_segmentation(
                    **input_kwargs)

            # Fluorescence Traces:
            if "Flourescence" not in ophys.data_interfaces:
                fluorescence = Fluorescence()
                ophys.add(fluorescence)
            else:
                fluorescence = ophys.data_interfaces["Fluorescence"]
            roi_response_dict = segext_obj.get_traces_dict()
            roi_table_region = ps.create_roi_table_region(
                description=f"region for Imaging plane{plane_no_loop}",
                region=list(range(segext_obj.get_num_rois())),
            )
            rate = (np.float("NaN")
                    if segext_obj.get_sampling_frequency() is None else
                    segext_obj.get_sampling_frequency())
            for i, j in roi_response_dict.items():
                data = getattr(segext_obj, f"_roi_response_{i}")
                if data is not None:
                    data = np.asarray(data)
                    trace_name = "RoiResponseSeries" if i == "raw" else i.capitalize(
                    )
                    trace_name = (trace_name if plane_no_loop == 0 else
                                  trace_name + f"_Plane{plane_no_loop}")
                    input_kwargs = dict(
                        name=trace_name,
                        data=data.T,
                        rois=roi_table_region,
                        rate=rate,
                        unit="n.a.",
                    )
                    if trace_name not in fluorescence.roi_response_series:
                        fluorescence.create_roi_response_series(**input_kwargs)

            # create Two Photon Series:
            if "TwoPhotonSeries" not in nwbfile.acquisition:
                warn(
                    "could not find TwoPhotonSeries, using ImagingExtractor to create an nwbfile"
                )

            # adding images:
            images_dict = segext_obj.get_images_dict()
            if any([image is not None for image in images_dict.values()]):
                images_name = ("SegmentationImages" if plane_no_loop == 0 else
                               f"SegmentationImages_Plane{plane_no_loop}")
                if images_name not in ophys.data_interfaces:
                    images = Images(images_name)
                    for img_name, img_no in images_dict.items():
                        if img_no is not None:
                            images.add_image(
                                GrayscaleImage(name=img_name, data=img_no.T))
                    ophys.add(images)

            # saving NWB file:
            if write:
                io.write(nwbfile)
                io.close()
                # test read
                with NWBHDF5IO(str(save_path), "r") as io:
                    io.read()
Exemple #9
0
def copy_obj(obj_old, nwb_old, nwb_new):
    """ Creates a copy of obj_old. """

    # ElectricalSeries --------------------------------------------------------
    if type(obj_old) is ElectricalSeries:
        nChannels = obj_old.electrodes.table['x'].data.shape[0]
        elecs_region = nwb_new.electrodes.create_region(
            name='electrodes',
            region=np.arange(nChannels).tolist(),
            description=''
        )
        return ElectricalSeries(
            name=obj_old.name,
            data=obj_old.data[:],
            electrodes=elecs_region,
            rate=obj_old.rate,
            description=obj_old.description
        )

    # DynamicTable ------------------------------------------------------------
    if type(obj_old) is DynamicTable:
        return DynamicTable(
            name=obj_old.name,
            description=obj_old.description,
            colnames=obj_old.colnames,
            columns=obj_old.columns,
        )

    # LFP ---------------------------------------------------------------------
    if type(obj_old) is LFP:
        obj = LFP(name=obj_old.name)
        assert len(obj_old.electrical_series) == 1, (
                'Expected precisely one electrical series, got %i!' %
                len(obj_old.electrical_series))
        els = list(obj_old.electrical_series.values())[0]
        nChannels = els.data.shape[1]

        ####
        # first check for a table among the new file's data_interfaces
        if els.electrodes.table.name in nwb_new.processing[
            'ecephys'].data_interfaces:
            LFP_dynamic_table = nwb_new.processing['ecephys'].data_interfaces[
                els.electrodes.table.name]
        else:
            # othewise use the electrodes as the table
            LFP_dynamic_table = nwb_new.electrodes
        ####

        elecs_region = LFP_dynamic_table.create_region(
            name='electrodes',
            region=[i for i in range(nChannels)],
            description=els.electrodes.description
        )

        obj_ts = obj.create_electrical_series(
            name=els.name,
            comments=els.comments,
            conversion=els.conversion,
            data=els.data[:],
            description=els.description,
            electrodes=elecs_region,
            rate=els.rate,
            resolution=els.resolution,
            starting_time=els.starting_time
        )

        return obj

    # TimeSeries --------------------------------------------------------------
    if type(obj_old) is TimeSeries:
        return TimeSeries(
            name=obj_old.name,
            description=obj_old.description,
            data=obj_old.data[:],
            rate=obj_old.rate,
            resolution=obj_old.resolution,
            conversion=obj_old.conversion,
            starting_time=obj_old.starting_time,
            unit=obj_old.unit
        )

    # DecompositionSeries -----------------------------------------------------
    if type(obj_old) is DecompositionSeries:
        list_columns = []
        for item in obj_old.bands.columns:
            bp = VectorData(
                name=item.name,
                description=item.description,
                data=item.data[:]
            )
            list_columns.append(bp)
        bandsTable = DynamicTable(
            name=obj_old.bands.name,
            description=obj_old.bands.description,
            columns=list_columns,
            colnames=obj_old.bands.colnames
        )
        return DecompositionSeries(
            name=obj_old.name,
            data=obj_old.data[:],
            description=obj_old.description,
            metric=obj_old.metric,
            unit=obj_old.unit,
            rate=obj_old.rate,
            # source_timeseries=lfp,
            bands=bandsTable,
        )

    # Spectrum ----------------------------------------------------------------
    if type(obj_old) is Spectrum:
        file_elecs = nwb_new.electrodes
        nChannels = len(file_elecs['x'].data[:])
        elecs_region = file_elecs.create_region(
            name='electrodes',
            region=np.arange(nChannels).tolist(),
            description=''
        )
        return Spectrum(
            name=obj_old.name,
            frequencies=obj_old.frequencies[:],
            power=obj_old.power,
            electrodes=elecs_region
        )
Exemple #10
0
def spectral_decomposition(block_path, bands_vals):
    """
    Takes preprocessed LFP data and does the standard Hilbert transform on
    different bands. Takes about 20 minutes to run on 1 10-min block.

    Parameters
    ----------
    block_path : str
        subject file path
    bands_vals : [2,nBands] numpy array with Gaussian filter parameters, where:
        bands_vals[0,:] = filter centers [Hz]
        bands_vals[1,:] = filter sigmas [Hz]

    Returns
    -------
    Saves spectral power (DecompositionSeries) in the current NWB file.
    Only if container for this data do not exist in the file.
    """

    # Get filter parameters
    band_param_0 = bands_vals[0, :]
    band_param_1 = bands_vals[1, :]

    with NWBHDF5IO(block_path, 'r+', load_namespaces=True) as io:
        nwb = io.read()
        lfp = nwb.processing['ecephys'].data_interfaces[
            'LFP'].electrical_series['preprocessed']
        rate = lfp.rate

        nBands = len(band_param_0)
        nSamples = lfp.data.shape[0]
        nChannels = lfp.data.shape[1]
        Xp = np.zeros(
            (nBands, nChannels, nSamples))  #power (nBands,nChannels,nSamples)

        # Apply Hilbert transform ---------------------------------------------
        print('Running Spectral Decomposition...')
        start = time.time()
        for ch in np.arange(nChannels):
            Xch = lfp.data[:,
                           ch] * 1e6  # 1e6 scaling helps with numerical accuracy
            Xch = Xch.reshape(1, -1)
            Xch = Xch.astype('float32')  # signal (nChannels,nSamples)
            X_fft_h = None
            for ii, (bp0, bp1) in enumerate(zip(band_param_0, band_param_1)):
                kernel = gaussian(Xch, rate, bp0, bp1)
                X_analytic, X_fft_h = hilbert_transform(Xch,
                                                        rate,
                                                        kernel,
                                                        phase=None,
                                                        X_fft_h=X_fft_h)
                Xp[ii, ch, :] = abs(X_analytic).astype('float32')
        print('Spectral Decomposition finished in {} seconds'.format(
            time.time() - start))

        # data: (ndarray) dims: num_times * num_channels * num_bands
        Xp = np.swapaxes(Xp, 0, 2)

        # Spectral band power
        # bands: (DynamicTable) frequency bands that signal was decomposed into
        band_param_0V = VectorData(
            name='filter_param_0',
            description='frequencies for bandpass filters',
            data=band_param_0)
        band_param_1V = VectorData(
            name='filter_param_1',
            description='frequencies for bandpass filters',
            data=band_param_1)
        bandsTable = DynamicTable(
            name='bands',
            description='Series of filters used for Hilbert transform.',
            columns=[band_param_0V, band_param_1V],
            colnames=['filter_param_0', 'filter_param_1'])
        decs = DecompositionSeries(
            name='DecompositionSeries',
            data=Xp,
            description='Analytic amplitude estimated with Hilbert transform.',
            metric='amplitude',
            unit='V',
            bands=bandsTable,
            rate=rate,
            source_timeseries=lfp)

        # Storage of spectral decomposition on NWB file ------------------------
        ecephys_module = nwb.processing['ecephys']
        ecephys_module.add_data_interface(decs)
        io.write(nwb)
        print('Spectral decomposition saved in ' + block_path)
Exemple #11
0
def get_bipolar_referenced_electrodes(X,
                                      electrodes,
                                      rate,
                                      grid_size=None,
                                      grid_step=1):
    '''
    Bipolar referencing of electrodes according to the scheme of Dr. John Burke

    Each electrode (with obvious exceptions at the edges) yields two bipolar-
    referenced channels, one for the "right" and one for the "below" neighbors.
    These are returned as an ElectricalSeries.

    Input arguments:
    --------
    X:
        numpy array containing (raw) electrode traces (Nelectrodes x T)
    electrodes:
        DynamicTableRegion containing the metadata for the electrodes whose
        traces are in X
    rate:
        sampling rate of X; for storage in ElectricalSeries
    grid_size:
        numpy array with the two dimensions of the grid (2, )

    Returns:
    --------
    bipolarElectrodes:
        ElectricalSeries containing the bipolar-referenced (pseudo) electrodes
        and associated metadata.  (NB that a, e.g., 16x16 grid yields 960 of
        these pseudo-electrodes.)
    '''

    # set mutable default argument(s)
    if grid_size is None:
        grid_size = np.array([16, 16])

    # malloc
    elec_layout = np.arange(np.prod(grid_size) - 1, -1,
                            -1).reshape(grid_size).T
    elec_layout = elec_layout[::grid_step, ::grid_step]
    grid_size = elec_layout.T.shape  # in case grid_step > 1
    Nchannels = 2 * np.prod(grid_size) - np.sum(grid_size)
    XX = np.zeros((Nchannels, X.shape[1]))

    # create a new dynamic table to hold the metadata
    column_names = ['x', 'y', 'z', 'imp', 'location', 'label', 'bad']
    columns = [
        VectorData(name=name, description=electrodes.table[name].description)
        for name in column_names
    ]
    bipolarTable = DynamicTable(
        name='bipolar-referenced metadata',
        description=('pseudo-channels derived via John Burke style'
                     ' bipolar referencing'),
        colnames=column_names,
        columns=columns,
    )

    # compute bipolar-ref'd channel and add a new row of metadata to table
    def add_new_channel(iChannel, iElectrode, jElectrode):
        jElectrode = int(jElectrode)

        # "bipolar referencing": the difference of neighboring electrodes
        XX[iChannel, :] = X[iElectrode, :] - X[jElectrode, :]

        # add a row to the table for this new pseudo-electrode
        bipolarTable.add_row({
            'location':
            '_'.join({
                electrodes.table['location'][iElectrode],
                electrodes.table['location'][jElectrode]
            }),
            'label':
            '-'.join([
                electrodes.table['label'][iElectrode],
                electrodes.table['label'][jElectrode]
            ]),
            'bad': (electrodes.table['bad'][iElectrode]
                    or electrodes.table['bad'][jElectrode]),
            **{
                name: electrodes.table[name][iElectrode]
                for name in ['x', 'y', 'z', 'imp']
            },
        })
        return iChannel + 1

    iChannel = 0

    # loop across columns and rows (remembering that grid is transposed)
    for i in range(grid_size[1]):
        for j in range(grid_size[0]):
            if j < grid_size[0] - 1:
                iChannel = add_new_channel(iChannel, elec_layout[i, j],
                                           elec_layout[i, j + 1])
            if i < grid_size[1] - 1:
                iChannel = add_new_channel(iChannel, elec_layout[i, j],
                                           elec_layout[i + 1, j])

    # create one big region for the entire table
    bipolarTableRegion = bipolarTable.create_region(
        'electrodes', [i for i in range(Nchannels)], 'all bipolar electrodes')

    return XX, bipolarTable, bipolarTableRegion
Exemple #12
0
def test_device():
    nwbfile = NWBFile('session description',
                      'session id',
                      datetime.now(tzlocal()),
                      experimenter='experimenter name',
                      lab='lab name',
                      institution='institution name',
                      experiment_description=('experiment description'),
                      session_id='sessionid')
    laserline_device = LaserLine(name='mylaserline1',
                                 reference='test_ref_laserline',
                                 analog_modulation_frequency=Measurement(
                                     name='None',
                                     description='None',
                                     unit='Hz',
                                     data=[100]),
                                 power=Measurement(name='None',
                                                   description='None',
                                                   unit='uW',
                                                   data=[100]))

    laserline_devices_ = LaserLineDevices()
    laserline_devices_.add_laserline(laserline_device)
    laserline_devices_.create_laserline(
        name='mylaserline2',
        reference='test_ref_laserline',
        analog_modulation_frequency=Measurement(name='None',
                                                description='None',
                                                unit='Hz',
                                                data=[100]),
        power=Measurement(name='None',
                          description='None',
                          unit='uW',
                          data=[100]))

    photodetector_device = PhotoDetector(name='myphotodetector1',
                                         reference='test_ref_photodetector',
                                         gain=Measurement(name='None',
                                                          description='None',
                                                          unit='Hz',
                                                          data=[1]),
                                         bandwidth=Measurement(
                                             name='None',
                                             description='None',
                                             unit='uW',
                                             data=[50]))

    photodetector_devices_ = PhotoDetectorDevices()
    photodetector_devices_.add_photodetector(photodetector_device)

    lockinamp_device = LockInAmplifier(name='mylockinamp',
                                       demodulation_filter_order=10.0,
                                       reference='test_ref',
                                       demod_bandwidth=Measurement(
                                           name='None',
                                           description='None',
                                           unit='Hz',
                                           data=[150]),
                                       columns=[
                                           VectorData(name='channel_name',
                                                      description='None',
                                                      data=['name1', 'name2']),
                                           Measurement(name='offset',
                                                       description='None',
                                                       unit='mV',
                                                       data=[140, 260]),
                                           VectorData(name='gain',
                                                      description='None',
                                                      data=[250, 250])
                                       ])
    lockinamp_devices_ = LockInAmplifierDevices()
    lockinamp_devices_.add_lockinamp(lockinamp_device)

    nwbfile.add_device(
        TEMPO(name='tempo_test',
              laserline_devices=laserline_devices_,
              photodetector_devices=photodetector_devices_,
              lockinamp_devices=lockinamp_devices_))

    # testing laserline_device
    assert_array_equal(
        np.array(nwbfile.devices['tempo_test'].laserline_devices.children[0].
                 analog_modulation_frequency.data), np.array([100]))
    # testing photodetector_device
    assert_array_equal(
        np.array(nwbfile.devices['tempo_test'].photodetector_devices.
                 children[0].bandwidth.data), np.array([50]))
    # testing lockinamp_device
    assert_array_equal(
        np.array(nwbfile.devices['tempo_test'].lockinamp_devices.children[0].
                 columns[1].data), np.array([140, 260]))

    with NWBHDF5IO('test_ndx-tempo.nwb', 'w') as io:
        io.write(nwbfile)
        del nwbfile
    with NWBHDF5IO('test_ndx-tempo.nwb', 'r', load_namespaces=True) as io:
        nwb = io.read()
        # testing laserline_device
        assert_array_equal(
            np.array(nwb.devices['tempo_test'].laserline_devices.children[0].
                     analog_modulation_frequency.data), np.array([100]))
        # testing photodetector_device
        assert_array_equal(
            np.array(nwb.devices['tempo_test'].photodetector_devices.
                     children[0].bandwidth.data), np.array([50]))
        # testing lockinamp_device
        assert_array_equal(
            np.array(nwb.devices['tempo_test'].lockinamp_device.children[0].
                     columns[1].data), np.array([140, 260]))
Exemple #13
0
def copy_obj(obj_old, nwb_old, nwb_new):
    """ Creates a copy of obj_old. """

    # ElectricalSeries --------------------------------------------------------
    if type(obj_old) is ElectricalSeries:
        # If reference electrodes table is bipolar scheme
        if isinstance(obj_old.electrodes.table, BipolarSchemeTable):
            bst_old = obj_old.electrodes.table
            bst_old_df = bst_old.to_dataframe()
            bst_new = nwb_new.lab_meta_data['ecephys_ext'].bipolar_scheme_table

            for id, row in bst_old_df.iterrows():
                index_anodes = row['anodes'].index.tolist()
                index_cathodes = row['cathodes'].index.tolist()
                bst_new.add_row(anodes=index_anodes, cathodes=index_cathodes)
            bst_new.anodes.table = nwb_new.electrodes
            bst_new.cathodes.table = nwb_new.electrodes

            # if there are custom columns
            new_cols = list(bst_old_df.columns)
            default_cols = ['anodes', 'cathodes']
            [new_cols.remove(col) for col in default_cols]
            for col in new_cols:
                col_data = list(bst_old[col].data[:])
                bst_new.add_column(name=str(col),
                                   description=str(bst_old[col].description),
                                   data=col_data)

            elecs_region = DynamicTableRegion(name='electrodes',
                                              data=bst_old_df.index.tolist(),
                                              description='desc',
                                              table=bst_new)
        else:
            region = np.array(obj_old.electrodes.table.id[:])[
                obj_old.electrodes.data[:]].tolist()
            elecs_region = nwb_new.create_electrode_table_region(
                name='electrodes', region=region, description='')
        els = ElectricalSeries(name=obj_old.name,
                               data=obj_old.data[:],
                               electrodes=elecs_region,
                               rate=obj_old.rate,
                               description=obj_old.description)
        return els

    # DynamicTable ------------------------------------------------------------
    if type(obj_old) is DynamicTable:
        return DynamicTable(
            name=obj_old.name,
            description=obj_old.description,
            colnames=obj_old.colnames,
            columns=obj_old.columns,
        )

    # LFP ---------------------------------------------------------------------
    if type(obj_old) is LFP:
        obj = LFP(name=obj_old.name)
        assert len(obj_old.electrical_series) == 1, (
            'Expected precisely one electrical series, got %i!' %
            len(obj_old.electrical_series))
        els = list(obj_old.electrical_series.values())[0]

        ####
        # first check for a table among the new file's data_interfaces
        if els.electrodes.table.name in nwb_new.processing[
                'ecephys'].data_interfaces:
            LFP_dynamic_table = nwb_new.processing['ecephys'].data_interfaces[
                els.electrodes.table.name]
        else:
            # othewise use the electrodes as the table
            LFP_dynamic_table = nwb_new.electrodes
        ####

        region = np.array(
            els.electrodes.table.id[:])[els.electrodes.data[:]].tolist()
        elecs_region = LFP_dynamic_table.create_region(
            name='electrodes',
            region=region,
            description=els.electrodes.description)

        obj.create_electrical_series(name=els.name,
                                     comments=els.comments,
                                     conversion=els.conversion,
                                     data=els.data[:],
                                     description=els.description,
                                     electrodes=elecs_region,
                                     rate=els.rate,
                                     resolution=els.resolution,
                                     starting_time=els.starting_time)

        return obj

    # TimeSeries --------------------------------------------------------------
    if type(obj_old) is TimeSeries:
        return TimeSeries(name=obj_old.name,
                          description=obj_old.description,
                          data=obj_old.data[:],
                          rate=obj_old.rate,
                          resolution=obj_old.resolution,
                          conversion=obj_old.conversion,
                          starting_time=obj_old.starting_time,
                          unit=obj_old.unit)

    # DecompositionSeries -----------------------------------------------------
    if type(obj_old) is DecompositionSeries:
        list_columns = []
        for item in obj_old.bands.columns:
            bp = VectorData(name=item.name,
                            description=item.description,
                            data=item.data[:])
            list_columns.append(bp)
        bandsTable = DynamicTable(name=obj_old.bands.name,
                                  description=obj_old.bands.description,
                                  columns=list_columns,
                                  colnames=obj_old.bands.colnames)
        return DecompositionSeries(
            name=obj_old.name,
            data=obj_old.data[:],
            description=obj_old.description,
            metric=obj_old.metric,
            unit=obj_old.unit,
            rate=obj_old.rate,
            # source_timeseries=lfp,
            bands=bandsTable,
        )

    # Spectrum ----------------------------------------------------------------
    if type(obj_old) is Spectrum:
        file_elecs = nwb_new.electrodes
        nChannels = len(file_elecs['x'].data[:])
        elecs_region = file_elecs.create_region(
            name='electrodes',
            region=np.arange(nChannels).tolist(),
            description='')
        return Spectrum(name=obj_old.name,
                        frequencies=obj_old.frequencies[:],
                        power=obj_old.power,
                        electrodes=elecs_region)

    # Survey tables ------------------------------------------------------------
    if obj_old.neurodata_type == 'SurveyTable':
        if obj_old.name == 'nrs_survey_table':
            n_rows = len(obj_old['nrs_pain_intensity_rating'].data)
            for i in range(n_rows):
                nrs_survey_table.add_row(
                    **{c: obj_old[c][i]
                       for c in obj_old.colnames})
            return nrs_survey_table

        elif obj_old.name == 'vas_survey_table':
            n_rows = len(obj_old['vas_pain_intensity_rating'].data)
            for i in range(n_rows):
                vas_survey_table.add_row(
                    **{c: obj_old[c][i]
                       for c in obj_old.colnames})
            return vas_survey_table

        elif obj_old.name == 'mpq_survey_table':
            n_rows = len(obj_old['throbbing'].data)
            for i in range(n_rows):
                mpq_survey_table.add_row(
                    **{c: obj_old[c][i]
                       for c in obj_old.colnames})
            return mpq_survey_table
Exemple #14
0
 def with_table_columns(self):
     cols = [VectorData(**d) for d in self.spec]
     table = DynamicTable("with_table_columns",
                          'a test table',
                          columns=cols)
     return table