File size: 6,985 Bytes
5f59ba1 fef59a7 5f59ba1 fef59a7 5f59ba1 |
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 178 179 180 |
"""
Streamlit application
"""
from loguru import logger
import mpld3
import streamlit as st
import streamlit.components.v1 as components
from streamlit.errors import StreamlitAPIException
import yaml
import lsystc as ls
import specific_values as sv
st.set_page_config(page_title="Curves with L-systems", page_icon="🖼️", layout="wide")
@st.cache_data
def load_result(axiom, mult_axiom, rules, rotation_angle, starting_angle, skipped, nb_iterations, coeff):
"""
Return the result of the L-system with the specified parameters
:param axiom:
:param mult_axiom:
:param rules:
:param rotation_angle:
:param starting_angle:
:param skipped:
:param nb_iterations:
:param coeff:
:return: the result of the "L-System rendering"
"""
try:
config = ls.Config(skipped=skipped)
rules = rules.strip("; ")
rules_list = []
if rules:
for item in rules.split(";"):
if ':' in item:
splits = item.split(":")
if len(splits) == 2 and splits[0].strip():
left = splits[0].strip()
right = splits[1].strip()
rules_list.append((left, right))
else:
raise ValueError(f"Every rule must be correctly written ( {item} )")
else:
raise ValueError(f"Every non empty rule must include a column character ( {item} ) ")
rls = ls.Lsystc(config, axiom * mult_axiom, rules_list, nbiter=nb_iterations, verbose=sv.verbose)
rls.turtle(step=sv.step, angle=rotation_angle, angleinit=starting_angle, coeff=coeff,
color_length=sv.color_length, color_map=sv.color_map)
result = rls.render(sv.renderer, save_files=sv.save_files, show_more=sv.show_more, show_3d=sv.show_3d,
return_type=sv.return_type)
except ValueError as ex:
st.warning(f"Please verify your parameters - {ex}")
st.stop()
except Exception as ex:
st.warning("Please verify your parameters")
if sv.verbose:
logger.exception(f"Something went wrong : {ex}")
st.stop()
else:
return result
def write_specific(content):
"""
Write streamlit content
:param content: streamlit content
:return: None
"""
try:
st.write(content)
except StreamlitAPIException as exc:
# Currently : streamlit.errors.StreamlitAPIException: `_repr_html_()` is not a valid Streamlit command.
if sv.verbose:
logger.error(exc)
def on_change_selection():
"""
Change the parameters when the starting example is changed
:return: None
"""
current_selection = st.session_state.my_selection
axiom, mult_axiom, rules, rotation_angle, starting_angle, nb_iter, skipped, coeff = examples_data[current_selection]
st.session_state.my_axiom = axiom
st.session_state.my_mult_axiom = mult_axiom
st.session_state.my_rules = rules
st.session_state.my_rotation_angle = rotation_angle
st.session_state.my_starting_angle = starting_angle
st.session_state.my_nb_iter = nb_iter
st.session_state.my_skipped = skipped
st.session_state.my_coeff = coeff
sv.redraw_auto = True
with open("curves_parameters.yaml", 'r', encoding='utf8') as f:
curves_parameters = yaml.safe_load(f)
EXAMPLES_DEFAULT = 0
examples_names = []
examples_data = {}
for c_name, c_params in curves_parameters.items():
examples_names.append(c_name)
c_axiom = c_params.get('axiom', '')
c_axiom_multiplier = c_params.get('axiom_multiplier', 1)
c_rules = c_params.get('rules', '')
c_rotation_angle = c_params.get('rotation_angle', 90.0)
c_starting_angle = c_params.get('starting_angle', 0)
c_nb_iter = c_params.get('nb_iter', 1)
c_skipped = c_params.get('skipped', '')
c_coeff = c_params.get('coeff', 1.0)
examples_data[c_name] = (c_axiom, c_axiom_multiplier, c_rules,
c_rotation_angle, c_starting_angle, c_nb_iter, c_skipped, c_coeff)
EXAMPLES_DEFAULT_name = examples_names[EXAMPLES_DEFAULT]
def_axiom, def_mult_axiom, def_rules, def_rotation_angle, def_starting_angle, def_nb_iter, def_skipped, def_coeff = \
examples_data[EXAMPLES_DEFAULT_name]
with st.sidebar:
MD_INTRO = """
You have the flexibility to select a starting example and to change the parameters :sunglasses:
"""
st.markdown(MD_INTRO)
input_selection = st.selectbox('Starting example', examples_names,
index=EXAMPLES_DEFAULT, on_change=on_change_selection, key="my_selection")
input_axiom = st.text_input('Starting axiom', def_axiom, key="my_axiom")
input_mult_axiom = st.number_input('Multiplier for axiom', value=def_mult_axiom, min_value=1, key="my_mult_axiom")
input_rules = st.text_input('Rules', def_rules, help="Example for 2 rules -> A: ABC ; B: CAB ; ",
key="my_rules")
input_rotation_angle = st.number_input('Angle of rotation',
value=def_rotation_angle, min_value=1.0, max_value=360.0, step=1.0,
format='%f', key="my_rotation_angle")
input_starting_angle = st.number_input('Starting angle',
value=def_starting_angle, min_value=0, max_value=360,
format='%d', key="my_starting_angle")
input_skipped = st.text_input('Skipped characters', def_skipped, key="my_skipped")
input_coeff = st.number_input('Coefficient',
value=def_coeff, format='%f', key="my_coeff")
input_nb_iter = st.number_input('Number of iterations',
value=def_nb_iter, min_value=1, max_value=15, format='%d', key="my_nb_iter")
st.markdown("# Curves with L-systems")
st.markdown("""**Click on "Draw" to display the curve**""")
if st.button('Draw') or sv.redraw_auto or 'start' not in st.session_state:
sv.redraw_auto = False
st.session_state['start'] = True
res = load_result(input_axiom, input_mult_axiom, input_rules, input_rotation_angle, input_starting_angle,
input_skipped, input_nb_iter, input_coeff)
if sv.return_type == 'image':
write_specific(st.image(res, caption='Generated image'))
else:
if sv.renderer == 'matplot':
# Pyplot figure
# write_specific(st.pyplot(res))
fig_html = mpld3.fig_to_html(res)
components.html(fig_html, height=600)
elif sv.renderer == 'bokeh':
st.bokeh_chart(res, use_container_width=True)
elif sv.renderer == 'plotly':
st.plotly_chart(res, use_container_width=True)
st.markdown("---")
st.markdown("More details on Lindenmayer systems here : [Wikipedia](https://en.wikipedia.org/wiki/L-system)")
|