In [7]:
import os
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import imageio.v2 as imageio
from sqlalchemy import create_engine
import itertools

spinner = itertools.cycle(['-', '/', '|', '\\'])

def connect_to_db():
    host = os.environ.get("DB_HOST")
    user = os.environ.get("DB_USER")
    password = os.environ.get("DB_PASSWORD")
    db= "CPAP"

    conn = create_engine(f"postgresql://{user}:{password}@{host}:5432/{db}")
    return conn

conn = connect_to_db()

def get_event_counts(conn, start_date, end_date):
    query = """
        SELECT DISTINCT 
            CASE
                WHEN time >= '2022-11-06 02:00:00' 
                    THEN time - INTERVAL '1 hour'
                ELSE time
            END AS time,
            flow
        FROM waveview
        WHERE time BETWEEN %s and %s
        ORDER BY 1
    """
    with conn.connect() as connection:
        event_counts = connection.execute(query, (start_date, end_date))
        return event_counts.fetchall()

def generate_plots(start_date, end_date):
    days = (end_date - start_date).days + 1
    for i in range(days):
        print(f"\r{next(spinner)} Running day {i}...", end="")
        curr_date = start_date + pd.DateOffset(days=i)
        next_date = curr_date + pd.DateOffset(days=1)
        data = get_event_counts(conn, curr_date, next_date)
        df = pd.DataFrame(data, columns=['time', 'flow'])
        print(f"\r{next(spinner)} Running day {i}...", end="")
        plt.style.use('dark_background')
        print(f"\r{next(spinner)} Running day {i}...", end="")
        plt.plot(df['time'], df['flow'],
                    color='indigo'
                    )
        print(f"\r{next(spinner)} Running day {i}...", end="")
        plt.xlabel('Time')
        plt.ylabel('Flow')
        plt.title(f'CPAP Flow on {curr_date.strftime("%Y-%m-%d")}')
        print(f"\r{next(spinner)} Running day {i}...", end="")
        # Set x-axis ticks to hourly intervals
        hourly_ticks = pd.date_range(curr_date, next_date, freq='H')
        hourly_labels = hourly_ticks.strftime('%H:%M')
        plt.xticks(ticks=hourly_ticks, labels=hourly_labels, rotation=90)
        print(f"\r{next(spinner)} Running day {i}...", end="")
        plt.xticks(rotation=45, ha='right')
        plt.ylim(-150, 150)
        plt.gca().yaxis.grid(True)
        plt.subplots_adjust(bottom=0.2)
        print(f"\r{next(spinner)} Running day {i}...", end="")
        plt.savefig(f'./images/flow_{curr_date.strftime("%Y%m%d")}.png')
        plt.clf()
        print(f"\r{next(spinner)} Running day {i}...", end="")

def create_gif(start_date, end_date):
    generate_plots(start_date, end_date)
    images = []
    days = (end_date - start_date).days + 1
    fps = 10
    for i in range(days):
        print(f"\r{next(spinner)} Gif Generating {i}...", end="")
        curr_date = start_date + pd.DateOffset(days=i)
        filename = f'./images/flow_{curr_date.strftime("%Y%m%d")}.png'
        images.append(imageio.imread(filename))
    imageio.mimsave(f'./gifs/flow_{start_date.strftime("%Y%m%d")}_{end_date.strftime("%Y%m%d")}_{fps}fps.gif', images, fps=fps)

start_date = pd.Timestamp('2022-08-30 12:00:00')
end_date = pd.Timestamp('2023-02-01 12:00:00')
create_gif(start_date, end_date)
\ Gif Generating 155...
<Figure size 640x480 with 0 Axes>