Snake River Total Dissolved Gas (TDG) Overview Table

In [1]:
#Ignore the performance warning
import warnings
warnings.filterwarnings('ignore')
In [2]:
from cwms_read.cwms_read import get_cwms
import pandas as pd
from collections import OrderedDict
from datetime import datetime, timedelta
from get_avgs import washington_method
import numpy as np
from pytz import timezone
now = datetime.now(timezone('US/Pacific')) #- timedelta(hours = 8)
#start_date = (2017, 6, 1)
#end_date = (2017, 8, 2)
start_date = (2018, 4, 1)
end = now - timedelta(days = 1)
end_date = (end.year, end.month, end.day)
start_index = '-'.join([str(x) for x in start_date])
In [3]:
%%capture


tuples = [
    
    ('Lower Granite', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('Lower Granite', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('Lower Granite', 'TW', 'LGNW', '% sat' ),
    ('Lower Granite', 'd/s FB', 'LGSA', '% sat'),
    
    ('Little Goose', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('Little Goose', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('Little Goose', 'TW', 'LGSW', '% sat' ),
    ('Little Goose', 'd/s FB', 'LMNA', '% sat'),
    
    ('Lower Monumental', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('Lower Monumental', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('Lower Monumental', 'TW', 'LMNW', '% sat' ),
    ('Lower Monumental', 'd/s FB', ' IHRA ', '% sat'),
    
    ('Ice Harbor', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('Ice Harbor', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('Ice Harbor', 'TW', 'IDSW', '% sat' ),
    ('Ice Harbor', 'Pasco', 'PAQW', '% sat' ),
    ('Ice Harbor', 'd/s FB', 'MCNA', '% sat'),
]

columns = pd.MultiIndex.from_tuples(tuples, names = ['Project','',' ','units'])

paths = [
    
        'LWG.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'LWG.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'LGNW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        'LGSA.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        
        'LGS.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'LGS.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'LGSW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        'LMNA.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
         
        'LMN.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'LMN.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'LMNW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        'IHRA.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
    
        'IHR.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'IHR.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'IDSW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        'PAQW.%-Saturation-TDG.Inst.1Hour.0.GOES-COMPUTED-REV',
        'MCNA.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        
        ]


index = pd.date_range(start='-'.join([str(x) for x in start_date]), end='-'.join([str(x) for x in end_date]),  freq='D', name='date')
df = pd.DataFrame(columns = columns, data = np.nan, index = index)
meta = {}
for path, column in zip(paths, tuples):
    data = get_cwms(path, start_date = start_date, end_date = end_date, public = True, fill = True)
    if isinstance(data,pd.DataFrame):
        meta.update(data.__dict__['metadata'])
        data = data.groupby(pd.Grouper(freq = 'D')).mean()
        df[column] = data.iloc[:,0]
    else: continue
df = df.round(0)
In [4]:
%%capture

"""
Questionable data is defined as values that are missing 1/3 or more data for calculation


"""



column_dict = {
                'LGNW': ('Lower Granite','TW'),
                'LGSA': ('Lower Granite', 'd/s FB'),
                'LGSW': ('Little Goose', 'TW'),
                'LMNA': ('Little Goose', 'd/s FB'),
                'LMNW': ('Lower Monumental', 'TW'), 
                'IHRA': ('Lower Monumental', 'd/s FB'),
                'IDSW': ('Ice Harbor', 'TW'),
                'PAQW': ('Ice Harbor','Pasco'),
                'MCNA': ('Ice Harbor', 'd/s FB'),
              }


site_list = list(column_dict.keys())
path = '.%-Saturation-TDG.Inst.1Hour.0.GOES-COMPUTED-REV '
site_list = [x+path for x in site_list]
questionable = pd.DataFrame(index = df.index, columns = df.columns, data = False)
wash_start = datetime(*start_date) - timedelta(days = 10)
wash_start = (wash_start.year, wash_start.month, wash_start.day)
wash_end = (now.year, now.month, now.day)
for key, value in column_dict.items():
    p = key+path
    data = get_cwms(p, start_date=wash_start, end_date=wash_end, public = True, fill = True)
    if isinstance(data, pd.DataFrame):
        series = data.iloc[:,0]
        wash = series.pipe(washington_method)
        wash.index = [x.replace(hour = 0, minute = 0, second = 0) for x in wash.index]
        wash.index.name = 'date'
        wash = wash.loc[df.index]
        quality = wash['wa_quality'] != True
        questionable[value] = quality 
    
In [5]:
"""
Get the meta dictionary keys match the column names so can be used below

"""

paths.insert(-1,'PAQW.%-Saturation-TDG.Inst.1Hour.0.GOES-COMPUTED-RAW')
p = []
for path in paths:
    column_name = '_'.join(path.split('.')[:2])
    column_name = '_'.join(column_name.split('-'))
    p.append(column_name)
    
meta_col_dict = {key:value for key,value in zip(p, list(df.columns))}
temp_meta = {}
for key, value in meta.items():
    
    try:
        temp_meta.update({meta_col_dict[key]: value})
    except KeyError:
        continue
        
meta.update(temp_meta)
In [6]:
%%capture

"""
Lack of Load or involuntary spill: 6 hours of 24 hours that the project is spilling above the voluntary spill cap
with a 2 kcfs buffer
This will be the asteriks on the actual spill columns



From the urban dictionary: asteriks
Incorrect pronounciation of the word 'asterisk'. Use of the word 'asteriks' is a result of the USA's substandard education system.
Jim: Hey Lou, what's that star thingy called that you get from pressing SHIFT + 8? 

Lou: an asteriks 

Jim: Aha! I knew you were a dumbass.


"""
site_dict = OrderedDict([
            ('Lower Granite',['LWG']),
            ('Little Goose',['LGS']),
            ('Lower Monumental', ['LMN']),
            ('Ice Harbor', ['IHR'])
          ])

column_dict = {
    'LWG': 'Lower Granite',
    'LGS': 'Little Goose',
    'LMN': 'Lower Monumental',
    'IHR': 'Ice Harbor'
    
}

# Collecting the daily spill caps to compare against the hourly spill
site_list = list(sum(site_dict.values(), []))
spill_cap_path = '.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB'
spill_cap_list = [x+spill_cap_path for x in site_list]

spill_cap = get_cwms(spill_cap_list, public = True, fill = True, start_date=start_date, end_date=end_date, timezone = 'PST')
if isinstance(spill_cap, pd.DataFrame):
    spill_cap.columns = [x.split('_')[0] for x in spill_cap.columns]
    spill_cap.rename(columns = column_dict, inplace = True)


    # Collecting the hourly spill to compare against the daily spill caps
    spill_path = '.Flow-Spill.Ave.1Hour.1Hour.CBT-REV'
    spill_list = [x+spill_path for x in site_list]

    spill = get_cwms(spill_list, public = True, start_date=start_date, end_date=end_date, timezone = 'PST', fill = True)
    spill.columns = [x.split('.')[0] for x in spill.columns]
    spill.rename(columns = column_dict, inplace = True)
    
    #subtracting 16 hours from the spill index because the spill change occurs at 1600, then I can group by day
    spill.index = spill.index - timedelta(hours = 16)

    # Group the data by day to check if the project was in involuntary spill
    sg = spill.groupby(pd.Grouper(level='date', freq='D'))
    scg = spill_cap.groupby(pd.Grouper(level='date', freq='D')).mean().groupby(pd.Grouper(level='date', freq='D'))
    date = list(scg.groups.keys())
    inv_spill = pd.DataFrame(index = date, columns = spill.columns)
    for group, value in scg:
        g = sg.get_group(group)
        
        s = value.iloc[0]
        inv_spill.loc[group] = g.apply(lambda x: x.gt(s+2), axis = 1).sum()>5

    """
    Create boolean df for asterik
    """    


    projects = list(set(df.columns.get_level_values(0).tolist()))
    inv_spill_bool = pd.DataFrame(data = False,index = df.index, columns = df.columns)
    for project in projects:
        inv_spill_bool.loc[:,(project, 'Actual Spill')] = inv_spill[project]

    inv_spill_bool.fillna(value = False, inplace = True)
else: inv_spill_bool = False
In [7]:
"""
Minimum Generation: at least 6 hours of 24 that the project is at minimum generation
This will be the green on the actual spill columns
"""
min_gen_dict_kcfs = OrderedDict([
            ('Lower Granite',13.2),
            ('Little Goose',14.7),
            ('Lower Monumental', 12.5),
            ('Ice Harbor', 10.0)
          ])

min_gen_kcfs = pd.Series(min_gen_dict_kcfs)

# Collecting the daily generation flow to compare against the minimum generation flow, group by day
site_list = list(sum(site_dict.values(), []))
gen_flow_path = '.Flow-Gen.Ave.1Hour.1Hour.CBT-REV'
gen_flow_list = [x+gen_flow_path for x in site_list]
gen_flow = get_cwms(gen_flow_list, col_names = site_list, public = True, start_date=start_date, end_date=end_date, timezone = 'PST', fill = True)
gen_flow.columns = [x.split('_')[0] for x in gen_flow.columns]
gen_flow.rename(columns = column_dict, inplace = True)

gen_flow_grouped = gen_flow.groupby(pd.Grouper(level='date', freq='D'))
 
    
# Creat a df fill with min gen data as dummy data
date = list(gen_flow_grouped.groups.keys())
min_gen = pd.DataFrame(index = date)
for key, value in min_gen_kcfs.items():
    min_gen[key] = value

#check if proj in min generation for the day and fill min_gen with result  
min_gen.index.rename('date', inplace = True)
min_gen_grouped = min_gen.groupby(pd.Grouper(level='date', freq='D'))
for group, value in gen_flow_grouped:
    compare_df = pd.DataFrame(index = value.index)
    for column in value.columns:
        compare_df[column] =  min_gen_kcfs[column]
    bool_df = value<= compare_df
    min_gen.loc[group] = bool_df.sum()>5

"""
Create boolean df for css
"""    
    
    
projects = list(set(df.columns.get_level_values(0).tolist()))
min_gen_bool = pd.DataFrame(data = False,index = df.index, columns = df.columns)
for project in projects:
    min_gen_bool.loc[:,(project, 'Actual Spill')] = min_gen[project]
In [8]:
"""
Not Meeting TDG Gas Cap Tailwater: defined as combined OR WA value > 120.5
Not Meeting TDG Gas Cap Forebay: defined as combined OR WA value > 115.5
This will be the blue on the TW and downstream forebay columns
"""
idx = pd.IndexSlice
gas_cap_exceeds = df.copy()
tw = gas_cap_exceeds.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'TW']]
fb = gas_cap_exceeds.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'d/s FB']]
gas_cap_exceeds[tw.columns] = tw.applymap(lambda x: x > 120.5)
gas_cap_exceeds[fb.columns] = fb.applymap(lambda x: x > 115.5)
gas_cap_exceeds = gas_cap_exceeds.sort_index(axis=1)[df.columns]
gas_cap_exceeds = gas_cap_exceeds.applymap(lambda x: x if type(x) == bool else False)
gas_cap_exceeds.head()

"""
Combine gas cap by project: If true in one gauge, true for all project, except Ice Harbor special case
"""

gas_cap_by_gauge =  pd.DataFrame(data = False,index = gas_cap_exceeds.index, columns = gas_cap_exceeds.columns)
projects = list(set(df.columns.get_level_values(0).tolist()))
for project in projects:
    data = gas_cap_exceeds.loc[:,project].sort_index(axis=1).loc[idx[:,['TW', 'd/s FB']]]
    gas_cap_by_gauge.loc[:,(project, 'TW')] = data.apply(lambda x: x.any(),axis = 1)
    gas_cap_by_gauge.loc[:,(project, 'd/s FB')] = data.apply(lambda x: x.any(),axis = 1)
gas_cap_by_gauge['Ice Harbor'] = gas_cap_exceeds['Ice Harbor']
In [9]:
"""
Most restrictive gauge defined as:

Bold tailrace if:
(Tailrace TDG -120) > (ds Forebay -115)
Else:
Bold ds Forebay

Bold regardless of TDG value (above or below target).


This is the updated bold bold 

"""

idx = pd.IndexSlice
most_restrictive_gauge = df.copy()
tw = most_restrictive_gauge.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'TW']]
fb = most_restrictive_gauge.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'d/s FB']]



most_restrictive_gauge[tw.columns] = (tw - 120).values >= (fb - 115).values
most_restrictive_gauge[fb.columns] = (tw - 120).values <= (fb - 115).values


most_restrictive_gauge = most_restrictive_gauge.sort_index(axis=1)[df.columns]
most_restrictive_gauge = most_restrictive_gauge.applymap(lambda x: x if type(x) == bool else False)
In [10]:
#"""
#Gas cap meets TW: defined as combined OR WA value > 119
#Gas cap meets FB: defined as combined OR WA value > 114

#This will be the bold on the TW and downstream forebay columns
#"""
#idx = pd.IndexSlice
#gas_cap_meets = df.copy()
#tw = gas_cap_meets.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'TW']]
#fb = gas_cap_meets.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'d/s FB']]
#gas_cap_meets[tw.columns] = tw.applymap(lambda x: x >= 119)
#gas_cap_meets[fb.columns] = fb.applymap(lambda x: x >= 114)
#gas_cap_meets = gas_cap_meets.sort_index(axis=1)[df.columns]
#gas_cap_meets = gas_cap_meets.applymap(lambda x: x if type(x) == bool else False)
In [11]:
"""
Convert the dataframe to string because it displays better, remove decimals, add the asterik, and format the index to be date only (no time), for all dataframes.  
If index not formated for all df's the styling will not work
"""

df_string = df.copy().round(0).astype(str).applymap(lambda x: x.replace('.0', ''))
if isinstance(inv_spill_bool, pd.DataFrame):
    df_string[inv_spill_bool] = df_string[inv_spill_bool] + '*'
df_string.replace('nan', '--', inplace = True)




spill_cap = df_string.sort_index(axis = 1).loc[:,pd.IndexSlice[:,'Spill Cap']].copy()
for column in spill_cap.columns:
    series = spill_cap[column]
    for index,value in enumerate(series[1:]):
        previous_value = series[index]
        if value != previous_value:
            df_string[column][index+1] = ('{}{}{}'.format(str(previous_value), '→', str(value)))




for dataframe in [df_string,gas_cap_by_gauge,min_gen_bool, most_restrictive_gauge, questionable]:
    dataframe.index = dataframe.index.strftime('%Y-%m-%d')
In [12]:
"""
Custom css
"""


def hover(hover_color="#ffff99"):
    return dict(selector="tbody tr:hover",
                props=[("background-color", "%s" % hover_color)])

styles = [
    
   
]
In [13]:
"""
table key
"""

blue = '#7194da'
green = '#cfff95'

def highlight(value):
    return table_css.applymap(lambda x: x)
key_list =[
            'Most restrictive gauge used to determine spill cap',
            'Project spilling above the voluntary spill cap for 6 or more hours',
            'TDG measurements exceeded the daily criteria (i.e. gas cap)',
            'Project operating at minimum generation for 6 or more hours',
            '1/3 of data or more missing for value calculation',
            'No data'
        ]
table_key = pd.DataFrame({'Table Key':key_list })                         
table_key.set_index('Table Key', inplace = True)
table_key['value']=['value','*','','','value', '--']
table_css = pd.DataFrame({'Table Key':key_list,'value':['font-weight: 900',\
                                                        '',\
                                                        'background-color: ' + blue,\
                                                        'background-color: '+ green, \
                                                        'color: red',
                                                        '']})
table_css.set_index('Table Key', inplace = True)
table_key.style.apply(highlight, axis = None)


hide_index = [{'selector': '.row_heading, .blank', 'props': [('display', 'none;')]}]
key_styles = styles # + hide_index
key_html = (table_key.style)
key_html.apply(highlight,axis = None).set_uuid('key')
Out[13]:
value
Table Key
Most restrictive gauge used to determine spill cap value
Project spilling above the voluntary spill cap for 6 or more hours *
TDG measurements exceeded the daily criteria (i.e. gas cap)
Project operating at minimum generation for 6 or more hours
1/3 of data or more missing for value calculation value
No data --
In [14]:
"""
Adding table styles
"""

def tbl_css(value,css,df):
    return df.applymap(lambda x: css if x else '')

s = df_string.style

table_styles = styles + [hover()]

html = (
          s.set_table_styles(table_styles)
          .set_caption("Spill Cap changes occur at 16:00 PST.")
       )

html \
.apply(tbl_css, css = 'font-weight: 900', df = most_restrictive_gauge, axis = None) \
.apply(tbl_css, css = 'background-color: #7194da', df = gas_cap_by_gauge, axis = None) \
.apply(tbl_css, css = 'background-color: #cfff95', df = min_gen_bool, axis = None)\
.apply(tbl_css, css = 'color: red', df = questionable, axis = None) \
.set_uuid('data_table')
Out[14]:
Spill Cap changes occur at 16:00 PST.
Project Lower Granite Little Goose Lower Monumental Ice Harbor
Spill Cap Actual Spill TW d/s FB Spill Cap Actual Spill TW d/s FB Spill Cap Actual Spill TW d/s FB Spill Cap Actual Spill TW Pasco d/s FB
Starting → Change Daily Average LGNW LGSA Starting → Change Daily Average LGSW LMNA Starting → Change Daily Average LMNW IHRA Starting → Change Daily Average IDSW PAQW MCNA
units kcfs kcfs % sat % sat kcfs kcfs % sat % sat kcfs kcfs % sat % sat kcfs kcfs % sat % sat % sat
2018-04-01 45 7 107 107 42 0 107 105 40 0 105 104 90 10 107 104 105
2018-04-02 45 7 107 107 42 0 107 105 40 0 105 104 90 8 107 103 105
2018-04-03 45 44 117 105 42 41 118 104 40 40 116 104 90 58 115 103 103
2018-04-04 45→47 45 118 105 42 42 118 105 40→43 41 116 104 90 62 115 103 103
2018-04-05 47→49 48 119 105 42 42 117 116 43→46 44 117 112 90 69 116 104 105
2018-04-06 49→51 50 119 111 42→39 41 118 119 46 46 117 116 90 74 116 105 107
2018-04-07 51→53 52 120 117 39 38 117 120 46 46 117 118 90 81 118 106 108
2018-04-08 53→50 52 120 117 39→37 38 117 119 46→44 46 118 118 90→93 91 119 104 108
2018-04-09 50 49 118 115 37 36 116 114 44 44 118 113 93→96 94 120 104 107
2018-04-10 50 49 119 116 37→35 36 116 117 44→42 43 118 116 96 96 120 106 109
2018-04-11 50→47 49 119 118 35→33 34 116 118 42 42 118 117 96 96 121 106 112
2018-04-12 47→45 47 119 118 33→30 31 116 118 42→40 42 118 117 96→93 95 121 104 112
2018-04-13 45 45 118 114 30→32 29 114 114 40 40 117 113 93 93 120 103 107
2018-04-14 45 45 118 112 32→37 32 115 113 40 40 118 113 93 93 120 105 108
2018-04-15 45 45 118 116 37 36 116 117 40 40 118 116 93 93 121 107 111
2018-04-16 45 45 118 117 37 36 116 117 40 40 118 116 93→92 93 121 105 111
2018-04-17 45 45 118 115 37 37 116 115 40 40 117 113 92 92 120 103 109
2018-04-18 45 45 118 111 37→39 37 116 114 40 40 117 112 92 92 119 107 106
2018-04-19 45 45 118 113 39 38 116 116 40 40 117 114 92 92 119 111 110
2018-04-20 45 45 119 116 39→34 36 116 117 40 40 117 116 92 92 119 111 113
2018-04-21 45 45 118 116 34 32 116 117 40 40 117 116 92 83 119 111 113
2018-04-22 45→42 44 118 116 34 32 116 116 40→37 39 116 115 92 82 118 111 112
2018-04-23 42 42 118 116 34 32 116 116 37 37 116 116 92 88 118 111 113
2018-04-24 42→39 41 118 118 34→30 31 116 117 37→33 35 117 117 92 85 118 112 114
2018-04-25 39→36 38 117 119 30→28 28 116 118 33 32 116 117 92 89 119 113 115
2018-04-26 36 35 117 119 28 27 116 118 33 32 116 118 92 86 119 113 116
2018-04-27 36→31 34 117 120 28 27 117 119 33→31 30 116 119 92→85 90 120 114 117
2018-04-28 31→33 32 115 119 28 29 116 119 31 34 117 118 85 85 119 111 116
2018-04-29 33 33 115 115 28 40 117 116 31 44 119 115 85 85 119 114 112
2018-04-30 33 33 115 112 28 42 118 116 31 47 119 115 85 85 119 114 113
2018-05-01 33→34 33 115 111 28 37 117 117 31 41 119 116 85 85 119 114 114
2018-05-02 34→35 38 117 111 28→30 28 115 116 31 34 117 116 85 74 118 115 115
2018-05-03 35 35 117 112 30 30 115 117 31 36 117 117 85 85 118 116 115
2018-05-04 35 35 116 114 30 30 116 115 31 30 116 117 85 81 118 116 116
2018-05-05 35 35 116 115 30 30 116 116 31 30 115 117 85 85 118 116 117
2018-05-06 35→34 35 116 116 30→28 29 116 117 31→29 42 119 116 85 85 118 117 117
2018-05-07 34→31 37 117 116 28→26 44 121 117 29 66 124 116 85→80 91 121 117 117
2018-05-08 31 33 116 114 26 42 120 121 29 65 123 121 80 86 121 119 118
2018-05-09 31 35 117 113 26 45 121 121 29 66 124 121 80 85 121 118 118
2018-05-10 31 49 121 111 26 62 124 119 29 80 126 119 80 105 124 119 117
2018-05-11 31 51 121 111 26 65 124 123 29 72 127 120 80 102 125 117 117
2018-05-12 31 44 119 116 26 52 122 124 29 46 121 122 80 91 122 120 119
2018-05-13 31→33 34 117 116 26 40 118 124 29 30 118 122 80 80 120 123 122
2018-05-14 33→31 32 115 116 26 29 117 122 29→27 38 119 121 80 80 119 125 124
2018-05-15 31 31 115 115 26 34 118 120 27 42 119 121 80 82 120 126 126
2018-05-16 31 31 115 114 26 37 118 118 27 43 120 119 80 85 121 124 126
2018-05-17 31 39 117 113 26 52 119 117 27 53 121 117 80 92 122 124 123
2018-05-18 31 44 118 111 26 56 120 121 27 55 121 118 80 95 122 124 123
2018-05-19 31 43 118 113 26 73 126 122 27 59 121 120 80 100 123 124 124
2018-05-20 31 42 118 114 26 53 122 127 27 54 121 120 80 95 122 123 124
2018-05-21 31 42 118 114 26 53 121 125 27 52 121 121 80 92 122 123 123
2018-05-22 31 39 118 114 26 52 121 122 27 53 122 121 80 94 122 124 123
2018-05-23 31 46 120 115 26 61 123 123 27 60 -- 121 80 102 124 125 125
2018-05-24 31 49 119 114 26 59 123 123 27 60 121 120 80 99 124 124 125
2018-05-25 31 57 124 116 26 68 124 123 27 74 122 120 80 109 125 123 124
2018-05-26 31 73 126 116 26 79 126 124 27 80 122 120 80 115 126 120 123
2018-05-27 31 67 126 118 26 81 127 128 27 84 121 122 80 123 130 119 119
2018-05-28 31 56 123 120 26 69 124 129 27 70 121 123 80 108 125 120 121
2018-05-29 31 52 122 120 26 77 126 126 27 64 122 123 80 104 124 119 120
2018-05-30 31 50 121 117 26 62 125 127 27 61 122 122 80 102 124 119 120
2018-05-31 31 42 119 116 26 55 125 126 27 55 122 121 80 98 126 118 120
2018-06-01 31 45 118 115 26 56 123 124 27 55 121 121 80 97 123 116 118
2018-06-02 31 34 117 112 26 47 123 123 27 59 121 118 80 92 125 119 117
2018-06-03 31 31 115 114 26 27 118 124 27 29 119 121 80 82 120 120 121
2018-06-04 31 31 115 114 26 25 114 120 27 27 115 121 80 80 119 118 120
2018-06-05 31 31 115 112 26 28 114 115 27 31 116 118 80 80 119 117 118
2018-06-06 31 31 115 112 26 25 114 115 27 29 115 115 80 80 119 118 117
2018-06-07 31→33 32 115 113 26 25 114 115 27 27 115 115 80 80 118 117 118
2018-06-08 33→35 34 117 113 26 25 114 114 27 27 114 115 80 80 118 115 118
2018-06-09 35 35 117 113 26 25 114 114 27 27 114 114 80 80 117 114 116
2018-06-10 35 36 116 111 26 25 114 113 27 27 114 112 80→85 79 117 111 113
2018-06-11 35 35 117 110 26→28 28 114 111 27→29 27 114 110 85→90 80 117 113 110
2018-06-12 35→37 36 117 110 28→30 28 113 112 29→31 30 114 111 90 75 118 114 114
2018-06-13 37 37 118 114 30 29 114 114 31→33 31 114 113 90 63 118 113 115
2018-06-14 37 37 117 113 30 29 114 113 33 33 115 113 90 60 116 111 114
2018-06-15 37 37 118 114 30→32 30 115 113 33 32 115 113 90 55 117 112 113
2018-06-16 37→39 38 118 114 32 33 116 114 33→35 34 115 114 90 50 116 112 113
2018-06-17 39→41 40 118 115 32 33 117 115 35→37 34 115 115 90 44 115 111 113
2018-06-18 41 41 117 115 32 33 117 115 37 37 115 115 90 47 115 110 113
2018-06-19 41 41 118 115 32 33 117 116 37 36 116 114 90 54 116 111 111
2018-06-20 41→39 42 118 119 32→30 32 116 117 37 37 116 116 90 60 116 112 112
2018-06-21 39 19 117 119 30 20 115 118 37→21 17 119 117 90 21 116 111 113
2018-06-22 39 19 114 117 30 20 113 118 21 17 119 117 90 20 116 111 113
2018-06-23 39 19 114 116 30 21 113 116 21 17 119 115 90 39 116 109 111
2018-06-24 39 19 114 115 30 21 112 113 21 17 118 115 90 50 116 110 111
2018-06-25 39 19 114 114 30 19 112 114 21 17 118 115 90 30 116 111 112
2018-06-26 39 19 114 111 30 18 112 113 21 17 118 114 90 19 115 110 109
2018-06-27 39 19 114 111 30 18 112 112 21 17 118 113 90 36 115 113 112
2018-06-28 39 19 114 111 30 27 117 112 21 17 117 114 90 48 116 113 112
2018-06-29 39 19 115 110 30 15 114 112 21 17 116 113 90 22 115 113 112
2018-06-30 39 17 115 110 30 13 112 111 21 17 116 113 90 13 112 112 112
2018-07-01 39 18 115 109 30 12 112 111 21 17 116 112 90 27 114 112 112
2018-07-02 39 18 115 109 30 12 112 111 21 17 116 112 90 33 114 109 111
2018-07-03 39 18 115 108 30 13 112 109 21 17 116 112 90 19 112 108 110
2018-07-04 39 18 115 108 30 12 113 110 21 17 116 112 90 13 112 108 111
2018-07-05 39 18 116 108 30 11 113 110 21 17 116 112 90 26 113 110 109
2018-07-06 39 18 115 108 30 13 113 110 21 17 116 111 90 34 114 111 110
2018-07-07 39 18 115 108 30 13 113 111 21 17 116 111 90 16 113 109 109
2018-07-08 39 18 115 112 30 13 114 111 21 17 116 113 90 14 112 110 111
2018-07-09 39 18 115 112 30 11 114 111 21 17 116 113 90 28 114 111 111
2018-07-10 39 18 115 112 30 14 114 111 21 17 117 113 90 33 114 108 110
2018-07-11 39 18 115 110 30 13 113 112 21 17 117 113 90 18 114 110 109
2018-07-12 39 18 115 110 30 13 113 112 21 17 117 113 90 14 112 109 109
2018-07-13 39 18 116 110 30 12 113 112 21 16 117 113 90 29 113 111 111
2018-07-14 39 18 116 110 30 12 113 112 21 15 117 114 90 31 112 110 111
2018-07-15 39 18 116 113 30 11 114 113 21 17 117 116 90 31 113 109 111
2018-07-16 39 18 116 113 30 11 114 113 21 17 117 116 90 30 113 110 111
2018-07-17 39 18 116 113 30 12 114 113 21 16 117 114 90 34 112 111 111
2018-07-18 39 18 116 113 30 11 113 114 21 17 117 114 90 30 113 110 110
2018-07-19 39 18 115 112 30 11 116 113 21 17 117 113 90 28 113 109 109
2018-07-20 39 18 116 111 30 10 116 112 21 17 116 112 90 26 113 107 108
2018-07-21 39 18 116 110 30 9 114 111 21 17 117 111 90 23 112 107 108
2018-07-22 39 18 116 109 30 10 115 110 21 17 117 111 90 23 112 107 107
2018-07-23 39 18 116 109 30 11 115 110 21 17 116 111 90 25 112 109 108
2018-07-24 39 16 116 110 30 11 114 110 21 17 117 111 90 26 113 110 108
2018-07-25 39 16 115 110 30 11 114 111 21 14 116 113 90 27 113 110 109
2018-07-26 39 17 115 110 30 10 114 112 21 16 119 115 90 25 113 109 111
2018-07-27 39 17 116 111 30 11 114 113 21 16 118 115 90 30 114 109 112
2018-07-28 39 17 116 112 30 10 114 113 21 16 117 115 90 20 114 110 112
2018-07-29 39 17 116 112 30 10 110 112 21 17 117 114 90 28 113 110 111
2018-07-30 39 17 116 112 30 9 111 112 21 17 117 115 90 21 114 110 111
2018-07-31 39 17 116 112 30 11 113 112 21 16 117 115 90 28 114 110 111
2018-08-01 39 18 116 112 30 11 114 112 21 17 117 115 90 27 114 109 110
2018-08-02 39 18 116 112 30 9 114 111 21 17 116 115 90 22 114 109 110
2018-08-03 39 18 116 112 30 11 114 109 21 17 116 114 90 26 113 107 108
2018-08-04 39 18 116 110 30 9 112 109 21 17 116 112 90 23 113 107 106
2018-08-05 39 16 116 110 30 11 110 108 21 17 116 111 90 23 113 107 106
2018-08-06 39 15 115 109 30 17 115 108 21 14 116 110 90 18 113 108 107
2018-08-07 39 18 115 108 30 19 115 109 21 17 116 111 90 26 114 109 108
2018-08-08 39 17 115 109 30 20 114 109 21 16 116 113 90 24 113 109 110
2018-08-09 39 18 112 109 30 22 115 109 21 17 115 114 90 27 114 109 110
2018-08-10 39 18 112 111 30 9 114 109 21 16 115 114 90 20 114 109 110
2018-08-11 39 18 111 112 30 10 110 110 21 17 115 114 90 22 113 107 109
2018-08-12 39 15 111 111 30 11 110 110 21 14 115 112 90 18 113 106 107
2018-08-13 39 19 116 109 30 9 109 109 21 12 113 111 90 17 112 106 107
2018-08-14 39 19 116 109 30 9 109 109 21 11 115 111 90 20 113 108 106
2018-08-15 39 20 116 109 30 10 109 107 21 15 115 110 90 21 114 108 107
2018-08-16 39 20 115 107 30 10 109 108 21 12 114 111 90 17 113 108 107
2018-08-17 39 14 113 106 30 9 109 108 21 10 112 111 90 15 112 107 107
2018-08-18 39 14 110 107 30 9 109 108 21 10 112 110 90 18 110 108 107
2018-08-19 39 12 110 108 30 9 109 108 21 9 111 110 90 16 110 107 107
2018-08-20 39 12 108 108 30 9 108 108 21 7 110 111 90 14 108 105 107
2018-08-21 39 13 109 108 30 7 108 109 21 9 112 111 90 16 109 105 106
2018-08-22 39 14 111 109 30 7 109 108 21 11 113 110 90 20 111 105 107
2018-08-23 39 14 110 109 30 9 109 107 21 10 114 110 90 19 112 105 106
2018-08-24 39 13 109 107 30 9 109 107 21 8 111 108 90 14 109 103 104
2018-08-25 39 15 109 106 30 9 109 107 21 12 113 107 90 20 112 103 104
2018-08-26 39 20 115 105 30 9 108 107 21 13 114 107 90 19 113 102 103
2018-08-27 39 12 110 105 30 9 108 107 21 10 114 107 90 17 112 102 101
2018-08-28 39 13 109 104 30 9 109 106 21 9 111 107 90 18 110 102 102
2018-08-29 39 18 113 105 30 7 109 106 21 15 116 107 90 21 113 103 103
2018-08-30 39 15 113 105 30 10 109 106 21 14 115 107 90 21 113 104 103
2018-08-31 39 18 112 104 30 10 109 105 21 17 115 107 90 21 113 103 103
2018-09-01 39→-- 0 111 105 30→-- 0 109 106 21→-- 0 114 107 90→-- 0 109 103 103
2018-09-02 -- 0 99 106 -- 0 105 105 -- 0 106 107 -- 0 109 103 104
2018-09-03 -- 0 99 106 -- 0 105 105 -- 0 105 108 -- 0 109 102 104
2018-09-04 -- 0 99 106 -- 0 104 104 -- 0 105 108 -- 0 109 102 105
2018-09-05 -- 0 101 106 -- 0 105 106 -- 0 106 -- -- 0 110 101 105
2018-09-06 -- 0 101 107 -- 0 106 106 -- 0 106 -- -- 0 110 -- --
2018-09-07 -- 0 101 109 -- 0 107 105 -- 0 105 -- -- 0 110 -- --
2018-09-08 -- 0 101 108 -- 0 106 104 -- 0 104 -- -- 0 109 -- --
2018-09-09 -- 0 100 104 -- 0 101 104 -- 0 104 -- -- 0 106 -- --
2018-09-10 -- 0 101 104 -- 0 100 104 -- 0 104 -- -- 0 105 -- --
2018-09-11 -- 0 101 104 -- 0 100 104 -- 0 105 -- -- 0 105 -- --
2018-09-12 -- 0 100 105 -- 0 101 105 -- 0 105 -- -- 0 105 -- --
2018-09-13 -- 0 100 105 -- 0 101 105 -- 0 104 -- -- 0 105 -- --
2018-09-14 -- 0 100 103 -- 0 101 104 -- 0 102 -- -- 0 104 -- --
2018-09-15 -- 0 100 102 -- 0 101 104 -- 0 102 -- -- 0 104 -- --
2018-09-16 -- 0 98 101 -- 0 100 101 -- 0 101 -- -- 0 103 -- --
2018-09-17 -- 0 97 100 -- 0 98 102 -- 0 102 -- -- 0 102 -- --
2018-09-18 -- 0 98 99 -- 0 98 103 -- 0 103 -- -- 0 102 -- --
2018-09-19 -- 0 99 99 -- 0 98 102 -- 0 102 -- -- 0 102 -- --
2018-09-20 -- 0 99 99 -- 0 98 101 -- 0 102 -- -- 0 102 -- --
2018-09-21 -- 0 98 98 -- 0 98 -- -- 0 103 -- -- 0 102 -- --
2018-09-22 -- 0 98 -- -- 0 98 -- -- 0 102 -- -- 0 102 -- --
2018-09-23 -- 0 97 -- -- 0 98 -- -- 0 101 -- -- 0 101 -- --
2018-09-24 -- 0 97 -- -- 0 97 -- -- 0 100 -- -- 0 101 -- --
2018-09-25 -- 0 97 -- -- 0 97 -- -- 0 99 -- -- 0 100 -- --
2018-09-26 -- 0 98 -- -- 0 97 -- -- 0 99 -- -- 0 101 -- --
2018-09-27 -- 0 99 -- -- 0 98 -- -- 0 100 -- -- 0 102 -- --
2018-09-28 -- 0 101 -- -- 0 98 -- -- 0 99 -- -- 0 102 -- --
2018-09-29 -- 0 99 -- -- 0 98 -- -- 0 99 -- -- 0 101 -- --
2018-09-30 -- 0 99 -- -- 0 98 -- -- 0 99 -- -- 0 101 -- --
2018-10-01 -- 0 98 -- -- 0 98 -- -- 0 98 -- -- 0 101 -- --
2018-10-02 -- 0 99 -- -- 0 99 -- -- 0 99 -- -- 0 100 -- --
2018-10-03 -- 0 98 -- -- 0 98 -- -- 0 98 -- -- 0 100 -- --
2018-10-04 -- 0 97 -- -- 0 97 -- -- 0 97 -- -- 0 99 -- --
2018-10-05 -- 0 96 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-10-06 -- 0 97 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-10-07 -- 0 96 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-10-08 -- 0 96 -- -- 0 96 -- -- 0 98 -- -- 0 98 -- --
2018-10-09 -- 0 97 -- -- 0 96 -- -- 0 98 -- -- 0 98 -- --
2018-10-10 -- 0 96 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-10-11 -- 0 96 -- -- 3 107 -- -- 0 96 -- -- 0 98 -- --
2018-10-12 -- 0 96 -- -- 3 113 -- -- 0 96 -- -- 0 99 -- --
2018-10-13 -- 0 96 -- -- 0 109 -- -- 0 96 -- -- 0 99 -- --
2018-10-14 -- 0 95 -- -- 0 94 -- -- 0 95 -- -- 0 98 -- --
2018-10-15 -- 0 95 -- -- 0 94 -- -- 0 95 -- -- 0 97 -- --
2018-10-16 -- 0 96 -- -- 0 94 -- -- 0 95 -- -- 0 98 -- --
2018-10-17 -- 0 96 -- -- 3 117 -- -- 0 95 -- -- 0 98 -- --
2018-10-18 -- 0 96 -- -- 0 114 -- -- 0 97 -- -- 0 98 -- --
2018-10-19 -- 0 96 -- -- 0 95 -- -- 0 97 -- -- 0 98 -- --
2018-10-20 -- 0 97 -- -- 0 95 -- -- 0 98 -- -- 0 99 -- --
2018-10-21 -- 0 97 -- -- 0 95 -- -- 0 99 -- -- 0 98 -- --
2018-10-22 -- 0 97 -- -- 0 95 -- -- 0 99 -- -- 0 98 -- --
2018-10-23 -- 0 98 -- -- 0 96 -- -- 0 98 -- -- 0 98 -- --
2018-10-24 -- 0 98 -- -- 0 96 -- -- 0 97 -- -- 0 99 -- --
2018-10-25 -- 0 98 -- -- 0 95 -- -- 0 96 -- -- 0 98 -- --
2018-10-26 -- 0 98 -- -- 0 96 -- -- 0 98 -- -- 0 97 -- --
2018-10-27 -- 0 99 -- -- 0 96 -- -- 0 98 -- -- 0 99 -- --
2018-10-28 -- 0 99 -- -- 0 97 -- -- 0 98 -- -- 0 98 -- --
2018-10-29 -- 0 99 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-10-30 -- 0 98 -- -- 0 96 -- -- 0 96 -- -- 0 98 -- --
2018-10-31 -- 0 99 -- -- 0 97 -- -- 0 96 -- -- 0 98 -- --
2018-11-01 -- 0 99 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-11-02 -- 0 99 -- -- 0 98 -- -- 0 98 -- -- 0 99 -- --
2018-11-03 -- 0 98 -- -- 0 98 -- -- 0 97 -- -- 0 98 -- --
2018-11-04 -- 0 99 -- -- 0 99 -- -- 0 98 -- -- 0 99 -- --
2018-11-05 -- 0 99 -- -- 0 99 -- -- 0 98 -- -- 0 99 -- --
2018-11-06 -- 0 99 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- --
2018-11-07 -- 0 99 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- --
2018-11-08 -- 0 98 -- -- 0 97 -- -- 0 97 -- -- 0 97 -- --
2018-11-09 -- 0 98 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-11-10 -- 0 98 -- -- 0 97 -- -- 0 97 -- -- 0 97 -- --
2018-11-11 -- 0 97 -- -- 0 150 -- -- 0 96 -- -- 0 97 -- --
2018-11-12 -- 0 96 -- -- 0 150 -- -- 0 96 -- -- 0 96 -- --
2018-11-13 -- 0 96 -- -- 0 150 -- -- 0 96 -- -- 0 96 -- --
2018-11-14 -- 0 97 -- -- 0 96 -- -- 0 96 -- -- 0 97 -- --
2018-11-15 -- 0 97 -- -- 0 96 -- -- 0 97 -- -- 0 97 -- --
2018-11-16 -- 0 98 -- -- 0 96 -- -- 0 97 -- -- 0 97 -- --
2018-11-17 -- 0 97 -- -- 0 95 -- -- 0 96 -- -- 0 97 -- --
2018-11-18 -- 0 97 -- -- 0 95 -- -- 0 96 -- -- 0 97 -- --
2018-11-19 -- 0 97 -- -- 0 95 -- -- 0 96 -- -- 0 97 -- --
2018-11-20 -- 0 98 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-11-21 -- 0 99 -- -- 0 96 -- -- 0 97 -- -- 0 97 -- --
2018-11-22 -- 0 100 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-11-23 -- 0 100 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-11-24 -- 0 100 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-11-25 -- 0 98 -- -- 0 94 -- -- 0 95 -- -- 0 96 -- --
2018-11-26 -- 0 99 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-11-27 -- 0 100 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-11-28 -- 0 100 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-11-29 -- 0 101 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-11-30 -- 0 101 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-12-01 -- 0 100 -- -- 0 97 -- -- 0 97 -- -- 0 98 -- --
2018-12-02 -- 0 99 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- --
2018-12-03 -- 0 98 -- -- 0 95 -- -- 0 96 -- -- 0 97 -- --
2018-12-04 -- 0 97 -- -- 0 95 -- -- 0 95 -- -- 0 96 -- --
2018-12-05 -- 0 98 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-12-06 -- 0 98 -- -- 0 96 -- -- 0 96 -- -- 0 96 -- --
2018-12-07 -- 0 98 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-12-08 -- 0 97 -- -- 0 95 -- -- 0 95 -- -- 0 95 -- --
2018-12-09 -- 0 97 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-12-10 -- 0 97 -- -- 0 95 -- -- 0 96 -- -- 0 96 -- --
2018-12-11 -- 0 98 -- -- 0 97 -- -- 0 98 -- -- 0 97 -- --
2018-12-12 -- 0 98 -- -- 0 97 -- -- 0 98 -- -- 0 97 -- --
2018-12-13 -- 0 98 -- -- 0 97 -- -- 0 97 -- -- 0 96 -- --
2018-12-14 -- 0 99 -- -- 0 98 -- -- 0 99 -- -- 0 97 -- --
2018-12-15 -- 0 99 -- -- 0 98 -- -- 0 98 -- -- 0 97 -- --
2018-12-16 -- 0 99 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- --
2018-12-17 -- 0 100 -- -- 0 97 -- -- 0 98 -- -- 0 98 -- --
2018-12-18 -- 0 101 -- -- 0 98 -- -- 0 99 -- -- 0 99 -- --
2018-12-19 -- 0 100 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- --
2018-12-20 -- 0 100 -- -- 0 98 -- -- 0 99 -- -- 0 100 -- --
2018-12-21 -- 0 100 -- -- 0 98 -- -- 0 99 -- -- 0 100 -- --
2018-12-22 -- 0 99 -- -- 0 97 -- -- 0 98 -- -- 0 98 -- --
2018-12-23 -- 0 100 -- -- 0 97 -- -- 0 98 -- -- 0 98 -- --
2018-12-24 -- 0 100 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- --
2018-12-25 -- 0 99 -- -- 0 97 -- -- 0 98 -- -- 0 98 -- --
In [15]:
pd.DataFrame().style.set_table_styles(table_styles).set_uuid('header-fixed')
Out[15]:
In [16]:
tz = 'US/Pacific'
now = datetime.now(timezone(tz))
print('{}{}{}{}'.format('Executed: ', str(now), ' ', tz))
Executed: 2018-12-26 11:33:36.058367-08:00 US/Pacific