Skip to content

Commit 6d4d23f

Browse files
committed
adding widgets
1 parent 437f836 commit 6d4d23f

File tree

10 files changed

+387
-0
lines changed

10 files changed

+387
-0
lines changed

src/accessvis/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from . import _version
55
from .earth import *
66
from .utils import *
7+
from .widgets import *
78

89
# Add current directory to sys.path because python is deranged
910
sys.path.append(os.path.dirname(__file__))

src/accessvis/widgets/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .widget_base import Widget, WidgetMPL, list_widgets
2+
from .season_widget import SeasonWidget
3+
from .calendar_widget import CalendarWidget
4+
from .clock_widget import ClockWidget
5+
from .image_widget import ImageWidget
6+
from .text_widget import TextWidget
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
import calendar
4+
import datetime
5+
from .widget_base import WidgetMPL
6+
7+
class CalendarWidget(WidgetMPL):
8+
def __init__(self,lv, text_colour='black', **kwargs):
9+
super().__init__(lv=lv, **kwargs)
10+
self.text_colour = text_colour
11+
self.arrow = None
12+
13+
def _make_mpl(self):
14+
15+
plt.rc('axes', linewidth=4)
16+
plt.rc('font', weight='bold')
17+
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(5, 5))
18+
fig.patch.set_facecolor((0, 0, 0, 0)) # make background transparent
19+
ax.set_facecolor('white') # adds a white ring around edge
20+
21+
# Setting up grid
22+
ax.set_rticks([])
23+
ax.grid(False)
24+
ax.set_theta_zero_location('NW')
25+
ax.set_theta_direction(-1)
26+
27+
# Label Angles
28+
MONTH = []
29+
for i in range(1, 13):
30+
MONTH.append(calendar.month_name[i][0])
31+
MONTH = np.roll(MONTH, 2)
32+
ANGLES = np.linspace(0.0, 2 * np.pi, 12, endpoint=False)
33+
ax.tick_params(axis='x', which='major', pad=12, labelcolor=self.text_colour)
34+
ax.set_xticks(ANGLES)
35+
ax.set_xticklabels(MONTH, size=20)
36+
ax.spines['polar'].set_color(self.text_colour)
37+
38+
# Make Colours:
39+
ax.bar(x=0, height=10, width=np.pi * 2, color='black')
40+
for i in range(12):
41+
c = 'darkorange' if i % 2 else 'darkcyan'
42+
ax.bar(x=i * np.pi / 6, height=10, width=np.pi / 6, color=c)
43+
44+
return fig, ax
45+
46+
47+
def _update_mpl(self, fig, ax, date: datetime.datetime = None, show_year=True):
48+
if show_year:
49+
title = str(date.year)
50+
else:
51+
title = ''
52+
fig.suptitle(title, fontsize=20, fontweight='bold', y=0.08, color=self.text_colour)
53+
54+
if date is None:
55+
return
56+
else:
57+
day_of_year = date.timetuple().tm_yday - 1
58+
position = day_of_year / 365. * np.pi * 2.0
59+
self.arrow = ax.arrow(position, 0, 0, 8.5, facecolor='#fff', width=0.1, head_length=2,
60+
edgecolor="black") # , zorder=11, width=1)
61+
62+
def _reset_mpl(self, fig, ax, **kwargs):
63+
fig.suptitle('')
64+
if self.arrow is not None:
65+
self.arrow.remove()

src/accessvis/widgets/clock_widget.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import datetime
2+
from .widget_base import WidgetMPL
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
6+
7+
class ClockWidget(WidgetMPL):
8+
def __init__(self, lv, text_colour='black', background='white',
9+
show_seconds=False, show_minutes=True, show_hours=True, **kwargs):
10+
super().__init__(lv=lv, **kwargs)
11+
self.text_colour = text_colour
12+
self.background = background
13+
self.show_hours = show_hours
14+
self.show_minutes = show_minutes
15+
self.show_seconds = show_seconds
16+
self.lines = []
17+
18+
# based on https://inprogrammer.com/analog-clock-python/
19+
def _make_mpl(self):
20+
fig = plt.figure(figsize=(2.5, 2.5), dpi=100)
21+
fig.patch.set_facecolor((0, 0, 0, 0)) # make background transparrent
22+
ax = fig.add_subplot(111, polar=True)
23+
plt.setp(ax.get_yticklabels(), visible=False)
24+
ax.set_xticks(np.linspace(0, 2 * np.pi, 12, endpoint=False))
25+
ax.set_xticklabels(range(1, 13))
26+
ax.tick_params(axis='x', which='major', labelcolor=self.text_colour)
27+
ax.set_theta_direction(-1)
28+
ax.set_theta_offset(np.pi / 3.0)
29+
ax.grid(False)
30+
plt.ylim(0, 1)
31+
32+
ax.set_facecolor(self.background)
33+
ax.spines['polar'].set_color(self.text_colour)
34+
35+
return fig, ax
36+
37+
def _update_mpl(self, fig, ax, time: datetime.time = None, **kwargs):
38+
hour = time.hour
39+
minute = time.minute
40+
second = time.second
41+
angles_h = 2 * np.pi * hour / 12 + 2 * np.pi * minute / (12 * 60) + 2 * second / (12 * 60 * 60) - np.pi / 6.0
42+
angles_m = 2 * np.pi * minute / 60 + 2 * np.pi * second / (60 * 60) - np.pi / 6.0
43+
angles_s = 2 * np.pi * second / 60 - np.pi / 6.0
44+
if time is None:
45+
return
46+
47+
if self.show_seconds:
48+
lines = ax.plot([angles_s, angles_s], [0, 0.9], color=self.text_colour, linewidth=1)
49+
self.lines.extend(lines)
50+
if self.show_minutes:
51+
lines = ax.plot([angles_m, angles_m], [0, 0.7], color=self.text_colour, linewidth=2)
52+
self.lines.extend(lines)
53+
if self.show_hours:
54+
lines = ax.plot([angles_h, angles_h], [0, 0.3], color=self.text_colour, linewidth=4)
55+
self.lines.extend(lines)
56+
57+
def _reset_mpl(self, fig, ax, **kwargs):
58+
for i in self.lines:
59+
i.remove()
60+
self.lines.clear()

src/accessvis/widgets/image_widget.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import numpy as np
2+
import imageio
3+
4+
from .widget_base import Widget
5+
6+
7+
class ImageWidget(Widget):
8+
def __init__(self, lv, file_path: str, **kwargs):
9+
super().__init__(lv, **kwargs)
10+
self.file_path = file_path
11+
12+
def _make_pixels(self, *args, **kwargs):
13+
img = imageio.imread(self.file_path)
14+
array = np.asarray(img)
15+
return array

src/accessvis/widgets/screen.frag

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
in vec4 vColour;
3+
in vec3 vVertex;
4+
in vec2 vTexCoord; // scale 0 .. 1
5+
6+
//Custom uniform
7+
uniform sampler2D uTexture;
8+
uniform float widthToHeight = 1; // 1 means square, 2 means width is double height
9+
uniform float scale = 0.5; // Scale down to half the height of the box
10+
uniform vec2 offset = vec2(0,0);
11+
12+
out vec4 outColour;
13+
14+
void main(void)
15+
{
16+
vec2 size = vec2(scale*widthToHeight, scale);
17+
vec2 texCoord = vTexCoord/size;
18+
texCoord.y = 1-texCoord.y;
19+
20+
texCoord.x += (1 - 1/size.x) * offset.x;
21+
texCoord.y += (1/size.y - 1) * offset.y;
22+
23+
24+
25+
if (texCoord.x >= 0.0 && texCoord.y >= 0.0 && texCoord.x <= 1.0 && texCoord.y <= 1.0)
26+
outColour = texture(uTexture, texCoord);
27+
else
28+
discard;
29+
30+
//Discard transparent to skip depth write
31+
//This fixes depth buffer output interfering with other objects
32+
// in transparent areas
33+
if (outColour.a <= 0.1)
34+
discard;
35+
}
36+

src/accessvis/widgets/screen.vert

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
in vec3 aVertexPosition;
2+
in vec3 aVertexNormal;
3+
in vec4 aVertexColour;
4+
in vec2 aVertexTexCoord;
5+
6+
uniform mat4 uMVMatrix;
7+
uniform mat4 uPMatrix;
8+
uniform mat4 uNMatrix;
9+
10+
uniform vec4 uColour;
11+
12+
out vec4 vColour;
13+
out vec3 vVertex;
14+
out vec3 vNormal;
15+
out vec2 vTexCoord;
16+
void main(void) {
17+
gl_Position = vec4(aVertexPosition, 1.0);
18+
19+
vNormal = normalize(mat3(uNMatrix) * aVertexNormal);
20+
21+
if (uColour.a > 0.0)
22+
vColour = uColour;
23+
else
24+
vColour = aVertexColour;
25+
26+
vTexCoord = aVertexTexCoord;
27+
vVertex = aVertexPosition;
28+
}
29+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
import datetime
4+
5+
from .widget_base import WidgetMPL
6+
7+
class SeasonWidget(WidgetMPL):
8+
# TODO: Change colours so summer colour starts in december, not jan.
9+
# Consider adding in astronomical seasons (solstices).
10+
def __init__(self, lv, text_colour='black', hemisphere='south', **kwargs):
11+
super().__init__(lv=lv, **kwargs)
12+
self.text_colour = text_colour
13+
self.hemisphere = hemisphere
14+
self.arrow = None
15+
16+
def _make_mpl(self):
17+
plt.rc('axes', linewidth=4)
18+
plt.rc('font', weight='bold')
19+
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(5, 5))
20+
fig.patch.set_facecolor((0, 0, 0, 0)) # make background transparrent
21+
ax.set_facecolor('white') # adds a white ring around edge
22+
23+
# Setting up grid
24+
ax.set_rticks([])
25+
ax.grid(False)
26+
ax.set_theta_zero_location('NW')
27+
ax.set_theta_direction(-1)
28+
29+
# Label Angles
30+
MONTH = ['Jan', 'Apr', 'Jul', 'Oct']
31+
ANGLES = np.linspace(0.0, 2 * np.pi, 4, endpoint=False)
32+
ax.tick_params(axis='x', which='major', pad=12, labelcolor=self.text_colour)
33+
ax.set_xticks(ANGLES)
34+
ax.set_xticklabels(MONTH, size=20)
35+
ax.spines['polar'].set_color(self.text_colour)
36+
37+
# Make Colours:
38+
ax.bar(x=0, height=10, width=np.pi * 2, color='black')
39+
ax.bar(x=5 * np.pi / 4, height=10, width=np.pi / 2,
40+
color='darkcyan' if self.hemisphere == 'south' else 'darkorange') # Southern Winter
41+
ax.bar(x=np.pi / 4, height=10, width=np.pi / 2,
42+
color='darkorange' if self.hemisphere == 'south' else 'darkcyan') # Southern Summer
43+
44+
return fig, ax
45+
46+
def _update_mpl(self, fig, ax, date: datetime.datetime = None, show_year=True):
47+
if show_year and date is not None:
48+
title = str(date.year)
49+
else:
50+
title = ''
51+
fig.suptitle(title, fontsize=20, fontweight='bold', y=0.08, color=self.text_colour)
52+
53+
if date is None:
54+
return
55+
else:
56+
day_of_year = date.timetuple().tm_yday - 1
57+
position = day_of_year / 365. * np.pi * 2.0
58+
self.arrow = ax.arrow(position, 0, 0, 8.5, facecolor='#fff', width=0.1, head_length=2,
59+
edgecolor="black") # , zorder=11, width=1)
60+
61+
def _reset_mpl(self, fig, ax, **kwargs):
62+
fig.suptitle('')
63+
if self.arrow is not None:
64+
self.arrow.remove()

src/accessvis/widgets/text_widget.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import matplotlib.pyplot as plt
2+
from .widget_base import WidgetMPL
3+
4+
5+
class TextWidget(WidgetMPL):
6+
def __init__(self, lv, width=300, height=50, text_colour='black', background=(0, 0, 0, 0), **kwargs):
7+
super().__init__(lv, **kwargs)
8+
self.width = width
9+
self.height = height
10+
self.text_colour = text_colour
11+
self.background = background
12+
13+
def _make_mpl(self):
14+
fig, ax = plt.subplots(figsize=(self.width / 100, self.height / 100), dpi=100)
15+
fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
16+
ax.set_axis_off()
17+
fig.patch.set_facecolor(self.background)
18+
19+
return fig, ax
20+
21+
def _update_mpl(self, fig, ax, text='', **kwargs):
22+
ax.text(0.5, 0.5, text, ha='center', va='center', fontsize=20, color=self.text_colour)
23+
24+
def _reset_mpl(self, fig, ax, **kwargs):
25+
pass

0 commit comments

Comments
 (0)