Repository navigation
Expand file tree
/
Copy pathmatplotlib_cs.py
More file actions
177 lines (140 loc) · 5.16 KB
/
Copy pathmatplotlib_cs.py
File metadata and controls
177 lines (140 loc) · 5.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# -*- coding: utf-8 -*-
import json
import sys, getopt
import matplotlib.pyplot as plot
import matplotlib.patches as patches
import numpy as np
from matplotlib import rc
from flask import Flask, url_for, request, json, Response, abort, jsonify
from task import Task
import datetime
import matplotlib.dates as mdates
from helpers import if_string_convert_to_datetime
import matplotlib.ticker as ticker
# Script builds a matplotlib figure based on information, passed to it through json file.
# Path to the JSON must be passed in first command line argument.
# a trick to enable text labels in cyrillic
rc('font', **{'sans-serif': 'Arial','family': 'sans-serif'})
app = Flask(__name__)
def main(args):
host = "127.0.0.1"
app.run(host=host, port=57123)
@app.route('/', methods=['POST', 'GET'])
def api_check_alive():
return '', 200
@app.route('/plot', methods=['POST', 'GET'])
def api_plot():
json_raw = request.json
task = json.loads(json_raw)
t = Task(task)
fig = plot.figure(figsize=[t.w/(1.0*t.dpi), t.h/(1.0*t.dpi)])
# precreate, make basic settings and save subplots
subplots = {}
subplot_index = 1
for i in range(0, t.rows):
for j in range(0, t.columns):
axes = fig.add_subplot(t.rows, t.columns, subplot_index)
subplots[subplot_index] = axes
# set_grid(axes)
subplot_index += 1
# draw items on each subplot
for subplot in t.subplots:
axes = subplots[subplot.index]
plot.sca(axes)
set_titles(subplot)
for item in subplot.items:
if item.is_visible == True:
item.plot(axes)
if subplot.show_legend:
plot.legend(loc=subplot.legend_location, frameon=subplot.frameon)
set_grid(fig, axes, subplot.grid)
plot.tight_layout()
save_figure_to_file(task)
if not task["onlySaveImage"]:
plot.show()
plot.close("all")
return '', 200
@app.route('/kill', methods=['POST', 'GET'])
def api_kill():
raise RuntimeError('Stop web service')
def save_figure_to_file(task):
"""
Saves figure content to the file if it's path is provided
:type task: dict
:param task: Deserialized json with task description
:return:
"""
if "filename" in task and task["filename"] is not None:
print ("Saving figure to file {0}".format(task["filename"]))
plot.savefig(task["filename"], dpi=task["dpi"])
def set_grid(fig, axes, grid):
"""
Setup axes grid
:param axes:
:return:
"""
axes.grid(which=grid.which)
axes.grid(which='minor', alpha=grid.minor_alpha)
axes.grid(which='major', alpha=grid.major_alpha)
axes.grid(grid.on)
if grid.x_lim is not None:
axes.set_xlim(grid.x_lim[0], grid.x_lim[1])
if grid.y_lim is not None:
axes.set_ylim(grid.y_lim[0], grid.y_lim[1])
# if time ticks defined
if grid.x_time_ticks is not None and len(grid.x_time_ticks) > 0:
timeTicks = []
for stringTick in grid.x_time_ticks:
timeTick = if_string_convert_to_datetime(stringTick)
timeTicks.append(timeTick)
# distance between nodes will be equal
if grid.regular_time_axis:
n = len(grid.x_time_ticks)
def format_date(x, pos=None):
thisind = np.clip(int(x + 0.5), 0, n - 1)
return timeTicks[thisind].strftime(grid.time_ticks_format['value'])
axes.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
# else distance between time nodes will be as is
else:
formatter = mdates.DateFormatter(grid.time_ticks_format['value'])
axes.xaxis.set_major_formatter(formatter)
axes.set_xticks(timeTicks)
# if no time ticks defined
elif grid.x_major_ticks is not None:
axes.set_xticks(build_ticks_list(grid.x_major_ticks))
if grid.x_minor_ticks is not None:
axes.set_xticks(build_ticks_list(grid.x_minor_ticks), minor=True)
if grid.y_major_ticks is not None:
axes.set_yticks(build_ticks_list(grid.y_major_ticks))
if grid.y_minor_ticks is not None:
axes.set_yticks(build_ticks_list(grid.y_minor_ticks), minor=True)
# set font and rotation
labels = axes.get_xticklabels()
if grid.x_tick_fontsize is not None and grid.x_tick_fontsize!=0:
plot.setp(labels, fontsize=grid.x_tick_fontsize)
if grid.x_tick_rotation is not None and grid.x_tick_rotation!=0:
plot.setp(labels, rotation=grid.x_tick_rotation)
def build_ticks_list(lims):
'''
First two values in lims are the minimum and the maximum values, while third value is a step.
Values starting from 4 are additional values which will be added to the grid
:param lims:
:return:
'''
ticks = np.arange(lims[0], lims[1] + lims[2], lims[2])
if len(lims) > 3:
for i in range(3, len(lims)):
ticks = np.append(ticks, [lims[i]])
return ticks
def set_titles(task):
"""
Setup subplot X and Y axis titles
:param task:
:return:
"""
plot.title(u"{0}".format(task.title))
plot.xlabel(task.xtitle)
plot.ylabel(task.ytitle)
# entry point
if __name__ == "__main__":
main(sys.argv[1:])