Source code for allensdk.brain_observatory.behavior.criteria

"""
Functions for calculating mtrain state transitions.
If criteria are met, return true. Otherwise, return false.
"""

import logging
from allensdk.core.exceptions import DataFrameKeyError, DataFrameIndexError


logger = logging.getLogger(__name__)


[docs]def two_out_of_three_aint_bad(session_summary): """Returns true if 2 of the last 3 days showed a peak d-prime above 2. Args: session_summary (pd.DataFrame): Pandas dataframe with daily values for 'dprime_peak', ordered ascending by training day, for at least the past 3 days. If dataframe is not properly ordered, criterion may not be correctly calculated. This function does not sort the data to preserve prior behavior (sorting column was not required by mtrain function). The mtrain implementation created the required columns if they didn't exist, so a more informative error is raised here to assist end-users in debugging. Returns: bool: True if criterion is met, False otherwise """ if len(session_summary) < 3: raise DataFrameIndexError("Not enough data in session_summary frame. " "Expected >= 3 rows, got {}".format(len(session_summary))) try: last_three = session_summary["dprime_peak"][-3:] except KeyError as e: raise DataFrameKeyError("Failed accessing last three values in colum" "'dprime_peak'.\n df length={}, df columns={}\n" .format(len(session_summary), list(session_summary)), e) logger.info('dprime_peak over last three days: {}'.format(list(last_three))) criteria = bool( ((last_three > 2).sum() > 1) # at least two of the last three ) logger.info("'Two out of three ain't bad' criteria met: '{}'".format(criteria)) return criteria
[docs]def yesterday_was_good(session_summary): """Returns true if the last day showed a peak d-prime above 2 Args: session_summary (pd.DataFrame): Pandas dataframe with daily values for 'dprime_peak', ordered ascending by training day, for at least 1 day. If dataframe is not properly ordered, criterion may not be correctly calculated. This function does not sort the data to preserve prior behavior (sorting column was not required by mtrain function). The mtrain implementation created the required columns if they didn't exist, so a more informative error is raised here to assist end-users in debugging. Returns: bool: True if criterion is met, False otherwise """ if len(session_summary) < 1: raise DataFrameIndexError("Not enough data in session_summary frame. " "Expected >= 1 row(s), got {}".format(len(session_summary))) try: last_day = session_summary['dprime_peak'].iloc[-1] except KeyError as e: raise DataFrameKeyError("Failed accessing last three values in colum" "'dprime_peak'.\n df length={}, df columns={}\n" .format(len(session_summary), list(session_summary)), e) criteria = bool(last_day > 2) logger.info("'Yesterday was good' criteria met: {}".format(criteria)) return criteria
[docs]def no_response_bias(session_summary): """the mouse meets this criterion if their last session exhibited a response bias between 10% and 90% Args: session_summary (pd.DataFrame): Pandas dataframe with daily values for 'response_bias', ordered ascending by training day, for at least 1 day. If dataframe is not properly ordered, criterion may not be correctly calculated. This function does not sort the data to preserve prior behavior (sorting column was not required by mtrain function). The mtrain implementation created the required columns if they didn't exist, so a more informative error is raised here to assist end-users in debugging. Returns: bool: True if criterion is met, False otherwise """ if len(session_summary) < 1: raise DataFrameIndexError("Not enough data in session_summary frame. " "Expected >= 1 row(s), got {}".format(len(session_summary))) try: response_bias = session_summary['response_bias'].iloc[-1] except KeyError as e: raise DataFrameKeyError("Failed accessing last values in colum" "'response_bias'.\n df length={}, df columns={}\n" .format(len(session_summary), list(session_summary)), e) criteria = (response_bias < 0.9) & (response_bias > 0.1) logger.info("'No response bias' criteria met: {} (response bias={})" .format(criteria, response_bias)) return criteria
[docs]def whole_lotta_trials(session_summary): """ Mouse meets this criterion if the last session has more than 300 trials. Args: session_summary (pd.DataFrame): Pandas dataframe with daily values for 'num_contingent_trials', ordered ascending by training day, for at least 1 day. If dataframe is not properly ordered, criterion may not be correctly calculated. This function does not sort the data to preserve prior behavior (sorting column was not required by mtrain function). The mtrain implementation created the required columns if they didn't exist, so a more informative error is raised here to assist end-users in debugging. Returns: bool: True if criterion is met, False otherwise """ if len(session_summary) < 1: raise DataFrameIndexError("Not enough data in session_summary frame. " "Expected >= 1 row(s), got {}".format(len(session_summary))) try: num_trials = session_summary['num_contingent_trials'].iloc[-1] except KeyError as e: raise DataFrameKeyError("Failed accessing last values in colum" "'num_contingent_trials'.\n df length={}, df columns={}\n" .format(len(session_summary), list(session_summary)), e) criteria = num_trials > 300 logger.info("'Trials > 300' criteria met: {} (n trials={})".format(criteria, num_trials)) return criteria
[docs]def mostly_useful(trials): """ Returns True if fewer than half the trial time on the last day were aborted trials. Args: trials (pd.DataFrame): Pandas dataframe with columns 'training_day', 'trial_type', and 'trial_length'. Returns: bool: True if criterion is met, False otherwise """ if len(trials) == 0: # empty df would return true, but shouldn't return False last_day = trials['training_day'].max() group = trials.groupby('training_day').get_group(last_day) trial_fractions = group.groupby('trial_type')['trial_length'].sum() \ / group['trial_length'].sum() aborted = trial_fractions['aborted'] criteria = aborted < 0.5 logger.info("Fewer than half the trials were aborted on the last training day: {} " "(% aborted trials={})".format(criteria, aborted)) return criteria
[docs]def consistency_is_key(session_summary): '''need some way to judge consistency of various parameters - dprime - num trials - hit rate - fa rate - lick timing ''' raise NotImplementedError
[docs]def consistent_behavior_within_session(session_summary): '''need some way to measure consistent performance within a session - compare peak to overall dprime? - variance in rolling window dprime? ''' raise NotImplementedError
[docs]def n_complete(threshold, count): """ For compatibility with original API. If count >= threshold, return True. Otherwise return False. Args: threshold (numeric): Threshold for the count to meet. count (numeric): The count to compare to the threshold. Returns: True if count >= threshold, otherwise False. """ return count >= threshold
[docs]def meets_engagement_criteria(session_summary): """ Returns true if engagement criteria were met for the past 3 days, else false. Args: session_summary (pd.DataFrame): Pandas dataframe with daily values for 'dprime_peak' and 'num_engaged_trials', ordered ascending by training day, for at least 3 days. If dataframe is not properly ordered, criterion may not be correctly calculated. This function does not sort the data to preserve prior behavior (sorting column was not required by mtrain function) The mtrain implementation created the required columns if they didn't exist, so a more informative error is raised here to assist end-users in debugging. Returns: bool: True if criterion is met, False otherwise """ criteria = 3 if len(session_summary) < 3: raise DataFrameIndexError("Not enough data in session_summary frame. " "Expected >= 3 rows, got {}".format(len(session_summary))) try: session_summary['engagement_criteria'] = ( (session_summary['dprime_peak'] > 1.0) & (session_summary['num_engaged_trials'] > 100) ) engaged_days = session_summary['engagement_criteria'].iloc[-3:].sum() except KeyError as e: raise DataFrameKeyError("Failed accessing columns 'dprime_peak' and/or " "'num_engaged_trials' for 3 days.\n df length={}, df columns={}\n" .format(len(session_summary), list(session_summary)), e) return engaged_days == criteria
[docs]def summer_over(trials): """ Returns true if the maximum value of 'training_day' in the trials dataframe is >= 40, else false. """ return trials['training_day'].max() >= 40