def cb_plot_testcase(attr, old, new, curr_doc: CurrentDoc): """ Plot given test case to the input plot and show results in the output plots. :param attr: not used :param old: not used :param new: changed attribute 'value' of the dropdown menu testcases (string) :return: none """ # bool to show callbacks that a testcase is being plotted curr_doc.plotting_test_case = True # clear input plot cb_button_delete(curr_doc, all_selected=True) # start plotting of specific test case if new == "single_beam_load": vis_init.expand_msg2user(curr_doc, "Single beam lineload test") visualisation_tests.single_beam_lineload_visu(curr_doc) elif new == "two_beam_lineload": vis_init.expand_msg2user(curr_doc, "Two beam lineload test") visualisation_tests.two_beam_lineload_visu(curr_doc) elif new == "fin_struc_soft_lab": vis_init.expand_msg2user(curr_doc, "Final structure software lab") visualisation_tests.example_unterlagen_visu(curr_doc) # testcase plotting done curr_doc.plotting_test_case = False
def cb_button_element_click(curr_doc: CurrentDoc, button_enum): """ Callback for all element buttons: - deselects previous button and select new button or deselect selected button if it already was selected before - saves selected one as Enum in 'button_activated' and change it's background color :param button_enum: Enum that corresponds to the button that was clicked (ElementSupportEnum) :return: none """ # unselect button if same button is selected again if not curr_doc.button_activated == -1 and curr_doc.button_activated == button_enum.value: button_style = button_enum.name curr_doc.buttons[curr_doc.button_activated].css_classes = [ button_style ] # update the currently activated button to none curr_doc.button_activated = -1 curr_doc.data_sources.ds_active_button.data['type'] = [-1] curr_doc.data_sources.ds_active_button.trigger( 'data', curr_doc.data_sources.ds_active_button.data, curr_doc.data_sources.ds_active_button.data) # reset datasource for first node for line elements data = dict(type=[], node_x=[], node_y=[], name_node1=[]) curr_doc.data_sources.ds_1st_chosen.data = data return # unselect previously selected button, if one was selected before at all if not curr_doc.button_activated == -1: found, button_style, value = eLnum.value_in_enum( eLnum.ElSupEnum, curr_doc.button_activated) curr_doc.buttons[curr_doc.button_activated].css_classes = [ button_style ] else: reset_element_info(curr_doc) # change background color of newly selected element button button_style = button_enum.name + '_selected' curr_doc.buttons[button_enum.value].css_classes = [button_style] # update the currently activated button curr_doc.button_activated = button_enum.value curr_doc.data_sources.ds_active_button.data['type'] = [ curr_doc.button_activated ] curr_doc.data_sources.ds_active_button.trigger( 'data', curr_doc.data_sources.ds_active_button.data, curr_doc.data_sources.ds_active_button.data) # reset datasource for first node for line elements data = dict(type=[], node_x=[], node_y=[], name_node1=[]) curr_doc.data_sources.ds_1st_chosen.data = data
def cb_elinfo_beam(attr, old, new, curr_doc: CurrentDoc): """ Callback for the beam CheckboxGroup. Set EI and/ or EA to be infinite. :param attr: not used :param old: not used :param new: changed attribute 'active' of the beam CheckboxGroup (list) :return: none """ # block user input while element info box gets changed (because of cb_get_textinput) curr_doc.elinfo_input_blocked = True elinfo = curr_doc.input_element_info element_index = curr_doc.elinfo_current_element[2] # get current state of EA and EI ea_infinite = False ei_infinite = False if curr_doc.data_sources.ds_nodedep_elements.data['ea'][ element_index] == float("inf"): ea_infinite = True if curr_doc.data_sources.ds_nodedep_elements.data['ei'][ element_index] == float("inf"): ei_infinite = True # EA was changed to infinite if 0 in new and not ea_infinite: curr_doc.data_sources.ds_nodedep_elements.data['ea'][ element_index] = float("inf") elinfo["ea"].disabled = True # EA was changed to finite elif 0 not in new and ea_infinite: curr_doc.data_sources.ds_nodedep_elements.data['ea'][ element_index] = 1.0 elinfo["ei"].value = "%3.1f" % 1.0 elinfo["ea"].disabled = False # EI was changed to infinite if 1 in new and not ei_infinite: curr_doc.data_sources.ds_nodedep_elements.data['ei'][ element_index] = float("inf") elinfo["ei"].disabled = True # EI was changed to finite elif 1 not in new and ei_infinite: curr_doc.data_sources.ds_nodedep_elements.data['ei'][ element_index] = 1.0 elinfo["ei"].value = "%3.1f" % 1.0 elinfo["ei"].disabled = False # release for user input curr_doc.elinfo_input_blocked = False
def cb_get_textinput(attr, old, new, curr_doc: CurrentDoc, key): """ Callback for the TextInputs of the element info box. :param attr: not used :param old: previous attribute 'value' of the TextInput (string) :param new: changed attribute 'value' of the TextInput (string) :param key: key of the specific TextInput (string) :return: none """ # check whether user input is blocked if curr_doc.elinfo_input_blocked: return element_name = curr_doc.elinfo_current_element[0] element_indep = curr_doc.elinfo_current_element[1] element_index = curr_doc.elinfo_current_element[2] try: value = float(new) except ValueError: curr_doc.div_input.text = "Error: Please enter a number!" return # TODO: idea - don't accept zeros as TextInput for some keys? # if not(key == "angle" or key == "xn_start" or key == "xn_end" or key == "yq_start" or key == "yq_end") \ # and value == 0: # vis_init.div_input.text = "Error: Please enter a non-zero number!" # return # change data sources and glyphs in plot according to text input if key == "angle": # convert angle to radians and call method to adapt the angle in the input plot angle = math.radians(value) if element_indep: curr_doc.data_sources.ds_indep_elements.data['angle'][ element_index] = angle vis_editEl.change_angle_indep(curr_doc, element_name, angle, element_index) else: curr_doc.data_sources.ds_nodedep_elements.data['angle'][ element_index] = angle vis_editEl.change_angle_nodedep(curr_doc, element_name, angle, element_index) elif key == "k": k = curr_doc.data_sources.ds_nodedep_elements.data['k'][element_index] curr_doc.data_sources.ds_nodedep_elements.data['k'][ element_index] = value if value < 0 <= k: vis_editEl.draw_moment_negative(curr_doc, element_name, element_index, negative=True) elif value > 0 >= k: vis_editEl.draw_moment_negative(curr_doc, element_name, element_index, negative=False) elif key == "force": curr_doc.data_sources.ds_nodedep_elements.data['f'][ element_index] = value elif key == "moment": moment = curr_doc.data_sources.ds_nodedep_elements.data['moment'][ element_index] curr_doc.data_sources.ds_nodedep_elements.data['moment'][ element_index] = value if value < 0 <= moment: vis_editEl.draw_moment_negative(curr_doc, element_name, element_index, negative=True) elif value > 0 >= moment: vis_editEl.draw_moment_negative(curr_doc, element_name, element_index, negative=False) elif key == "h": curr_doc.data_sources.ds_nodedep_elements.data['h'][ element_index] = value elif key == "ea": curr_doc.data_sources.ds_nodedep_elements.data['ea'][ element_index] = value elif key == "ei": curr_doc.data_sources.ds_nodedep_elements.data['ei'][ element_index] = value elif key == "xn_start" or key == "xn_end" or key == "yq_start" or key == "yq_end": nodedep_llxn = curr_doc.data_sources.ds_nodedep_elements.data['ll_x_n'] nodedep_llyq = curr_doc.data_sources.ds_nodedep_elements.data['ll_y_q'] elinfo = curr_doc.input_element_info curr_doc.elinfo_input_blocked = True if key == "xn_start": xn_start = value xn_end = nodedep_llxn[element_index][1] yq_start = nodedep_llyq[element_index][0] yq_end = nodedep_llyq[element_index][1] if (xn_start == 0 and xn_end == 0 and yq_start == 0 and yq_end == 0): yq_start, yq_end = -1, -1 elinfo["yq_start"].value = "%3.1f" % yq_start elinfo["yq_end"].value = "%3.1f" % yq_end elif (xn_start > 0 and xn_end <= 0) or (xn_start < 0 and xn_end >= 0): xn_end = 0 elinfo["xn_end"].value = "%3.1f" % xn_end elif key == "xn_end": xn_start = nodedep_llxn[element_index][0] xn_end = value yq_start = nodedep_llyq[element_index][0] yq_end = nodedep_llyq[element_index][1] if (xn_end == 0 and xn_start == 0 and yq_start == 0 and yq_end == 0): yq_start, yq_end = -1, -1 elinfo["yq_start"].value = "%3.1f" % yq_start elinfo["yq_end"].value = "%3.1f" % yq_end elif (xn_end > 0 and xn_start <= 0) or (xn_end < 0 and xn_start >= 0): xn_start = 0 elinfo["xn_start"].value = "%3.1f" % xn_start elif key == "yq_start": xn_start = nodedep_llxn[element_index][0] xn_end = nodedep_llxn[element_index][1] yq_start = value yq_end = nodedep_llyq[element_index][1] if (yq_start == 0 and yq_end == 0 and xn_end == 0 and xn_start == 0): xn_start, xn_end = 1, 1 elinfo["xn_start"].value = "%3.1f" % xn_start elinfo["xn_end"].value = "%3.1f" % xn_end elif (yq_start > 0 and yq_end <= 0) or (yq_start < 0 and yq_end >= 0): yq_end = 0 elinfo["yq_end"].value = "%3.1f" % yq_end else: xn_start = nodedep_llxn[element_index][0] xn_end = nodedep_llxn[element_index][1] yq_start = nodedep_llyq[element_index][0] yq_end = value if (yq_end == 0 and yq_start == 0 and xn_end == 0 and xn_start == 0): xn_start, xn_end = 1, 1 elinfo["xn_start"].value = "%3.1f" % xn_start elinfo["xn_end"].value = "%3.1f" % xn_end elif (yq_end > 0 and yq_start <= 0) or (yq_end < 0 and yq_start >= 0): yq_start = 0 elinfo["yq_start"].value = "%3.1f" % yq_start curr_doc.elinfo_input_blocked = False # check lineload before change if not (xn_start == 0 and xn_end == 0 and yq_start == 0 and yq_end == 0): load_x_n = (xn_start, xn_end) load_y_q = (yq_start, yq_end) # change data source nodedep_llxn[element_index] = load_x_n nodedep_llyq[element_index] = load_y_q # draw adapted line load local = curr_doc.data_sources.ds_nodedep_elements.data['ll_local'][ element_index] vis_editEl.draw_lineload(curr_doc, element_name, load_x_n, load_y_q, local, element_index) else: curr_doc.div_input.text = "Error: Invalid line load values, one value has to be non-zero!" return elif key == "dT": tt = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][1] at = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][2] curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index] = (value, tt, at) elif key == "T": dt = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][0] at = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][2] curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index] = (dt, value, at) elif key == "aT": dt = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][0] tt = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index][1] curr_doc.data_sources.ds_nodedep_elements.data['dT_T'][ element_index] = (dt, tt, value) # tell user about changed value curr_doc.div_input.text = "New value accepted!"
def cb_show_element_info(attr, old, new, curr_doc: CurrentDoc, indep=False, nodedep=False): """ Callback to show information about an element in the input plot when ds_element_info was changed. ds_element_info gets changed by cb_plot_tap when a tap in the input plot was caught without an element button being active. Also called when an element was just added to the plot and it was not an element of a test case. :param attr: not used :param old: not used :param new: changed ds_element_info.data when no button element is active and a tap in the plot was caught (dict) :param indep: True if just added element is a node independent one (bool) :param nodedep: True if just added element is a node independent one (bool) :return: none """ # block user input while element info box gets changed (because of cb_get_textinput) curr_doc.elinfo_input_blocked = True reset_element_info(curr_doc) elinfo = curr_doc.input_element_info indep_x = curr_doc.data_sources.ds_indep_elements.data['x'] indep_y = curr_doc.data_sources.ds_indep_elements.data['y'] indep_t = curr_doc.data_sources.ds_indep_elements.data['type'] indep_n = curr_doc.data_sources.ds_indep_elements.data['name'] indep_a = curr_doc.data_sources.ds_indep_elements.data['angle'] nodedep_n1 = curr_doc.data_sources.ds_nodedep_elements.data['name_node1'] nodedep_n2 = curr_doc.data_sources.ds_nodedep_elements.data['name_node2'] nodedep_t = curr_doc.data_sources.ds_nodedep_elements.data['type'] nodedep_n = curr_doc.data_sources.ds_nodedep_elements.data['name'] nodedep_x = curr_doc.data_sources.ds_nodedep_elements.data['x'] nodedep_y = curr_doc.data_sources.ds_nodedep_elements.data['y'] nodedep_l = curr_doc.data_sources.ds_nodedep_elements.data['length'] nodedep_dt = curr_doc.data_sources.ds_nodedep_elements.data['dT_T'] nodedep_k = curr_doc.data_sources.ds_nodedep_elements.data['k'] nodedep_h = curr_doc.data_sources.ds_nodedep_elements.data['h'] nodedep_ei = curr_doc.data_sources.ds_nodedep_elements.data['ei'] nodedep_ea = curr_doc.data_sources.ds_nodedep_elements.data['ea'] nodedep_m = curr_doc.data_sources.ds_nodedep_elements.data['moment'] nodedep_f = curr_doc.data_sources.ds_nodedep_elements.data['f'] nodedep_lll = curr_doc.data_sources.ds_nodedep_elements.data['ll_local'] nodedep_llxn = curr_doc.data_sources.ds_nodedep_elements.data['ll_x_n'] nodedep_llyq = curr_doc.data_sources.ds_nodedep_elements.data['ll_y_q'] nodedep_a = curr_doc.data_sources.ds_nodedep_elements.data['angle'] # check if element was just added if indep: index = len(indep_x) - 1 name = indep_n[index] elif nodedep: index = len(curr_doc.data_sources.ds_nodedep_elements.data['x']) - 1 name = nodedep_n[index] # search for element in data sources if it was not just added else: # initialize for element search index = -1 name = False tap_x = new['tap_x'][0] tap_y = new['tap_y'][0] # check if tap was on an node independent element in the input plot for i in range(0, len(indep_x)): if abs(indep_x[i] - tap_x) < curr_doc.catch_radius and abs( indep_y[i] - tap_y) < curr_doc.catch_radius: index = i name = indep_n[index] indep = True break # check if tap was on a node dependent element else: # search in glyph data source of type spring, load_point, load_moment or temp ds_glyph = curr_doc.data_sources.ds_glyph_springsPointMomentTemp ds_glyph_x = ds_glyph.data['glyph_x'] ds_glyph_y = ds_glyph.data['glyph_y'] for j in range(len(ds_glyph_x)): if abs(ds_glyph_x[j] - tap_x) < curr_doc.catch_radius and abs( ds_glyph_y[j] - tap_y) < curr_doc.catch_radius: name = ds_glyph.data['name_user'][j] break # search in glyph data source of beams else: ds_glyph = curr_doc.data_sources.ds_glyph_beam ds_glyph_x = ds_glyph.data['x'] ds_glyph_y = ds_glyph.data['y'] for j in range(len(ds_glyph_x)): if abs(ds_glyph_x[j] - tap_x) < curr_doc.catch_radius and abs( ds_glyph_y[j] - tap_y) < curr_doc.catch_radius: name = ds_glyph.data['name_user'][j] break # search in glyph data source of line loads else: ds_glyph = curr_doc.data_sources.ds_glyph_lineload ds_glyph_x = ds_glyph.data['glyph_x'] ds_glyph_y = ds_glyph.data['glyph_y'] for j in range(len(ds_glyph_x)): if abs(ds_glyph_x[j] - tap_x) < curr_doc.catch_radius and abs( ds_glyph_y[j] - tap_y) < curr_doc.catch_radius: name = ds_glyph.data['name_user'][j] break # get index of element in data source of node dependent elements if name: for i in range(len(nodedep_n)): if name == nodedep_n[i]: index = i break # reaction if no element was found for that tap if index == -1: curr_doc.div_input.text = "No button element active and no element of graph clicked." return # make information about current element global for the callbacks and get enum_type if indep: curr_doc.elinfo_current_element = (name, True, index) enum_type = indep_t[index] else: curr_doc.elinfo_current_element = (name, False, index) enum_type = nodedep_t[index] # adapt element info box elinfo["name"].value = name if indep: # set values elinfo["x"].value = "%3.1f" % indep_x[index] curr_doc.div_element_info["x"].text = "x:" elinfo["y"].value = "%3.1f" % indep_y[index] curr_doc.div_element_info["y"].text = "y:" # enable input if not enum_type == eLnum.ElSupEnum.NODE.value and not enum_type == eLnum.ElSupEnum.JOINT.value: elinfo["angle"].disabled = False elinfo["angle"].value = "%3.1f" % math.degrees(indep_a[index]) elif enum_type == eLnum.ElSupEnum.SPRING_SUPPORT.value or enum_type == eLnum.ElSupEnum.SPRING_MOMENT_SUPPORT.value: # set values elinfo["x"].value = "%3.1f" % nodedep_x[index] curr_doc.div_element_info["x"].text = "x:" elinfo["y"].value = "%3.1f" % nodedep_y[index] curr_doc.div_element_info["y"].text = "y:" elinfo["angle"].value = "%3.1f" % math.degrees(nodedep_a[index]) elinfo["k"].value = "%3.1f" % nodedep_k[index] # enable input elinfo["angle"].disabled = False elinfo["k"].disabled = False elif enum_type == eLnum.ElSupEnum.SPRING.value: # set values elinfo["x"].value = nodedep_n1[index] curr_doc.div_element_info["x"].text = "node 1:" elinfo["y"].value = nodedep_n2[index] curr_doc.div_element_info["y"].text = "node 2:" elinfo["angle"].value = "%3.1f" % math.degrees(nodedep_a[index]) elinfo["k"].value = "%3.1f" % nodedep_k[index] # enable input elinfo["k"].disabled = False elif enum_type == eLnum.ElSupEnum.LOAD_POINT.value: # set values elinfo["x"].value = "%3.1f" % nodedep_x[index] curr_doc.div_element_info["x"].text = "x:" elinfo["y"].value = "%3.1f" % nodedep_y[index] curr_doc.div_element_info["y"].text = "y:" elinfo["angle"].value = "%3.1f" % math.degrees(nodedep_a[index]) elinfo["force"].value = "%3.1f" % nodedep_f[index] # enable input elinfo["angle"].disabled = False elinfo["force"].disabled = False elif enum_type == eLnum.ElSupEnum.LOAD_MOMENT.value: # set values elinfo["x"].value = "%3.1f" % nodedep_x[index] curr_doc.div_element_info["x"].text = "x:" elinfo["y"].value = "%3.1f" % nodedep_y[index] curr_doc.div_element_info["y"].text = "y:" elinfo["moment"].value = "%3.1f" % nodedep_m[index] # enable input elinfo["moment"].disabled = False elif enum_type == eLnum.ElSupEnum.LOAD_TEMP.value: # set values elinfo["x"].value = nodedep_n1[index] curr_doc.div_element_info["x"].text = "node 1:" elinfo["y"].value = nodedep_n2[index] curr_doc.div_element_info["y"].text = "node 2:" elinfo["dT"].value = "%3.1f" % nodedep_dt[index][0] elinfo["T"].value = "%3.1f" % nodedep_dt[index][1] elinfo["aT"].value = "%3.1f" % nodedep_dt[index][2] # enable input elinfo["dT"].disabled = False elinfo["T"].disabled = False elinfo["aT"].disabled = False elif enum_type == eLnum.ElSupEnum.BEAM.value: # set values elinfo["x"].value = nodedep_n1[index] curr_doc.div_element_info["x"].text = "node 1:" elinfo["y"].value = nodedep_n2[index] curr_doc.div_element_info["y"].text = "node 2:" elinfo["angle"].value = "%3.1f" % math.degrees(nodedep_a[index]) elinfo["length"].value = "%3.1f" % nodedep_l[index] elinfo["h"].value = "%3.1f" % nodedep_h[index] ea = nodedep_ea[index] ei = nodedep_ei[index] active = [] if ea == float("inf"): active.append(0) else: elinfo["ea"].value = "%3.1f" % ea elinfo["ea"].disabled = False if ei == float("inf"): active.append(1) else: elinfo["ei"].value = "%3.1f" % ei elinfo["ei"].disabled = False curr_doc.group_element_info["beam"].active = active # enable input curr_doc.group_element_info["beam"].disabled = False elinfo["h"].disabled = False elif enum_type == eLnum.ElSupEnum.LOAD_LINE.value: # set values elinfo["x"].value = nodedep_n1[index] curr_doc.div_element_info["x"].text = "node 1:" elinfo["y"].value = nodedep_n2[index] curr_doc.div_element_info["y"].text = "node 2:" elinfo["length"].value = "%3.1f" % nodedep_l[index] elinfo["xn_start"].value = "%3.1f" % nodedep_llxn[index][0] elinfo["xn_end"].value = "%3.1f" % nodedep_llxn[index][1] elinfo["yq_start"].value = "%3.1f" % nodedep_llyq[index][0] elinfo["yq_end"].value = "%3.1f" % nodedep_llyq[index][1] local = nodedep_lll[index] if local: curr_doc.group_element_info["ll"].active = 0 curr_doc.div_element_info["xn"].text = "* n" curr_doc.div_element_info["yq"].text = "* q" else: curr_doc.group_element_info["ll"].active = 1 curr_doc.div_element_info["xn"].text = "* p<sub>x</sub>" curr_doc.div_element_info["yq"].text = "* p<sub>y</sub>" # enable input curr_doc.group_element_info["ll"].disabled = False elinfo["xn_start"].disabled = False elinfo["xn_end"].disabled = False elinfo["yq_start"].disabled = False elinfo["yq_end"].disabled = False # resize element info box to children truly containing information (WARNING: too slow!) # vis_init.layout_element_info.children[1].children.insert(0, vis_init.children_element_info["del"]) # vis_init.layout_element_info.children[1].children.insert(0, vis_init.children_element_info["name"]) # for key in elinfo: # if not key == "name" and not key == "del": # if not elinfo[key].value == "": # child = vis_init.children_element_info[key] # child_index = len(vis_init.layout_element_info.children[1].children) - 1 # vis_init.layout_element_info.children[1].children.insert(child_index, child) # show element info box # vis_init.layout_element_info.visible = True # release for user input curr_doc.elinfo_input_blocked = False
def cb_adapt_plot_indep(attr, old, new, curr_doc: CurrentDoc): """ Callback to react when the data source of the input plot has changed through cb_plot_tab. :param attr: not used :param old: not used, because doesn't show correct values after cb_button_delete run (dict) :param new: updated ds_input.data (dict) :return: none """ # check if element was added or deleted or just edited if not len(new['x']) == curr_doc.len_ds_input: curr_doc.len_ds_input = len(new['x']) # reset "same" of plot elements, used to check which entries of ds_input still exist and are plotted curr_doc.data_sources.ds_indep_elements.data['same'] = [False] * len( curr_doc.data_sources.ds_indep_elements.data['same']) ds_input_x = new['x'] ds_input_y = new['y'] ds_input_t = new['type'] ds_indep_x = curr_doc.data_sources.ds_indep_elements.data['x'] ds_indep_y = curr_doc.data_sources.ds_indep_elements.data['y'] ds_indep_t = curr_doc.data_sources.ds_indep_elements.data['type'] ds_indep_n = curr_doc.data_sources.ds_indep_elements.data['name'] ds_indep_s = curr_doc.data_sources.ds_indep_elements.data['same'] # get image glyphs that were already there before ds_input changed same = [False] * len(ds_input_x) for i in range(len(ds_input_x)): for j in range(len(ds_indep_x)): # let it get first fitting object several times - prevents new creation of same object in input plot if ds_input_x[i] == ds_indep_x[j] and ds_input_y[ i] == ds_indep_y[j]: if ds_input_t[i] == ds_indep_t[j]: ds_indep_s[j] = True same[i] = True else: same[i] = True curr_doc.div_input.text = "An object already exists at this position. " \ "New object wasn't created!" break # delete image glyphs if their corresponding entries in d_input were deleted (cb_button_delete) # adaptive while condition necessary because length of ds_indep_x changes through deletion! i = 0 while True: if i == len(ds_indep_x): break if not ds_indep_s[i]: vis_elToP.delete_indep(curr_doc, name=ds_indep_n[i], index=i) else: i += 1 # create new image glyphs for elements that were added to ds_input for i in range(len(ds_input_x)): if not same[i]: # configure name and increse object id name = str(ds_input_t[i]) + "-" + str(curr_doc.object_id) curr_doc.object_id += 1 # adapt name in ds_input ds_input_data = curr_doc.data_sources.ds_input.data.copy() ds_input_data['name_user'][i] = name curr_doc.data_sources.ds_input.data = ds_input_data # dat_src.ds_input.trigger('data', dat_src.ds_input.data, ds_input_data) if curr_doc.plotting_test_case: try: angle = curr_doc.test_case_angle[ curr_doc.test_case_count_indep] except: angle = 0.0 curr_doc.test_case_count_indep += 1 else: angle = 0.0 # add node independent element vis_elToP.add_indep(curr_doc, x=ds_input_x[i], y=ds_input_y[i], enum_type=ds_input_t[i], name=name, angle=angle)
def cb_button_delete(curr_doc: CurrentDoc, all_selected=False, single=False): """ Callback for both delete buttons of the input plot and the "delete element" button of the element info box. :param all_selected: bool, if True button "delete all" was clicked and method deletes all plot elements, if False method deletes only selected elements in the plot (bool) :param single: Tuple of a single element displayed in the element info box that shall be deleted of the form (name (string), indep (bool), index (int)) :return: none """ if all_selected: curr_doc.object_id = 0 # delete all entries of the ColumnDataSource corresponding to the input plot and update the plot data = dict(x=[], y=[], type=[], name_user=[]) curr_doc.data_sources.ds_input.data = data curr_doc.data_sources.ds_input.trigger( 'data', curr_doc.data_sources.ds_input.data, curr_doc.data_sources.ds_input.data) # deactivate currently activated button element if not curr_doc.button_activated == -1: found, button_enum = eLnum.get_enum_of_value( eLnum.ElSupEnum, curr_doc.button_activated) cb_button_element_click(curr_doc, button_enum) elif single: if curr_doc.elinfo_current_element[1]: del curr_doc.data_sources.ds_input.data['x'][ curr_doc.elinfo_current_element[2]] del curr_doc.data_sources.ds_input.data['y'][ curr_doc.elinfo_current_element[2]] del curr_doc.data_sources.ds_input.data['type'][ curr_doc.elinfo_current_element[2]] del curr_doc.data_sources.ds_input.data['name_user'][ curr_doc.elinfo_current_element[2]] curr_doc.data_sources.ds_input.trigger( 'data', curr_doc.data_sources.ds_input.data, curr_doc.data_sources.ds_input.data) else: vis_elToP.delete_nodedep( curr_doc, name_nodedep=curr_doc.elinfo_current_element[0], index_nodedep=curr_doc.elinfo_current_element[2]) reset_element_info(curr_doc) else: s_x = curr_doc.data_sources.ds_input_selected.data['x'] s_y = curr_doc.data_sources.ds_input_selected.data['y'] len_s = len(s_x) len_ds = len(curr_doc.data_sources.ds_input.data['x']) # delete selected elements from the datasource of the input plot (dat_src.ds_input) and update for i in range(len_s): for j in range(len_ds): if s_x[i] == curr_doc.data_sources.ds_input.data['x'][ j] and s_y[i] == curr_doc.data_sources.ds_input.data[ 'y'][j]: del curr_doc.data_sources.ds_input.data['x'][j] del curr_doc.data_sources.ds_input.data['y'][j] del curr_doc.data_sources.ds_input.data['type'][j] del curr_doc.data_sources.ds_input.data['name_user'][j] len_ds -= 1 break curr_doc.data_sources.ds_input.trigger( 'data', curr_doc.data_sources.ds_input.data, curr_doc.data_sources.ds_input.data) # reset datasource for selected element curr_doc.data_sources.ds_input_selected.data = dict(x=[], y=[]) # reset datasource for first node for line elements data = dict(type=[], node_x=[], node_y=[], name_node1=[]) curr_doc.data_sources.ds_1st_chosen.data = data
'''############################### IMPORTS ###############################''' # general imports import numpy as np # import bokeh module from bokeh.models import ColumnDataSource from bokeh.io import curdoc from bokeh.models.callbacks import CustomJS # import local file from Classes.ColumnDataSources import ColumnDataSources from Classes.CurrentDocument import CurrentDoc from testing_collection import test_runner as test_lib import vis_initialization as vis_init '''############################### # INITIALIZATION MAIN ###############################''' curr_doc = CurrentDoc(curdoc()) vis_init.initialize(curr_doc, max_indep_elements=20, catch_radius=0.15) # curdoc().add_root(doc_layout) run_tests = False # run tests or not if run_tests: test_lib.run_tests(curr_doc)
def initialize(curr_doc: CurrentDoc, max_indep_elements=20, catch_radius=0.15): """ Creates and configures all bokeh objects and starts the web app. :param max_indep_elements: maximum number of node independent elements accepted in the input plot (int) :param catch_radius: radius in which to select an element in input plot (double) :return: none """ curr_doc.catch_radius = catch_radius ''' ############################### # TEXT BOXES ############################### ''' # Div object showing x and y position of the cursor in the input plot div_xy = Div(width=75, height=25) # Div object showing hints for the graphical input into the input plot through the element buttons div_input_width = curr_doc.plot_input.plot_width - div_xy.width - 10 curr_doc.div_input = Div(width=div_input_width, height=div_xy.height) # Div object showing general text messages to the user curr_doc.div_msg = Div(css_classes=["MSG_BOX"], text=" ", width=curr_doc.plot_input.plot_width, height=100) # doc.div_msg = Div(css_classes=["MSG_BOX"], text=" ", width=doc.plot_input.plot_width, height=100) ''' ############################### # INPUT PLOT ############################### ''' # style and configuration of the input plot # this plot is used to allow the user to connect mechanical elements tooltips = [("name", "@name_user"), ("(x, y)", "(@x{0.0}, @y{0.0})")] curr_doc.plot_input = figure( # plot_width=600, plot_height=300, tools="pan,wheel_zoom,reset,lasso_select,hover,save", toolbar_location="above", # x_axis_label='x', y_axis_label='y', x_minor_ticks=10, y_minor_ticks=10, x_range=Range1d(start=0, end=5), y_range=Range1d(start=0, end=5), match_aspect=True, aspect_scale=1.0, tooltips=tooltips, ) curr_doc.plot_input.toolbar.logo = None configure_input_plot(curr_doc, curr_doc.plot_input, div_xy, max_indep_elements) ''' ############################### # OUTPUT PLOTS ############################### ''' # initialize plots for the output after calculations plot_output_width = 800 plot_output_height = 250 curr_doc.plot_normal_f = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_normal_f.toolbar.logo = None curr_doc.plot_normal_f.title.text = 'Normal force' curr_doc.plot_normal_disp = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_normal_disp.toolbar.logo = None curr_doc.plot_normal_disp.title.text = 'Normal displacement' curr_doc.plot_shear_f = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_shear_f.toolbar.logo = None curr_doc.plot_shear_f.title.text = 'Shear force' curr_doc.plot_moment = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_moment.toolbar.logo = None curr_doc.plot_moment.title.text = 'Bending moment' curr_doc.plot_shear_disp = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_shear_disp.toolbar.logo = None curr_doc.plot_shear_disp.title.text = 'Shear displacement' curr_doc.plot_shear_angle = figure(plot_width=plot_output_width, plot_height=plot_output_height, active_scroll="wheel_zoom") curr_doc.plot_shear_angle.toolbar.logo = None curr_doc.plot_shear_angle.title.text = 'Rotation angle' curr_doc.plot_list = [ curr_doc.plot_normal_f, curr_doc.plot_normal_disp, curr_doc.plot_shear_f, curr_doc.plot_moment, curr_doc.plot_shear_angle, curr_doc.plot_shear_disp ] # add plot renderer ds = ColumnDataSource(data=dict(x=[], y=[])) curr_doc.plot_normal_f.circle('x', 'y', source=ds) curr_doc.plot_normal_disp.circle('x', 'y', source=ds) curr_doc.plot_shear_f.circle('x', 'y', source=ds) curr_doc.plot_moment.circle('x', 'y', source=ds) curr_doc.plot_shear_disp.circle('x', 'y', source=ds) curr_doc.plot_normal_f.circle('x', 'y', source=ds) curr_doc.plot_shear_angle.circle('x', 'y', source=ds) ''' ############################### # TEST CASES ############################### ''' menu_tc = [("Single beam load", "single_beam_load"), ("Two beam lineload", "two_beam_lineload"), ("Angled structure", "fin_struc_soft_lab")] dropdown_tc = Dropdown(label="Show test case", menu=menu_tc, width=150) dropdown_tc.on_change('value', partial(vis_cbs.cb_plot_testcase, curr_doc=curr_doc)) # partial(vis_cbs.cb_get_textinput, key=key_elinfo_n) ''' ############################### # CALCULATE AND DELETE BUTTONS ############################### ''' # add and configure a button to start calculations button_calc = Button(label="Calculate", width=240) button_calc.on_click( partial(vis_cbs.cb_button_calculation, curr_doc, button_calc)) # add and configure a button to delete selected elements of the input graph b_del_w = int((button_calc.width - 10) / 2) button_del_selected = Button(label="Delete selected", width=b_del_w) button_del_selected.on_click( partial(vis_cbs.cb_button_delete, curr_doc=curr_doc, all_selected=False)) # add and configure a button to delete selected elements of the input graph button_del_all = Button(label="Delete all", width=b_del_w) button_del_all.on_click( partial(vis_cbs.cb_button_delete, curr_doc=curr_doc, all_selected=True)) ''' ############################################ # BOX OF ELEMENTS TO SELECT FOR INPUT PLOT ############################################ ''' # titles for groups of mechanical elements text_supports = Div(text="Supports:", width=100, height=20) text_springs = Div(text="Springs:", width=100, height=20) text_node = Div(text="Node:", width=100, height=20) text_joints = Div(text="Joints:", width=100, height=20) text_elements = Div(text="Line elements:", width=100, height=20) text_loads = Div(text="Loads:", width=100, height=20) b_height = 50 b_line_width = 72 # configure buttons for mechanical supports button_support_clamped = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_CLAMPED.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.SUPPORT_CLAMPED.value] = button_support_clamped button_support_clamped.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_CLAMPED)) button_support_normal = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_NORMAL_FORCE.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.SUPPORT_NORMAL_FORCE.value] = button_support_normal button_support_normal.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_NORMAL_FORCE)) button_support_transverse = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_TRANSVERSE_FORCE.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SUPPORT_TRANSVERSE_FORCE. value] = button_support_transverse button_support_transverse.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_TRANSVERSE_FORCE)) button_support_fixed_conti = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_FIXED_CONTINUOUS.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SUPPORT_FIXED_CONTINUOUS. value] = button_support_fixed_conti button_support_fixed_conti.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_FIXED_CONTINUOUS)) button_support_fixed_joint = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_FIXED_JOINT.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.SUPPORT_FIXED_JOINT.value] = button_support_fixed_joint button_support_fixed_joint.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_FIXED_JOINT)) button_support_roller_conti = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_ROLLER_CONTINUOUS.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SUPPORT_ROLLER_CONTINUOUS. value] = button_support_roller_conti button_support_roller_conti.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_ROLLER_CONTINUOUS)) button_support_roller_joint = Button( label="", css_classes=[eLnum.ElSupEnum.SUPPORT_ROLLER_JOINT.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SUPPORT_ROLLER_JOINT. value] = button_support_roller_joint button_support_roller_joint.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SUPPORT_ROLLER_JOINT)) button_spring_support = Button( label="", css_classes=[eLnum.ElSupEnum.SPRING_SUPPORT.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.SPRING_SUPPORT.value] = button_spring_support button_spring_support.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SPRING_SUPPORT)) button_spring_moment_support = Button( label="", css_classes=[eLnum.ElSupEnum.SPRING_MOMENT_SUPPORT.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SPRING_MOMENT_SUPPORT. value] = button_spring_moment_support button_spring_moment_support.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SPRING_MOMENT_SUPPORT)) # configure curr_doc.buttons for connectors button_node = Button(label="", css_classes=[eLnum.ElSupEnum.NODE.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.NODE.value] = button_node button_node.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.NODE)) button_joint = Button(label="", css_classes=[eLnum.ElSupEnum.JOINT.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.JOINT.value] = button_joint button_joint.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.JOINT)) button_joint_normal = Button( label="", css_classes=[eLnum.ElSupEnum.JOINT_NORMAL_FORCE.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.JOINT_NORMAL_FORCE.value] = button_joint_normal button_joint_normal.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.JOINT_NORMAL_FORCE)) button_joint_transverse = Button( label="", css_classes=[eLnum.ElSupEnum.JOINT_TRANSVERSE_FORCE.name], width=b_height, height=b_height) curr_doc.buttons[ eLnum.ElSupEnum.JOINT_TRANSVERSE_FORCE.value] = button_joint_transverse button_joint_transverse.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.JOINT_TRANSVERSE_FORCE)) button_spring = Button(label="", css_classes=[eLnum.ElSupEnum.SPRING.name], width=b_line_width, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.SPRING.value] = button_spring button_spring.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.SPRING)) # configure buttons for mechanical 1D or 2D elements # button_rod = Button(label="", css_classes=[eLnum.ElSupEnum.ROD.name], width=b_line_width, height=b_height) # curr_doc.buttons[eLnum.ElSupEnum.ROD.value] = button_rod # button_rod.on_click(partial(vis_cbs.cb_button_element_click, button_enum=eLnum.ElSupEnum.ROD)) button_beam = Button(label="", css_classes=[eLnum.ElSupEnum.BEAM.name], width=b_line_width, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.BEAM.value] = button_beam button_beam.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.BEAM)) # configure buttons for mechanical loads button_load_point = Button(label="", css_classes=[eLnum.ElSupEnum.LOAD_POINT.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.LOAD_POINT.value] = button_load_point button_load_point.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.LOAD_POINT)) button_load_moment = Button(label="", css_classes=[eLnum.ElSupEnum.LOAD_MOMENT.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.LOAD_MOMENT.value] = button_load_moment button_load_moment.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.LOAD_MOMENT)) button_load_random = Button(label="", css_classes=[eLnum.ElSupEnum.LOAD_LINE.name], width=b_line_width, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.LOAD_LINE.value] = button_load_random button_load_random.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.LOAD_LINE)) button_load_temp = Button(label="", css_classes=[eLnum.ElSupEnum.LOAD_TEMP.name], width=b_height, height=b_height) curr_doc.buttons[eLnum.ElSupEnum.LOAD_TEMP.value] = button_load_temp button_load_temp.on_click( partial(vis_cbs.cb_button_element_click, curr_doc=curr_doc, button_enum=eLnum.ElSupEnum.LOAD_TEMP)) ''' ############################### # ELEMENT INFO BOX ############################### ''' elinfo_object_height = 26 elinfo_label_width1 = 60 elinfo_label_width2 = 40 elinfo_input_width = 60 # labels for values of an element of the input plot text_elinfo_name = Div(text="name:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_x = Div(text="x:", width=elinfo_label_width1, height=elinfo_object_height) curr_doc.div_element_info["x"] = text_elinfo_x text_elinfo_y = Div(text="y:", width=elinfo_label_width1, height=elinfo_object_height) curr_doc.div_element_info["y"] = text_elinfo_y text_elinfo_angle1 = Div(text="angle:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_angle2 = Div(text="°", width=elinfo_label_width2 - 20, height=elinfo_object_height) spacer_y_a = Div(text="", width=text_elinfo_angle2.width, height=elinfo_object_height) text_elinfo_k1 = Div(text="spring:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_k2 = Div(text="* k", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_length1 = Div(text="length:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_length2 = Div(text="* l", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_force1 = Div(text="force:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_force2 = Div(text="* F", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_moment1 = Div(text="moment:", width=elinfo_label_width1, height=elinfo_object_height) text_elinfo_moment2 = Div(text="* M", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_beam = Div(text="BEAM", width=elinfo_object_height, height=elinfo_label_width1, css_classes=["ELINFO_VERTICAL_TEXT"]) text_elinfo_h = Div(text="* h", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_ei = Div(text="* EI", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_ea = Div(text="* EA", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_lineload = Div(text="LINE LOAD", width=elinfo_object_height, height=elinfo_label_width1, css_classes=["ELINFO_VERTICAL_TEXT"]) text_elinfo_xn = Div(text="* n", width=elinfo_label_width2 - 10, height=elinfo_object_height) curr_doc.div_element_info["xn"] = text_elinfo_xn text_elinfo_yq = Div(text="* q", width=elinfo_label_width2 - 10, height=elinfo_object_height) curr_doc.div_element_info["yq"] = text_elinfo_yq text_elinfo_temp = Div(text="TEMP.", width=elinfo_object_height, height=elinfo_label_width1, css_classes=["ELINFO_VERTICAL_TEXT"]) text_elinfo_dt = Div(text="* dT", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_tt = Div(text="* T", width=elinfo_label_width2, height=elinfo_object_height) text_elinfo_at = Div(text="* αT", width=elinfo_label_width2, height=elinfo_object_height) # text inputs showing the current value of an input plot element and taking input for a value change # name input_elinfo_name = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_n = "name" curr_doc.input_element_info[key_elinfo_n] = input_elinfo_name input_elinfo_name.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_n)) # xy input_elinfo_x = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_x = "x" curr_doc.input_element_info[key_elinfo_x] = input_elinfo_x input_elinfo_x.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_x)) input_elinfo_y = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_y = "y" curr_doc.input_element_info[key_elinfo_y] = input_elinfo_y input_elinfo_y.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_y)) # angle input_elinfo_angle = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_angle = "angle" curr_doc.input_element_info[key_elinfo_angle] = input_elinfo_angle input_elinfo_angle.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_angle)) # spring constant input_elinfo_k = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_k = "k" curr_doc.input_element_info[key_elinfo_k] = input_elinfo_k input_elinfo_k.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_k)) # length input_elinfo_length = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_length = "length" curr_doc.input_element_info[key_elinfo_length] = input_elinfo_length input_elinfo_k.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_length)) # point load input_elinfo_force = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_f = "force" curr_doc.input_element_info[key_elinfo_f] = input_elinfo_force input_elinfo_force.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_f)) # moment input_elinfo_moment = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_m = "moment" curr_doc.input_element_info[key_elinfo_m] = input_elinfo_moment input_elinfo_moment.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_m)) # beam input_elinfo_h = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_h = "h" curr_doc.input_element_info[key_elinfo_h] = input_elinfo_h input_elinfo_h.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_h)) check_elinfo_beam = CheckboxGroup(labels=["EA -> inf.", "EI -> inf."], active=[], disabled=True, width=elinfo_input_width + elinfo_label_width1) curr_doc.group_element_info["beam"] = check_elinfo_beam check_elinfo_beam.on_change( 'active', partial(vis_cbs.cb_elinfo_beam, curr_doc=curr_doc)) input_elinfo_ea = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_ea = "ea" curr_doc.input_element_info[key_elinfo_ea] = input_elinfo_ea input_elinfo_ea.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_ea)) input_elinfo_ei = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_ei = "ei" curr_doc.input_element_info[key_elinfo_ei] = input_elinfo_ei input_elinfo_ei.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_ei)) # line load radio_elinfo_ll = RadioGroup( labels=["local", "global"], active=0, disabled=True, # "angle" width=elinfo_input_width + elinfo_label_width1) curr_doc.group_element_info["ll"] = radio_elinfo_ll radio_elinfo_ll.on_change( 'active', partial(vis_cbs.cb_elinfo_lineload, curr_doc=curr_doc)) input_elinfo_xns = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height + 20, disabled=True, title="start") key_elinfo_xns = "xn_start" curr_doc.input_element_info[key_elinfo_xns] = input_elinfo_xns input_elinfo_xns.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_xns)) input_elinfo_xne = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height + 20, disabled=True, title="end") key_elinfo_xne = "xn_end" curr_doc.input_element_info[key_elinfo_xne] = input_elinfo_xne input_elinfo_xne.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_xne)) input_elinfo_yqs = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_yqs = "yq_start" curr_doc.input_element_info[key_elinfo_yqs] = input_elinfo_yqs input_elinfo_yqs.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_yqs)) input_elinfo_yqe = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_yqe = "yq_end" curr_doc.input_element_info[key_elinfo_yqe] = input_elinfo_yqe input_elinfo_yqe.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_yqe)) # temperature load input_elinfo_dt = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_dt = "dT" curr_doc.input_element_info[key_elinfo_dt] = input_elinfo_dt input_elinfo_dt.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_dt)) input_elinfo_tt = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_tt = "T" curr_doc.input_element_info[key_elinfo_tt] = input_elinfo_tt input_elinfo_tt.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_tt)) input_elinfo_at = TextInput(value="-", width=elinfo_input_width, height=elinfo_object_height, disabled=True) key_elinfo_at = "aT" curr_doc.input_element_info[key_elinfo_at] = input_elinfo_at input_elinfo_at.on_change( 'value', partial(vis_cbs.cb_get_textinput, curr_doc=curr_doc, key=key_elinfo_at)) # button for deleting an input plot element button_elinfo_del = Button(label="Delete element", width=elinfo_label_width1 + elinfo_input_width + elinfo_label_width2, height=elinfo_object_height + 10, disabled=False) button_elinfo_del.on_click( partial(vis_cbs.cb_button_delete, curr_doc=curr_doc, single=True)) ''' ############################### # CHECKBOXES FOR OUTPUT PLOTS ############################### ''' check_labels = ["Min/ max values", "Start/ end values", "Zero points"] check_init_active = [1] check_plot_nf = CheckboxGroup(labels=check_labels, active=check_init_active) # inline=False text_plot_nf = Div(text="", width=100, height=10) check_plot_nf.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_normal_f, div=text_plot_nf)) check_plot_nd = CheckboxGroup(labels=check_labels, active=check_init_active) text_plot_nd = Div(text="", width=100, height=10) check_plot_nd.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_normal_disp, div=text_plot_nd)) check_plot_sf = CheckboxGroup(labels=check_labels, active=check_init_active) text_plot_sf = Div(text="", width=100, height=10) check_plot_sf.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_shear_f, div=text_plot_sf)) check_plot_mo = CheckboxGroup(labels=check_labels, active=check_init_active) text_plot_mo = Div(text="", width=100, height=10) check_plot_mo.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_moment, div=text_plot_mo)) check_plot_sa = CheckboxGroup(labels=check_labels, active=check_init_active) text_plot_sa = Div(text="", width=100, height=10) check_plot_sa.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_shear_angle, div=text_plot_sa)) check_plot_sd = CheckboxGroup(labels=check_labels, active=check_init_active) text_plot_sd = Div(text="", width=100, height=10) check_plot_sd.on_change( 'active', partial(vis_cbs.cb_toggle_characteristic_values, curr_doc=curr_doc, output_plot=curr_doc.plot_shear_disp, div=text_plot_sd)) ''' ############################### # IMAGES: SIGN CONVENTION ############################### ''' sign_convention_N = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_N_u.png' width=100 height=60>", width=100, height=60) sign_convention_u = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_N_u.png' width=100 height=60>", width=100, height=60) sign_convention_SF = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_SF_w.png' width=100 height=60>", width=100, height=60) sign_convention_M = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_M.png' width=100 height=60>", width=100, height=60) sign_convention_phi = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_phi.png' width=100 height=60>", width=100, height=60) sign_convention_w = Div( text= "<img src='/System_of_Beams/static/images/sign_convention_SF_w.png' width=100 height=60>", width=100, height=60) ''' ############################### # HTML LATEX DESCRIPTION ############################### ''' # latex packages not working with updated bokeh! # description_filename = join(dirname(__file__), "description.html") # description = LatexDiv(text=open(description_filename).read(), render_as_text=False, width=910) ''' #################################### # CREATE LAYOUT AND START DOCUMENT #################################### ''' spacer = Div(text="", width=20, height=20) minispacer = Div(text="", width=0, height=0) # element buttons layout_supports_1 = row(button_support_clamped, button_support_normal, button_support_transverse) layout_supports_2 = row(button_support_fixed_joint, button_support_fixed_conti, button_support_roller_joint, button_support_roller_conti) layout_springs = row(button_spring_support, button_spring_moment_support) layout_node = row(button_node) layout_joints = row(button_joint, button_joint_normal, button_joint_transverse, button_spring) layout_elements = row(button_beam) # button_rod, layout_loads = row(button_load_point, button_load_moment, button_load_random, button_load_temp) layout_input_elements = column( spacer, text_supports, layout_supports_1, layout_supports_2, row(column(text_springs, layout_springs), spacer, minispacer, column(text_node, layout_node)), text_joints, layout_joints, text_elements, layout_elements, text_loads, layout_loads) # element info box elinfo_name = row(text_elinfo_name, input_elinfo_name) curr_doc.children_element_info[key_elinfo_n] = elinfo_name elinfo_xy = row(text_elinfo_x, input_elinfo_x, spacer_y_a, text_elinfo_y, input_elinfo_y) curr_doc.children_element_info[key_elinfo_x] = elinfo_xy elinfo_angle_length = row(text_elinfo_angle1, input_elinfo_angle, text_elinfo_angle2, text_elinfo_length1, input_elinfo_length, text_elinfo_length2) curr_doc.children_element_info[key_elinfo_angle] = elinfo_angle_length elinfo_k = row(text_elinfo_k1, input_elinfo_k, text_elinfo_k2) curr_doc.children_element_info[key_elinfo_k] = elinfo_k elinfo_force = row(text_elinfo_force1, input_elinfo_force, text_elinfo_force2) curr_doc.children_element_info[key_elinfo_f] = elinfo_force elinfo_moment = row(text_elinfo_moment1, input_elinfo_moment, text_elinfo_moment2) curr_doc.children_element_info[key_elinfo_m] = elinfo_moment elinfo_beam = row( minispacer, column(minispacer, text_elinfo_beam), column(check_elinfo_beam, row(input_elinfo_h, text_elinfo_h)), column(row(input_elinfo_ea, text_elinfo_ea), row(input_elinfo_ei, text_elinfo_ei))) curr_doc.children_element_info[key_elinfo_h] = elinfo_beam elinfo_lineload = row( minispacer, column(spacer, text_elinfo_lineload), column(spacer, radio_elinfo_ll), column(row(input_elinfo_xns, input_elinfo_xne), row(input_elinfo_yqs, input_elinfo_yqe)), column(spacer, text_elinfo_xn, text_elinfo_yq)) curr_doc.children_element_info[key_elinfo_ei] = elinfo_lineload elinfo_dt = row( minispacer, column(minispacer, text_elinfo_temp), column( row(input_elinfo_dt, text_elinfo_dt, minispacer, input_elinfo_at, text_elinfo_at), row(input_elinfo_tt, text_elinfo_tt))) curr_doc.children_element_info[key_elinfo_dt] = elinfo_dt curr_doc.layout_element_info = row( minispacer, column(minispacer, elinfo_name, elinfo_xy, elinfo_angle_length, spacer, elinfo_k, elinfo_force, elinfo_moment, spacer, elinfo_beam, spacer, elinfo_lineload, spacer, elinfo_dt, spacer, button_elinfo_del, minispacer), minispacer, css_classes=["ELEMENT_INFO_BOX"], margin=(20, 0, 0, 20), visible=True) # input plot with element buttons, delete and calculation buttons and divs user_input = row(curr_doc.plot_input, spacer, layout_input_elements) user_input_info = row(curr_doc.div_input, div_xy, spacer, button_del_selected, button_del_all) user_msg = row(curr_doc.div_msg, spacer, button_calc) # output plots and check boxes for characteristic values user_output = column( row(curr_doc.plot_normal_f, spacer, column(spacer, check_plot_nf, sign_convention_N)), row(curr_doc.plot_normal_disp, spacer, column(spacer, check_plot_nd, sign_convention_u)), row(curr_doc.plot_shear_f, spacer, column(spacer, check_plot_sf, sign_convention_SF)), row(curr_doc.plot_moment, spacer, column(spacer, check_plot_mo, sign_convention_M)), row(curr_doc.plot_shear_angle, spacer, column(spacer, check_plot_sa, sign_convention_phi)), row(curr_doc.plot_shear_disp, spacer, column(spacer, check_plot_sd, sign_convention_w))) # assemble complete layout doc_layout = column( spacer, row(spacer, spacer, dropdown_tc), row(column(user_input, user_input_info, user_msg), minispacer, curr_doc.layout_element_info), spacer, user_output) # add layout curr_doc.curr_doc.add_root(doc_layout) # set title of browser tab curr_doc.curr_doc.title = split(dirname(__file__))[-1].replace( '_', ' ').replace('-', ' ') doc_title = split(dirname(__file__))[-1].replace('_', ' ').replace('-', ' ')