Esempio n. 1
0
    def get_stimulus_presentations(self):
        stimulus_timestamps = self.get_stimulus_timestamps()
        behavior_stimulus_file = self.get_behavior_stimulus_file()
        data = pd.read_pickle(behavior_stimulus_file)
        stimulus_presentations_df_pre = get_stimulus_presentations(
            data, stimulus_timestamps)
        stimulus_metadata_df = get_stimulus_metadata(data)
        idx_name = stimulus_presentations_df_pre.index.name
        stimulus_index_df = stimulus_presentations_df_pre.reset_index().merge(
            stimulus_metadata_df.reset_index(),
            on=['image_name']).set_index(idx_name)
        stimulus_index_df.sort_index(inplace=True)
        stimulus_index_df = stimulus_index_df[[
            'image_set', 'image_index', 'start_time'
        ]].rename(columns={'start_time': 'timestamps'})
        stimulus_index_df.set_index('timestamps', inplace=True, drop=True)
        stimulus_presentations_df = stimulus_presentations_df_pre.merge(
            stimulus_index_df,
            left_on='start_time',
            right_index=True,
            how='left')
        assert len(stimulus_presentations_df_pre) == len(
            stimulus_presentations_df)

        return stimulus_presentations_df[sorted(
            stimulus_presentations_df.columns)]
Esempio n. 2
0
    def get_stimulus_presentations(self) -> pd.DataFrame:
        """Get stimulus presentation data.

        NOTE: Uses timestamps that do not account for monitor delay.

        :returns: pd.DataFrame --
            Table whose rows are stimulus presentations
            (i.e. a given image, for a given duration, typically 250 ms)
            and whose columns are presentation characteristics.
        """
        stimulus_timestamps = self.get_stimulus_timestamps()
        data = self._behavior_stimulus_file()
        raw_stim_pres_df = get_stimulus_presentations(data,
                                                      stimulus_timestamps)

        # Fill in nulls for image_name
        # This makes two assumptions:
        #   1. Nulls in `image_name` should be "gratings_<orientation>"
        #   2. Gratings are only present (or need to be fixed) when all
        #      values for `image_name` are null.
        if pd.isnull(raw_stim_pres_df["image_name"]).all():
            if ~pd.isnull(raw_stim_pres_df["orientation"]).all():
                raw_stim_pres_df["image_name"] = (
                    raw_stim_pres_df["orientation"].apply(
                        lambda x: f"gratings_{x}"))
            else:
                raise ValueError("All values for 'orentation' and 'image_name'"
                                 " are null.")

        stimulus_metadata_df = get_stimulus_metadata(data)

        idx_name = raw_stim_pres_df.index.name
        stimulus_index_df = (raw_stim_pres_df.reset_index().merge(
            stimulus_metadata_df.reset_index(),
            on=["image_name"]).set_index(idx_name))
        stimulus_index_df = (stimulus_index_df[[
            "image_set", "image_index", "start_time", "phase",
            "spatial_frequency"
        ]].rename(columns={
            "start_time": "timestamps"
        }).sort_index().set_index("timestamps", drop=True))
        stim_pres_df = raw_stim_pres_df.merge(stimulus_index_df,
                                              left_on="start_time",
                                              right_index=True,
                                              how="left")
        if len(raw_stim_pres_df) != len(stim_pres_df):
            raise ValueError("Length of `stim_pres_df` should not change after"
                             f" merge; was {len(raw_stim_pres_df)}, now "
                             f" {len(stim_pres_df)}.")

        stim_pres_df['is_change'] = is_change_event(
            stimulus_presentations=stim_pres_df)

        # Sort columns then drop columns which contain only all NaN values
        return stim_pres_df[sorted(stim_pres_df)].dropna(axis=1, how='all')
def test_get_stimulus_metadata(behavior_stimuli_data_fixture,
                               remove_stimuli, expected_metadata):
    for key in remove_stimuli:
        # do this because at current images are not tested and there's a
        # hard coded path that prevents testing when this is fixed this can
        # be removed.
        del behavior_stimuli_data_fixture['items']['behavior']['stimuli'][key]
    stimulus_metadata = get_stimulus_metadata(behavior_stimuli_data_fixture)

    expected_df = pd.DataFrame.from_dict(expected_metadata)
    expected_df.set_index(['image_index'], inplace=True, drop=True)

    assert stimulus_metadata.equals(expected_df)
Esempio n. 4
0
    def from_stimulus_file(
            cls,
            stimulus_file: StimulusFile,
            stimulus_timestamps: StimulusTimestamps,
            limit_to_images: Optional[List] = None) -> "Presentations":
        """Get stimulus presentation data.

        :param stimulus_file
        :param limit_to_images
            Only return images given by these image names
        :param stimulus_timestamps


        :returns: pd.DataFrame --
            Table whose rows are stimulus presentations
            (i.e. a given image, for a given duration, typically 250 ms)
            and whose columns are presentation characteristics.
        """
        stimulus_timestamps = stimulus_timestamps.value
        data = stimulus_file.data
        raw_stim_pres_df = get_stimulus_presentations(data,
                                                      stimulus_timestamps)

        # Fill in nulls for image_name
        # This makes two assumptions:
        #   1. Nulls in `image_name` should be "gratings_<orientation>"
        #   2. Gratings are only present (or need to be fixed) when all
        #      values for `image_name` are null.
        if pd.isnull(raw_stim_pres_df["image_name"]).all():
            if ~pd.isnull(raw_stim_pres_df["orientation"]).all():
                raw_stim_pres_df["image_name"] = (
                    raw_stim_pres_df["orientation"].apply(
                        lambda x: f"gratings_{x}"))
            else:
                raise ValueError("All values for 'orentation' and 'image_name'"
                                 " are null.")

        stimulus_metadata_df = get_stimulus_metadata(data)

        idx_name = raw_stim_pres_df.index.name
        stimulus_index_df = (raw_stim_pres_df.reset_index().merge(
            stimulus_metadata_df.reset_index(),
            on=["image_name"]).set_index(idx_name))
        stimulus_index_df = (stimulus_index_df[[
            "image_set", "image_index", "start_time", "phase",
            "spatial_frequency"
        ]].rename(columns={
            "start_time": "timestamps"
        }).sort_index().set_index("timestamps", drop=True))
        stim_pres_df = raw_stim_pres_df.merge(stimulus_index_df,
                                              left_on="start_time",
                                              right_index=True,
                                              how="left")
        if len(raw_stim_pres_df) != len(stim_pres_df):
            raise ValueError("Length of `stim_pres_df` should not change after"
                             f" merge; was {len(raw_stim_pres_df)}, now "
                             f" {len(stim_pres_df)}.")

        stim_pres_df['is_change'] = is_change_event(
            stimulus_presentations=stim_pres_df)

        # Sort columns then drop columns which contain only all NaN values
        stim_pres_df = \
            stim_pres_df[sorted(stim_pres_df)].dropna(axis=1, how='all')
        if limit_to_images is not None:
            stim_pres_df = \
                stim_pres_df[stim_pres_df['image_name'].isin(limit_to_images)]
            stim_pres_df.index = pd.Int64Index(range(stim_pres_df.shape[0]),
                                               name=stim_pres_df.index.name)
        stim_pres_df = cls._postprocess(presentations=stim_pres_df)
        return Presentations(presentations=stim_pres_df)