Columbia 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
import pandas
from collections import OrderedDict
from datetime import datetime, timedelta
from get_avgs import oregon_method, washington_method, combine
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 = [
    ('McNary', 'u/s FB', 'MCNA', '% sat'),
    ('McNary', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('McNary', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('McNary', 'TW', 'MCPW', '% sat' ),
    ('McNary', 'd/s FB', 'JDY', '% sat'),
    
    ('John Day', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('John Day', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('John Day', 'TW', 'JHAW', '% sat' ),
    ('John Day', 'd/s FB', 'TDA', '% sat'),
    
    ('The Dalles', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('The Dalles', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('The Dalles', 'TW', 'TDDO', '% sat' ),
    ('The Dalles', 'd/s FB', ' BON ', '% sat'),
    
    ('Bonneville', 'Spill Cap', 'Starting → Change', 'kcfs'),
    ('Bonneville', 'Actual Spill', 'Daily Average', 'kcfs'),
    ('Bonneville', 'TW', 'CCIW', '% sat' ),
    
]

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

paths = [
        'MCNA.%-Saturation-TDG.Inst.1Hour.0.GOES-COMPUTED-REV',
        'MCN.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'MCN.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'MCPW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-Combined-REV',
        'JDY.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
        
        'JDA.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'JDA.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'JHAW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-Combined-REV',
        'TDA.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
         
        'TDA.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'TDA.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'TDDO.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-Combined-REV',
        'BON.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-WAmethod-REV',
    
        'BON.Flow-Spill-Cap-Fish.Inst.~1Day.0.CENWDP-COMPUTED-PUB', 
        'BON.Flow-Spill.Ave.1Hour.1Hour.CBT-REV',
        'CCIW.%-Saturation-TDG.Ave.~1Day.12Hours.CENWDP-COMPUTED-Combined-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)
    try:
        meta.update(data.__dict__['metadata'])
        data = data.groupby(pd.Grouper(freq = 'D')).mean()
        df[column] = data.iloc[:,0]
    except: continue
df = df.round(0)
In [4]:
"""
Questionable data is defined as values that are missing 1/3 or more data for calculation

"""


column_dict = {
                
                'MCPW': ('McNary', 'TW'),
                'JDY':  ('McNary', 'd/s FB'),
                'JHAW': ('John Day','TW'),
                'TDA':  ('John Day','d/s FB'),
                'TDDO': ('The Dalles','TW'),
                'BON':  ('The Dalles','d/s FB'),
                'CCIW': ('Bonneville', 'TW'),
                
              }

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)
qual_start = datetime(*start_date) - timedelta(days = 10)
qual_start = (qual_start.year, qual_start.month, qual_start.day)
qual_end = (now.year, now.month, now.day)
for key, value in column_dict.items():
    p = key+path
    data = get_cwms(p, start_date=qual_start, end_date=qual_end, public = True)
    try:
        series = data.iloc[:,0]
        wash = series.copy().pipe(washington_method)
        oregon = series.copy().pipe(oregon_method)
        combined = combine(oregon, wash, qual_start, end_date)
        combined.index = [x.replace(hour = 0, minute = 0, second = 0) for x in combined.index]
        combined.index.name = 'date'
        combined = combined.loc[df.index]
        quality = combined['quality'] != True
        questionable[value] = quality 
    except:continue
        
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([
            ('McNary',['MCN']),
            ('John Day',['JDA']),
            ('The Dalles', ['TDA']),
            ('Bonneville', ['BON'])
          ])

column_dict = {
    'MCN': 'McNary',
    'JDA': 'John Day',
    'TDA': 'The Dalles',
    'BON': 'Bonneville'
    
}

# 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')

try:
    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')
    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)
    
except: inv_spill_bool = ''
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([
            ('McNary', 61.2),
            ('John Day', 61.2),
            ('The Dalles', 61.2),
            ('Bonneville', 40.8)
          ])

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')
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
"""

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']]]
    try:
        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)
    except:
        continue
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']]
bon = tw[['Bonneville']] > 120
tw = tw[['John Day', 'McNary', 'The Dalles']]
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[('Bonneville', 'TW', 'CCIW', '% sat' )] =  bon.iloc[:,0]

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', ''))
try:
    df_string[inv_spill_bool] = df_string[inv_spill_bool] + '*'
except:
    pass
df_string = df_string.replace('nan', '--')



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 McNary John Day The Dalles Bonneville
u/s FB 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
MCNA Starting → Change Daily Average MCPW JDY Starting → Change Daily Average JHAW TDA Starting → Change Daily Average TDDO BON Starting → Change Daily Average CCIW
units % sat kcfs kcfs % sat % sat kcfs kcfs % sat % sat kcfs kcfs % sat % sat kcfs kcfs % sat
2018-04-01 105 190 0 104 104 140 0 103 104 125 15 104 105 128 1 112
2018-04-02 104 190 20 105 104 140 0 103 103 125 15 104 104 128 1 112
2018-04-03 103 190 32 107 103 140 0 103 103 125 40 107 104 128 1 111
2018-04-04 103 190 58 108 103 140 0 103 103 125 31 106 106 128 1 110
2018-04-05 105 190 61 112 104 140 0 104 104 125 43 107 107 128 1 111
2018-04-06 106 190 60 112 105 140 0 105 105 125 51 108 110 128 1 113
2018-04-07 107 190 60 113 106 140 0 106 105 125 58 108 110 128 20 113
2018-04-08 107 190 73 113 106 140 12 110 105 125 66 108 109 128 32 113
2018-04-09 106 190 90 114 106 140 14 111 106 125 72 110 108 128 40 114
2018-04-10 108 190→195 184 118 108 140→135 138 120 114 125 123 118 111 128→126 127 120
2018-04-11 111 195 195 120 108 135→140 137 119 116 125→119 122 120 116 126→121 125 121
2018-04-12 109 195 195 120 108 140 140 118 115 119→113 117 120 118 121 120 120
2018-04-13 106 195 195 119 108 140→143 141 119 114 113 113 118 116 121→123 121 120
2018-04-14 107 195→198 196 120 111 143→146 144 119 116 113→108 111 119 118 123 124 120
2018-04-15 110 198 198 120 112 146→143 145 119 118 108→100 105 120 120 123 124 121
2018-04-16 110 198 198 120 112 143 143 119 118 100 99 119 120 123→121 123 121
2018-04-17 107 198 198 120 112 143 143 119 114 100 100 117 115 121 121 119
2018-04-18 105 198 198 120 113 143 143 119 116 100 109 119 117 121 121 120
2018-04-19 108 198 198 120 112 143→140 142 119 116 100 100 119 118 121 120 120
2018-04-20 112 198 198 120 111 140 140 119 116 100→90 97 117 118 121 120 120
2018-04-21 113 198 198 120 113 140 140 118 116 90 90 117 117 121 120 120
2018-04-22 111 198 198 120 115 140→135 138 118 117 90 90 118 116 121 120 119
2018-04-23 112 198 198 120 116 135→130 133 118 117 90→85 88 118 116 121 120 120
2018-04-24 113 198→193 196 120 116 130→120 127 118 118 85→75 82 118 117 121 120 120
2018-04-25 114 193→175 187 120 118 120→110 117 118 118 75→65 74 118 118 121 119 120
2018-04-26 115 175→165 172 120 121 110→100 107 118 118 65 69 117 118 121 122 121
2018-04-27 116 165→145 158 119 121 100→90 97 118 119 65 64 118 118 121 121 121
2018-04-28 113 145 145 119 120 90 95 117 115 65 69 115 114 121 120 120
2018-04-29 110 145 172 118 117 90 128 119 114 65→90 122 120 113 121 148 122
2018-04-30 112 145 175 120 113 90 127 119 113 90 134 119 116 121 168 123
2018-05-01 113 145 163 119 109 90 146 120 112 90 137 118 116 121 165 123
2018-05-02 114 145 173 119 111 90 147 120 115 90 158 123 118 121 161 123
2018-05-03 115 145 175 119 113 90 135 119 115 90 144 123 122 121 155 124
2018-05-04 116 145 150 119 114 90 113 118 115 90 116 118 121 121 130 124
2018-05-05 116 145 197 120 117 90 155 121 118 90 130 120 119 121 149 123
2018-05-06 116 145 205 121 117 90 160 121 118 90 146 122 120 121 162 123
2018-05-07 117 145 242 122 116 90 182 124 119 90 198 123 120 121 191 123
2018-05-08 117 145 259 124 119 90 211 127 121 90 226 124 124 121 203 124
2018-05-09 117 145 258 124 119 90 220 127 122 90 215 124 124 121 203 124
2018-05-10 116 145 269 124 119 90 220 126 120 90 231 122 122 121 214 124
2018-05-11 116 145 310 127 117 90 247 128 121 90 255 122 121 121 229 126
2018-05-12 118 145 345 130 118 90 270 132 126 90 297 126 124 121 257 128
2018-05-13 121 145 340 131 125 90 263 132 128 90 302 127 128 121 271 128
2018-05-14 122 145 363 132 129 90 258 132 128 90 292 127 128 121 269 --
2018-05-15 125 145 370 134 131 90 266 132 130 90 294 127 128 121 286 --
2018-05-16 124 145 362 134 130 90 275 133 129 90 296 127 124 121 311 --
2018-05-17 122 145 335 133 128 90 285 133 125 90 281 124 121 121 295 --
2018-05-18 122 145 335 130 122 90 286 133 128 90 270 125 123 121 298 --
2018-05-19 123 145 335 130 125 90 286 133 129 90 270 126 127 121 295 --
2018-05-20 123 145 335 130 127 90 285 134 129 90 270 126 126 121 286 --
2018-05-21 122 145 335 130 126 90 284 134 129 90 270 125 124 121 290 --
2018-05-22 123 145 335 131 127 90 280 133 131 90 264 126 128 121 293 --
2018-05-23 124 145 335 133 129 90 270 132 131 90 291 127 129 121 283 --
2018-05-24 124 145 342 132 129 90 270 132 129 90 310 126 126 121 290 --
2018-05-25 123 145 328 131 127 90 256 132 127 90 301 126 125 121 270 --
2018-05-26 120 145 321 131 123 90 228 129 123 90 293 123 123 121 256 --
2018-05-27 119 145 324 132 119 90 221 129 122 90 285 122 120 121 258 --
2018-05-28 120 145 295 132 119 90 200 127 122 90 278 122 120 121 258 --
2018-05-29 120 145 298 128 119 90 211 127 117 90 262 120 119 121 248 --
2018-05-30 119 145 295 130 119 90 218 128 123 90 244 123 120 121 242 --
2018-05-31 119 145 233 130 119 90 159 126 123 90 214 123 121 121 213 --
2018-06-01 115 145 230 123 117 90 145 121 115 90 196 119 119 121 179 --
2018-06-02 115 145 239 123 117 90 156 122 119 90 205 121 123 121 208 --
2018-06-03 120 145 207 122 117 90 114 120 119 90 114 120 123 121 160 --
2018-06-04 118 145 191 121 116 90 105 119 114 90 120 114 120 121 160 --
2018-06-05 117 145 190 120 117 90 115 119 116 90 109 117 115 121 139 --
2018-06-06 117 145 193 121 117 90 127 119 117 90 121 119 117 121 142 --
2018-06-07 117 145 167 120 116 90 91 118 117 90 105 119 117 121 124 --
2018-06-08 116 145 145 118 115 90→95 92 117 113 90→105 95 116 114 121 120 --
2018-06-09 114 145 148 118 115 95 95 117 114 105 105 117 112 121 120 --
2018-06-10 110 145 145 118 112 95→100 97 117 111 105 105 116 113 121 120 --
2018-06-11 109 145→155 148 118 110 100→110 103 118 111 105 105 116 113 121 121 --
2018-06-12 112 155→160 157 118 109 110→125 115 118 113 105 105 116 115 121 121 --
2018-06-13 114 160→170 163 118 109 125→130 127 118 113 105 105 118 116 121 121 --
2018-06-14 113 170→190 173 119 109 130→140 133 117 113 105 105 119 114 121 121 --
2018-06-15 112 190 180 120 111 140 140 118 115 105 105 121 114 121 120 --
2018-06-16 112 190 112 119 111 140 86 117 116 105 81 119 115 121 96 --
2018-06-17 112 190 105 115 110 140 83 115 113 105 78 117 117 121 95 --
2018-06-18 111 190 111 118 110 140 83 115 113 105 79 117 117 121 91 --
2018-06-19 111 190 112 119 113 140 68 115 113 105 83 117 115 121 96 --
2018-06-20 112 190 116 119 115 140 70 115 114 105 83 118 117 121 100 --
2018-06-21 113 190 117 119 115 140 90 116 114 105 83 118 117 121 95 --
2018-06-22 112 190 109 119 112 140 79 116 110 105 77 115 112 121 90 --
2018-06-23 109 190 120 120 110 140 70 114 109 105 86 115 109 121 96 --
2018-06-24 111 190 125 121 110 140 80 115 112 105 93 117 113 121 101 --
2018-06-25 110 190 130 120 110 140 98 116 112 105 90 117 113 121 95 --
2018-06-26 109 190 128 118 108 140 101 118 111 105 97 116 111 121 91 --
2018-06-27 111 190 165 120 110 140 110 118 111 105 98 116 112 121 96 --
2018-06-28 112 190 134 119 110 140 80 117 110 105 94 115 111 121 101 --
2018-06-29 111 190 124 118 108 140 101 117 110 105 95 115 110 121 96 --
2018-06-30 112 190 122 118 107 140 88 116 110 105 86 115 110 121 90 --
2018-07-01 111 190 103 117 107 140 60 115 109 105 75 115 110 121 95 --
2018-07-02 110 190 95 117 107 140 56 114 107 105 64 113 109 121 100 --
2018-07-03 109 190 97 117 106 140 79 116 108 105 73 114 109 121 95 --
2018-07-04 110 190 86 116 107 140 62 115 111 105 59 116 110 121 90 --
2018-07-05 108 190 85 116 107 140 48 114 111 105 58 116 113 121 91 --
2018-07-06 109 190 91 117 106 140 53 114 110 105 63 115 112 121 100 --
2018-07-07 108 190 84 116 106 140 64 114 108 105 58 114 111 121 95 --
2018-07-08 111 190 88 116 106 140 66 114 110 105 62 115 111 121 90 --
2018-07-09 111 190 84 116 107 140 47 114 110 105 58 115 111 121 94 --
2018-07-10 108 190 93 116 107 140 55 114 108 105 64 113 109 121 100 --
2018-07-11 109 190 100 116 107 140 80 115 110 105 74 115 111 121 95 117
2018-07-12 109 190 103 116 108 140 76 116 112 105 71 116 114 121 90 117
2018-07-13 110 190 90 116 108 140 49 116 112 105 60 116 115 121 95 117
2018-07-14 110 190 90 116 108 140 57 115 111 105 68 115 114 121 100 117
2018-07-15 110 190 92 116 109 140 67 114 111 105 59 116 113 121 95 117
2018-07-16 110 190 100 117 111 140 77 117 112 105 73 117 114 121 90 117
2018-07-17 110 190 93 117 111 140 53 117 112 105 65 117 113 121 94 117
2018-07-18 109 190 91 117 111 140 53 115 110 105 61 116 111 121 100 117
2018-07-19 108 190 92 116 109 140 68 115 107 105 63 113 108 121→130 96 116
2018-07-20 106 190 87 116 107 140 61 114 107 105 57 112 106 130 90 116
2018-07-21 107 190 87 116 106 140 54 115 107 105 67 113 105 130 95 116
2018-07-22 106 190 81 115 105 140 42 114 108 105 51 114 108 130 99 117
2018-07-23 107 190 86 117 105 140 51 114 109 105 65 115 112 130 94 117
2018-07-24 108 190 100 117 105 140 58 114 109 105 71 115 112 130 90 117
2018-07-25 109 190 84 116 106 140 46 114 108 105 56 114 112 130 95 116
2018-07-26 110 190 87 116 107 140 51 115 108 105 60 114 111 130 100 117
2018-07-27 111 190 92 117 108 140 51 114 108 105 64 114 111 130 96 117
2018-07-28 111 190 86 117 109 140 48 115 108 105 58 114 110 130 91 117
2018-07-29 110 190 87 116 109 140 51 115 110 105 62 115 110 130 94 116
2018-07-30 110 190 93 117 110 140 54 115 111 105 67 116 112 130 100 117
2018-07-31 110 190 90 117 110 140 51 114 111 105 63 116 112 130 96 117
2018-08-01 110 190 76 116 109 140 42 114 108 105 50 113 109 130 89 117
2018-08-02 109 190 75 115 109 140 40 114 107 105 49 112 107 130 87 115
2018-08-03 106 190 61 114 107 140 34 113 106 105 43 111 105 130 80 116
2018-08-04 106 190 69 114 105 140 39 113 106 105 49 112 105 130 85 116
2018-08-05 106 190 68 114 105 140 37 113 109 105 46 113 107 130 90 117
2018-08-06 106 190 78 115 105 140 47 113 109 105 60 115 110 130 96 116
2018-08-07 107 190 80 115 106 140 44 113 109 105 51 114 111 130 101 117
2018-08-08 109 190 74 115 107 140 43 113 109 105 54 115 112 130 95 117
2018-08-09 109 190 82 115 107 140 44 115 109 105 53 114 112 130 91 117
2018-08-10 110 190 84 116 107 140 47 115 108 105 59 114 111 130 97 116
2018-08-11 108 190 72 115 107 140 41 114 106 105 50 112 108 130 101 117
2018-08-12 106 190 61 113 106 140 36 114 106 105 43 112 106 130 83 117
2018-08-13 106 190 67 114 108 140 37 114 110 105 47 114 106 130 81 115
2018-08-14 106 190 79 115 108 140 43 115 110 105 53 115 109 130 94 116
2018-08-15 107 190 79 116 107 140 46 114 110 105 57 115 112 130 99 118
2018-08-16 107 190 69 115 107 140 41 114 111 105 49 114 112 130 96 117
2018-08-17 107 190 61 114 106 140 35 114 106 105 43 113 109 130 78 117
2018-08-18 107 190 59 114 104 140 32 112 105 105 40 111 105 130 76 114
2018-08-19 107 190 61 115 106 140 32 113 109 105 38 112 106 130 70 114
2018-08-20 106 190 68 114 107 140 39 114 109 105 49 114 107 130 80 117
2018-08-21 105 190 73 114 107 140 43 114 109 105 53 114 107 130 92 117
2018-08-22 106 190 84 116 107 140 46 114 110 105 57 115 111 130 98 117
2018-08-23 105 190 77 115 107 140 41 114 110 105 49 114 111 130 97 117
2018-08-24 104 190 64 114 105 140 37 113 106 105 46 112 108 130 95 117
2018-08-25 103 190 84 115 103 140 44 113 104 105 55 111 104 130 93 117
2018-08-26 102 190 75 115 103 140 46 114 105 105 57 111 104 130 96 116
2018-08-27 101 190 64 114 102 140 38 113 105 105 47 111 105 130 88 117
2018-08-28 101 190 69 114 102 140 38 112 108 105 46 111 107 130 83 116
2018-08-29 103 190 80 114 103 140 43 114 109 105 52 114 110 130 90 117
2018-08-30 103 190 67 114 102 140 39 114 108 105 48 113 110 130 95 118
2018-08-31 102 190 57 114 102 140 34 115 105 105 44 111 107 130 86 118
2018-09-01 103 190→-- 0 113 102 140→-- 1 112 105 105→-- 0 110 106 130→-- 2 116
2018-09-02 104 -- 0 104 103 -- 1 103 104 -- 0 104 -- -- 1 117
2018-09-03 104 -- 0 104 103 -- 1 103 103 -- 0 103 104 -- 1 116
2018-09-04 104 -- 0 105 105 -- 1 104 102 -- 0 103 104 -- 1 119
2018-09-05 104 -- 0 104 105 -- 1 105 103 -- 0 103 104 -- 1 120
2018-09-06 -- -- 0 103 105 -- 1 105 104 -- 0 104 103 -- 1 119
2018-09-07 -- -- 0 103 105 -- 1 105 105 -- 0 104 103 -- 1 118
2018-09-08 -- -- 0 103 105 -- 1 104 105 -- 0 104 103 -- 1 118
2018-09-09 -- -- 0 103 105 -- 1 105 103 -- 0 104 103 -- 1 117
2018-09-10 -- -- 0 103 105 -- 1 105 103 -- 0 103 103 -- 1 114
2018-09-11 -- -- 0 102 104 -- 2 104 103 -- 0 103 103 -- 1 118
2018-09-12 -- -- 0 102 103 -- 1 103 102 -- 0 103 102 -- 1 122
2018-09-13 -- -- 0 101 103 -- 1 103 102 -- 0 103 102 -- 1 119
2018-09-14 -- -- 0 101 101 -- 1 102 102 -- 0 103 102 -- 1 117
2018-09-15 -- -- 0 101 101 -- 1 101 102 -- 0 103 102 -- 1 120
2018-09-16 -- -- 0 100 101 -- 1 101 102 -- 0 102 102 -- 1 119
2018-09-17 -- -- 0 100 100 -- 1 100 100 -- 0 101 102 -- 1 117
2018-09-18 -- -- 0 101 100 -- 2 101 101 -- 0 101 102 -- 1 118
2018-09-19 -- -- 0 100 100 -- 1 101 101 -- 0 102 102 -- 1 115
2018-09-20 -- -- 0 100 99 -- 1 101 100 -- 0 102 102 -- 1 115
2018-09-21 -- -- 0 100 100 -- 1 101 100 -- 0 101 101 -- 1 118
2018-09-22 -- -- 0 100 100 -- 1 101 100 -- 0 101 101 -- 1 113
2018-09-23 -- -- 0 100 99 -- 1 101 100 -- 0 101 100 -- 1 115
2018-09-24 -- -- 0 99 99 -- 1 100 99 -- 0 101 100 -- 4 121
2018-09-25 -- -- 0 100 99 -- 1 100 99 -- 0 100 101 -- 1 118
2018-09-26 -- -- 0 100 99 -- 1 100 99 -- 0 100 101 -- 1 120
2018-09-27 -- -- 0 100 -- -- 1 102 -- -- 0 101 102 -- 1 120
2018-09-28 -- -- 0 101 -- -- 1 102 -- -- 0 102 -- -- 1 --
2018-09-29 -- -- 0 101 -- -- 1 103 -- -- 0 102 -- -- 1 --
2018-09-30 -- -- 0 100 -- -- 1 103 -- -- 0 102 -- -- 1 --
2018-10-01 -- -- 0 100 -- -- 1 102 -- -- 0 102 -- -- 1 --
2018-10-02 -- -- 0 100 -- -- 1 101 -- -- 0 102 -- -- 1 --
2018-10-03 -- -- 0 100 -- -- 1 101 -- -- 0 101 -- -- 1 --
2018-10-04 -- -- 0 99 -- -- 1 101 -- -- 0 100 -- -- 1 --
2018-10-05 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-06 -- -- 0 98 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-10-07 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-08 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-09 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-10 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-11 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-12 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-13 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-14 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-10-15 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-10-16 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-10-17 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-18 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-19 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-20 -- -- 0 99 -- -- 1 100 -- -- 0 101 -- -- 1 --
2018-10-21 -- -- 0 100 -- -- 1 100 -- -- 0 101 -- -- 1 --
2018-10-22 -- -- 0 100 -- -- 1 100 -- -- 0 101 -- -- 1 --
2018-10-23 -- -- 0 100 -- -- 1 100 -- -- 0 101 -- -- 1 --
2018-10-24 -- -- 0 100 -- -- 1 100 -- -- 0 99 -- -- 0 --
2018-10-25 -- -- 0 99 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-10-26 -- -- 0 99 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-10-27 -- -- 0 100 -- -- 1 101 -- -- 0 100 -- -- 1 --
2018-10-28 -- -- 0 100 -- -- 1 101 -- -- 0 100 -- -- 1 --
2018-10-29 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-10-30 -- -- 0 98 -- -- 1 101 -- -- 0 100 -- -- 1 --
2018-10-31 -- -- 0 98 -- -- 1 101 -- -- 0 101 -- -- 1 --
2018-11-01 -- -- 0 98 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-11-02 -- -- 0 99 -- -- 1 100 -- -- 0 101 -- -- 1 --
2018-11-03 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-11-04 -- -- 0 100 -- -- 1 101 -- -- 0 100 -- -- 1 --
2018-11-05 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-11-06 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-11-07 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-08 -- -- 0 97 -- -- 0 99 -- -- 0 98 -- -- 1 --
2018-11-09 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-10 -- -- 0 98 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-11 -- -- 0 97 -- -- 1 99 -- -- 0 98 -- -- 1 --
2018-11-12 -- -- 0 97 -- -- 1 97 -- -- 0 98 -- -- 1 --
2018-11-13 -- -- 0 97 -- -- 1 97 -- -- 0 97 -- -- 1 --
2018-11-14 -- -- 0 98 -- -- 1 98 -- -- 0 98 -- -- 1 --
2018-11-15 -- -- 0 99 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-16 -- -- 0 99 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-17 -- -- 0 99 -- -- 1 99 -- -- 0 98 -- -- 1 --
2018-11-18 -- -- 0 98 -- -- 1 98 -- -- 0 98 -- -- 1 --
2018-11-19 -- -- 0 97 -- -- 1 98 -- -- 0 98 -- -- 1 --
2018-11-20 -- -- 0 98 -- -- 1 98 -- -- 0 98 -- -- 1 --
2018-11-21 -- -- 0 98 -- -- 1 99 -- -- 0 98 -- -- 1 --
2018-11-22 -- -- 0 100 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-11-23 -- -- 0 100 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-11-24 -- -- 0 100 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-25 -- -- 0 99 -- -- 1 99 -- -- 0 98 -- -- 1 --
2018-11-26 -- -- 0 99 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-27 -- -- 0 100 -- -- 1 99 -- -- 0 99 -- -- 1 --
2018-11-28 -- -- 0 99 -- -- 1 100 -- -- 0 100 -- -- 1 --
2018-11-29 -- -- 0 99 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-11-30 -- -- 0 99 -- -- 1 100 -- -- 0 99 -- -- 1 --
2018-12-01 -- -- 0 98 -- -- 0 100 -- -- 0 99 -- -- 1 --
2018-12-02 -- -- 0 98 -- -- 0 98 -- -- 0 98 -- -- 1 --
2018-12-03 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- -- 1 --
2018-12-04 -- -- 0 95 -- -- 0 97 -- -- 0 97 -- -- 1 --
2018-12-05 -- -- 0 96 -- -- 0 98 -- -- 0 98 -- -- 1 --
2018-12-06 -- -- 0 96 -- -- 0 97 -- -- 0 98 -- -- 1 --
2018-12-07 -- -- 0 95 -- -- 0 97 -- -- 0 98 -- -- 1 --
2018-12-08 -- -- 0 96 -- -- 0 96 -- -- 0 97 -- -- 1 --
2018-12-09 -- -- 0 95 -- -- 0 96 -- -- 0 97 -- -- 1 --
2018-12-10 -- -- 0 96 -- -- 0 96 -- -- 0 97 -- -- 1 --
2018-12-11 -- -- 0 98 -- -- 0 97 -- -- 0 98 -- -- 1 --
2018-12-12 -- -- 0 98 -- -- 0 97 -- -- 0 98 -- -- 1 --
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-13 07:33:05.961457-08:00 US/Pacific