From e017cc00d97679786d97c469733117c016e3ba9b Mon Sep 17 00:00:00 2001
From: gsingh58 <gurmail-singh@wisc.edu>
Date: Wed, 13 Mar 2024 09:34:43 -0500
Subject: [PATCH] web_4_lec_002 added

---
 .../14-web-4-and-regex-1/web_4_lec_002.py     | 115 ++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 lecture_material/14-web-4-and-regex-1/web_4_lec_002.py

diff --git a/lecture_material/14-web-4-and-regex-1/web_4_lec_002.py b/lecture_material/14-web-4-and-regex-1/web_4_lec_002.py
new file mode 100644
index 0000000..e5907d5
--- /dev/null
+++ b/lecture_material/14-web-4-and-regex-1/web_4_lec_002.py
@@ -0,0 +1,115 @@
+import flask
+
+# Notes for matplotlib.pyplot module
+"""
+fig, ax = plt.subplots(figsize=(3, 2)) enables us to create a new plot
+fig.savefig(<file object>, format=<fig format>) enables us to save the figure into a file - default format is png
+plt.close() closes most recent fig
+plt.tight_layout() enables us to avoid cropping of the image
+"""
+
+# Notes for io module
+"""
+io.BytesIO for fake binary file
+io.StringIO for fake text file
+<fileobject>.getvalue() returns the content of the fake file
+"""
+
+# Notes for flask
+"""
+flask.request.args enables us process query string
+@app.route("<URL>", methods=["POST"]) enables us to process HTTP POST requests
+flask.request.get_data() enables us to access data (byte format) sent via HTTP POST request
+"""
+
+temps = [80, 85, 83, 90]
+
+app = flask.Flask("my dashboard")
+
+# DYNAMIC
+@app.route("/")
+def home():
+    return """
+    <html>
+    <body bgcolor="Salmon">
+    
+    <h3>Example 1: PNG</h3>
+    <img src="plot1.png">
+    
+    <h3>Example 2: SVG</h3>
+    <img src="plot2.svg">
+    
+    </body>
+    </html>
+    """ 
+
+# TODO: add route to plot1.png 
+"""
+IMPORTANT: file name and extension should match as in html content
+Steps:
+     1. generate a plot
+     2. return the image contents:
+         2a. v1: write and read from a temporary file
+         2b. v2: use a fake file (io module)
+     3. fix the content type: default content type is text/html: Content-Type: text/html
+         3a. How can we find various content types? Google for "MIME types".
+     4. IMPORTANT: close the figure. If this is not done, after 20 refreshes, you will start getting the below warning:
+More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
+     5. try to set y_label for the plot. This will not show up. 
+     6. create a line plot with temps Series
+
+"""
+
+# TODO: add route to plot2.svg
+"""
+IMPORTANT: file name and extension should match as in html content
+Things to change from plot1 function:
+     1. Change content type
+     2. Change format for savefig
+     3. SVG files have text type (unlike PNG) - so we should use io.StringIO
+
+"""
+
+# TODO: add route for "/upload"
+"""
+Steps:
+     1. support query string:
+         - with key/parameter as temps and value as "," separated temperature values
+         - add the values into temps list
+     2. return len(temps)
+     
+Disadvantages of query string approach:
+     1. If we have a lot of data, it is difficult to type. What if we are trying to upload a video?
+     2. Caching:
+         - memory of what we have already seen before; instead of slow web request, show what was already sent previously for the same request
+         - browser cache
+         - cache devices that sit in front of the server
+         - server caching
+         
+Use POST request instead:
+     1. Update route to add "methods=["POST"]"
+     2. Humans don't send POST requests, instead we need to use "curl -X POST <URL> -d <data>" --- curl is a simple command line tool that enables us to send HTTP requests
+     3. Use flask.request.get_data() - make sure to convert type to str
+"""
+
+# TODO: change SVG to histogram - very sensitive to number of "bins"
+# TODO: change PNG to CDF (Cumulative Distribution Function):
+"""
+Idea: sort the data to observe some distribution, then switch x and y axes
+Steps:
+     1. sort the data
+     2. switch x and y axes
+     3. normalize the y axis from 0 to 100 - make sure to set ylim to 0
+     4. change line plot "drawstyle" to "steps-post" - avoid extrapolating information between points
+
+    s = pd.Series(sorted(temps))
+    rev = pd.Series((s.index+1)/len(s)*100, index=s.values)
+    rev.plot.line(ax=ax, ylim=0, drawstyle="steps-post")
+"""
+
+if __name__ == "__main__":
+    # threaded must be False whenever we use matplotlib
+    app.run(host="0.0.0.0", debug=True, threaded=False)
+
+# app.run never returns, so don't define functions
+# after this (the def lines will never be reached)
-- 
GitLab