from IPython.display import HTML, display
display(HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<a href="javascript:code_toggle()">^</a>'''))
print('')
# REQUEST INDEXES
import requests
r = requests.get("https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/indexes/videotheques_index.json")
movies = r.json()['index']
button_color = 'black' # #7d1b27 darkRed
print('\n', '\n', '\n', '\n', '\n')
import ipywidgets as widgets
index = widgets.Dropdown(
options=movies,
value="2001_a_space_odyssey",
description='MOVIE',
disabled=False,
)
display(index)
print('\n', '\n', '\n', '\n', '\n')
from IPython.display import clear_output
# PLOT SOM
button_icons = ['„','‹','ˆ',"'",'~','˛','˝','¸','¯','•','º',"˙",'«','”','¨','˘']
def plot_som(event):
clear_output()
display(plot_som_button)
my_movie = '/'+index.value
#print (index.value)
import requests
r = requests.get("https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/soms%s/contour-rgb.json"%my_movie)
global som_index
som_index = r.json()
how_many = 16
plot_x, plot_y = 4,4
# OPEN IMAGES ------------------------------
import requests
s3BucketName = "panoramas-of-cinema"
region_name = 'eu-central-1'
frames_plot = []
for i in range(how_many):
bmu = str(i)
objectKey = "soms%s/%s.jpg"%(my_movie,bmu)
this_frame = "https://%s.s3.%s.amazonaws.com/%s"%(s3BucketName,region_name,objectKey)
r = requests.get(this_frame)
if r.status_code == 200:
img = r.content
else:
this_frame = "https://%s.s3.%s.amazonaws.com/soms/empty_bmu.jpg"%(s3BucketName,region_name)
img = requests.get(this_frame).content
frames_plot.append( (bmu, _, img) )
# BUTTON EVENT ------------------------------
def on_button_clicked(event):
global bmu_2p
this_button = id(event)
all_buttons = my_som['w_buttons']
for i, b in enumerate(all_buttons):
this_id = id(b)
if this_button == this_id:
bmu_2p = my_som['w_buttons'][i].tooltip
global my_globals_bmu
my_globals_bmu = {'plotted':[], 'w_buttons':[]}
# PLOT ------------------------------
from ipywidgets import Button, HBox, VBox
import ipywidgets as widgets
k = 0
movie_index, movie_names = 0, []
vboxes = []
for i in range(plot_x):
this_col = []
for j in range(plot_y):
if k < len(frames_plot):
try:
image_w = widgets.Image(value=frames_plot[k][2], format='jpg', width=250) #height=400
button = widgets.Button(description=button_icons[k], tooltip=frames_plot[k][0])
my_som['w_buttons'].append(button)
button.on_click( on_button_clicked )
this_box = [image_w, button]
this_col = this_col+this_box
except:
raise
k+=1
box = VBox( this_col )
vboxes.append(box)
display(HBox( vboxes ))
my_som = {'plotted':[], 'w_buttons':[]}
plot_som_button = widgets.Button(description="show map", button_style='info')
plot_som_button.style.button_color = button_color
display(plot_som_button)
plot_som_button.on_click(plot_som)
# DISPLAY WIDGETS
from IPython.display import display, clear_output
from ipywidgets import interactive, interact
import ipywidgets as widgets
# PLOT RANDOM FRAMES
def plot_frames_bmu(event):
clear_output()
display(plot_bmu_button)
my_movie = '/'+index.value
print (index.value, end=' ')
how_many = 16
plot_x, plot_y = 4,4
my_frames = som_index[bmu_2p]
if len(my_frames) < how_many:
how_many = len(my_frames)
this_sample = []
print ("%s"%button_icons[int(bmu_2p)])
for i in range(len(my_frames)):
if len(my_globals_bmu['plotted']) == len(my_frames):
my_globals_bmu['plotted'] = []
print("...you've seen it all")
if i in my_globals_bmu['plotted']:
pass
else:
this_sample.append(i)
my_globals_bmu['plotted'].append(i)
if len(my_globals_bmu['plotted']) == len(my_frames):
print('...last batch')
break
if len(this_sample) == how_many:
break
# OPEN IMAGES ------------------------------
import requests
s3BucketName = "panoramas-of-cinema"
region_name = 'eu-central-1'
i=0
frames_plot = []
for frame in my_frames:
if i in this_sample:
try:
objectKey = "frames_db%s/by_scene_thumbnail%s" % (my_movie, frame)
this_frame = "https://%s.s3.%s.amazonaws.com/%s"%(s3BucketName,region_name,objectKey)
img = requests.get(this_frame).content
frames_plot.append( (my_movie, frame, img) )
except:
raise
i+=1
# PLOT ------------------------------
def on_button_clicked(event):
global movie_2p
global frame_2p
this_button = id(event)
G = globals()
all_buttons = G['my_globals_bmu']['w_buttons']
for i, b in enumerate(all_buttons):
this_id = id(b)
if this_button == this_id:
movie_2p = my_globals_bmu['w_buttons'][i].tooltip
frame_2p = my_globals_bmu['w_buttons'][i].description
print('...plotting %s images from %s'%(how_many, len(my_frames)))
from ipywidgets import Button, HBox, VBox
import ipywidgets as widgets
k = 0
movie_index, movie_names = 0, []
vboxes = []
for i in range(plot_x):
this_col = []
for j in range(plot_y):
if k < len(frames_plot):
try:
image_w = widgets.Image(value=frames_plot[k][2], format='png', width=250) #height=400
button = widgets.Button(description=frames_plot[k][1], tooltip=frames_plot[k][0])
my_globals_bmu['w_buttons'].append(button)
button.on_click( on_button_clicked )
this_box = [image_w, button]
this_col = this_col+this_box
except:
raise
k+=1
box = VBox( this_col )
vboxes.append(box)
display(HBox( vboxes ))
plot_bmu_button = widgets.Button(description="navigate", button_style='info')
plot_bmu_button.style.button_color = button_color
display(plot_bmu_button)
plot_bmu_button.on_click(plot_frames_bmu)
print('\n', '\n', '\n', '\n', '\n')
def refresh_index(event):
clear_output()
my_movie = '/'+index.value
r = requests.get("https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/inventories%s.json"%my_movie)
query_response = r.json()
print (index.value)
print ('')
# SHOW PLACES
print ('PLACES INDEX')
for e in sorted(query_response['places']):
print(e, end=' . ')
print('')
# SHOW INDEXES
print ('')
print ('')
print ('OBJECTS INDEX')
for e in sorted(query_response['objects']):
print(e, end=' . ')
print ('')
print ('')
display(refresh_index_button)
refresh_index_button = widgets.Button(description="show indexes", button_style='info')
refresh_index_button.style.button_color = button_color
display(refresh_index_button)
refresh_index_button.on_click(refresh_index)
# DISPLAY WIDGETS
from IPython.display import display, clear_output
from ipywidgets import interactive, interact
import ipywidgets as widgets
options = []
s=0.01
for i in range(100):
options.append("%.2f"%s)
s+=.01
def p(place, confidence):
return
def o(obj, confidence):
return
w_places = interactive(p, place='',
confidence = widgets.SelectionRangeSlider(options=options, index=(0,99), description='confidence') )
w_objects = interactive(o, obj='',
confidence = widgets.SelectionRangeSlider(options=options, index=(0,99), description='confidence') )
display(w_places)
display(w_objects)
def f(no_faces, yes_faces):
return
w_faces = interactive(f, no_faces=True, yes_faces=True)
display(w_faces)
# REFRESH QUERY
def refresh_query(event):
clear_output()
display(refresh_button)
my_movie = '/'+index.value
print (index.value)
place = w_places.kwargs['place']
place_conf = "%s,%s"%(w_places.kwargs['confidence'])
obj = w_objects.kwargs['obj']
obj_conf = "%s,%s"%(w_objects.kwargs['confidence'])
faces = str()
if w_faces.kwargs['no_faces']:
faces = faces+'no_faces'
if w_faces.kwargs['yes_faces']:
if len(faces) > 0:
faces = faces+',small_faces'
else:
faces = faces+'small_faces'
#
this_query = 'http://pocquery-env.eba-ap3n3cr3.eu-central-1.elasticbeanstalk.com/queryMovie?'
if place: this_query = this_query+'places=%s,%s'%(place,place_conf)
if faces: this_query = this_query+'&faces=%s'%faces
if obj: this_query = this_query+'&objects=%s,%s'%(obj,obj_conf)
this_query = this_query+'&movie=%s'%(my_movie[1:])
global my_frames
my_frames = requests.get(this_query).json()['response']
print (len(my_frames), 'images with this search') # this_query[73:]
global my_globals
my_globals = {'plotted':[], 'w_buttons':[]}
refresh_button = widgets.Button(description="search", button_style='info')
refresh_button.style.button_color = button_color
display(refresh_button)
refresh_button.on_click(refresh_query)
# PLOT RANDOM FRAMES
def plot_frames(event):
clear_output()
display(plot_button)
my_movie = '/'+index.value
how_many = 16
plot_x, plot_y = 4,4
if len(my_frames) < how_many:
how_many = len(my_frames)
all_i = [ i for i in range(len(my_frames)) ]
import random
on_off = True
this_sample = []
while on_off:
if len(my_globals['plotted']) == len(my_frames):
my_globals['plotted'] = []
print("...you've seen it all")
r = random.choice(all_i)
if r in my_globals['plotted']:
pass
else:
this_sample.append(r)
my_globals['plotted'].append(r)
if len(my_globals['plotted']) == len(my_frames):
print('...last batch')
break
if len(this_sample) == how_many:
break
# OPEN IMAGES ------------------------------
import requests
s3BucketName = "panoramas-of-cinema"
region_name = 'eu-central-1'
i=0
frames_plot = []
for e in my_frames:
film = e['movieId']
frame = e['frameId']
if i in this_sample:
try:
objectKey = "frames_db%s/by_scene_thumbnail%s" % (my_movie, frame)
this_frame = "https://%s.s3.%s.amazonaws.com/%s"%(s3BucketName,region_name,objectKey)
img = requests.get(this_frame).content
frames_plot.append( (film, frame, img) )
except:
raise
i+=1
# PLOT ------------------------------
def on_button_clicked(event):
global movie_2p
global frame_2p
this_button = id(event)
G = globals()
all_buttons = G['my_globals']['w_buttons']
for i, b in enumerate(all_buttons):
this_id = id(b)
if this_button == this_id:
movie_2p = my_globals['w_buttons'][i].tooltip
frame_2p = my_globals['w_buttons'][i].description
print('...plotting %s images from %s'%(how_many, len(my_frames)))
from ipywidgets import Button, HBox, VBox
import ipywidgets as widgets
k = 0
movie_index, movie_names = 0, []
vboxes = []
for i in range(plot_x):
this_col = []
for j in range(plot_y):
if k < len(frames_plot):
try:
image_w = widgets.Image(value=frames_plot[k][2], format='png', width=250) #height=400
button = widgets.Button(description=frames_plot[k][1], tooltip=frames_plot[k][0])
my_globals['w_buttons'].append(button)
button.on_click( on_button_clicked )
this_box = [image_w, button]
this_col = this_col+this_box
except:
raise
k+=1
box = VBox( this_col )
vboxes.append(box)
display(HBox( vboxes ))
plot_button = widgets.Button(description="show", button_style='info')
plot_button.style.button_color = button_color
display(plot_button)
plot_button.on_click(plot_frames)
print('\n', '\n', '\n', '\n', '\n')
from IPython.display import Image, display
def get_hq_image(event):
clear_output()
display(hq_image_button)
objectKey = "frames_db%s/by_scene%s" % (movie_2p, frame_2p)
display(Image(url='https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/%s'%objectKey, width=450))
print('%s%s'%(movie_2p[1:],frame_2p[6:-4]))
hq_image_button = widgets.Button(description="hq image", button_style='info')
hq_image_button.style.button_color = button_color
display(hq_image_button)
hq_image_button.on_click(get_hq_image)
print('\n', '\n', '\n', '\n', '\n')
# PLAY THE CLIP
def play_clip(event):
clear_output()
display(ui1)
global r
clip_query = 'http://pocgetclip-env.eba-4phq6b4m.eu-central-1.elasticbeanstalk.com/clip?movie=%s&frame=%s'%(movie_2p[1:],frame_2p[7:-4])
r = requests.get(clip_query).json()
#print(r)
from IPython.display import Video
display(Video(r['play'], height=300, html_attributes="controls autoplay"))
print('%s%s'%(movie_2p[1:],frame_2p[6:-4]))
def play_before(event):
clear_output()
display(ui1)
from IPython.display import Video
display(Video(r['before'], height=300, html_attributes="controls autoplay"))
this_f = r['before'].find('frame-')
print('%s%s'%(movie_2p[1:],r['before'][(this_f)+5:-4]))
def play_after(event):
clear_output()
display(ui1)
from IPython.display import Video
display(Video(r['after'], height=300, html_attributes="controls autoplay"))
this_f = r['after'].find('frame-')
print('%s%s'%(movie_2p[1:],r['after'][(this_f)+5:-4]))
# buttons box
play_button = widgets.Button(description="play", button_style='info')
play_button.style.button_color = button_color
playB_button = widgets.Button(description="<<<", button_style='info')
playB_button.style.button_color = button_color
playA_button = widgets.Button(description=">>>", button_style='info')
playA_button.style.button_color = button_color
ui1 = widgets.HBox([playB_button, play_button, playA_button])
display(ui1)
play_button.on_click(play_clip)
playB_button.on_click(play_before)
playA_button.on_click(play_after)
no sound ? try Safari ))
print('\n', '\n', '\n', '\n', '\n')
# GLOBAL
r = requests.get("https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/indexes/categories.json")
text_cat = r.json()
# DISPLAY WIDGETS
from IPython.display import display, clear_output
from ipywidgets import interactive, interact
import ipywidgets as widgets
def search_text(text, confidence, max_results, c):
return
w_search_text = interactive(search_text, text='gone south',
confidence=widgets.SelectionRangeSlider(options=options, index=(0,99), description='confidence'),
max_results='10',
c=widgets.HTML(description='categories', value="<a target='_blank' href='https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/indexes/categories.txt'>></a>", placeholder='')
)
display(w_search_text)
# REFRESH QUERY
import requests, ast
def format_text(query):
this_query = query.replace(' ', '%20')
return this_query
def get_cat(movie):
cat_names = ['SOLARIS MON AMOUR','EQUILIBRIUM OF AN OLDBOY',
'THE 400 CHILDREN OF LA HEINE','Y TU MAMA TAMBIEN DEPARTED']
for k in text_cat:
if movie in text_cat[k]:
return ( int(k)+1, cat_names[int(k)] )
def text_search(event):
clear_output()
display(search_button)
# MAKE A QUERY ------------------------------
text = format_text(w_search_text.kwargs['text'])
confX = w_search_text.kwargs['confidence'][0]
confY = w_search_text.kwargs['confidence'][1]
max_results = w_search_text.kwargs['max_results']
cat = get_cat('/'+index.value)
app_http = 'http://ec2-3-127-150-33.eu-central-1.compute.amazonaws.com'
this_query = app_http+'/subs?'
if text: this_query = this_query+'text=%s&confidence_min=%s&confidence_max=%s'%(text,confX,confY)
if max_results: this_query = this_query+'&maxResults=%s&category=%s'%(max_results,cat[0])
#print(this_query)
my_text = ast.literal_eval(requests.get(this_query).text)['body']
if len(my_text) == 0:
print ('nothing here')
return
# BUTTON EVENT ------------------------------
def on_button_clicked(event):
global movie_2p
global frame_2p
this_button = id(event)
for i, b in enumerate(buttons_text):
this_id = id(b)
if this_button == this_id:
movie_2p = buttons_text[i].description
frame_2p = '/frame-%06d.jpg'%float(buttons_text[i].tooltip)
# DISPLAY THE RESULTS ------------------------------
from ipywidgets import VBox, Label, Button
print ('')
display( Label('˛ %s'%cat[1].lower()) )
# formatting
texts_results = []
for movie, timestamp, prev, this, nex in my_text:
this_text = prev+' '+this+' '+nex
texts_results+=[this_text]
# widgets
global buttons_text
buttons_text = []
items = []
for i, t in enumerate(texts_results):
button = Button(description=my_text[i][0], tooltip=str(my_text[i][1]))
buttons_text.append(button)
button.on_click( on_button_clicked )
items.append(Label(' '))
items.append(Label(t.lower()))
hlink = widgets.HTML(description='', value=" <a target='_blank' href='https://panoramas-of-cinema.s3.eu-central-1.amazonaws.com/subtitles_db%s/subs.txt'>></a>"%my_text[i][0], placeholder='')
uiH = widgets.HBox([button, hlink])
items.append(uiH)
display( VBox(items) )
search_button = widgets.Button(description="search", button_style='info')
search_button.style.button_color = button_color
display(search_button)
search_button.on_click(text_search)
print('\n', '\n', '\n', '\n', '\n')
tag_http = 'http://poctag-env.eba-vjpstfpz.eu-central-1.elasticbeanstalk.com/tags'
# DISPLAY WIDGETS
def getUser(user):
return
def getTag(tag):
return
w_user = interactive(getUser, user='')
w_tag = interactive(getTag, tag='')
# REFRESH QUERY
def add_tag(event):
clear_output()
display(w_tag)
display(w_user)
display(add_tag_button)
this_user = w_user.kwargs['user']
this_tag = w_tag.kwargs['tag']
this_frame = '%s,%s'%(movie_2p,frame_2p)
this_request = tag_http+'?action=ADD&tag=%s&user=%s&frame=%s'%(this_tag,this_user,this_frame)
r = requests.get(this_request).json()['statusCode']
if r == 200: print('tag added to : %s %s'%(movie_2p, frame_2p))
else: print ('error %s'%r)
add_tag_button = widgets.Button(description="add tag", button_style='info')
add_tag_button.style.button_color = button_color
add_tag_button.on_click(add_tag)
display(w_tag)
display(w_user)
display(add_tag_button)
print('\n', '\n', '\n', '\n', '\n')
this_request = tag_http+'?action=GET_ALL_USERS'
r = requests.get(this_request).json()['body']
for e in sorted(r):
print(e, end=' . ')
print('')
print('')
def get_users(event):
clear_output()
this_request = tag_http+'?action=GET_ALL_USERS'
r = requests.get(this_request).json()['body']
for e in sorted(r):
print(e, end=' . ')
display(refresh_users_button)
refresh_users_button = widgets.Button(description="refresh users", button_style='info')
refresh_users_button.style.button_color = button_color
display(refresh_users_button)
refresh_users_button.on_click(get_users)
# BOXES
def getUserSearch(user_search):
return
def getTagSearch(tag_search):
return
w_user_search = interactive(getUserSearch, user_search='')
w_tag_search = interactive(getTagSearch, tag_search='')
# BUTTON
def search_tag(event):
clear_output()
display(w_tag_search)
display(w_user_search)
display(search_tag_button)
this_user = w_user_search.kwargs['user_search']
this_tag = w_tag_search.kwargs['tag_search']
global my_frames_tag
if len(this_user) > 0 and len(this_tag) > 0:
this_request = tag_http+'?action=GET_FRAMES_USER_TAG&tag=%s&user=%s'%(this_tag,this_user)
my_frames_tag = requests.get(this_request).json()
this_length = len(my_frames_tag['body'])
print (this_length, 'images with this search')
elif len(this_user) > 0 and len(this_tag) == 0:
this_request = tag_http+'?action=GET_FRAMES_USER&user=%s'%(this_user)
my_frames_tag = requests.get(this_request).json()
this_length = len(my_frames_tag['body'])
print (this_length, 'images with this search')
this_tags = set([ f['tag'] for f in my_frames_tag['body'] ])
print (this_user, 'is talking about . ', end='')
for e in sorted(this_tags): print(e, end=' . ')
elif len(this_user) == 0 and len(this_tag) > 0:
this_request = tag_http+'?action=GET_FRAMES_TAG&tag=%s'%(this_tag)
my_frames_tag = requests.get(this_request).json()
this_length = len(my_frames_tag['body'])
print (this_length, 'images with this search')
this_users = set([ f['user'] for f in my_frames_tag['body'] ])
print (this_tag, 'is talked about by . ', end='')
for e in sorted(this_users): print(e, end=' . ')
else:
print ('type a user name and/or a tag')
global my_globals_tag
my_globals_tag = {'plotted':[], 'w_buttons':[]}
search_tag_button = widgets.Button(description="search tag", button_style='info')
search_tag_button.style.button_color = button_color
search_tag_button.on_click(search_tag)
display(w_tag_search)
display(w_user_search)
display(search_tag_button)
# PLOT RANDOM FRAMES
def plot_frames_tags(event):
clear_output()
display(plot_button_tags)
my_frames = my_frames_tag['body']
how_many = 16
plot_x, plot_y = 4,4
if len(my_frames) < how_many:
how_many = len(my_frames)
all_i = [ i for i in range(len(my_frames)) ]
import random
on_off = True
this_sample = []
while on_off:
if len(my_globals_tag['plotted']) == len(my_frames):
my_globals_tag['plotted'] = []
print("...you've seen it all")
r = random.choice(all_i)
if r in my_globals_tag['plotted']:
pass
else:
this_sample.append(r)
my_globals_tag['plotted'].append(r)
if len(my_globals_tag['plotted']) == len(my_frames):
print('...last batch')
break
if len(this_sample) == how_many:
break
# OPEN IMAGES ------------------------------
import requests
s3BucketName = "panoramas-of-cinema"
region_name = 'eu-central-1'
i=0
frames_plot = []
for e in my_frames:
film = e['movie']
frame = e['frame']
if i in this_sample:
try:
objectKey = "frames_db%s/by_scene_thumbnail%s" % (film, frame)
this_frame = "https://%s.s3.%s.amazonaws.com/%s"%(s3BucketName,region_name,objectKey)
img = requests.get(this_frame).content
frames_plot.append( (film, frame, img) )
except:
raise
i+=1
# PLOT ------------------------------
def on_button_clicked(event):
global movie_2p_tag, frame_2p_tag
global movie_2p, frame_2p
this_button = id(event)
G = globals()
all_buttons = G['my_globals_tag']['w_buttons']
for i, b in enumerate(all_buttons):
this_id = id(b)
if this_button == this_id:
movie_2p_tag = my_globals_tag['w_buttons'][i].description
frame_2p_tag = my_globals_tag['w_buttons'][i].tooltip
movie_2p = my_globals_tag['w_buttons'][i].description
frame_2p = my_globals_tag['w_buttons'][i].tooltip
print('...plotting %s images from %s'%(how_many, len(my_frames)))
from ipywidgets import Button, HBox, VBox
import ipywidgets as widgets
k = 0
movie_index, movie_names = 0, []
vboxes = []
for i in range(plot_x):
this_col = []
for j in range(plot_y):
if k < len(frames_plot):
try:
image_w = widgets.Image(value=frames_plot[k][2], format='png', width=250) #height=400
button = widgets.Button(description=frames_plot[k][0], tooltip=frames_plot[k][1])
my_globals_tag['w_buttons'].append(button)
button.on_click( on_button_clicked )
this_box = [image_w, button]
this_col = this_col+this_box
except:
raise
k+=1
box = VBox( this_col )
vboxes.append(box)
display(HBox( vboxes ))
plot_button_tags = widgets.Button(description="show", button_style='info')
plot_button_tags.style.button_color = button_color
display(plot_button_tags)
plot_button_tags.on_click(plot_frames_tags)
print('\n', '\n', '\n', '\n', '\n')
def delete_tag(event):
clear_output()
display(delete_tag_button)
this_user = w_user_search.kwargs['user_search']
this_tag = w_tag_search.kwargs['tag_search']
if len(this_user) > 0 and len(this_tag) > 0:
this_frame = '%s,%s'%(movie_2p_tag,frame_2p_tag)
this_request = tag_http+'?action=DELETE&tag=%s&user=%s&frame=%s'%(this_tag,this_user,this_frame)
r = requests.get(this_request).json()['statusCode']
if r == 200: print('tag deleted : %s %s'%(movie_2p_tag, frame_2p_tag))
else: print ('error %s'%r)
else:
print ('! user or tag is missing')
delete_tag_button = widgets.Button(description="delete", button_style='info')
delete_tag_button.style.button_color = button_color
display(delete_tag_button)
delete_tag_button.on_click(delete_tag)
print('\n', '\n', '\n', '\n', '\n')
ETH Zurich Department of Architecture Chair for Digital Architectonics 2021