【tornado建站】给网站添加在线绘图脚本

到上一篇文章已经完成了博客所需的基础框架,包括博客展示、分页及数据库内容读写等,这里还想要添加自动画图的功能

先大致准备一下前端代码,因为后期还要添加其他画图工具,这里就先传入一个draw_type来标识:

<section>
	<header class="main">
		<h1>{{draw_type.upper()}}</h1>
	</header>
	{% if draw_type=="heatmap" %}
		<span class="image main"><img src="{{ static_url("images/heatmap.png") }}" alt="" /></span>
	{% end %}
</section>
<section>
	<form id="upload-form" action="/tool/{{draw_type}}" method="post" enctype="multipart/form-data" >
		<div class="main">
			<input type="file" name="file" id="file" class="inputfile" />
		</div>
		<div class="row gtr-uniform">
			<div class="col-6 col-12-xsmall">
				<select name="save-type" id="save-type">
					<option value="png">选择保存的图片格式 默认png</option>
					<option value="png">png</option>
					<option value="tiff">tiff</option>
					<option value="jpg">jpg</option>
				</select>
			
				<div class="col-6 col-12-xsmall">
				{% if draw_type=="heatmap" %}
					<input type="text" name="color" id="color" placeholder="请输入颜色 默认 RdYlBu_r" />
				{% end %}
				</div>
			</div>
		</div>
		<div class="main">
			<input type="submit" value="submit" name="submit" id="submit" class="primary" />
		</div>
	</form>
</section>

然后写python代码

要完成画图,首先是需要用户输入参数,然后后台画图后提供下载,所以需要一个get,一个post功能。

class ToolHandler(tornado.web.RequestHandler):

	def get(self, draw_type):
		self.render('tool.html', draw_type=draw_type)
		
	def post(self, draw_type):
	        save_type = self.get_argument('save-type')
			submit = self.get_argument('submit')
			if draw_type == "heatmap":
				color = self.get_argument('color')
				if not color:
					color = "RdYlBu_r"
			if not save_type:
				save_type = "png"
			if submit:
			# 读取上传的文件,并保存到本地
				upload_path = os.path.join(os.path.dirname(__file__), 'static', 'files')  # 文件的暂存路径
				file_metas = self.request.files.get('file', None)  # 提取表单中‘name’为‘file’的文件元数据
				if not file_metas:
					raise tornado.web.HTTPError(404)
				for meta in file_metas:
					filename = meta['filename']
					current_time = time.strftime('%Y%m%d', time.localtime(time.time()))
					filename = current_time+str(random.randint(0, 10000000))+"."+filename.split(".")[-1]
					file_path = os.path.join(upload_path, filename)
					with open(file_path, 'wb') as up:
						up.write(meta['body'])
			if os.path.exists(file_path):
			# 如果文件上传好了就开始画图
				if draw_type == "heatmap":
					drawing_cls = config.DrawingConfig(file_path, save_type, color)
					drawing_cls.heatmap
					# 准备把画图配置都写到config中,都通过config配置及调用
			if os.path.exists(file_path+"."+save_type):
			# 如果画图好了,就开始进行文件下载
				self.set_header('Content-Type', 'application/octet-stream')
				self.set_header('Content-Disposition', 'attachment; filename=' + filename+"."+save_type)
				with open(file_path+"."+save_type, 'rb') as f:
					while True:
						data = f.read()
						if not data:
							break
						self.write(data)
				self.finish()

好了,tornado相关的代码完成,接下来写一个画heatmap的脚本。

# -*- coding: utf-8 -*-

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm
import re
plt.switch_backend('agg')
# agg让画图后台进行,不然后面部署到服务器上会出错

class HeatMap:

	def __init__(self, data_path, save_type="png", color="RdYlBu_r"):
		self.data_path = data_path
		self.color = color
		self.save_type = save_type

	def read_data(self):
		# 支持三种格式,都通过pandas读取数据
		if re.findall('.xlsx$', self.data_path):
			datas = pd.read_excel(self.data_path)
		elif re.findall('.csv$', self.data_path):
			datas = pd.read_excel(self.data_path)
		elif re.findall('.txt$', self.data_path):
			datas = pd.read_table(self.data_path)
		else:
			raise IOError("only xlsx/txt/csv supported!!")
		# 提取数据中的最大值,最小值,以及header
		header = []
		data_max = 0
		data_min = 0
		for x in datas:
			header.append(str(x))
			if datas[x][np.argmax(datas[x])] > data_max:
				data_max = datas[x][np.argmax(datas[x])]
			if datas[x][np.argmin(datas[x])] < data_min:
				data_min = datas[x][np.argmin(datas[x])]
		return datas, header, data_max, data_min

	def map_color(self):
		# 获取heatmap图的颜色
		cmap = matplotlib.cm.get_cmap(self.color, 1000)
		return cmap

	def main(self):
		datas, header, data_max, data_min = self.read_data()
		plt.figure()
		plt_tmp = plt.imshow(datas, interpolation="nearest", cmap=self.map_color(), aspect='auto', vmin=data_min, vmax=data_max)
		plt.xticks(range(len(header)), header, rotation=60)
		plt.yticks((),())
		cb = plt.colorbar(mappable=plt_tmp, cax=None, ax=None, shrink=1)
		cb.set_label('(%)')
		plt.savefig(self.data_path+"."+self.save_type)

然后再config中加入heatmap绘图的配置:

class DrawingConfig:

	def __init__(self, file_path, save_type="png", color="YdYlBu_r"):
		self.file_path = file_path
		self.save_type = save_type
		self.color = color
	
	@property  # 这里想直接 DrawingConfig.heatmap 调用
	def heatmap(self):
		return heatmap.HeatMap(self.file_path, save_type=self.save_type, color=self.color).main()

其他类型的绘图也通过同种方式添加,这样网站的开发就几乎完成了,后面再美化美化就可以往服务器上部署了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值