-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplot_generator.py
117 lines (106 loc) · 4.19 KB
/
plot_generator.py
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
import csv
import datetime
from bokeh.plotting import figure, output_file, show
from bokeh.models.widgets import Tabs, Panel, DateSlider, Toggle
from bokeh.layouts import layout
from bokeh.models import CustomJS, ColumnDataSource, HoverTool, LabelSet
dates=[]
stats=[]
with open('Stats.csv', newline='') as csvfile:
csvreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
csvreader = list(csvreader)[1:] #[1:] drops headers
for rawrow in csvreader:
rowdata=rawrow[0].split(',')
date=rowdata[0].split('-')
date=datetime.date(int(date[0]),int(date[1]),int(date[2]))
dates.append(date)
stats.append(int(float(rowdata[1])))
output_file('BOINC Total Credit Over Time.html', title='BOINC Total Credit Over Time')
dispsource=ColumnDataSource(data=dict(x=dates,
y=stats))
eventdates=[datetime.date(2004,6,22),datetime.date(2014,3,8),datetime.date(2017,6,14)]
labeltext=['Seti@home starts to use BOINC','Bitcoin Utopia Begins','Bitcoin Utopia Ends']
eventstats=[]
for date in eventdates:
closestdate=min(dates, key=lambda x:abs(x-date)) #find the closest date in dates
closestdate=dates.index(closestdate) #change from date to the index
eventstats.append(stats[closestdate]) #adds stats at the closest date
labelsource=ColumnDataSource(data=dict(x=eventdates,y=eventstats,text=labeltext))
panels=[]
plots=[]
for axistype in ['linear','log']:
labels = LabelSet(x='x',
y='y',
text='text',
source=labelsource,
angle=-3.14/2) #-pi/2 is 90 deg clockwise (makes it virtical)
p = figure(plot_width=650,
plot_height=600,
x_axis_type='datetime',
y_axis_type=axistype,
x_axis_label='Date',
y_axis_label='Total Credit',
x_range=(min(dates),max(dates)),
output_backend='webgl')
p.add_layout(labels) #add annoations to the charts
try:
p.left[0].formatter.use_scientific = False #disable scientific notation
except:
pass #fails if using log scale so it's ignore if failed
p.title.text = 'BOINC Total Credit Over Time'
p.title.align = 'center'
p.add_tools(HoverTool(tooltips = [
('Date','@x{%F}'), # {%F} formats dates like YYYY-MM-DD
('Total Credit','@y')],
formatters={'x': 'datetime'}))
p.scatter('x','y',source=dispsource, size=2, color='navy', alpha=0.5)
plots.append(p)
panels.append(Panel(child=p,title=axistype))
tabs=Tabs(tabs=panels)
callback= CustomJS(args=dict(stats=stats,dates=dates,plots=plots), code='''
var len = cb_obj.value;
var closest = stats[dates.indexOf(dates.reduce(function(prev, curr) {
return (Math.abs(curr - len) < Math.abs(prev - len) ? curr : prev);
}))]
plots[0].x_range.end=len;
plots[0].y_range.end=closest;
plots[0].y_range.start=0;
plots[1].x_range.end=len;
plots[1].y_range.end=closest;
plots[1].y_range.start=1;
''')
#changes x range to be (0,slider_value)
#changes y range to be (0 or 1, the closest stastics value to slider)
slider = DateSlider(start=min(dates), end=max(dates), value=max(dates), step=1, title='Time')
slider.js_on_change('value', callback)
loopchange = CustomJS(args=dict(slider=slider,endlen=max(dates),minlen=min(dates)), code='''
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
var len = slider.value;
var loopcount=0;
while (cb_obj.active){
if (len>=endlen){
loopcount++;
if(loopcount==2){
cb_obj.active=false;
break;
}
len=minlen;
}
len = len+864000000;
slider.value = len;
await sleep(4)
}
}
run();
''')
#loops through slider twice (only looks like once if starting at the end)
#adds 10 days at a time
#sleeps 4 milliseconds inbetween each increment
button = Toggle(label='▶\uFE0E', button_type='success')
#\uFE0E forces non emoji rendering (only on some browsers)
button.js_on_click(loopchange)
arrangement = layout([slider,button], tabs)
show(arrangement)