Pyplot gráficos desarrollo

Dibuja gráfico y guarda imagen con logo en Python y Pyplot. Código desarrollado para elpetro.pe.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# https://matplotlib.org/tutorials/introductory/pyplot.html#sphx-glr-tutorials-introductory-pyplot-py

import time
from datetime import datetime, timedelta
import pytz

import sys, getopt, os
import argparse

import urllib2

import mysql.connector
from pymysql import Binary

import matplotlib
matplotlib.use('Agg')

from pylab import *

import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.font_manager as font_manager
import matplotlib.image as image
import mpl_toolkits 


import numpy as np
import pandas as pd 
import matplotlib.dates as mdates
import matplotlib.cbook as cbook
from matplotlib.dates import DayLocator, HourLocator, DateFormatter, drange
from numpy import arange

import pymysql
import pymysql.cursors

from phpserialize import serialize, unserialize
import zlib
import json
import types  
import unicodedata
from datetime import datetime

import png
from PIL import Image, ImageFile

import string
import ast


path_font = '/var/www/elpetro.pe/htdocs/wp-content/plugins/eb/fonts/arial_regular/arial_regular.ttf'
prop = font_manager.FontProperties(fname=path_font)






#                                                   BASE DE DATOS


# Connect DDBB
def bbdd_con():

    try:
        conn = pymysql.connect(host='localhost', port=3306, user='xxx', passwd='xxx', db='xxx', charset='utf8')

    except Exception as e:
        print(e)

    else:
        return conn



# Criptodivisas
def get_db_criptodivisas ( id = 0 ) :
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")

    if id == 0 :
        cur.execute("SELECT * FROM c_criptodivisa WHERE nolistado = 0 AND enabled = 1 ORDER BY name")

    else :
        cur.execute("SELECT * FROM c_criptodivisa WHERE id_c_criptodivisa = %s", ( [id] ))

    items = cur.fetchall()
    cur.close()
    conn.close()
    return items





# Divisas
def get_db_divisas ( id = 0 ) :
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")

    if id == 0 :
        cur.execute("SELECT * FROM c_divisa WHERE enabled = 1 ORDER BY menu_order" )

    else :
        cur.execute("SELECT * FROM c_divisa WHERE id_c_divisa = %s", ( [id] ))

    items = cur.fetchall()
    cur.close()
    conn.close()
    return items




# Criptodivisa Json
def get_db_prices_criptodivisas_hours ( hours = 24, compression = 4) :

    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("SELECT id_c_criptodivisa_json, datetime, json_data, compression FROM c_criptodivisa_json WHERE datetime >= DATE_SUB(NOW(),INTERVAL %s HOUR) ORDER BY datetime ASC", ( [ hours, ] ) )

    items = cur.fetchall()
    cur.close()
    conn.close()


    price24 = []
    for item in items :
        id_c_criptodivisa_json = item[0]
        datetime = item[1]

        compression = item[3]

        if compression == 4 :
            json_data = json.loads(zlib.decompress ( item[2] ))


        elif compression == 2 :

            unserialize_j = unserialize( zlib.decompress(item[2]))
            json_data_dumps = json.dumps(unserialize_j).replace("'", "\"")

            json_data = json.loads(json_data_dumps)

        price24.append ( { 'id_c_criptodivisa_json' : id_c_criptodivisa_json, 'datetime' : datetime, 'json_data' : json_data, 'compression' : compression } )

    return price24




# Criptodivisa Json ID
def get_db_criptodivisa_id ( id ) :
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("""SELECT id_c_criptodivisa_json, datetime, json_data,  json_data, compression FROM c_criptodivisa_json WHERE id_c_criptodivisa_json = %s""" , ( [ id, ]))

    items = cur.fetchall()
    cur.close()
    conn.close()
    return items





# Divisas Json (tipos de cambio)
def get_db_divisas_json () :
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute( """SELECT * FROM c_divisa_json WHERE compression = 4  ORDER BY datetime  DESC LIMIT 1""" )

    items = cur.fetchall()
    cur.close()
    conn.close()
    return items



#                                                   FILE GET CONTENTS
def file_get_contents(filename, use_include_path = 0, context = None, offset = -1, maxlen = -1):
    if (filename.find('://') > 0):
        ret = urllib2.urlopen(filename).read()
        if (offset > 0):
            ret = ret[offset:]
        if (maxlen > 0):
            ret = ret[:maxlen]
        return ret
    else:
        fp = open(filename,'rb')
        try:
            if (offset > 0):
                fp.seek(offset)
            ret = fp.read(maxlen)
            return ret
        finally:
            fp.close( )





#                                                   CREA CHARTS


def draw_chart ( idc, datetime, plot_x, plot_y, criptodivisa_name, criptodivisa_symbol, divisa_name, divisa_symbol ) :

    formatter = DateFormatter('%d/%m %H:%M')

    json_date_time_file = datetime.strftime('%Y%m%d%H%M')
    file_name = str(idc) + "_" + criptodivisa_symbol + "_" + divisa_symbol + ".png"
    path_file = "/var/www/elpetro.pe/htdocs/wp-content/plugins/eb/graficos/"

    min_date = plot_x[0]
    max_date = plot_x[-1]

    str_date = min_date.strftime('%d %b %Y - %H:%M') + "   al   " + max_date.strftime('%d %b %Y - %H:%M')

    titulo = "Precios del " + criptodivisa_symbol  + " " + criptodivisa_name + " en " + divisa_name + " (" + divisa_symbol + ")"
    titulo_x = "Del  " + str_date + "  (UTC-5/Lima)"
    titulo_y = "Precio en " + divisa_symbol

    x = plot_x 
    y = plot_y 

    fig = plt.figure() 
    fig, ax = plt.subplots(figsize=(15,5))
    ax.plot(x, y)
    fig.suptitle(titulo, fontsize=20)
    ax.set(xlabel=titulo_x, ylabel=titulo_y )
    plt.margins(0.000,0.1)
    ttl = ax.title
    ttl.set_position([.5, 1.03])
    fig.autofmt_xdate()
    plt.gcf().axes[0].xaxis.set_major_formatter(formatter)  
    plt.xticks(fontsize=8)
    ax.xaxis.labelpad = 20
    ax.grid()

    logo = plt.imread("/var/www/elpetro.pe/python/elpetroperu_chart_25.png")
    ax.figure.figimage(logo, 120, 130, alpha=1, zorder=1)

    url_graf =  path_file + file_name
    url_graf_th =  path_file + "t_" + file_name

    fig.savefig(url_graf, bbox_inches='tight', pad_inches = 0.25)

    fig_th = image.thumbnail(url_graf, url_graf_th, scale=0.25)

    plt.close('all')





#                                                               DIBUJA CHART 24 HORAS TEMP
def last24 ( dtime = -1 ) :

    precios24 = get_db_prices_criptodivisas_hours () 

    criptodivisas = get_db_criptodivisas ()
    divisas = get_db_divisas ()

    id_errors = []

    for criptodivisa in criptodivisas :
        done = False

        criptodivisa_name = criptodivisa[1]
        criptodivisa_symbol = criptodivisa[2]

        for divisa in divisas :
            divisa_name = divisa[1]
            divisa_symbol = divisa[2]

            plot_x = []
            plot_y = []

            
            for item_criptodivisa in precios24:
              	id_c_criptodivisa_json = item_criptodivisa.get('id_c_criptodivisa_json')

                datetime = item_criptodivisa.get('datetime')
                datetime_pe = datetime

                if dtime > 0 :
                    datetime_pe = datetime + timedelta( hours = dtime )
                elif dtime < 0 :
                    datetime_pe = datetime - timedelta( hours = abs ( dtime ))

                

                data_y = item_criptodivisa.get('json_data')
                y = 0
                
                try :
                    y = data_y[criptodivisa_symbol][divisa_symbol]  #[criptodivisa_symbol][divisa_symbol]

                    if y :
                        plot_y.append( y )
                        plot_x.append( datetime_pe )
                    else :
                        id_errors.append( id_c_criptodivisa_json )
                        done = True

                except :
                    id_errors.append( id_c_criptodivisa_json )
                    done = True
                    
                if done :
                    break

            if done :
                break

            draw_chart ( id_c_criptodivisa_json, datetime, plot_x, plot_y, criptodivisa_name, criptodivisa_symbol, divisa_name, divisa_symbol)

    id_c_criptodivisa_json = precios24[-1].get('id_c_criptodivisa_json')

    date_min = precios24[0].get('datetime') - timedelta( hours = abs ( dtime ))
    date_max = precios24[-1].get('datetime') - timedelta( hours = abs ( dtime ))

    str_date = " del  " + date_min.strftime('%d %b %Y - %H:%M') + "   al   " + date_max.strftime('%d %b %Y - %H:%M') + "  (UTC-5/Lima)."


    if len( id_errors ) :

        print "ERRORS price24[] " , id_errors


    t = datetime.now() - timedelta(hours=6)
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("""INSERT INTO c_figure ( id_c_criptodivisa_json, fechahora, date_str ) VALUES ( %s, %s, %s )""", ([id_c_criptodivisa_json, t, str_date ]))
    conn.commit()
    cur.close()
    conn.close()




#                                                               LOAD RATES FROM EXTERNAL JSON
def get_json_rate () :
    api_id = "xxx"
    json_url = "https://openexchangerates.org/api/latest.json?app_id=" + api_id

    jsond = json.loads (file_get_contents( json_url ))
    return jsond





#                                                               INSERT RATES IN LOCAL BD
def set_rate_db (rates ) :
    json_compress = zlib.compress ( json.dumps ( rates ) ) 
    compression = 4

    t = datetime.now() - timedelta(hours=6)
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("""INSERT INTO c_divisa_json (datetime, json_data, compression) VALUES (%s, %s, %s)""", ( [ t, json_compress , compression ]))
    conn.commit()
    cur.close()
    conn.close()




#                                                               LOAD RATES FROM DB
def get_db_rate ( compression = 4 ) :
    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")

    cur.execute("""SELECT id_c_divisa_json, datetime, json_data, compression FROM c_divisa_json WHERE compression = %s ORDER BY datetime DESC LIMIT 1""", ( [ compression, ]))
    items = cur.fetchall()
    cur.close()
    conn.close()

    item = items[0]
    id_c_divisa_json = item[0]
    datetime = item[1]
    json_data = json.loads(zlib.decompress(item[2]))
    compression = item[3]
    rates = { 'id_c_divisa_json' : id_c_divisa_json, 'datetime' : datetime, 'json_data': json_data, 'compression': compression  }
    return rates



def get_db_rate_alternative ( compression = 4 ) :
    divisas = get_db_divisas ()
    rates = {}
    id_c_divisa_alt = ""
    datetime = ""
    for divisa in divisas:
        key_divisa = divisa[4]
        conn = bbdd_con()
        cur = conn.cursor()
        cur.execute("set names utf8;")
        cur.execute("""SELECT id_c_divisa_alt, divisa_symbol, price, datetime FROM c_divisa_alt WHERE divisa_symbol = %s ORDER BY datetime DESC LIMIT 1""", ( [ key_divisa, ]))
        items = cur.fetchall()
        cur.close()
        conn.close()
        item = items[0]
        id_c_divisa_alt = item[0]
        datetime = item[3]
        rates[key_divisa] = item[2]

    cambio = {}
    cambio['rates'] = json.loads (json.dumps ( (rates)))
    return  cambio





#                                                               LOAD CRIPTODIVISAS PRICES FROM EXTERNAL JSON
def get_json_criptodivisas_price () :
    criptodivisas = get_db_criptodivisas ()
    divisas = get_db_divisas ()

    divisas_json = get_db_divisas_json ()
    divisas_rate = json.loads(zlib.decompress(divisas_json[0][2]))
    
    criptodivisa_symbols = []
    for criptodivisa in criptodivisas :
        criptodivisa_symbols.append( criptodivisa[2])

    criptodivisas_query = ','.join( criptodivisa_symbols )


    divisa_symbols = []
    for divisa in divisas :
        divisa_symbols.append( divisa[4])

    divisas_query = ','.join( divisa_symbols )

    api_id = "xxx"
    json_url = "https://min-api.cryptocompare.com/data/pricemulti?fsyms=" + criptodivisas_query + "&tsyms=" + divisas_query

    prices = json.loads (  file_get_contents( json_url ))
    return prices









#                                                               INSERT CRIPTODIVISAS PRICES BBDD IN DB (MEMORY JSON ARRAY)
def set_db_price_criptodivisas ( precios, compression = 4 ) :

    t = datetime.now() - timedelta(hours=6)

    json_compress = zlib.compress ( json.dumps (precios ) )     

    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("""INSERT INTO c_criptodivisa_json (datetime, json_data, compression) VALUES (%s, %s, %s)""", ( [ t , json_compress , compression ]))
    conn.commit()
    cur.close()
    conn.close()






def compare_criptodivisas ( horas = 24 ) :

    precios24 = get_db_prices_criptodivisas_hours () 

    criptodivisas = get_db_criptodivisas ()
    divisas = get_db_divisas ()

    values = {}
    for criptodivisa in criptodivisas :
        criptodivisa_symbol = criptodivisa[2]
        values[criptodivisa_symbol.decode('utf-8')] = {}

        for divisa in divisas :
            divisa_symbol = divisa[2]
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')] = {}

            precios = []

            precio_open = precios24[0].get ('json_data')[criptodivisa_symbol][divisa_symbol]
            precio_close = precios24[-1].get ('json_data')[criptodivisa_symbol][divisa_symbol]

            for precio24 in precios24 :
                data = precio24.get ('json_data')

                precios.append ( data[criptodivisa_symbol][divisa_symbol] )
                
            precio_max = max ( precios )
            precio_min = min ( precios )
            precio_diff = precio_max - precio_min
            precio_diff_porcentaje = get_change_porcentage (precio_max, precio_min)

            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']  = {}
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_max']  = precio_max
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_min']  = precio_min
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_open']  = precio_open
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_close']  = precio_close
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_diff']  = precio_diff
            values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_diff_porcentaje']  = precio_diff_porcentaje


    
    criptodivisa_symbol = u'BTC'
    divisa_symbol = u'EUR'

    precio_max = values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_max'] 
    precio_min = values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_min']  
    precio_open = values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_open']  
    precio_close = values[criptodivisa_symbol.decode('utf-8')][divisa_symbol.decode('utf-8')]['precio']['precio_close'] 


    path_file = "/var/www/elpetro.pe/htdocs/wp-content/plugins/eb/graficos_compare/"
    url_graf = path_file + "c" + str( time.time() ) + ".png"

    width = 0.1 # the width of the bar

    fig, ax = plt.subplots() 
    rects1 = ax.bar( .1  , precio_open, width,)
    rects2 = ax.bar( .2 ,  precio_min, width,)
    rects2 = ax.bar( .3 ,  precio_max, width,)
    rects2 = ax.bar( .4 ,  precio_close, width,)

    fig.savefig(url_graf, bbox_inches='tight', pad_inches = 0.25)
    plt.close('all')




def debug_db_rate ( id_min = 0, id_max = 0, divisa = False) :

    if id_min == 0 :
        conn = bbdd_con()
        cur = conn.cursor()
        cur.execute("set names utf8;")
        cur.execute("SELECT id_c_divisa_json FROM c_divisa_json ORDER BY datetime DESC LIMIT 1")
        item = cur.fetchone()
        if item is not None:
            id_min = item[0]
        cur.close()
        conn.close()

    if id_max == 0 :
        id_max = id_min

    conn = bbdd_con()
    cur = conn.cursor()
    cur.execute("set names utf8;")
    cur.execute("""SELECT id_c_divisa_json, datetime, json_data, compression FROM c_divisa_json WHERE id_c_divisa_json>=%s AND id_c_divisa_json<=%s""", ( [ id_min , id_max ]))
    items = cur.fetchall()
    cur.close()
    conn.close()

    for item in items :
        data = json.loads(zlib.decompress ( item[2] ))

        if divisa :
            data_val = data.get ('rates')[divisa.encode('utf-8')]
            print item[0], item[1], "divisa " + divisa + ": " + str ( data_val ), item[3]
        else :
            print item[0], item[1], data, item[3]








#                                                               CALCULA PORCENTAJE
def get_change_porcentage (current, previous) :
    if current == previous:
        return 0
    try:
       return (((current - previous))/previous)*100.0
    except ZeroDivisionError:
        return 0




#                                                               ARGS PARSER
def main(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument('-q', default="24", help="Query to process")
    parser.add_argument('-min', default=0, type=int, help="Min id query")
    parser.add_argument('-max', default=0, type=int, help="Max id query")
    parser.add_argument('-divisa', default=False, help="Divisa symbol in query")
    args = parser.parse_args()



    if args.q == 'get_json_rate' :
        rates = get_json_rate ()
        return rates

    if args.q == 'set_rate_db' :
        rates = get_json_rate ()
        set_rate_db ( rates )

    if args.q == 'get_db_rate' :
        rates = get_db_rate_alternative ()
        return rates


    if args.q == 'get_json_criptodivisas_price' :
        prices = get_db_rate ()
        return prices

    if args.q == 'add_json_array_PTR' :
        prices = get_json_criptodivisas_price ()
        prices_ptr = add_json_array_PTR ( prices )
        return prices_ptr

    if args.q == 'set_db_price_criptodivisas' :
        prices = get_json_criptodivisas_price ()
        prices_ptr = add_json_array_PTR ( prices )
        set_db_price_criptodivisas ( prices_ptr )




    if args.q == 'last24' :
        last24 ()


    if args.q == 'history' :
        history ()


    if args.q == 'compare_criptodivisas' :
        compare_criptodivisas ()



    if args.q == 'debug_db_rate' :
        id_min = args.min
        id_max = args.max
        divisa = args.divisa
        debug_db_rate ( id_min, id_max, divisa)






if __name__ == "__main__":
   main(sys.argv[1:])