def onclick(self, event): """ This function is in charge of the mouse-click behaviour. A left mouse button click is recognized, the mouse location serves as an initial condition for trajectories. """ # TODO: check if try/except is the best thing to do here! if not self.canvas.zoomMode: event1 = event.xdata is not None event2 = event.ydata is not None button = event.button == 1 if not self.myWidget.Equilibria.tgl: # event.xdata and event.ydata are initial conditions for integration # mouse click will also be recognized if clicked outside of the graph area, so filter that: if event1 and event2 and button: forward, backward = self.myWidget.trajectory_direction() if self.myWidget.mySystem.Trajectories.plot_trajectory([event.xdata, event.ydata], forward, backward): myLogger.message("New initial condition: " + str(event.xdata) + ", " + str(event.ydata)) else: pass else: # equilibrium point if event1 and event2 and button: equilibrium_point = self.myWidget.Equilibria.find_equilibrium([event.xdata, event.ydata]) if equilibrium_point is not None: # is this supposed to be here? pass #~ jacobian = self.myWidget.Equilibria.approx_ep_jacobian(equilibrium_point) #~ self.myWidget.mySystem.myPyplane.new_linearized_system(self.myWidget.mySystem, jacobian, equilibrium_point) else: myLogger.debug_message("in zoom mode")
def load_system(self, file_name): """ load previous system (from tmp file) """ with open(file_name, 'r') as sysfile: self.xDotLineEdit.setText(sysfile.readline().strip()) self.yDotLineEdit.setText(sysfile.readline().strip()) myLogger.message(file_name + " loaded")
def onclick(self, event): """ This function is in charge of the mouse-click behaviour. A left mouse button click is recognized, the mouse location serves as an initial condition for trajectories. """ # TODO: check if try/except is the best thing to do here! if not self.canvas.zoomMode: event1 = event.xdata is not None event2 = event.ydata is not None button = event.button == 1 if not self.myWidget.Equilibria.tgl: # event.xdata and event.ydata are initial conditions for integration # mouse click will also be recognized if clicked outside of the graph area, so filter that: if event1 and event2 and button: forward, backward = self.myWidget.trajectory_direction() if self.myWidget.mySystem.Trajectories.plot_trajectory([event.xdata, event.ydata], forward, backward): myLogger.message("New initial condition: " + str(event.xdata) + ", " + str(event.ydata)) else: pass else: # equilibrium point if event1 and event2 and button: equilibrium_point = self.myWidget.Equilibria.find_equilibrium([event.xdata, event.ydata]) if equilibrium_point is not None: # is this supposed to be here? pass # jacobian = self.myWidget.Equilibria.approx_ep_jacobian(equilibrium_point) # self.myWidget.mySystem.myPyplane.new_linearized_system(self.myWidget.mySystem, jacobian, equilibrium_point) else: myLogger.debug_message("in zoom mode")
def onpick(self, event): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() # ind = event.ind myLogger.message("Equilibrium Point chosen: "+str(xdata)+", "+str(ydata))
def update(self): """ This function plots streamlines. """ self.remove() if self.tgl: xmin, xmax, ymin, ymax = self.myWidget.Plot.canvas.axes.axis() N = int(myConfig.read("Streamlines", "stream_gridPointsInX")) M = int(myConfig.read("Streamlines", "stream_gridPointsInY")) stream_linewidth = float(myConfig.read("Streamlines", "stream_linewidth")) stream_color = str(myConfig.read("Streamlines", "stream_color")) stream_density = float(myConfig.read("Streamlines", "stream_density")) a = np.linspace(xmin, xmax, N) b = np.linspace(ymin, ymax, M) X1, Y1 = np.meshgrid(a, b) try: DX1, DY1 = self.myWidget.mySystem.equation.rhs([X1, Y1]) streamplot = self.myWidget.Plot.canvas.axes.streamplot(X1, Y1, DX1, DY1, density=stream_density, linewidth=stream_linewidth, color=stream_color) self.sl_stack.append(streamplot) myLogger.message("Streamplot created") except: myLogger.debug_message("No system yet") self.myWidget.Plot.canvas.draw()
def add(self): try: fct_string = str(self.mySystem.myPyplane.yLineEdit.text()) except UnicodeEncodeError as exc: myLogger.error_message("input error!") myLogger.debug_message(str(exc)) fct_string = str(self.mySystem.myPyplane.yLineEdit.text()) if fct_string != "": try: self.fct_expr = sp.sympify(fct_string) self.fct = sp.lambdify((self.x, self.y), self.fct_expr, 'numpy') xmin, xmax, ymin, ymax = self.mySystem.Phaseplane.Plot.canvas.axes.axis( ) # plot the function for an x-interval twice as big as the current window deltax = (xmax - xmin) / 2 deltay = (ymax - ymin) / 2 plot_xmin = xmin - deltax plot_xmax = xmax + deltax plot_ymin = ymin - deltay plot_ymax = ymax + deltay pts_in_x = int(myConfig.read("Functions", "fct_gridPointsInX")) pts_in_y = int(myConfig.read("Functions", "fct_gridPointsInY")) fct_color = myConfig.read("Functions", "fct_color") fct_linewidth = float( myConfig.read("Functions", "fct_linewidth")) x = np.arange(plot_xmin, plot_xmax, (xmax - xmin) / pts_in_x) y = np.arange(plot_ymin, plot_ymax, (ymax - ymin) / pts_in_y) X, Y = np.meshgrid(x, y) myfunc = self.fct(X, Y) # TODO: plots like y=1/x have a connection between -inf and +inf that is not actually there! # plot function and put on function-stack new_fct = self.mySystem.Phaseplane.Plot.canvas.axes.contour( X, Y, myfunc, [0], zorder=100, linewidths=fct_linewidth, colors=fct_color) # new_fct = self.myGraph.plot_pp.axes.plot(xvalue, yvalue, label="fct", color="green") self.fct_stack.append(new_fct) self.mySystem.Phaseplane.Plot.update() myLogger.message("function plot: 0 = " + fct_string) except Exception as error: # TODO: use handle_exception for this myLogger.error_message(str(error)) else: myLogger.error_message("Please enter function.")
def plot_equilibrium(self, z_equilibrium, jacobian): """ this function plots an equilibrium point """ self.eq_plot = self.myWidget.Plot.canvas.axes.plot(z_equilibrium[0], z_equilibrium[1], 'ro', picker=5) # equilibrium point in t(x,y): # TODO: let user specify this in config! # TODO: show equilibria in x(t) and y(t) as well! if self.myWidget.mySystem.Phaseplane.backwardCheckbox.isChecked(): tmin = -float(myConfig.read("Trajectories", "traj_integrationtime")) else: tmin = 0 if self.myWidget.mySystem.Phaseplane.forwardCheckbox.isChecked(): tmax = float(myConfig.read("Trajectories", "traj_integrationtime")) else: tmax = 0 # equilibrium line from tmin to tmax if not (tmin == 0 and tmax == 0): self.myWidget.mySystem.Txy.Plot.canvas.axes.plot( [z_equilibrium[0], z_equilibrium[0]], [z_equilibrium[1], z_equilibrium[1]], [tmin, tmax], linestyle="dashed", color="r") # marker t=0: self.myWidget.mySystem.Txy.Plot.canvas.axes.plot([z_equilibrium[0]], [z_equilibrium[1]], [0], 'o', color="r") self.myWidget.mySystem.Txy.Plot.update() #~ self.stack[str(z_equilibrium)] = self.eq_plot equilibrium_point = Container() equilibrium_point.coordinates = z_equilibrium equilibrium_point.plot = self.eq_plot equilibrium_point.character = self.characterize_equilibrium(jacobian) self.stack.append(equilibrium_point) # label equilibrium point self.myWidget.Plot.canvas.axes.text(z_equilibrium[0], z_equilibrium[1], equilibrium_point.character, fontsize=10) self.update_equilibria() # TODO: this call probably move somewhere else: if len(self.stack) > 0: self.myWidget.show_linearization_objects() myLogger.message("Equilibrium Point found at: " + str(z_equilibrium)) myLogger.message("jacobian:\n" + str(jacobian))
def onpick(self, event): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() ind = event.ind myLogger.message("Equilibrium Point chosen: "+str(xdata)+", "+str(ydata)) equilibrium = [map(float,xdata)[0], map(float,ydata)[0]]
def onpick(self, event): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() ind = event.ind myLogger.message("Equilibrium Point chosen: " + str(xdata) + ", " + str(ydata)) equilibrium = [map(float, xdata)[0], map(float, ydata)[0]]
def handle_exception(error): myLogger.error_message("Error: An Python Exception occured.") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message("See the log file config/logmessages.txt for full traceback ") exc_type, exc_value, exc_tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_tb) tb_msg = "".join(lines) myLogger.append_to_file(tb_msg)
def plot_eigenvectors(self, equilibrium): if self.linear: # system is linear -> calculate jacobian x, y = sp.symbols("x, y") xdot = self.equation.x_dot_expr ydot = self.equation.y_dot_expr A11 = xdot.diff(x) A12 = xdot.diff(y) A21 = ydot.diff(x) A22 = ydot.diff(y) jac = np.array([[A11,A12],[A21,A22]], dtype=float) eigenvalues, eigenvectors = np.linalg.eig(jac) eigvec0 = eigenvectors[:,0] eigvec1 = eigenvectors[:,1] # calculating eigenvalues and eigenvectors: #~ eigenvalues, eigenvectors = self.Phaseplane.Equilibria.get_eigenval_eigenvec(equilibrium) myLogger.message("Eigenvectors: (" + str(eigvec0[0]) + ", " + str(eigvec0[1]) + ") and (" + str(eigvec1[0]) + ", " + str(eigvec1[1]) + ")") # scaling xmin, xmax, ymin, ymax = self.Phaseplane.Plot.get_limits() d1 = (xmax-xmin)/10 d2 = (ymax-ymin)/10 d_large = (xmax-xmin)*(ymax-ymin) EV0 = np.array([np.real(eigvec0[0]),np.real(eigvec0[1])]) EV0_norm = np.sqrt(EV0[0]**2+EV0[1]**2) EV0_scaled = np.array([d1*(1/EV0_norm)*EV0[0],d1*(1/EV0_norm)*EV0[1]]) EV1 = np.array([np.real(eigvec1[0]),np.real(eigvec1[1])]) EV1_norm = np.sqrt(EV1[0]**2+EV1[1]**2) EV1_scaled = np.array([d1*(1/EV1_norm)*EV1[0],d1*(1/EV1_norm)*EV1[1]]) # plot equilibrium: self.Phaseplane.Plot.canvas.axes.plot(equilibrium[0], equilibrium[1], 'ro', picker=2) # plot eigenvectors: color_eigenvec = myConfig.read("Linearization", "lin_eigenvector_color") color_eigenline = myConfig.read("Linearization", "lin_eigenvector_linecolor") if myConfig.get_boolean("Linearization","lin_show_eigenline"): self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], d_large*EV0_scaled[0], d_large*EV0_scaled[1], head_width=0, head_length=0, color=color_eigenline) self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], -d_large*EV0_scaled[0], -d_large*EV0_scaled[1], head_width=0, head_length=0, color=color_eigenline) if myConfig.get_boolean("Linearization","lin_show_eigenvector"): self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], EV0_scaled[0], EV0_scaled[1], head_width=0, head_length=0, color=color_eigenvec) if myConfig.get_boolean("Linearization","lin_show_eigenline"): self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], d_large*EV1_scaled[0], d_large*EV1_scaled[1], head_width=0, head_length=0, color=color_eigenline) self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], -d_large*EV1_scaled[0], -d_large*EV1_scaled[1], head_width=0, head_length=0, color=color_eigenline) if myConfig.get_boolean("Linearization","lin_show_eigenvector"): self.Phaseplane.Plot.canvas.axes.arrow(equilibrium[0], equilibrium[1], EV1_scaled[0], EV1_scaled[1], head_width=0, head_length=0, color=color_eigenvec) self.Phaseplane.Plot.add_eigenvectors_to_title(eigvec0, eigvec1)
def export_as_pdf(self, filename): filename_pp = str(filename) + "_pp.pdf" self.myGraph.plot_pp.fig.savefig(filename_pp, bbox_inches='tight') filename_x = str(filename) + "_x.pdf" self.myGraph.plot_x.fig.savefig(filename_x, bbox_inches='tight') filename_y = str(filename) + "_y.pdf" self.myGraph.plot_y.fig.savefig(filename_y, bbox_inches='tight') myLogger.message("plot exported as\n\t" + filename_pp + ",\n\t" + filename_x + ",\n\t" + filename_y)
def handle_exception(error): myLogger.error_message("Error: An Python Exception occured.") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message( "See the log file config/logmessages.txt for full traceback ") exc_type, exc_value, exc_tb = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_tb) tb_msg = "".join(lines) myLogger.append_to_file(tb_msg)
def export_as_eps(self, filename): filename_pp = str(filename) + "_pp.eps" #filename_pp = "/home/klim/asd.eps" self.myGraph.plot_pp.fig.savefig(filename_pp, bbox_inches='tight') filename_x = str(filename) + "_x.eps" self.myGraph.plot_x.fig.savefig(filename_x, bbox_inches='tight') filename_y = str(filename) + "_y.eps" self.myGraph.plot_y.fig.savefig(filename_y, bbox_inches='tight') myLogger.message("plot exported as\n\t" + filename_pp + ",\n\t" + filename_x + ",\n\t" + filename_y)
def add(self): try: fct_string = str(self.mySystem.myPyplane.yLineEdit.text()) except UnicodeEncodeError as exc: myLogger.error_message("input error!") myLogger.debug_message(str(exc)) fct_string = str(self.mySystem.myPyplane.yLineEdit.text()) if fct_string != "": try: self.fct_expr = sp.sympify(fct_string) self.fct = sp.lambdify((self.x, self.y), self.fct_expr, 'numpy') xmin, xmax, ymin, ymax = self.mySystem.Phaseplane.Plot.canvas.axes.axis() # plot the function for an x-interval twice as big as the current window deltax = (xmax - xmin) / 2 deltay = (ymax - ymin) / 2 plot_xmin = xmin - deltax plot_xmax = xmax + deltax plot_ymin = ymin - deltay plot_ymax = ymax + deltay pts_in_x = int(myConfig.read("Functions", "fct_gridPointsInX")) pts_in_y = int(myConfig.read("Functions", "fct_gridPointsInY")) fct_color = myConfig.read("Functions", "fct_color") fct_linewidth = float(myConfig.read("Functions", "fct_linewidth")) x = np.arange(plot_xmin, plot_xmax, (xmax - xmin) / pts_in_x) y = np.arange(plot_ymin, plot_ymax, (ymax - ymin) / pts_in_y) X, Y = np.meshgrid(x, y) myfunc = self.fct(X, Y) # TODO: plots like y=1/x have a connection between -inf and +inf that is not actually there! # plot function and put on function-stack new_fct = self.mySystem.Phaseplane.Plot.canvas.axes.contour(X, Y, myfunc, [0], zorder=100, linewidths=fct_linewidth, colors=fct_color) # new_fct = self.myGraph.plot_pp.axes.plot(xvalue, yvalue, label="fct", color="green") self.fct_stack.append(new_fct) self.mySystem.Phaseplane.Plot.update() myLogger.message("function plot: 0 = " + fct_string) except Exception as error: # TODO: use handle_exception for this myLogger.error_message(str(error)) else: myLogger.error_message("Please enter function.")
def create_trajectory(self): initial_condition = self.parent.read_init() forward, backward = self.parent.trajectory_direction() cond1 = initial_condition[0] is not None cond2 = initial_condition[1] is not None # check if trajectory with initial_condition exists already cond3 = not str(initial_condition) in self.traj_dict if cond1 and cond2 and cond3: self.plot_trajectory(initial_condition, forward, backward) myLogger.message("New initial condition: " + str(initial_condition[0]) + ", " + str(initial_condition[1]))
def onclick(self, event): """ This function is in charge of the mouse-click behaviour. A left mouse button click is recognized, the mouse location serves as an initial condition for trajectories. """ #TODO: check if try/except is the best thing to do here! if not self.plot_pp.zoomMode: try: mySystem except: # only capture mouse click if system exists myLogger.error_message("Please enter system.") else: cond1 = mySystem.x_dot is not None cond2 = mySystem.x_dot is not None cond3 = str(self.parent.xDotLineEdit.text()) != "" cond4 = str(self.parent.yDotLineEdit.text()) != "" if cond1 and cond2 and cond3 and cond4: event1 = event.xdata is not None event2 = event.ydata is not None button = event.button == 1 if not myEquilibria.eqp_toggle: # event.xdata and event.ydata are initial conditions for integration # mouse click will also be recognized if clicked outside of the graph area, so filter that: if event1 and event2 and button: forward, backward = self.trajectory_direction() if myTrajectories.plot_trajectory( [event.xdata, event.ydata], forward, backward): myLogger.message("New initial condition: " + str(event.xdata) + ", " + str(event.ydata)) else: pass else: # equilibrium point if event1 and event2 and button: equilibrium_point = myEquilibria.find_equilibrium( [event.xdata, event.ydata]) if equilibrium_point is not None: self.parent.add_linearization_tab( equilibrium_point) else: # only capture mouse click if system exists myLogger.error_message("Please enter system.") else: myLogger.debug_message("in zoom mode")
def export_as_pdf(self, filename): system = self.get_current_system() if system != None: filename_pp = str(filename) + "_pp.pdf" system.Phaseplane.Plot.canvas.fig.savefig(filename_pp, bbox_inches='tight') filename_x = str(filename) + "_x.pdf" system.Xt.Plot.canvas.fig.savefig(filename_x, bbox_inches='tight') filename_y = str(filename) + "_y.pdf" system.Yt.Plot.canvas.fig.savefig(filename_y, bbox_inches='tight') myLogger.message("plot exported as\n\t" + filename_pp + ",\n\t" + filename_x + ",\n\t" + filename_y)
def plot_equilibrium(self, z_equilibrium, jacobian): """ this function plots an equilibrium point """ self.eq_plot = self.myWidget.Plot.canvas.axes.plot(z_equilibrium[0], z_equilibrium[1], 'ro', picker=5) # equilibrium point in t(x,y): # TODO: let user specify this in config! # TODO: show equilibria in x(t) and y(t) as well! if self.myWidget.mySystem.Phaseplane.backwardCheckbox.isChecked(): tmin = -float(myConfig.read("Trajectories", "traj_integrationtime")) else: tmin = 0 if self.myWidget.mySystem.Phaseplane.forwardCheckbox.isChecked(): tmax = float(myConfig.read("Trajectories", "traj_integrationtime")) else: tmax = 0 # equilibrium line from tmin to tmax if not(tmin==0 and tmax==0): self.myWidget.mySystem.Txy.Plot.canvas.axes.plot([z_equilibrium[0],z_equilibrium[0]], [z_equilibrium[1],z_equilibrium[1]], [tmin, tmax], linestyle="dashed", color="r") # marker t=0: self.myWidget.mySystem.Txy.Plot.canvas.axes.plot([z_equilibrium[0]], [z_equilibrium[1]], [0], 'o', color="r") self.myWidget.mySystem.Txy.Plot.update() #~ self.stack[str(z_equilibrium)] = self.eq_plot equilibrium_point = Container() equilibrium_point.coordinates = z_equilibrium equilibrium_point.plot = self.eq_plot equilibrium_point.character = self.characterize_equilibrium(jacobian) self.stack.append(equilibrium_point) # label equilibrium point self.myWidget.Plot.canvas.axes.text(z_equilibrium[0], z_equilibrium[1], equilibrium_point.character, fontsize=10) self.update_equilibria() # TODO: this call probably move somewhere else: if len(self.stack) > 0: self.myWidget.show_linearization_objects() myLogger.message("Equilibrium Point found at: " + str(z_equilibrium)) myLogger.message("jacobian:\n" + str(jacobian))
def submit(self): """ This function gets called after clicking on the submit button """ myLogger.message("New system submitted...") try: xtxt = str(self.xDotLineEdit.text()) ytxt = str(self.yDotLineEdit.text()) except UnicodeEncodeError as exc: myLogger.warn_message("UnicodeEncodeError! Please check input.") myLogger.debug_message(str(exc)) else: cond1 = str(self.xDotLineEdit.text()) != "" cond2 = str(self.yDotLineEdit.text()) != "" if cond1 and cond2: x_string = str(self.xDotLineEdit.text()) y_string = str(self.yDotLineEdit.text()) try: # Non-modal (!) Box intended for calming down the user... info_box = QtWidgets.QMessageBox(self) info_box.setAttribute(Qt.WA_DeleteOnClose) info_box.setStandardButtons(QtWidgets.QMessageBox.Ok) info_box.setIcon(QtWidgets.QMessageBox.Information) info_box.setWindowTitle("New system submitted") info_box.setText( "The new system is being processed now, please wait! \n" "Especially when LaTeX is used for the labels this may take some time and the " "program might seem unresponsive!") info_box.setModal(False) info_box.show() QtCore.QCoreApplication.processEvents() # Processing equations equation = (x_string, y_string) system = System(self, equation) self.systems.insert(0, system) self.save_tmp_system() myLogger.message("------ new system created ------") myLogger.message( " x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message( " y' = " + str(system.equation.what_is_my_system()[1]) + "\n", ) try: info_box.close() except RuntimeError: # if dialog has already been closed by the user pass except BaseException as exc: QtWidgets.QMessageBox.critical( self, "Error!", "An error occured while processing the system. " "Detailed error message: \n %s" % exc) myLogger.error_message(str(exc)) else: myLogger.error_message("Please check system!")
def save_system(self, file_name, system): x_dot_string = str(system[0]) y_dot_string = str(system[1]) f_ending = '.ppf' f_len = len(file_name) if file_name[f_len - 4:f_len] == f_ending: with open(file_name, 'w') as sysfile: sysfile.write(x_dot_string + "\n" + y_dot_string) else: with open(file_name + f_ending, 'w') as sysfile: sysfile.write(x_dot_string + "\n" + y_dot_string) myLogger.message("System saved as " + file_name)
def plot_equilibrium(self, z_equilibrium, jacobian): """ this function plots an equilibrium point """ self.eq_plot = self.plot_pp.axes.plot(z_equilibrium[0], z_equilibrium[1], 'ro', picker=5) self.eqp_stack[str(z_equilibrium)] = self.eq_plot # TODO: actually this function was implemented in graph class self.update_equilibria() myLogger.message("Equilibrium Point found at: " + str(z_equilibrium)) myLogger.message("jacobian:\n" + str(jacobian))
def remove(self): """ This function removes the vector field if existent. """ if len(self.stack) != 0: for i in xrange(0, len(self.stack)): try: self.stack.pop().remove() myLogger.message("Vector field removed") except Exception as error: myLogger.debug_message("Couldn't delete vector field") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) else: myLogger.debug_message("No vector field to delete")
def update(self): """ This function updates the vectorfield in the phase plane. """ self.remove() if self.tgl: # get axis limits xmin, xmax, ymin, ymax = self.myWidget.Plot.canvas.axes.axis() N = int(myConfig.read("Vectorfield", "vf_gridPointsInX")) M = int(myConfig.read("Vectorfield", "vf_gridPointsInY")) vf_color = str(myConfig.read("Vectorfield", "vf_color")) vf_arrowHeadWidth = float( myConfig.read("Vectorfield", "vf_arrowHeadWidth")) vf_arrowHeadLength = float( myConfig.read("Vectorfield", "vf_arrowHeadLength")) vf_arrowWidth = float(myConfig.read("Vectorfield", "vf_arrowWidth")) vf_arrowPivot = str(myConfig.read("Vectorfield", "vf_arrowPivot")) a = np.linspace(xmin - xmin / N, xmax - xmax / N, N) b = np.linspace(ymin - ymin / M, ymax - ymax / M, M) X1, Y1 = np.meshgrid(a, b) try: DX1, DY1 = self.myWidget.mySystem.equation.rhs([X1, Y1]) M = np.hypot(DX1, DY1) M[M == 0] = 1. DX1_mix, DY1_mix = DX1 / M, DY1 / M quiver = self.myWidget.Plot.canvas.axes.quiver( X1, Y1, DX1_mix, DY1_mix, angles='xy', headwidth=vf_arrowHeadWidth, headlength=vf_arrowHeadLength, width=vf_arrowWidth, pivot=vf_arrowPivot, color=vf_color) self.stack.append(quiver) myLogger.message("vector field created") except: myLogger.debug_message("Please enter system.") self.myWidget.Plot.update()
def load_system(self, file_name): """ load previous system (from tmp file) """ with open(file_name, 'r') as sysfile: # TODO: This does not work, but how would i find a way to store a system? # pps_file = pcl.loads(sysfile.read()) # system = System(self) # system.unpickle(pps_file) # self.systems.insert(0, system) # self.xDotLineEdit.setText(sysfile.readline().strip()) # self.yDotLineEdit.setText(sysfile.readline().strip()) xdot_string = str(sysfile.readline()) ydot_string = str(sysfile.readline()) self.xDotLineEdit.setText(xdot_string.strip()) self.yDotLineEdit.setText(ydot_string.strip()) myLogger.message(file_name + " loaded")
def remove_all(self): if len(self.fct_stack) != 0: for i in range(0, len(self.fct_stack)): fct = self.fct_stack.pop().collections for j in range(0, len(fct)): try: fct[j].remove() except Exception as error: myLogger.debug_message("couldn't delete function") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message("functions removed") else: myLogger.debug_message("no function to delete") self.mySystem.Phaseplane.Plot.update()
def remove_function_from_plot(self): if len(self.fct_stack) != 0: for i in range(0, len(self.fct_stack)): fct = self.fct_stack.pop().collections for j in range(0, len(fct)): try: fct[j].remove() except Exception as error: myLogger.debug_message("couldn't delete function") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message("functions removed") else: myLogger.debug_message("no function to delete") self.myGraph.update_graph(self.myGraph.plot_pp)
def save_system(self, file_name): x_dot_string = str(self.xDotLineEdit.text()) y_dot_string = str(self.yDotLineEdit.text()) f_ending = '.ppf' f_len = len(file_name) if file_name[f_len - 4:f_len] == f_ending: with open(file_name, 'w') as sysfile: sysfile.write(x_dot_string + "\n" + y_dot_string) else: with open(file_name + f_ending, 'w') as sysfile: sysfile.write(x_dot_string + "\n" + y_dot_string) myLogger.message("system saved as " + file_name)
def remove_function_from_plot(self): if len(self.fct_stack) != 0: for i in xrange(0, len(self.fct_stack)): fct = self.fct_stack.pop().collections for j in xrange(0, len(fct)): try: fct[j].remove() except Exception as error: myLogger.debug_message("couldn't delete function") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message("functions removed") else: myLogger.debug_message("no function to delete") self.myGraph.update_graph(self.myGraph.plot_pp)
def remove_all(self): if len(self.fct_stack) != 0: for i in xrange(0, len(self.fct_stack)): fct = self.fct_stack.pop().collections for j in xrange(0, len(fct)): try: fct[j].remove() except Exception as error: myLogger.debug_message("couldn't delete function") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) myLogger.message("functions removed") else: myLogger.debug_message("no function to delete") self.mySystem.Phaseplane.Plot.update()
def onclick(self, event): """ This function is in charge of the mouse-click behaviour. A left mouse button click is recognized, the mouse location serves as an initial condition for trajectories. """ #TODO: check if try/except is the best thing to do here! if not self.plot_pp.zoomMode: try: mySystem except: # only capture mouse click if system exists myLogger.error_message("Please enter system.") else: cond1 = mySystem.x_dot is not None cond2 = mySystem.x_dot is not None cond3 = str(self.parent.xDotLineEdit.text()) != "" cond4 = str(self.parent.yDotLineEdit.text()) != "" if cond1 and cond2 and cond3 and cond4: event1 = event.xdata is not None event2 = event.ydata is not None button = event.button == 1 if not myEquilibria.eqp_toggle: # event.xdata and event.ydata are initial conditions for integration # mouse click will also be recognized if clicked outside of the graph area, so filter that: if event1 and event2 and button: forward, backward = self.trajectory_direction() if myTrajectories.plot_trajectory([event.xdata, event.ydata], forward, backward): myLogger.message("New initial condition: " + str(event.xdata) + ", " + str(event.ydata)) else: pass else: # equilibrium point if event1 and event2 and button: myEquilibria.find_equilibrium([event.xdata, event.ydata]) else: # only capture mouse click if system exists myLogger.error_message("Please enter system.") else: myLogger.debug_message("in zoom mode")
def remove(self): if len(self.nc_stack) != 0: for i in xrange(0, len(self.nc_stack)): nc = self.nc_stack.pop().collections for j in xrange(0, len(nc)): try: nc[j].remove() except Exception as error: myLogger.debug_message("Could not delete nullcline.") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) # remove nullclines legend self.myWidget.Plot.canvas.axes.legend_ = None myLogger.message("Nullclines removed.") else: myLogger.debug_message("No nullclines to delete.")
def remove(self): if len(self.nc_stack) != 0: for i in xrange(0, len(self.nc_stack)): nc = self.nc_stack.pop().collections for j in xrange(0, len(nc)): try: nc[j].remove() except Exception as error: myLogger.debug_message("Could not delete nullcline.") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error)) # remove nullclines legend self.plot_pp.axes.legend_ = None myLogger.message("Nullclines removed.") else: myLogger.debug_message("No nullclines to delete.")
def create_trajectory(self): try: initial_condition = self.mySystem.Phaseplane.read_init() forward, backward = self.mySystem.Phaseplane.trajectory_direction() cond1 = initial_condition[0] is not None cond2 = initial_condition[1] is not None # check if trajectory with initial_condition exists already cond3 = not str(initial_condition) in self.traj_dict if cond1 and cond2 and cond3: self.plot_trajectory(initial_condition, forward, backward) myLogger.message("New initial condition: " + str(initial_condition[0]) + ", " + str(initial_condition[1])) except Exception as error: myLogger.error_message("Could not create trajectory") myLogger.debug_message(str(type(error))) myLogger.debug_message(str(error))
def submit(self): """ This function gets called after clicking on the submit button """ myLogger.message("New system submitted...") try: xtxt = str(self.xDotLineEdit.text()) ytxt = str(self.yDotLineEdit.text()) except UnicodeEncodeError as exc: myLogger.warn_message("UnicodeEncodeError! Please check input.") myLogger.debug_message(str(exc)) else: cond1 = str(self.xDotLineEdit.text()) != "" cond2 = str(self.yDotLineEdit.text()) != "" if cond1 and cond2: x_string = str(self.xDotLineEdit.text()) y_string = str(self.yDotLineEdit.text()) try: # Non-modal (!) Box intended for calming down the user... info_box = QtWidgets.QMessageBox(self) info_box.setAttribute(Qt.WA_DeleteOnClose) info_box.setStandardButtons(QtWidgets.QMessageBox.Ok) info_box.setIcon(QtWidgets.QMessageBox.Information) info_box.setWindowTitle("New system submitted") info_box.setText("The new system is being processed now, please wait! \n" "Especially when LaTeX is used for the labels this may take some time and the " "program might seem unresponsive!") info_box.setModal(False) info_box.show() QtCore.QCoreApplication.processEvents() # Processing equations equation = (x_string, y_string) system = System(self, equation) self.systems.insert(0, system) self.save_tmp_system() myLogger.message("------ new system created ------") myLogger.message(" x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message(" y' = " + str(system.equation.what_is_my_system()[1]) + "\n", ) try: info_box.close() except RuntimeError: # if dialog has already been closed by the user pass except BaseException as exc: QtWidgets.QMessageBox.critical(self, "Error!", "An error occured while processing the system. " "Detailed error message: \n %s" % exc) myLogger.error_message(str(exc)) else: myLogger.error_message("Please check system!")
def update(self): """ This function updates the vectorfield in the phase plane. """ self.remove() if self.tgl: # get axis limits xmin, xmax, ymin, ymax = self.myWidget.Plot.canvas.axes.axis() N = int(myConfig.read("Vectorfield", "vf_gridPointsInX")) M = int(myConfig.read("Vectorfield", "vf_gridPointsInY")) vf_color = str(myConfig.read("Vectorfield", "vf_color")) vf_arrowHeadWidth = float(myConfig.read("Vectorfield", "vf_arrowHeadWidth")) vf_arrowHeadLength = float(myConfig.read("Vectorfield", "vf_arrowHeadLength")) vf_arrowWidth = float(myConfig.read("Vectorfield", "vf_arrowWidth")) vf_arrowPivot = str(myConfig.read("Vectorfield", "vf_arrowPivot")) a = np.linspace(xmin - xmin / N, xmax - xmax / N, N) b = np.linspace(ymin - ymin / M, ymax - ymax / M, M) X1, Y1 = np.meshgrid(a, b) try: DX1, DY1 = self.myWidget.mySystem.equation.rhs([X1, Y1]) M = np.hypot(DX1, DY1) M[M == 0] = 1. DX1_mix, DY1_mix = DX1 / M, DY1 / M quiver = self.myWidget.Plot.canvas.axes.quiver(X1, Y1, DX1_mix, DY1_mix, angles='xy', headwidth=vf_arrowHeadWidth, headlength=vf_arrowHeadLength, width=vf_arrowWidth, pivot=vf_arrowPivot, color=vf_color) self.stack.append(quiver) myLogger.message("vector field created") except: myLogger.debug_message("Please enter system.") self.myWidget.Plot.update()
def remove(self): """ This function removes Streamlines if existent. """ if len(self.sl_stack) != 0: for i in range(0, len(self.sl_stack)): sl = self.sl_stack.pop() try: sl.lines.remove() except: pass #sl_arrows.remove() doesn't work # doesn't work either: del sl.arrows # as long as no other patches are used: self.myWidget.Plot.canvas.axes.patches = [] myLogger.message("Streamlines removed") else: myLogger.debug_message("No streamlines to delete")
def submit(self): """ This function gets called after clicking on the submit button """ try: xtxt = str(self.xDotLineEdit.text()) ytxt = str(self.yDotLineEdit.text()) except UnicodeEncodeError as exc: myLogger.warn_message("UnicodeEncodeError! Please check input.") myLogger.debug_message(str(exc)) else: cond1 = str(self.xDotLineEdit.text()) != "" cond2 = str(self.yDotLineEdit.text()) != "" if cond1 and cond2: x_string = str(self.xDotLineEdit.text()) y_string = str(self.yDotLineEdit.text()) equation = (x_string, y_string) system = System(self, equation) self.systems.insert(0, system) self.save_tmp_system() myLogger.message("------ new system created ------") myLogger.message(" x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message(" y' = " + str(system.equation.what_is_my_system()[1]) + "\n", ) else: myLogger.error_message("Please check system!")
def submit(self): """ This function gets called after clicking on the submit button """ try: xtxt = str(self.xDotLineEdit.text()) ytxt = str(self.yDotLineEdit.text()) except UnicodeEncodeError as exc: myLogger.warn_message("UnicodeEncodeError! Please check input.") myLogger.debug_message(str(exc)) else: cond1 = str(self.xDotLineEdit.text()) != "" cond2 = str(self.yDotLineEdit.text()) != "" if cond1 and cond2: x_string = str(self.xDotLineEdit.text()) y_string = str(self.yDotLineEdit.text()) equation = (x_string, y_string) system = System(self, equation) self.systems.insert(0, system) self.save_tmp_system() myLogger.message("------ new system created ------") myLogger.message(" x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message( " y' = " + str(system.equation.what_is_my_system()[1]) + "\n", ) else: myLogger.error_message("Please check system!")
def print_symbolic_nullclines(self): """ This function will try to find the symbolic nullclines. """ try: isoclines_x, isoclines_y = self.find_symbolic_nullclines() myLogger.message("Computed nullclines:") for i in range(len(isoclines_x)): myLogger.message("x = " + str(isoclines_x[i]).strip('[]')) for i in range(len(isoclines_y)): myLogger.message("y = " + str(isoclines_y[i]).strip('[]')) except: myLogger.message("Couldn't solve nullclines. There seems to be no algorithm implemented")
def update(self): """ This function plots streamlines. """ self.remove() if self.tgl: xmin, xmax, ymin, ymax = self.myWidget.Plot.canvas.axes.axis() N = int(myConfig.read("Streamlines", "stream_gridPointsInX")) M = int(myConfig.read("Streamlines", "stream_gridPointsInY")) stream_linewidth = float( myConfig.read("Streamlines", "stream_linewidth")) stream_color = str(myConfig.read("Streamlines", "stream_color")) stream_density = float( myConfig.read("Streamlines", "stream_density")) a = np.linspace(xmin, xmax, N) b = np.linspace(ymin, ymax, M) X1, Y1 = np.meshgrid(a, b) try: DX1, DY1 = self.myWidget.mySystem.equation.rhs([X1, Y1]) streamplot = self.myWidget.Plot.canvas.axes.streamplot( X1, Y1, DX1, DY1, density=stream_density, linewidth=stream_linewidth, color=stream_color) self.sl_stack.append(streamplot) myLogger.message("Streamplot created") except: myLogger.debug_message("No system yet") self.myWidget.Plot.canvas.draw()
def new_linearized_system(self, equation, name, equilibrium): xe, ye = equilibrium system = System(self, equation, name=name, linear=True) self.systems.insert(0, system) system.plot_eigenvectors(equilibrium) myLogger.message("------ new linearized system created at xe = " + str(xe) + ", ye = " + str(ye) + " ------") myLogger.message(" x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message(" y' = " + str(system.equation.what_is_my_system()[1]) + "\n", )
def print_symbolic_nullclines(self): """ This function will try to find the symbolic nullclines. """ try: isoclines_x, isoclines_y = self.find_symbolic_nullclines() myLogger.message("Computed nullclines:") for i in range(len(isoclines_x)): myLogger.message("x = " + str(isoclines_x[i]).strip('[]')) for i in range(len(isoclines_y)): myLogger.message("y = " + str(isoclines_y[i]).strip('[]')) except: myLogger.message( "Couldn't solve nullclines. There seems to be no algorithm implemented" )
def submit(self): """ This function gets called after clicking on the submit button """ try: xtxt = str(self.xDotLineEdit.text()) ytxt = str(self.yDotLineEdit.text()) except UnicodeEncodeError as exc: myLogger.warn_message("UnicodeEncodeError! Please check input.") myLogger.debug_message(str(exc)) else: cond1 = str(self.xDotLineEdit.text()) != "" cond2 = str(self.yDotLineEdit.text()) != "" if cond1 and cond2: # set right hand side, print rhs to logfield, solve, # then plot vector field # initialize system mySystem.__init__() # set rhs x_string = str(self.xDotLineEdit.text()) y_string = str(self.yDotLineEdit.text()) mySystem.set_rhs(x_string, y_string) try: # write to tmp file: self.save_system('library/tmp.ppf') # clear figure, if there is any self.myGraph.clear() # delete linearization tabs (index 3 to n) if len(self.linearization_stack) > 0: for i in xrange(0, len(self.linearization_stack)): index = 3 + len(self.linearization_stack) - i self.tabWidget.removeTab(index) #reset stack self.linearization_stack = [] myLogger.debug_message("All linearization tabs removed.") self.initializing() myLogger.message("------ new system created ------") myLogger.message(" x' = " + str(mySystem.what_is_my_system()[0])) myLogger.message(" y' = " + str(mySystem.what_is_my_system()[1]) + "\n", ) except Exception as error: handle_exception(error) else: myLogger.error_message("No system entered")
def new_linearized_system(self, equation, name, equilibrium): x_string, y_string = equation xe, ye = equilibrium system = System(self, equation, name=name, linear=True) self.systems.insert(0, system) system.plot_eigenvectors(equilibrium) myLogger.message("------ new linearized system created ------") myLogger.message(" x' = " + str(system.equation.what_is_my_system()[0])) myLogger.message( " y' = " + str(system.equation.what_is_my_system()[1]) + "\n", )
def add_function_to_plot(self): """ will plot additional functions and put it on a stack """ self.x = sp.symbols('x') self.y = sp.symbols('y') self.fct = None try: fct_txt = str(self.yLineEdit.text()) except UnicodeEncodeError as exc: myLogger.error_message("input error!") myLogger.debug_message(str(exc)) if fct_txt != "": try: self.fct_string = str(self.yLineEdit.text()) self.fct_expr = sp.sympify(self.fct_string) # self.fct = sp.lambdify(self.x,self.fct_expr,'numpy') self.fct = sp.lambdify((self.x, self.y), self.fct_expr, 'numpy') xmin, xmax, ymin, ymax = self.myGraph.get_limits( self.myGraph.plot_pp) # plot the function for an x-interval twice as big as the current window deltax = (xmax - xmin) / 2 deltay = (ymax - ymin) / 2 plot_xmin = xmin - deltax plot_xmax = xmax + deltax plot_ymin = ymin - deltay plot_ymax = ymax + deltay pts_in_x = int(myConfig.read("Functions", "fct_gridPointsInX")) pts_in_y = int(myConfig.read("Functions", "fct_gridPointsInY")) fct_color = myConfig.read("Functions", "fct_color") fct_linewidth = float( myConfig.read("Functions", "fct_linewidth")) x = np.arange(plot_xmin, plot_xmax, (xmax - xmin) / pts_in_x) y = np.arange(plot_ymin, plot_ymax, (ymax - ymin) / pts_in_y) X, Y = np.meshgrid(x, y) #yvalue = self.fct(xvalue) myfunc = self.fct(X, Y) # TODO: plots like y=1/x have a connection between -inf and +inf that is not actually there! # plot function and put on function-stack new_fct = self.myGraph.plot_pp.axes.contour( X, Y, myfunc, [0], zorder=100, linewidths=fct_linewidth, colors=fct_color) # new_fct = self.myGraph.plot_pp.axes.plot(xvalue, yvalue, label="fct", color="green") self.fct_stack.append(new_fct) self.myGraph.update_graph(self.myGraph.plot_pp) myLogger.message("function plot: 0 = " + self.fct_string) except Exception as error: handle_exception(error) else: myLogger.error_message("Please enter function.")