0

I am attempting to create something where a CSV file can be uploaded, a table of the data can then be viewed through the browser on /transform, and a static .png file can be retrieved from /plot using matplotlib to create the plot.

I don't know JavaScript or how to render a graph of the data in a browser, so I'm cheating and using matplotlib where I can save a plot to a static directory (/transform) and then serve it on /plot.

The problem I am running into is the pictures aren't updating. The first attempt works with the process described above, and then when I want to repeat the process I get the same picture graph served again and again. I thought the plots would just save over themselves on each repeat of the process but I may be wrong. Is this a browser cache issue?

from flask import Flask, make_response, request, render_template
from werkzeug.utils import secure_filename
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time



app = Flask(__name__)



@app.route('/')
def form():
    return render_template('form.html')

@app.route('/transform', methods=["POST"])
def transform_view():
    f = request.files['data_file']
    filename = secure_filename(f.filename)
    f.save(filename)

    df = pd.read_csv(filename, index_col='Date', parse_dates=True)

    OAT = pd.Series(df['OAT'])
    RAT = pd.Series(df['RAT'])
    MAT = pd.Series(df['MAT'])

    df_OATrat = (OAT - RAT)
    df_MATrat = (MAT - RAT)

    plt.scatter(df_OATrat,df_MATrat, color='grey', marker='+')
    plt.xlabel('OAT-RAT')
    plt.ylabel('MAT-RAT')
    plt.title('Economizer Diagnostics')
    plt.plot([0,-18],[0,-18], color='green', label='100% OSA during ideal conditions')
    plt.plot([0,20],[0,5], color='red', label='Minimum OSA in cooling mode')
    plt.plot([0,-38],[0,-9.5], color='blue', label='Minimum OSA in heating mode')
    plt.plot([0,0],[-20,10], color='black')
    plt.plot([-30,20],[0,0], color='black')
    plt.legend()
    plt.text(-3, -28, time.ctime(), fontsize=9)
    plt.savefig('static/plot.png')

    return render_template('table.html',  tables=[df.to_html(classes='data')], titles=df.columns.values)


@app.route('/plot', methods=['GET'])
def plot_view():   
    return render_template('serve.html')


if __name__ == '__main__':
    app.run(debug=True)

UPDATED SCRIPT to save plot into memory Vs static file

from flask import Flask, make_response, request, render_template, send_file
from io import BytesIO
from werkzeug.utils import secure_filename
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time



app = Flask(__name__)


@app.route('/')
def form():
    return render_template('form.html')

@app.route('/transform', methods=["POST"])
def transform_view():
    f = request.files['data_file']
    filename = secure_filename(f.filename)
    f.save(filename)

    df = pd.read_csv(filename, index_col='Date', parse_dates=True)

    OAT = pd.Series(df['OAT'])
    RAT = pd.Series(df['RAT'])
    MAT = pd.Series(df['MAT'])

    df_OATrat = (OAT - RAT)
    df_MATrat = (MAT - RAT)

    plt.scatter(df_OATrat,df_MATrat, color='grey', marker='+')
    plt.xlabel('OAT-RAT')
    plt.ylabel('MAT-RAT')
    plt.title('Economizer Diagnostics')
    plt.plot([0,-18],[0,-18], color='green', label='100% OSA during ideal conditions')
    plt.plot([0,20],[0,5], color='red', label='Minimum OSA in cooling mode')
    plt.plot([0,-38],[0,-9.5], color='blue', label='Minimum OSA in heating mode')
    plt.plot([0,0],[-20,10], color='black')
    plt.plot([-30,20],[0,0], color='black')
    #plt.legend()
    plt.text(-3, -28, time.ctime(), fontsize=9)
    img = BytesIO()
    plt.savefig(img)
    img.seek(0)
    resp = make_response(send_file(img, mimetype='image/png'))
    resp.cache_control.no_cache = True
    return resp


if __name__ == '__main__':
    app.run(debug=True)
bbartling
  • 3,288
  • 9
  • 43
  • 88
  • If you clear the cache, does the issue persist? That would allow you to narrow it down. – jonrsharpe May 13 '19 at 19:16
  • Yes in chrome if I do a `clear browsing data` it does appear to fix the issue where I can see other plots. Whats really odd is the matplotlib legend is getting doubled/screwed up. I never seen this issue as I used the script to plot the data before learning flask – bbartling May 13 '19 at 19:24

2 Answers2

1

If it's a caching issue, you can either implement a cache buster or disable cache once and for all.

To implement a cache buster, you can add automatic versioning to your static files.

To disable cache, set your headers on the response objects using make_response() and add no-cache to the response.

from flask import make_response

@app.route('/nocache')
def something_not_cached():
    resp = make_response(render_template(...))
    resp.cache_control.no_cache = True
    return resp
Gabe
  • 956
  • 7
  • 8
  • I updated the post to include an updated script with your recommendations. Im also experimenting around with saving the graph file into memory Vs a static file, but I am still running into the cache issue even with the `resp.cache_control.no_cache = True`. Is there anything on the updated script that you could recommend an improvement to try? Thanks – bbartling May 14 '19 at 16:35
0

Flask will cache static files. If you do a hard refresh in your browser your new items should be displayed. One thing you might experiment with is creating unique filenames for your plots and returning them to your rendered template.

You could add something like the code below (thanks to this answer)

import os.path


def next_file_name():
    num = 1
    while True:
        file_name = 'file%d.txt' % num
        if not os.path.exists(file_name):
            return file_name
        num += 1

Note that the filename incrementation strategy could run into performance problems if you have lots of files to iterate over, but it sounds like that may not be an issue in your particular case.

This answer (among many) also gives an example for how to increment filenames.

VizslaVizsla
  • 146
  • 1
  • 10