Building Energy Boot Camp 2018 - Unofficial Day 6

Today is an “Unofficial Day 6” because I spent quite a lot of time working on my project while still on vacation. Essentially, there was no meeting, but I still worked for just as long as I would’ve if there were a meeting, as I need to catch up with the others. Anyways, I worked on creating the Air Data Displaying Dashboard I discussed on Day 4. As I had no idea how to make GUI with Python, I first researched the Tkinter library, which is very commonly used for GUI and is fairly simple. With time, I set up the layout that you see below, which consists of Tkinter Labels and Radiobuttons. I decided to use Labels because the user cannot edit them. As I do not have access to town WiFi, my program currently gets its data from two CSVs.

Current program state

The result of today's work


The following is the code that I wrote to display the window above. It currently doesn’t use wings or the first floor, as I am still learning which rooms are in which wing, and which rooms are actually considered to be a part of the first floor.

# -*- coding: utf-8 -*-

from tkinter import *
import pandas as pd

CO2_PATH = '2018 Q1Q2 - AHS CO2 (07300-1530).csv'
TEMP_PATH = '2018 Q1Q2 - AHS Temps (07300-1530).csv'

UNITS = ['ppm', '°F']

root = Tk()
root.title("AHS Air Data")
root.configure(background='white')
root.resizable(False, False)

wing = StringVar(root, value='A')  # The selected wing
floor = IntVar(root, value=1)  # The selected floor
measurement = IntVar(root, value=1)  # The selected measurement


def set_wing():
    fill_fields(floor.get(), str(wing.get()), measurement.get())


def set_floor():
    fill_fields(floor.get(), str(wing.get()), measurement.get())


def set_measurement():
    fill_fields(floor.get(), str(wing.get()), measurement.get())


# Setup table layout
COLUMN_TITLES = ['Floor', 'Wing', 'Measurement', 'Average Value', 'Maximum Value', 'Room Number With Maximum Value']
col_number = 0

row_labels = []


def set_field_data(avg, max_avg, room_number, unit):
    # Change room number from something like "RM260 ZN11 ZN-T" to "260"
    room_number = room_number.split(' ', 1)[0][2:]

    row_labels[0].config(text=(str(round(avg, 2)) + ' ' + unit))
    row_labels[1].config(text=(str(round(max_avg, 2)) + ' ' + unit))
    row_labels[2].config(text=room_number)


def fill_fields(floor, wing, measure):
    df = 0  # Set a default value to keep scope

    if measure == 0:
        # CO2
        df = pd.read_csv(CO2_PATH, skipfooter=3, engine='python')

    else:
        # Temperature
        df = pd.read_csv(TEMP_PATH, skipfooter=3, engine='python')

    if floor != 1:
        # Get all rooms on floor 2 by getting all columns starting with RM2
        filtered_cols = [col for col in df if col.startswith('RM' + str(floor))]
        df = df[filtered_cols]

        avgs = df.mean()

        max_avg = 0
        max_room_num = ''

        for column in df:
            if df[column].mean() > max_avg:
                max_avg = df[column].mean()
                max_room_num = column

        avg = avgs.mean()

        set_field_data(avg, max_avg, max_room_num, UNITS[measure])


for col in COLUMN_TITLES:
    label = Label(text=col, fg="Blue", bg="White", width="30")

    label.grid(row=0, column=col_number, pady=(10, 0), sticky='we', ipady="2")

    # Add floor options
    if col_number == 0:
        FLOOR_NUMBERS = ['1st', '2nd', '3rd']
        current_row = 1

        for floor_letter in FLOOR_NUMBERS:
            Radiobutton(text=floor_letter, fg="Black", bg="White", variable=floor, value=int(floor_letter[0]),
                        command=set_floor).grid(row=current_row, column=col_number, sticky='we')
            current_row += 1

    # Add wing options
    elif col_number == 1:
        WING_LETTERS = ['A', 'B', 'C', 'D']
        current_row = 1

        for index, wing_letter in enumerate(WING_LETTERS):
            if index == len(WING_LETTERS) - 1:
                Radiobutton(text=wing_letter, fg="Black", bg="White", variable=wing, value=wing_letter,
                            command=set_wing).grid(row=current_row, column=col_number, sticky='we',
                                                   pady=(0, 10))
            else:
                Radiobutton(text=wing_letter, fg="Black", bg="White", variable=wing, value=wing_letter,
                            command=set_wing).grid(row=current_row, column=col_number, sticky='we')
            current_row += 1

    # Add measurement options

    elif col_number == 2:
        MEASUREMENTS = ['CO2', 'Temperature']
        current_row = 1

        for index, measure in enumerate(MEASUREMENTS):
            Radiobutton(text=measure, fg="Black", bg="White", variable=measurement, value=index,
                        command=set_measurement).grid(row=current_row, column=col_number, sticky='we')
            current_row += 1

    else:
        # Create empty cell for value
        row_label = Label(bg="White", fg="Black", relief=RIDGE, width="30")
        row_labels.append(row_label)

        row_label.grid(row=1, column=col_number, sticky='we', ipady="2", padx=5)

    col_number += 1

root.grid_columnconfigure(0, weight=1)
fill_fields(floor.get(), str(wing.get()), measurement.get())
root.mainloop()

I will continue to work on this project and hopefully finish it within the next day or two.