예제 #1
0
def showForms():
    form = ShiftLogForm()
    shiftLogDAO = shift_log_DAO()
    resident_list = shiftLogDAO.get_incompleted_residents()
    form.resident.choices = [(resident_map['resident_id'],
                              resident_map['name'])
                             for resident_map in resident_list]
    resident_dict = {
        resident_map['resident_id']: resident_map['name']
        for resident_map in resident_list
    }
    if request.method == 'POST':
        if form.validate_on_submit():
            # handle submitted data here
            # process form here
            submitted_name = form.resident.data
            # name_to_show = "testing"
            name_to_show = resident_dict[submitted_name]
            submitted_date = form.date.data
            submitted_time = form.time.data
            submitted_falls = form.falls.data
            submitted_near_falls = form.near_falls.data
            submitted_consumption = form.consumption.data
            submitted_toilet_visits = 0
            submitted_temperature = form.temperature.data
            submitted_sbp = form.sbp.data
            submitted_dbp = form.dbp.data
            submitted_pulse = form.pulse.data

            # shiftLogDAO = shift_log_DAO()

            if submitted_time == 1:
                day_night = "Day"
            else:
                day_night = "Night"

            shiftLog = Shift_log(submitted_date, submitted_time,
                                 submitted_name, submitted_falls,
                                 submitted_near_falls, submitted_consumption,
                                 submitted_toilet_visits,
                                 submitted_temperature, submitted_sbp,
                                 submitted_dbp, submitted_pulse)

            response = 'Shift log for ' + submitted_date.strftime(
                '%Y-%m-%d'
            ) + '(' + day_night + ') for ' + name_to_show + ' has already been recorded. Please enter another date.'
            try:
                shiftLogDAO.insert_shift_log(shiftLog)
            except:
                flash(response)
                return render_template('eosforms.html', form=form)

            response = 'Shift log for ' + name_to_show + ' has been successfully recorded. Click <a href="/admin/shift_log" class="alert-link">here</a> to view/edit responses.'
            flash(Markup(response))
            return redirect(url_for('showForms'))
        else:
            return render_template('eosforms.html', form=form)
    else:
        return render_template('eosforms.html', form=form)
예제 #2
0
 def create_view(self):
     form = ShiftLogForm()
     shiftLogDAO = shift_log_DAO()
     resident_list = shiftLogDAO.get_incompleted_residents()
     form.resident.choices = [(resident_map['resident_id'],
                               resident_map['name'])
                              for resident_map in resident_list]
     return render_template('eosforms.html', form=form)
예제 #3
0
def showOverviewResidents():
    '''
    This method prepares all the necessary variables to pass into the html for display
    Each resident will have the following:
    Name ('name'), List of Toilet Alerts ('toilet_alerts'),
            List of Sleep Alerts (WIP), Overall Alert Level ('alert_highest')
    NOTE: jinja templates do not allow for import of python modules, so all calculation will be done here
    '''
    residents_raw = resident_DAO.get_list_of_residents()
    residents = []
    date_in_use = datetime.datetime.now()
    # date_in_use = datetime.datetime(2018, 4, 19, 23, 34, 12) # TODO: change to current system time once live data is available
    juvo_date_in_use = datetime.datetime.now(
    )  # datetime.datetime(2018, 8, 12, 22, 34, 12) # TODO: change to current system time once live data is available
    for resident in residents_raw:
        r = {}
        r['name'] = resident['name']
        r['resident_id'] = resident['resident_id']

        # settle night toilet usage
        r['toilet_alerts'], __ = input_data.input_data.get_nightly_toilet_indicator(
            int(resident['resident_id']), date_in_use)
        r['toilet_tooltip'] = []
        if len(r['toilet_alerts']) == 0:
            r['toilet_tooltip'].append(
                "Night toilet visit numbers appear normal")
        else:  # NOTE: right now we just append, but use separate list for tooltips in case of future changes
            r['toilet_tooltip'].extend(r['toilet_alerts'])

        # settle sleep duration
        r['sleep_alerts'], __, __, __, __, __, __ = input_data.input_data.get_nightly_sleep_indicator(
            int(resident['resident_id']), date_in_use)
        r['sleep_tooltip'] = []
        if len(r['sleep_alerts']) == 0:
            r['sleep_tooltip'].append(
                "Normal level of motion during sleep detected")
        else:  # NOTE: for future changes
            r['sleep_tooltip'].extend(r['sleep_alerts'])

        r['vitals_alerts'], __, __, __, __ = input_data.input_data.get_vital_signs_indicator(
            resident['resident_id'], juvo_date_in_use)
        r['vitals_tooltip'] = []
        if len(r['vitals_alerts']) == 0:
            r['vitals_tooltip'].append(
                "Vital signs from previous week appear to be normal")
        else:
            r['vitals_tooltip'].extend(r['vitals_alerts'])

        # print("DEBUG resident id sleep_alerts", resident['resident_id'], r['sleep_alerts'])
        r['alert_highest'] = max(0, len(r['toilet_alerts']),
                                 len(r['sleep_alerts']),
                                 len(r['vitals_alerts']))
        residents.append(r)
    # return render_template('overview_residents_amanda.html', residents=residents)
    information = {}
    information['num_residents'] = len(
        resident_DAO.get_list_of_residents(location_filter='STB'))
    num_good_health = 0
    for r_dict in residents:
        if r_dict['alert_highest'] == 0:
            num_good_health += 1
    information['health_percentage'] = num_good_health / information[
        'num_residents'] * 100  # in percentage
    sldao = shift_log_DAO.shift_log_DAO()
    information['num_shift_forms'] = sldao.get_today_logs()
    sensor_statuses = sensor_mgmt.Sensor_mgmt.get_all_sensor_status_v2(
        retBatteryLevel=True)
    # print(sensor_statuses)
    sensor_down_count = 0
    for _sensor in sensor_statuses:
        if _sensor[1][0] > 0:
            sensor_down_count += 1
    information['sensors_down'] = sensor_down_count
    return render_template('overview_residents.html',
                           residents=residents,
                           information=information)
예제 #4
0
class input_shiftlogs(object):
    # input_raw_data = pd.DataFrame()
    sldao = shift_log_DAO()
    input_raw_data = sldao.get_all_logs()
    input_raw_data['datetime'] = pd.to_datetime(input_raw_data['datetime'],
                                                format='%Y-%m-%dT%H:%M:%S')
    input_raw_data['food_consumption'] = pd.to_numeric(
        input_raw_data['food_consumption'])
    input_raw_data['pulse_pressure'] = input_raw_data[
        'systolic_bp'] - input_raw_data['diastolic_bp']
    input_raw_max_date = input_raw_data['datetime'].max()
    input_raw_min_date = input_raw_data['datetime'].min()
    # print(input_raw_data)
    daytime_start = datetime.time(7, 30)
    daytime_end = datetime.time(19, 30)

    # changeable parameters NOTE: should be changeable
    para_temperature_max = 37.6
    para_temperature_min = 35.5
    para_temperature_sd = 0.66
    para_pulse_pressure_max = 50

    @staticmethod
    def update_shiftlogs_data():
        input_shiftlogs.input_raw_data = input_shiftlogs.sldao.get_all_logs()
        input_shiftlogs.input_raw_data['datetime'] = pd.to_datetime(
            input_shiftlogs.input_raw_data['datetime'],
            format='%Y-%m-%dT%H:%M:%S')
        input_shiftlogs.input_raw_data['food_consumption'] = pd.to_numeric(
            input_shiftlogs.input_raw_data['food_consumption'])
        input_shiftlogs.input_raw_data[
            'pulse_pressure'] = input_shiftlogs.input_raw_data[
                'systolic_bp'] - input_shiftlogs.input_raw_data['diastolic_bp']
        input_shiftlogs.input_raw_max_date = input_shiftlogs.input_raw_data[
            'datetime'].max()
        input_shiftlogs.input_raw_min_date = input_shiftlogs.input_raw_data[
            'datetime'].min()

    @staticmethod
    def date_only(original_date):
        return original_date.replace(hour=0, minute=0, second=0, microsecond=0)

    @staticmethod
    def get_logs_filter_options():
        '''Returns labels and values in an array of tuples'''
        return [('No. of Falls', 'num_falls'),
                ('No. of Near Falls', 'num_near_falls'),
                ('Food Consumption', 'food_consumption'),
                ('Temperature', 'temperature'),
                ('Systolic//Diastolic Bp', 'sys_dia'),
                ('Pulse Pressure', 'pulse_pressure'),
                ('Pulse Rate', 'pulse_rate')]

    @staticmethod
    def get_relevant_data(start_date, end_date, patient_id):
        '''
        Retrieve sensor data based on location, start and end dates, and the device
        grouped=True to get grouped data for toilet visits
        '''
        # TODO: this part probably is the best to convert to retrieve from DB
        relevant_data = input_shiftlogs.input_raw_data.loc[
            (input_shiftlogs.input_raw_data['patient_id'] == patient_id)
            & (input_shiftlogs.input_raw_data['datetime'] < end_date)
            & (input_shiftlogs.input_raw_data['datetime'] > start_date), [
                'patient_id', 'datetime', 'num_falls', 'num_near_falls',
                'food_consumption', 'temperature', 'systolic_bp',
                'diastolic_bp', 'pulse_pressure', 'pulse_rate'
            ]]
        return relevant_data

    @staticmethod
    def get_logs_by_date(start_date=input_raw_min_date,
                         end_date=input_raw_max_date,
                         patient_id=1,
                         time_period=None):
        """
        Function returns dates and aggregated number of times the sensor was activated
        To get day only, use time_period='Day' and to get night_only use time_period='Night'
        """

        # NOTE: last day of the returned output is not accurate if offset is used because the next day's data is needed to get the current night's data
        current_data = input_shiftlogs.get_relevant_data(
            start_date, end_date, patient_id)
        # print(current_data)

        # print(current_data)
        if time_period == 'Day':
            current_data = current_data.loc[(current_data['datetime'].dt.time
                                             >= input_shiftlogs.daytime_start)
                                            & (current_data['datetime'].dt.time
                                               < input_shiftlogs.daytime_end)]
        elif time_period == 'Night':
            current_data = current_data.loc[
                (current_data['datetime'].dt.time < input_shiftlogs.
                 daytime_start)
                |
                (current_data['datetime'].dt.time > input_shiftlogs.daytime_end
                 )]

        # group by date only
        current_data['date_only'] = current_data['datetime'].apply(
            input_shiftlogs.date_only)
        result_data = current_data.groupby(
            ['date_only'],
            as_index=False)['num_falls', 'num_near_falls', 'food_consumption',
                            'temperature', 'systolic_bp', 'diastolic_bp',
                            'pulse_pressure', 'pulse_rate'].mean()

        # add 0 for days with no data
        result_data.set_index('date_only', inplace=True)
        if isinstance(start_date, str):
            start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')

        if isinstance(end_date, str):
            end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')

        all_days_range = pd.date_range(start_date.date(),
                                       end_date.date() +
                                       datetime.timedelta(days=-1),
                                       freq='D')
        try:
            result_data = result_data.loc[all_days_range]
        except KeyError as e:
            erroroutput = pd.DataFrame()
            erroroutput['num_falls'] = []
            erroroutput['num_near_falls'] = []
            erroroutput['food_consumption'] = []
            erroroutput['temperature'] = []
            erroroutput['systolic_bp'] = []
            erroroutput['diastolic_bp'] = []
            erroroutput['pulse_pressure'] = []
            erroroutput['pulse_rate'] = []
            erroroutput['date_only'] = []
        result_data.fillna(0, inplace=True)

        # undo set index
        result_data.reset_index(inplace=True)
        result_data.rename(columns={'index': 'date_only'}, inplace=True)
        # print("result data from get_num_visits_by_date\n", result_data)
        return result_data

    @staticmethod
    def get_residents_options():
        return input_shiftlogs.input_raw_data['patient_id'].unique().tolist()

    @staticmethod
    def get_shiftlog_indicators(patient_id, current_sys_time=None):
        ret_alerts = []
        if not current_sys_time:
            current_sys_time = datetime.datetime.now()

        current_sys_date = current_sys_time.date()
        three_weeks_ago = current_sys_date + datetime.timedelta(days=-21)
        one_week_ago = current_sys_date + datetime.timedelta(days=-7)
        four_weeks_ago = current_sys_date + datetime.timedelta(days=-28)

        # get data first
        current_data = input_shiftlogs.get_relevant_data(
            four_weeks_ago, current_sys_date, patient_id)
        # print(current_data)
        # patient_id,datetime,num_falls,num_near_falls,food_consumption,temperature,systolic_bp,diastolic_bp,pulse_pressure,pulse_rate
        # compare averages
        three_week_data = current_data.loc[(current_data['datetime'] <
                                            one_week_ago)]
        # print(three_week_data)
        past_week_data = current_data.loc[
            current_data['datetime'] > one_week_ago]
        # print(past_week_data)

        # check averages then check for significant out-of-range numbers
        # check temperatures
        temperature_sd = three_week_data['temperature'].std(
        )  # NOTE: maybe can change to some other stdevs
        three_week_average_temp = three_week_data['temperature'].mean()
        past_week_average_temp = past_week_data['temperature'].mean()

        if (past_week_average_temp - input_shiftlogs.para_temperature_sd *
                temperature_sd) > three_week_average_temp:
            ret_alerts.append(
                "Significant increase in temperature in the past week")
        elif (past_week_average_temp + input_shiftlogs.para_temperature_sd *
              temperature_sd) < three_week_average_temp:
            ret_alerts.append(
                "Significant decrease in temperature in the past week")

        if any((past_week_data['temperature'] <
                input_shiftlogs.para_temperature_min)
               | (past_week_data['temperature'] >
                  input_shiftlogs.para_temperature_max)):
            ret_alerts.append("Abnormal temperatures detected in past week")

        return ret_alerts
예제 #5
0
import pandas as pd
import datetime

# pandas settings
pd.options.mode.chained_assignment = None  # default='warn
pd.set_option('display.expand_frame_repr', False)

if __name__ == '__main__':  # we want to import from same directory if using this
    # module as-is (for debugging mainly, or for loading data in the future)
    sys.path.append(".")
    from DAOs.shift_log_DAO import shift_log_DAO
else:  # if called from index.py
    from DAOs.shift_log_DAO import shift_log_DAO

# input_raw_data = pd.DataFrame()
sldao = shift_log_DAO()
input_raw_data = sldao.get_all_logs()
input_raw_data['datetime'] = pd.to_datetime(input_raw_data['datetime'],
                                            format='%Y-%m-%dT%H:%M:%S')
input_raw_data['food_consumption'] = pd.to_numeric(
    input_raw_data['food_consumption'])
input_raw_data['pulse_pressure'] = input_raw_data[
    'systolic_bp'] - input_raw_data['diastolic_bp']
input_raw_max_date = input_raw_data['datetime'].max()
input_raw_min_date = input_raw_data['datetime'].min()
# print(input_raw_data)
daytime_start = datetime.time(7, 30)
daytime_end = datetime.time(19, 30)


def date_only(original_date):