In [1]:
%matplotlib inline
%config InlineBackend.figure_format='retina'
from datacharm import *
import matplotlib
import matplotlib.dates as mpd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
import matplotlib.patches as mp
import datetime as dt
from io import BytesIO
import locale

from enerpi.database import extract_log_file
from enerpi.base import timeit
from enerpi.database import init_catalog


# Pandas to html!
INIT_LOG_MARK = "Init ENERPI logging & broadcasting..."


def _extract_log_file(log_file, extract_temps=True, verbose=True):
    rg_log_msg = re.compile('(?P<tipo>INFO|WARNING|DEBUG|ERROR) \[(?P<func>.+?)\] '
                            '- (?P<ts>\d{1,2}/\d\d/\d\d\d\d \d\d:\d\d:\d\d): (?P<msg>.*?)\n', re.DOTALL)
    with open(log_file, 'r') as log_f:
        df_log = pd.DataFrame(rg_log_msg.findall(log_f.read()),
                              columns=['tipo', 'func', 'ts', 'msg'])
    df_log.drop('func', axis=1, inplace=True)
    df_log['tipo'] = df_log['tipo'].astype('category')
    df_log['ts'] = df_log['ts'].apply(lambda x: dt.datetime.strptime(x, '%d/%m/%Y %H:%M:%S'))
    df_log.loc[df_log.msg.str.startswith('Tªs --> '), 'temp'] = True
    df_log.loc[df_log.msg.str.startswith('SENDED: '), 'debug_send'] = True
    b_warn = df_log.tipo == 'WARNING'
    df_log.loc[b_warn, 'no_red'] = df_log[b_warn].msg.str.startswith('OSError: [Errno 101] La red es inaccesible')
    df_log['exec'] = df_log['msg'].str.contains(INIT_LOG_MARK).cumsum().astype(int)
    df_log = df_log.set_index('ts')
    if extract_temps:
        rg_temps = 'Tªs --> (?P<CPU>\d{1,2}\.\d) / (?P<GPU>\d{1,2}\.\d) ºC'
        df_log = df_log.join(df_log[df_log['temp'].notnull()].msg.str.extract(rg_temps, expand=True).astype(float))
    if verbose:
        clasific = df_log.groupby(['exec', 'tipo']).count().dropna(how='all').astype(int)
        print_ok(clasific)
        conteo_tipos = df_log.groupby('tipo').count()
        if 'ERROR' in conteo_tipos.index:
            print_err(df_log[df_log.tipo == 'ERROR'].dropna(how='all', axis=1))
        if 'INFO' in conteo_tipos.index:
            print_info(df_log[df_log.tipo == 'INFO'].dropna(how='all', axis=1))
    return df_log



#log = extract_log_file('/Users/uge/Dropbox/PYTHON/PYPROJECTS/enerpi/enerpi/DATA/enerpi.log', verbose=False)
#ejecuciones = list(sorted(set(log['exec'])))
#print_red(ejecuciones)
#print_info(log.count())

#last = log[log['exec'] == ejecuciones[-1]]
#penult = log[log['exec'] == ejecuciones[-2]]
#last


 ==> Librerías, clases y métodos cargados:
 +++ "dt"                           +++ "os" 
 +++ "json" v:2.0.9                 +++ "pd" (pandas) v:0.18.1
 +++ "locale"                       +++ "plt" 
 +++ "math"                         +++ "re" v:2.2.1
 +++ "np" (numpy) v:1.11.1          +++ "sns" (seaborn) v:0.7.0
 +++ "sys" 
 ** "Colormap", "Line2D", "Normalize", "OrderedDict", "PathPatch", "namedtuple", "time"
 ==> Pretty printing funcs:
print_blue, print_bold, print_boldu, print_cyan, print_err, print_green, print_grey, print_greyb, print_info, print_infob, print_magenta, print_ok, print_red, print_redb, print_secc, print_tree_dict, print_warn, print_white, print_yellow, print_yellowb, printcolor
If you are in a jupyter notebook, insert this:
%matplotlib inline
%config InlineBackend.figure_format='retina'
If you are working with GEO data, insert this:
import geopandas as gpd
import shapely.geometry as sg
import cartopy.crs as ccrs

In [3]:
catalog = init_catalog(base_path='/Users/uge/ENERPIDATA/')
catalog


get_index TOOK: 0.014 s
archive_periodic TOOK: 0.001 s
Out[3]:
<HDFCatalog[DATA] ->/Users/uge/ENERPIDATA; From:agosto/2016; last_upd=19/08/16 13:43:45>
	INDEX [data_catalog.csv]:
                                                  cols is_cat is_raw     key  n_rows                                    st                     ts_fin                     ts_ini  \
0   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      14  CURRENT_MONTH/DATA_2016_08_DAY_12.h5 2016-08-12 23:00:00.000000 2016-08-12 10:00:00.000000   
2   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      24  CURRENT_MONTH/DATA_2016_08_DAY_13.h5 2016-08-13 23:00:00.000000 2016-08-13 00:00:00.000000   
4   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      24  CURRENT_MONTH/DATA_2016_08_DAY_14.h5 2016-08-14 23:00:00.000000 2016-08-14 00:00:00.000000   
6   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      24  CURRENT_MONTH/DATA_2016_08_DAY_15.h5 2016-08-15 23:00:00.000000 2016-08-15 00:00:00.000000   
8   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      23  CURRENT_MONTH/DATA_2016_08_DAY_16.h5 2016-08-16 22:00:00.000000 2016-08-16 00:00:00.000000   
10  [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]  False  False  /hours      24  CURRENT_MONTH/DATA_2016_08_DAY_17.h5 2016-08-17 23:00:00.000000 2016-08-17 00:00:00.000000   
1      [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   47122  CURRENT_MONTH/DATA_2016_08_DAY_12.h5 2016-08-12 23:59:59.778947 2016-08-12 10:46:25.990460   
3      [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   81159  CURRENT_MONTH/DATA_2016_08_DAY_13.h5 2016-08-13 23:59:58.992496 2016-08-13 00:00:00.784081   
5      [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   85608  CURRENT_MONTH/DATA_2016_08_DAY_14.h5 2016-08-14 23:59:59.474740 2016-08-14 00:00:00.002919   
7      [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   85541  CURRENT_MONTH/DATA_2016_08_DAY_15.h5 2016-08-15 23:59:59.311180 2016-08-15 00:00:00.485372   
9      [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   77470  CURRENT_MONTH/DATA_2016_08_DAY_16.h5 2016-08-16 22:02:20.349005 2016-08-16 00:00:00.321705   
11     [power, noise, ref, ldr, high_delta, execution]  False  False    /rms   79375  CURRENT_MONTH/DATA_2016_08_DAY_17.h5 2016-08-17 23:59:59.372437 2016-08-17 00:21:13.076529   
0   [kWh, t_ref, n_jump, n_exec, p_max, p_mean, p_min]   True  False  /hours      18  CURRENT_MONTH/DATA_2016_08_DAY_18.h5 2016-08-18 17:00:00.000000 2016-08-18 00:00:00.000000   
1      [power, noise, ref, ldr, high_delta, execution]   True   True    /rms   59165  CURRENT_MONTH/DATA_2016_08_DAY_18.h5 2016-08-18 17:03:32.375912 2016-08-18 00:00:00.376259   

                 ts_st  
0  2016-08-13 22:16:36  
2  2016-08-16 19:14:22  
4  2016-08-16 19:14:20  
6  2016-08-16 19:14:24  
8  2016-08-17 01:21:46  
10 2016-08-18 00:58:31  
1  2016-08-13 22:16:36  
3  2016-08-16 19:14:22  
5  2016-08-16 19:14:20  
7  2016-08-16 19:14:24  
9  2016-08-17 01:21:46  
11 2016-08-18 00:58:31  
0  2016-08-19 13:06:24  
1  2016-08-19 13:06:24  

In [28]:
# TILES optimization


IMG_BASEPATH = '/Users/uge/ENERPIDATA/PLOTS'
DEFAULT_IMG_MASK = 'enerpi_power_consumption_ldr_{:%Y%m%d_%H%M}_{:%Y%m%d_%H%M}.png'


def _gen_tableau20():
    # # These are the "Tableau 20" colors as RGB.
    tableau = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120),
               (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150),
               (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148),
               (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199),
               (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)]
    # Scale the RGB values to the [0, 1] range, which is the format matplotlib accepts.
    for i in range(len(tableau)):
        r, g, b = tableau[i]
        tableau[i] = (r / 255., g / 255., b / 255.)
    return tableau


# semaforo_4 = [sns.palettes.crayons[k] for k in ['Green', 'Sea Green', 'Mango Tango', 'Razzmatazz']]
# These are the "Tableau 20" colors as RGB.
tableau20 = _gen_tableau20()

lang, codec = locale.getlocale()
use_locale = '{}.{}'.format(lang, codec)
locale.setlocale(locale.LC_ALL, use_locale)

# sns.set_style('whitegrid')

REGEXPR_SVG_HEIGHT = re.compile(r'<svg height="\d{1,4}pt"')
REGEXPR_SVG_WIDTH = re.compile(r' width="(\d{1,4}pt")')

GRIDSPEC_FULL = {'left': 0, 'right': 1, 'bottom': 0, 'top': 1, 'hspace': 0}
# GRIDSPEC_NORMAL = {'left': 0.075, 'right': .925, 'bottom': 0.11, 'top': 0.91, 'hspace': 0}
FONTSIZE = 10
FONTSIZE_TILE = 12
TICK_PARAMS_TILE = dict(direction='in', pad=-15, length=3, width=.5)
font = {'family': 'sans-serif',
        'size': FONTSIZE}  # 'weight' : 'light',
matplotlib.rc('font', **font)


@timeit('_write_fig_to_svg')
def _write_fig_to_svg(fig, name_img):
    #plt.close(fig)
    canvas = FigureCanvas(fig)
    output = BytesIO()
    imgformat = 'svg'
    canvas.print_figure(output, format=imgformat, transparent=True)
    svg_out = output.getvalue()
    # preserve_ratio=True
    svg_out = REGEXPR_SVG_WIDTH.sub(' width="100%" preserveAspectRatio="none"',
                                    REGEXPR_SVG_HEIGHT.sub('<svg height="100%"', svg_out.decode(), count=0),
                                    count=0).encode()
    try:
        with open(name_img, 'wb') as f:
            f.write(svg_out)
    except Exception as e:
        print('HA OCURRIDO UN ERROR GRABANDO SVG A DISCO: {}'.format(e))
        return False
    return True


def _tile_figsize(fraction=1.):
    dpi = 72
    # height = 200
    # width = 1.875 * height
    height = 200
    width = 4.5 * height * fraction
    return (round(width / dpi, 2), round(height / dpi, 2))


@timeit('_prep_axis_tile')
def _prep_axis_tile(color):
    matplotlib.rcParams['axes.linewidth'] = 0
    fig, ax = plt.subplots(figsize=_tile_figsize(), dpi=72, gridspec_kw=GRIDSPEC_FULL, facecolor='none')
    fig.patch.set_alpha(0)
    ax.patch.set_alpha(0)
    ax.tick_params(direction='in', pad=-15, length=3, width=.5)
    ax.tick_params(axis='y', length=0, width=0, labelsize=FONTSIZE_TILE)
    ax.tick_params(axis='x', which='both', top='off', labelbottom='off')
    ax.xaxis.grid(True, color=color, linestyle=':', linewidth=1.5, alpha=.6)
    ax.yaxis.grid(True, color=color, linestyle=':', linewidth=1, alpha=.5)
    return fig, ax


@timeit('_adjust_tile_limits')
def _adjust_tile_limits(name, ylim, date_ini, date_fin, ax):
    ax.set_ylim(ylim)
    ax.set_xlim(left=date_ini, right=date_fin)
    yticks = list(ax.get_yticks())[1:-1]
    yticks_l = [v for v in yticks if (v - ylim[0] < (2 * (ylim[1] - ylim[0]) / 3)) and (v > ylim[0])]
    ax.set_yticks(yticks)
    if name == 'power':
        ax.set_yticklabels([str(round(float(y / 1000.), 1)) + 'kW' for y in yticks_l])
        ax.tick_params(pad=-45)
    elif name == 'ldr':
        ax.set_yticklabels([str(round(float(y / 10.))) + '%' for y in yticks_l])
        ax.tick_params(pad=-40)
    else:
        ax.tick_params(pad=-30)
        ax.set_yticklabels([str(round(y, 4)) for y in yticks_l])
    return ax


@timeit('plot_tile_last_24h')
def plot_tile_last_24h(data_s, rs_data_s=None, rm_data_s=None, barplot=False, ax=None, fig=None):
    color = [1, 0, 1]
    
    if ax is None:
        fig, ax = _prep_axis_tile(color)
    
    if not barplot and rm_data_s is not None:
        data_s = data_s.rolling(rm_data_s).mean()
    elif not barplot and rs_data_s is not None:
        data_s = data_s.resample(rs_data_s, label='left').mean()
    rango_ts = data_s.index[0], data_s.index[-1]
    date_ini, date_fin = [t.to_pydatetime() for t in rango_ts]

    if data_s is not None and not data_s.empty:
        lw, alpha = 1.5, 1.
        ax.grid(b=True, which='major')
        data_s = data_s.fillna(0)

        if barplot:
            div = .5
            ylim = (0, np.ceil((data_s.max() + div) // div) * div)
            ax.bar(data_s.index, data_s, width=1 / 28, edgecolor=color, color=[1, 1, 1, .5], linewidth=lw)
            ax.xaxis.set_major_locator(mpd.HourLocator((0, 12)))
            # ax.set_xticks([])
        else:
            if data_s.name == 'power':
                div = 500
                ylim = (0, np.ceil((data_s.max() + div / 5) / div) * div)
            else:  # ldr
                div = 100
                ylim = (0, np.ceil((data_s.max() + div / 2) // div) * div)
            data_s = data_s.fillna(0)
            ax.plot(data_s.index, data_s, color=color, linewidth=lw, alpha=alpha)
            ax.fill_between(data_s.index, data_s, color=color, alpha=alpha / 2)
            ax.xaxis.set_major_locator(mpd.HourLocator((0, 12)))
            ax.xaxis.set_minor_locator(mpd.HourLocator(interval=1))
    else:
        ylim = 0, 100
        ax.annotate('NO DATA!', xy=(.35, .3), xycoords='axes fraction',
                    va='center', ha='center', color=(.9, .9, .9), fontsize=25)
    
    _adjust_tile_limits(data_s.name, ylim, date_ini, date_fin, ax)
    return fig, ax


@timeit('gen_svg_tiles')
def gen_svg_tiles(path_dest, catalog, last_hours=(72, 48, 24)):
    total_hours = last_hours[0]
    last_data, last_data_c = catalog.get(last_hours=total_hours, with_summary_data=True)
    if last_data is not None:
        ahora = dt.datetime.now().replace(second=0, microsecond=0)
        xlim = mpd.date2num(ahora - dt.timedelta(hours=total_hours)), mpd.date2num(ahora)
        delta = xlim[1] - xlim[0]
        fig, ax = None, None
        for data_s, plot_bar in zip([last_data.power, last_data.ldr, last_data_c.kWh], 
                                    [False, False, True]):
            if ax is not None:
                plt.cla()
                fig.set_figwidth(_tile_figsize()[0])
            fig, ax = plot_tile_last_24h(data_s, rs_data_s='5min', barplot=plot_bar, ax=ax, fig=fig)  # , rm_data_s=300)
            for lh in last_hours:
                file = os.path.join(path_dest, 'tile_{}_{}_last_{}h.svg'.format('enerpi_data', data_s.name, lh))
                ax.set_xlim((xlim[0] + delta * (1 - lh / total_hours), xlim[1]))
                fig.set_figwidth(_tile_figsize(lh / total_hours)[0])
                _write_fig_to_svg(fig, name_img=file)
        if fig is not None:
            plt.close(fig)
        return True
    else:
        return False


    
gen_svg_tiles('/Users/uge/ENERPIDATA/PLOTS', catalog, last_hours=(96, 84, 72, 60, 48, 36, 24, 12))


_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_15.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_16.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_17.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_18.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5", KEY:/rms
ERROR en _load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5", KEY:/rms; -> ``/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5`` does not exist [<class 'OSError'>]
_load_hdf "/Users/uge/ENERPIDATA/temp.h5", KEY:/rms
ERROR en _load_hdf "/Users/uge/ENERPIDATA/temp.h5", KEY:/rms; -> ``/Users/uge/ENERPIDATA/temp.h5`` does not exist [<class 'OSError'>]
_prep_axis_tile TOOK: 0.035 s
_adjust_tile_limits TOOK: 0.007 s
plot_tile_last_24h TOOK: 0.088 s
_write_fig_to_svg TOOK: 0.219 s
_write_fig_to_svg TOOK: 0.086 s
_write_fig_to_svg TOOK: 0.080 s
_write_fig_to_svg TOOK: 0.066 s
_write_fig_to_svg TOOK: 0.062 s
_write_fig_to_svg TOOK: 0.048 s
_write_fig_to_svg TOOK: 0.045 s
_write_fig_to_svg TOOK: 0.040 s
_adjust_tile_limits TOOK: 0.007 s
plot_tile_last_24h TOOK: 0.016 s
_write_fig_to_svg TOOK: 0.229 s
_write_fig_to_svg TOOK: 0.087 s
_write_fig_to_svg TOOK: 0.075 s
_write_fig_to_svg TOOK: 0.071 s
_write_fig_to_svg TOOK: 0.060 s
_write_fig_to_svg TOOK: 0.051 s
_write_fig_to_svg TOOK: 0.040 s
_write_fig_to_svg TOOK: 0.031 s
_adjust_tile_limits TOOK: 0.010 s
plot_tile_last_24h TOOK: 0.072 s
_write_fig_to_svg TOOK: 0.075 s
_write_fig_to_svg TOOK: 0.065 s
_write_fig_to_svg TOOK: 0.061 s
_write_fig_to_svg TOOK: 0.064 s
_write_fig_to_svg TOOK: 0.077 s
_write_fig_to_svg TOOK: 0.056 s
_write_fig_to_svg TOOK: 0.056 s
_write_fig_to_svg TOOK: 0.058 s
gen_svg_tiles TOOK: 2.191 s
Out[28]:
True

In [27]:
gen_svg_tiles('/Users/uge/ENERPIDATA/PLOTS', catalog, last_hours=(72, 48, 24))


_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_16.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_17.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_18.h5", KEY:/rms
_load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5", KEY:/rms
ERROR en _load_hdf "/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5", KEY:/rms; -> ``/Users/uge/ENERPIDATA/CURRENT_MONTH/TODAY.h5`` does not exist [<class 'OSError'>]
_load_hdf "/Users/uge/ENERPIDATA/temp.h5", KEY:/rms
ERROR en _load_hdf "/Users/uge/ENERPIDATA/temp.h5", KEY:/rms; -> ``/Users/uge/ENERPIDATA/temp.h5`` does not exist [<class 'OSError'>]
_write_fig_to_svg TOOK: 0.157 s
_write_fig_to_svg TOOK: 0.059 s
_write_fig_to_svg TOOK: 0.040 s
_write_fig_to_svg TOOK: 0.165 s
_write_fig_to_svg TOOK: 0.058 s
_write_fig_to_svg TOOK: 0.045 s
_write_fig_to_svg TOOK: 0.061 s
_write_fig_to_svg TOOK: 0.052 s
_write_fig_to_svg TOOK: 0.045 s
gen_svg_tiles TOOK: 1.069 s
Out[27]:
True

In [37]:
mpd.HourLocator?
#mpd.DayLocator?

In [52]:
with pd.HDFStore('/Users/uge/Dropbox/PYTHON/PYPROJECTS/enerpi/enerpiweb/static/debug.h5', mode='r') as st:
    data = st['debug']
data['T'] = data.index.map(lambda x: x.time().strftime('%H:%M:%S'))
data.head()


Out[52]:
Power (W) LDR (%) nº samples T
ts
2016-08-20 15:04:53.947629+02:00 306 63.0 78 15:04:53
2016-08-20 15:04:54.949200+02:00 289 63.0 80 15:04:54
2016-08-20 15:04:55.959663+02:00 284 63.0 77 15:04:55
2016-08-20 15:04:56.970700+02:00 289 63.0 78 15:04:56
2016-08-20 15:04:57.973994+02:00 289 63.0 65 15:04:57

In [124]:
from ipywidgets import HTML

df = data.reset_index(drop=True)[['T', 'Power (W)', 'LDR (%)', 'nº samples']].head()

HTML(df.to_html(justify='center', index=False, bold_rows=True, notebook=True, show_dimensions=True))

In [159]:
new_html = (
    df.style.caption
    .format(percent)
    .applymap(color_negative_red, subset=['col1', 'col2'])
    .set_properties(**{'font-size': '9pt', 'font-family': 'Calibri'})
    .bar(subset=['col4', 'col5'], color='lightblue')
    .render()
)


  File "<ipython-input-159-86dff86651c1>", line 2
    df.style.caption?
                    ^
SyntaxError: invalid syntax

In [169]:
#df.style.set_uuid('idunico-tablebuffer').render()
#df.style.set_table_attributes('class="table-responsive"').render()

template = Template("""
        <style  type="text/css" >
        {% for s in table_styles %}
            #T_{{uuid}} {{s.selector}} {
            {% for p,val in s.props %}
                {{p}}: {{val}};
            {% endfor %}
            }
        {% endfor %}
        {% for s in cellstyle %}
            #T_{{uuid}}{{s.selector}} {
            {% for p,val in s.props %}
                {{p}}: {{val}};
            {% endfor %}
            }
        {% endfor %}
        </style>

        <table id="Table_{{uuid}}" {{ table_attributes }}>
        {% if caption %}
            <caption>{{caption}}</caption>
        {% endif %}
        <thead>
            {% for r in head %}
            <tr>
                {% for c in r %}
                <{{c.type}} class="{{c.class}}">{{c.value}}
                {% endfor %}
            </tr>
            {% endfor %}
        </thead>
        <tbody>
            {% for r in body %}
            <tr>
                {% for c in r %}
                <{{c.type}} id="T_{{uuid}}_{{c.id}}" class="{{c.class}}">
                    {{ c.display_value }}
                {% endfor %}
            </tr>
            {% endfor %}
        </tbody>
        </table>
        """)


Out[169]:
'\n        <style  type="text/css" >\n        \n        \n        </style>\n\n        <table id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="table-responsive">\n        \n\n        <thead>\n            \n            <tr>\n                \n                <th class="blank">\n                \n                <th class="col_heading level0 col0">T\n                \n                <th class="col_heading level0 col1">Power (W)\n                \n                <th class="col_heading level0 col2">LDR (%)\n                \n                <th class="col_heading level0 col3">nº samples\n                \n            </tr>\n            \n        </thead>\n        <tbody>\n            \n            <tr>\n                \n                <th id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="row_heading level3 row0">\n                    0\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row0_col0" class="data row0 col0">\n                    15:04:53\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row0_col1" class="data row0 col1">\n                    306\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row0_col2" class="data row0 col2">\n                    63\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row0_col3" class="data row0 col3">\n                    78\n                \n            </tr>\n            \n            <tr>\n                \n                <th id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="row_heading level3 row1">\n                    1\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row1_col0" class="data row1 col0">\n                    15:04:54\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row1_col1" class="data row1 col1">\n                    289\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row1_col2" class="data row1 col2">\n                    63\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row1_col3" class="data row1 col3">\n                    80\n                \n            </tr>\n            \n            <tr>\n                \n                <th id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="row_heading level3 row2">\n                    2\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row2_col0" class="data row2 col0">\n                    15:04:55\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row2_col1" class="data row2 col1">\n                    284\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row2_col2" class="data row2 col2">\n                    63\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row2_col3" class="data row2 col3">\n                    77\n                \n            </tr>\n            \n            <tr>\n                \n                <th id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="row_heading level3 row3">\n                    3\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row3_col0" class="data row3 col0">\n                    15:04:56\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row3_col1" class="data row3 col1">\n                    289\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row3_col2" class="data row3 col2">\n                    63\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row3_col3" class="data row3 col3">\n                    78\n                \n            </tr>\n            \n            <tr>\n                \n                <th id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474" class="row_heading level3 row4">\n                    4\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row4_col0" class="data row4 col0">\n                    15:04:57\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row4_col1" class="data row4 col1">\n                    289\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row4_col2" class="data row4 col2">\n                    63\n                \n                <td id="T_e2570c4c_66ec_11e6_a3f9_6c400897b474row4_col3" class="data row4 col3">\n                    65\n                \n            </tr>\n            \n        </tbody>\n        </table>\n        '

In [171]:
pd.Timestamp('2016-08-20 20:31:32.854454').replace(microsecond=0)


Out[171]:
Timestamp('2016-08-20 20:31:32')

In [ ]:


In [ ]:


In [ ]:


In [158]:
from enerpi import BASE_PATH

paleta = pd.read_csv(os.path.join(BASE_PATH, 'rsc', 'paleta_power_w.csv')
                    ).set_index('Unnamed: 0')['0'].str[1:-1].str.split(', ').apply(lambda x: [float(i) for i in x])

def aplica_paleta(serie):
    return ['background-color: rgba({}, {}, {}, .7); color: #fff'.format(
            *map(lambda x: int(255 * x), paleta.loc[:v].iloc[-1])) for v in serie]

#df.style
#paleta
#valores_w = [100, 150, 225, 300, 500, 1000, 1500, 2000, 4000, 6000]
#colores = [paleta.loc[:v].iloc[-1] for v in valores_w]
#sns.palplot(colores)
#plt.show()

html_styled = (df.style
               .apply(aplica_paleta, subset=['Power (W)'])
               .format({'LDR (%)': lambda x: "{:.1f} %".format(x),
                        'Power (W)': lambda x: "<strong>{}</strong> W".format(x)})
               .bar(subset=['LDR (%)'], color='lightblue')
               .render()
              )
print_blue(html_styled)
HTML(html_styled)



        <style  type="text/css" >
        
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col1 {
            
                background-color:  rgba(141, 144, 30, .7);
            
                 color:  #fff;
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col2 {
            
                width:  10em;
            
                 height:  80%;
            
                background:  linear-gradient(90deg,lightblue nan%, transparent 0%);
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col1 {
            
                background-color:  rgba(125, 147, 32, .7);
            
                 color:  #fff;
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col2 {
            
                width:  10em;
            
                 height:  80%;
            
                background:  linear-gradient(90deg,lightblue nan%, transparent 0%);
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col1 {
            
                background-color:  rgba(125, 147, 32, .7);
            
                 color:  #fff;
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col2 {
            
                width:  10em;
            
                 height:  80%;
            
                background:  linear-gradient(90deg,lightblue nan%, transparent 0%);
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col1 {
            
                background-color:  rgba(125, 147, 32, .7);
            
                 color:  #fff;
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col2 {
            
                width:  10em;
            
                 height:  80%;
            
                background:  linear-gradient(90deg,lightblue nan%, transparent 0%);
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col1 {
            
                background-color:  rgba(125, 147, 32, .7);
            
                 color:  #fff;
            
            }
        
            #T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col2 {
            
                width:  10em;
            
                 height:  80%;
            
                background:  linear-gradient(90deg,lightblue nan%, transparent 0%);
            
            }
        
        </style>

        <table id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" None>
        

        <thead>
            
            <tr>
                
                <th class="blank">
                
                <th class="col_heading level0 col0">T
                
                <th class="col_heading level0 col1">Power (W)
                
                <th class="col_heading level0 col2">LDR (%)
                
                <th class="col_heading level0 col3">nº samples
                
            </tr>
            
        </thead>
        <tbody>
            
            <tr>
                
                <th id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" class="row_heading level3 row0">
                    0
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col0" class="data row0 col0">
                    15:04:53
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col1" class="data row0 col1">
                    <strong>306</strong> W
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col2" class="data row0 col2">
                    63.0 %
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row0_col3" class="data row0 col3">
                    78
                
            </tr>
            
            <tr>
                
                <th id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" class="row_heading level3 row1">
                    1
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col0" class="data row1 col0">
                    15:04:54
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col1" class="data row1 col1">
                    <strong>289</strong> W
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col2" class="data row1 col2">
                    63.0 %
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row1_col3" class="data row1 col3">
                    80
                
            </tr>
            
            <tr>
                
                <th id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" class="row_heading level3 row2">
                    2
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col0" class="data row2 col0">
                    15:04:55
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col1" class="data row2 col1">
                    <strong>284</strong> W
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col2" class="data row2 col2">
                    63.0 %
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row2_col3" class="data row2 col3">
                    77
                
            </tr>
            
            <tr>
                
                <th id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" class="row_heading level3 row3">
                    3
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col0" class="data row3 col0">
                    15:04:56
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col1" class="data row3 col1">
                    <strong>289</strong> W
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col2" class="data row3 col2">
                    63.0 %
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row3_col3" class="data row3 col3">
                    78
                
            </tr>
            
            <tr>
                
                <th id="T_67e4cacc_66eb_11e6_89a1_6c400897b474" class="row_heading level3 row4">
                    4
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col0" class="data row4 col0">
                    15:04:57
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col1" class="data row4 col1">
                    <strong>289</strong> W
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col2" class="data row4 col2">
                    63.0 %
                
                <td id="T_67e4cacc_66eb_11e6_89a1_6c400897b474row4_col3" class="data row4 col3">
                    65
                
            </tr>
            
        </tbody>
        </table>
        

In [141]:
(df.style
 .apply(aplica_paleta, subset=['Power (W)'])
 #.format({'LDR (%)': lambda x: "{:.1f} %".format(x), 'Power (W)': lambda x: "<strong>{}</strong> W".format(x)})
 .bar(subset=['LDR (%)'], color='yellow')
 .set_properties(**{'font-size': '12pt', 'font-family': 'Calibri'})
)


Out[141]:
T Power (W) LDR (%) nº samples
0 15:04:53 306 63 78
1 15:04:54 289 63 80
2 15:04:55 284 63 77
3 15:04:56 289 63 78
4 15:04:57 289 63 65

In [ ]:


In [157]:
print(pd.formats.style.Styler.template.render())
pd.formats.style.Styler.use?


        <style  type="text/css" >
        
        
        </style>

        <table id="T_" >
        

        <thead>
            
        </thead>
        <tbody>
            
        </tbody>
        </table>
        

In [ ]:


In [27]:
# Lectura de nginx.conf
import re

raw = '''server {
    listen      80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;

    # EnerWeb
    location = /enerweb { rewrite ^ /enerweb/; }
    # location /enerweb { try_files $uri @enerweb; }
    # location @enerweb {
    location /enerweb/ {
        include uwsgi_params;
        uwsgi_param /home/pi/PYTHON/enerweb/enerwebapp/enerweb.wsgi.py /enerweb;
        uwsgi_pass unix:/tmp/enerweb.sock;
        uwsgi_read_timeout 300;
    }

    # EnerpiWeb
    location = /enerpi { rewrite ^ /enerpi/; }
    location /enerpi/ {
        include uwsgi_params;
        uwsgi_param /home/pi/PYTHON/enerpi/enerpiweb/__main__.py /enerpi;
        uwsgi_pass unix:/tmp/enerpiweb.sock;
        uwsgi_read_timeout 300;
    }

    # MotionEye
    location = /cams { rewrite ^ /cams/; }
    location /cams/ {
        proxy_pass http://127.0.0.1:8765/;
        proxy_read_timeout 120s;
        #access_log off;
    }

    # Home Assistant (HASS)
    location = /hass { rewrite ^ /hass/; }
    location /hass/ {
        proxy_pass http://127.0.0.1:8123/;
        proxy_read_timeout 120s;
        #access_log off;
    }
}'''


rg_servers = re.compile('server {(.*)}', flags=re.DOTALL | re.MULTILINE)
rg_lines = re.compile('(\n+?\s+)', flags=re.DOTALL | re.MULTILINE)
print(rg_servers.findall(raw)[0])
nginx = pd.DataFrame(rg_lines.split(rg_servers.findall(raw)[0])[::2], columns=['msg'])
nginx.tail()


    listen      80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;

    # EnerWeb
    location = /enerweb { rewrite ^ /enerweb/; }
    # location /enerweb { try_files $uri @enerweb; }
    # location @enerweb {
    location /enerweb/ {
        include uwsgi_params;
        uwsgi_param /home/pi/PYTHON/enerweb/enerwebapp/enerweb.wsgi.py /enerweb;
        uwsgi_pass unix:/tmp/enerweb.sock;
        uwsgi_read_timeout 300;
    }

    # EnerpiWeb
    location = /enerpi { rewrite ^ /enerpi/; }
    location /enerpi/ {
        include uwsgi_params;
        uwsgi_param /home/pi/PYTHON/enerpi/enerpiweb/__main__.py /enerpi;
        uwsgi_pass unix:/tmp/enerpiweb.sock;
        uwsgi_read_timeout 300;
    }

    # MotionEye
    location = /cams { rewrite ^ /cams/; }
    location /cams/ {
        proxy_pass http://127.0.0.1:8765/;
        proxy_read_timeout 120s;
        #access_log off;
    }

    # Home Assistant (HASS)
    location = /hass { rewrite ^ /hass/; }
    location /hass/ {
        proxy_pass http://127.0.0.1:8123/;
        proxy_read_timeout 120s;
        #access_log off;
    }

Out[27]:
msg
32 location /hass/ {
33 proxy_pass http://127.0.0.1:8123/;
34 proxy_read_timeout 120s;
35 #access_log off;
36 }\n

In [33]:
nginx['comment'] = nginx['msg'].str.startswith('#')
nginx['open'] = (~nginx['comment'] & nginx['msg'].str.contains('\{')).cumsum()
nginx['close'] = (~nginx['comment'] & nginx['msg'].str.contains('\}')).cumsum()
nginx


Out[33]:
msg comment open close
0 False 0 0
1 listen 80; False 0 0
2 server_name localhost; False 0 0
3 charset utf-8; False 0 0
4 client_max_body_size 75M; False 0 0
5 # EnerWeb True 0 0
6 location = /enerweb { rewrite ^ /enerweb/; } False 1 1
7 # location /enerweb { try_files $uri @enerweb; } True 1 1
8 # location @enerweb { True 1 1
9 location /enerweb/ { False 2 1
10 include uwsgi_params; False 2 1
11 uwsgi_param /home/pi/PYTHON/enerweb/enerwebapp/enerweb.wsgi.py /enerweb; False 2 1
12 uwsgi_pass unix:/tmp/enerweb.sock; False 2 1
13 uwsgi_read_timeout 300; False 2 1
14 } False 2 2
15 # EnerpiWeb True 2 2
16 location = /enerpi { rewrite ^ /enerpi/; } False 3 3
17 location /enerpi/ { False 4 3
18 include uwsgi_params; False 4 3
19 uwsgi_param /home/pi/PYTHON/enerpi/enerpiweb/__main__.py /enerpi; False 4 3
20 uwsgi_pass unix:/tmp/enerpiweb.sock; False 4 3
21 uwsgi_read_timeout 300; False 4 3
22 } False 4 4
23 # MotionEye True 4 4
24 location = /cams { rewrite ^ /cams/; } False 5 5
25 location /cams/ { False 6 5
26 proxy_pass http://127.0.0.1:8765/; False 6 5
27 proxy_read_timeout 120s; False 6 5
28 #access_log off; True 6 5
29 } False 6 6
30 # Home Assistant (HASS) True 6 6
31 location = /hass { rewrite ^ /hass/; } False 7 7
32 location /hass/ { False 8 7
33 proxy_pass http://127.0.0.1:8123/; False 8 7
34 proxy_read_timeout 120s; False 8 7
35 #access_log off; True 8 7
36 }\n False 8 8

In [109]:
import configparser

config = configparser.RawConfigParser()
config.read('/Users/uge/Dropbox/PYTHON/PYPROJECTS/enerpi/enerpi/config_enerpi.ini')

{s: dict(config[s]) for s in config.sections()}
#
#parser.read_file(p_conf)
#print(open(p_conf, 'r').readlines())


Out[109]:
{'BROADCAST': {'key_file': '~/.enerpi_secret_key',
  'udp_ip': '192.168.1.255',
  'udp_port': '57775'},
 'ENERPI_DATA': {'data_path': '~/ENERPIDATA',
  'default_img_mask': "'enerpi_power_consumption_ldr_{:%Y%m%d_%H%M}_{:%Y%m%d_%H%M}.png'",
  'file_logging': 'enerpi.log',
  'hdf_store': 'enerpi_data.h5',
  'img_basepath': '~/ENERPIDATA/PLOTS',
  'key': "'/rms'",
  'logging_level': 'DEBUG',
  'n_samples_buffer_disk': '60',
  'store_periodic_catalog_sec': '3600'},
 'ENERPI_SAMPLER': {'a_ref': '30.',
  'delta_sec_data': '1',
  'init_log_mark': '"Init ENERPI logging & broadcasting..."',
  'rms_roll_window_sec': '2',
  'ts_data_ms': '12',
  'tz': 'Europe/Madrid',
  'v_ref': '3.3',
  'voltaje': '236'},
 'MCP3008': {'ch_ldr': '7', 'ch_noise': '3', 'ch_probe': '4', 'ch_vref': '0'},
 'RGBLED': {'pin_b': '16', 'pin_g': '20', 'pin_r': '19'}}

In [115]:
list(config.keys())


Out[115]:
['DEFAULT', 'MCP3008', 'RGBLED', 'ENERPI_SAMPLER', 'BROADCAST', 'ENERPI_DATA']

In [116]:
config.get('ENERPI_DATA', 'LOGGING_LEVEL', fallback=4)


Out[116]:
'DEBUG'

In [127]:
pd.read_hdf('/Users/uge/ENERPIDATA/CURRENT_MONTH/DATA_2016_08_DAY_15.h5', '/hours')


Out[127]:
kWh t_ref n_jump n_exec p_max p_mean p_min
ts
2016-08-15 00:00:00 0.257087 0.999994 0 0 851.0 257.0 177.0
2016-08-15 01:00:00 0.231033 1.000025 0 0 267.0 231.0 202.0
2016-08-15 02:00:00 0.225473 0.999860 0 0 805.0 226.0 199.0
2016-08-15 03:00:00 0.226510 1.000217 0 0 259.0 226.0 207.0
2016-08-15 04:00:00 0.225938 0.999961 0 0 764.0 226.0 202.0
2016-08-15 05:00:00 0.221933 0.999845 0 0 250.0 222.0 204.0
2016-08-15 06:00:00 0.225141 1.000226 0 0 817.0 225.0 204.0
2016-08-15 07:00:00 0.219596 0.999956 0 0 257.0 220.0 201.0
2016-08-15 08:00:00 0.228523 0.999872 0 0 829.0 229.0 200.0
2016-08-15 09:00:00 0.308975 1.000179 0 0 2444.0 309.0 166.0
2016-08-15 10:00:00 0.975249 0.999818 0 0 2192.0 975.0 237.0
2016-08-15 11:00:00 0.733841 1.000046 0 0 2112.0 734.0 259.0
2016-08-15 12:00:00 0.610755 0.999987 0 0 3404.0 611.0 309.0
2016-08-15 13:00:00 0.745866 1.000078 0 0 2932.0 746.0 303.0
2016-08-15 14:00:00 0.429889 0.999809 0 0 1345.0 430.0 236.0
2016-08-15 15:00:00 0.300340 1.000233 0 0 393.0 300.0 225.0
2016-08-15 16:00:00 0.324271 0.999790 0 0 817.0 324.0 232.0
2016-08-15 17:00:00 0.365363 1.000124 0 0 478.0 365.0 310.0
2016-08-15 18:00:00 0.422254 1.000102 0 0 926.0 422.0 359.0
2016-08-15 19:00:00 0.410453 0.999817 0 0 537.0 411.0 320.0
2016-08-15 20:00:00 0.407947 1.000094 0 0 1222.0 408.0 336.0
2016-08-15 21:00:00 0.400214 1.000033 0 0 888.0 400.0 316.0
2016-08-15 22:00:00 0.403624 0.999916 1 1 1896.0 407.0 206.0
2016-08-15 23:00:00 0.184828 0.548637 0 0 399.0 337.0 302.0

In [75]:
s_b = parser['broadcast']
dict(s_b.items())


Out[75]:
{'key_file': '~/.enerpi_secret_key',
 'udp_ip': '192.168.1.255',
 'udp_port': '57775'}

In [119]:
config['BROADCAST']['udp_port']


Out[119]:
'57775'

In [113]:
s_b.getint('UDP_PORT', fallback=57775)


Out[113]:
57775

In [117]:
dict(config['RGBLED'].getint())


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-117-b2d74d8569eb> in <module>()
----> 1 dict(config['RGBLED'].getint())

TypeError: get() missing 1 required positional argument: 'option'

In [99]:
from ipywidgets import HTML


last = last.dropna(how='all', axis=1)
HTML(last.to_html(columns=['tipo', 'msg'], classes=['table', 'table-responsive', 'table-hover'], notebook=True))

In [121]:
dict(config['ENERPI_SAMPLER'])


Out[121]:
{'a_ref': '30.',
 'delta_sec_data': '1',
 'init_log_mark': '"Init ENERPI logging & broadcasting..."',
 'rms_roll_window_sec': '2',
 'ts_data_ms': '12',
 'tz': 'Europe/Madrid',
 'v_ref': '3.3',
 'voltaje': '236'}

In [ ]:


In [ ]: