def build(self): data = np.random.random((10, 10)) # Create the widgets. We need a vertical box to arrange the navigation toolbar hbox = BoxLayout() vbox = BoxLayout(orientation="vertical") label = Label(text="Click on the plot as many times as you want!") # Create the figure. fig = Figure() axes = fig.add_subplot() axes.imshow(data) canvas = FigureCanvasKivyAgg(fig) nav = NavigationToolbar2Kivy(canvas) # Add them to a container. vbox.add_widget(canvas) vbox.add_widget(nav.actionbar) hbox.add_widget(label) hbox.add_widget(vbox) # Add the callback of the canvas. canvas.mpl_connect("button_press_event", on_canvas_click) canvas.draw() # Return the top container. This can be any widget return hbox
class SimulacionScreenLayout(BoxLayout): def __init__(self, **kwargs): super(SimulacionScreenLayout, self).__init__(**kwargs) self.padding = [10, 10, 10, 10] self.orientation = 'vertical' self.faselabel = WidgetCreator.newlabel("Nombre de Fase", size_hint=(1.0, None)) self.add_widget(self.faselabel) chat = BoxLayout(orientation="horizontal", size_hint=(1, 1), spacing=10) chat.add_widget(WidgetCreator.newimage('assets/BotFace.jpg')) self.chatbox = ChatBox(size_hint=(1, 1)) chat.add_widget(self.chatbox) self.add_widget(chat) self.camara = Image(size_hint=(1, 1), pos_hint={'top': 1}) self.soundwave = FigureCanvasKivyAgg(AudioController().fig) self.userinputbox = UserInputBox(self.camara, self.soundwave, padding=[10, 10, 10, 10], spacing=10) self.add_widget(self.userinputbox) Clock.schedule_interval(self.update, 1.0 / 30.0) def update(self, dt): pose = camaracontroller.capturepose() self.userinputbox.poselabel.text = "Brazos: " + pose.name rostro = camaracontroller.capturegesture() self.userinputbox.rostrolabel.text = "Rostro: " + rostro.name if SelectorDeIconos.iconoderostro(rostro) is not None: self.userinputbox.rostroimage.source = SelectorDeIconos.iconoderostro(rostro) buf = camaracontroller.captureposeimage() self.soundwave.draw() if buf is not False: texture1 = Texture.create(size=(640, 480), colorfmt='bgr') texture1.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte') self.camara.texture = texture1
class WiecejWykresow(Screen): wykresy = ObjectProperty() def wykres(self): filename = "nowyplik.gpx" self.fig = metody.wykres(filename) self.cnv = FigureCanvasKivyAgg(self.fig) self.wykresy.add_widget(self.cnv) self.cnv.draw()
class GraphWidget(BoxLayout): game_widget = None to_display = [] graph_canvas = None fig = None ax = None paused = False nb_pointsdisplay = 1000 refresh_rate = 10 def __init__(self, **kwargs): super(GraphWidget, self).__init__(**kwargs) Clock.schedule_interval(self.update, 1.0 / self.refresh_rate) self.fig = plt.figure() self.ax = self.fig.add_subplot(111) self.line1, = self.ax.plot([]) self.ax.set_ylabel("Score Mean") self.graph_canvas = FigureCanvasKivyAgg(figure=self.fig) self.add_widget(self.graph_canvas) def update(self, dt): if self.paused: return False if self.game_widget is None or len(self.game_widget.scores) == 0: return nb_scores = min(len(self.game_widget.scores), self.nb_pointsdisplay) x_data = range(0, nb_scores) start = len(self.game_widget.scores) - nb_scores y_data = self.game_widget.scores[start:] self.line1.set_ydata(y_data) min_val, max_val = np.min(self.game_widget.scores), np.max( self.game_widget.scores) val_range = max_val - min_val margin = 5 * val_range / 100 self.ax.set_ylim(min_val - margin, max_val + margin) self.line1.set_xdata(x_data) self.ax.set_xlim(0, nb_scores) self.graph_canvas.draw() # self.graph_canvas.flush_events() def pause_resume(self): self.paused = not self.paused if not self.paused: Clock.schedule_interval(self.update, 1.0 / self.refresh_rate)
class IntensityPopup(Popup): def __init__(self): super(Popup, self).__init__() global intensitat_llum, Nx_inty, Ny_inty, w_det_ys self.inty_fig = plt.figure() self.inty_canvas = FigureCanvasKivyAgg(self.inty_fig) self.box2.add_widget(self.inty_canvas, 1) self.visu = plt.axes() self.inty_plot = self.visu.plot( intensitat_llum[int(Nx_inty / 2), w_det_ys:Ny_inty - w_det_ys]) self.inty_canvas.draw()
class AddLocationForm(BoxLayout): my_map = ObjectProperty() plot = ObjectProperty() stat = ObjectProperty() def __init__(self, **kwargs): super(AddLocationForm, self).__init__(**kwargs) self.my_map.map_source = "osm-fr" self.fig = plt.figure() def analizuj_plik(self): filename = 'krk1.gpx' f.wczytaj_dane(filename) lat, lon = f.wczytaj_dane(filename) self.draw_route(lat, lon) def statystyka(self): #statystyki filename = 'krk1.gpx' f.wczytaj_dane(filename) el, dates, DH, suma_odl, odl, czas_ost, czas, v, staty = f.statystyki( filename) self.stat.text = "{}".format(staty) #wyswietlanie w aplikacji def draw_route(self, lat, lon): #rysowanie trasy data_lay = MarkerMapLayer() self.my_map.add_layer(data_lay) # my_map jest obiektem klasy MapView for point in zip(lat, lon): self.draw_marker(*point, layer=data_lay) def draw_marker(self, lat, lon, layer=None, markerSource='dot.png'): if lat != None and lon != None: marker = MapMarker(lat=lat, lon=lon, source=markerSource) self.my_map.add_marker(marker, layer=layer) def rysuj_wykres(self): filename = 'krk1.gpx' f.wczytaj_dane(filename) el, dates, DH, suma_odl, odl, czas_ost, czas, v, staty = f.statystyki( filename) self.ax1 = self.fig.add_subplot(111) self.ax1.scatter(czas, odl) self.ax1.set_xlabel('czas') self.ax1.set_ylabel('odl') self.ax1.set_title('Odleglosc do czasu') self.cnv = FigureCanvasKivyAgg(self.fig) self.plot.add_widget(self.cnv) self.cnv.draw()
def showGraphs(self): if self.last_graphs is not None: self.ids.general_graphs.clear_widgets() self.ids.pareto_graph.clear_widgets() fitness_graph = FigureCanvasKivyAgg(self.last_graphs[0]) individual_graph = FigureCanvasKivyAgg(self.last_graphs[1]) pareto_graph = FigureCanvasKivyAgg(self.last_graphs[2]) self.ids.general_graphs.add_widget(fitness_graph) fitness_graph.draw() self.ids.general_graphs.add_widget(individual_graph) individual_graph.draw() self.ids.pareto_graph.add_widget(pareto_graph) pareto_graph.draw()
class Classical(BoxLayout): time_label = StringProperty() but1 = StringProperty() but2 = StringProperty() but3 = StringProperty() language = StringProperty() def __init__(self, **kwargs): super(Classical, self).__init__(**kwargs) #Language: self.language = "CA" self.time_label = "Temps" self.but1 = "Sobre el pic" self.but2 = "En el pic" self.but3 = "Sota el pic" self.cabut.color = (0,0.75,1,1) self.esbut.color = (1,1,1,1) self.enbut.color = (1,1,1,1) "Classical definitions" self.time_cla = 0. self.height_cla = 0.3 self.sigma_cla = 1./(np.sqrt(2*np.pi)*self.height_cla) self.mu_cla = 0 rob.m = 5 self.R = 0.2 self.k_cla = 0.5 self.tmax_cla = 10 self.xo_cla = 1.5 self.yin0 = np.array([self.xo_cla,0.0]) #Check if this is needed. self.timeslide_cla.disabled = True #It is not allowed to move the time bar. self.xarr_cla = xarr_cla = np.arange(-20, 20 + (20 - (-20))/float(1000)*0.1, (20 - (-20))/float(1000)) #Why not? #It initially used xarr_qua. But since the programs were separated, it uses this. It is only for plotting purposes. #Flux controllers. self.oldtop2_cla = self.height_cla self.oldk2_cla = self.k_cla #Clock (Classical): self.time_cla = 0. self.dtime0_cla = 0.01 #Default time step (used by RK4 and as default playing velocity). self.dtime_cla = 1.2*self.dtime0_cla #Defines the playing velocity = 1. self.oldtime1_cla = self.time_cla + 1 self.oldrow = -1 #Plots (Classical): self.canvas_cla = FigureCanvasKivyAgg(fig_cla) self.panel1.add_widget(self.canvas_cla) acl.axis('scaled') acl.set_xlabel("x (m)") acl.set_ylabel("y (m)") acl.axis([-2.5, 2.5, 0 , 3]) self.ground_cla, = acl.plot(self.xarr_cla, rob.fground(self.mu_cla, self.sigma_cla, self.k_cla, self.xarr_cla), 'k--') self.filled_cla = acl.fill_between(self.xarr_cla, 0, rob.fground(self.mu_cla, self.sigma_cla, self.k_cla, self.xarr_cla), color = (0.5,0.5,0.5,0.5)) self.ballcm, = acl.plot([], [], 'ro', ms=1) self.ballperim, = acl.plot([], [], 'r-', lw=1) self.filled_ball_cla = acl.fill_between([], []) #Empty one. Needs to be here in order to use self.name.remove() later. self.balldots, = acl.plot([], [], 'ro', ms=1) self.E_cla, = acl.plot([],[], 'g-.', lw=1, label = "E") acl.legend(loc=1) #First computations: self.demo1_cla_btn() Clock.schedule_interval(self.ballupdate, self.dtime0_cla) #Classical functions: #Changing parameters: def plotground(self): #It is only activated if some value changes. a = self.oldtop2_cla != self.height_cla b = self.oldk2_cla != self.k_cla if a or b: self.oldtop2_cla = self.height_cla self.oldk2_cla = self.k_cla #Changes and plots the new ground. self.ground_cla.set_data(self.xarr_cla, rob.fground(self.mu_cla, self.sigma_cla, self.k_cla, self.xarr_cla)) self.filled_cla.remove() self.filled_cla = acl.fill_between(self.xarr_cla, 0, rob.fground(self.mu_cla, self.sigma_cla, self.k_cla, self.xarr_cla), color = (0.5,0.5,0.5,0.5)) #Plotting. def plotball_0(self): x = self.supermatrix_cla[0, 1] XXcm = rob.xcm(self.R, self.mu_cla, self.sigma_cla, self.k_cla, x) YYcm = rob.ycm(self.R, self.mu_cla, self.sigma_cla, self.k_cla, x) gamma = np.arange(0, 2*np.pi + 0.5*0.02/self.R, 0.02/self.R) half_gamma = np.arange(0, np.pi, 0.02/self.R) XXr = XXcm + self.R*np.cos(gamma) YYr = YYcm + self.R*np.sin(gamma) Xdots = [] Ydots = [] for i in [-1./2., 0., 1./2., 1.]: Xdots.append(XXcm + self.R*np.sin(self.angle[0] + i*np.pi)/2.) Ydots.append(YYcm + self.R*np.cos(self.angle[0] + i*np.pi)/2.) self.ballperim.set_data(XXr, YYr) self.filled_ball_cla.remove() self.filled_ball_cla = acl.fill_between(XXcm + self.R*np.cos(half_gamma), YYcm - self.R*np.sin(half_gamma), YYcm + self.R*np.sin(half_gamma), color = (1,0,0,0.2)) self.ballcm.set_data(XXcm, YYcm) self.balldots.set_data(Xdots, Ydots) self.canvas_cla.draw() def plotball(self, t): if self.oldtime1_cla != t: if t >= self.supermatrix_cla[-1,0]: row = - 1 else: row = int(t/self.dtime0_cla) if self.oldrow != row: x = self.supermatrix_cla[row, 1] XXcm = rob.xcm(self.R, self.mu_cla, self.sigma_cla, self.k_cla, x) YYcm = rob.ycm(self.R, self.mu_cla, self.sigma_cla, self.k_cla, x) gamma = np.arange(0, 2*np.pi + 0.5*0.02/self.R, 0.02/self.R) half_gamma = np.arange(0, np.pi, 0.02/self.R) XXr = XXcm + self.R*np.cos(gamma) YYr = YYcm + self.R*np.sin(gamma) Xdots = [] Ydots = [] for i in [-1./2., 0., 1./2., 1.]: Xdots.append(XXcm + self.R*np.sin(self.angle[row] + i*np.pi)/2.) Ydots.append(YYcm + self.R*np.cos(self.angle[row] + i*np.pi)/2.) self.ballperim.set_data(XXr, YYr) self.filled_ball_cla.remove() self.filled_ball_cla = acl.fill_between(XXcm + self.R*np.cos(half_gamma), YYcm - self.R*np.sin(half_gamma), YYcm + self.R*np.sin(half_gamma), color = (1,0,0,0.2)) self.ballcm.set_data(XXcm, YYcm) self.balldots.set_data(Xdots, Ydots) self.canvas_cla.draw() self.oldrow = row self.oldtime1_cla = t def plotE_cla(self): #Plots the initial energy as a height (maximum height). x = np.arange(-2.6, 2.6, 0.1) y = self.Eheight + 0*x self.E_cla.set_data(x,y) self.canvas_cla.draw() #Playing. def ballupdate(self, dt): self.time_cla = self.timeslide_cla.value + self.dtime_cla #It starts again if the time reaches the top. if self.time_cla >= self.tmax_cla: self.time_cla = 0 self.timeslide_cla.value = self.time_cla self.plotball(self.time_cla) def reset_cla(self): #Sets time to 0 self.timeslide_cla.value = 0 self.time_cla = 0 def demo1_cla_btn(self): self.reset_cla() self.height_cla = 0.8 self.sigma_cla = 1./(np.sqrt(2*np.pi)*self.height_cla) self.k_cla = 0.8 self.plotground() #This version does not compute anything. It just reads the precomputed matrices. self.supermatrix_cla = np.load("Demo1_cla/super.npy") self.angle = np.load("Demo1_cla/ang.npy") #Plots the maximum height: self.Eheight = np.load("Demo1_cla/ene.npy") self.plotE_cla() self.demo1_button_cla.color = (0,0.75,1,1) self.demo2_button_cla.color = (1,1,1,1) self.demo3_button_cla.color = (1,1,1,1) def demo2_cla_btn(self): self.reset_cla() self.height_cla = 0.9 self.sigma_cla = 1./(np.sqrt(2*np.pi)*self.height_cla) self.k_cla = 0.8 self.plotground() #This version does not compute anything. It just reads the precomputed matrices. self.supermatrix_cla = np.load("Demo2_cla/super.npy") self.angle = np.load("Demo2_cla/ang.npy") #Plots the maximum height: self.Eheight = np.load("Demo2_cla/ene.npy") self.plotE_cla() self.demo2_button_cla.color = (0,0.75,1,1) self.demo1_button_cla.color = (1,1,1,1) self.demo3_button_cla.color = (1,1,1,1) def demo3_cla_btn(self): self.reset_cla() self.height_cla = 1 self.sigma_cla = 1./(np.sqrt(2*np.pi)*self.height_cla) self.k_cla = 0.8 self.plotground() #This version does not compute anything. It just reads the precomputed matrices. self.supermatrix_cla = np.load("Demo3_cla/super.npy") self.angle = np.load("Demo3_cla/ang.npy") #Plots the maximum height: self.Eheight = np.load("Demo3_cla/ene.npy") self.plotE_cla() self.demo3_button_cla.color = (0,0.75,1,1) self.demo2_button_cla.color = (1,1,1,1) self.demo1_button_cla.color = (1,1,1,1) def changecat(self): if self.language != "CA": self.language = "CA" self.time_label = "Temps" self.but1 = "Sobre el pic" self.but2 = "En el pic" self.but3 = "Sota el pic" self.cabut.color = (0,0.75,1,1) self.esbut.color = (1,1,1,1) self.enbut.color = (1,1,1,1) def changeesp(self): if self.language != "ES": self.language = "ES" self.time_label = "Tiempo" self.but1 = "Sobre el pico" self.but2 = "En el pico" self.but3 = "Bajo el pico" self.esbut.color = (0,0.75,1,1) self.cabut.color = (1,1,1,1) self.enbut.color = (1,1,1,1) def changeeng(self): if self.language != "EN": self.language = "EN" self.time_label = "Time" self.but1 = "Above the peak" self.but2 = "On the peak" self.but3 = "Under the peak" self.enbut.color = (0,0.75,1,1) self.esbut.color = (1,1,1,1) self.cabut.color = (1,1,1,1)
class TunnelPopup(Popup): amplada = NumericProperty() torn = StringProperty() def __init__(self,amplada): super(Popup, self).__init__() self.bwidth = amplada self.color = 'red' self.gpseudo_init() def gpseudo_init(self): self.hbar = 1.0 self.massa = 1.0 self.lx_max = 17.0 self.lx_min = -17.0 self.nx = 500 self.dx = (self.lx_max - self.lx_min)/float(self.nx) self.xx = np.arange(self.lx_min,self.lx_max + self.dx,self.dx) self.dt = 0.01 self.tmax = 1.5 self.temps = 0. self.nt = (self.tmax/self.dt)+1 self.r = 1j*self.dt/(2.0*(self.dx**2)) self.p0 = -200.0/self.lx_max self.bheight_quadrat = 76.0 self.bheight_gauss = 0.1 self.potencial() self.control_pot = 'quadrat' self.max_pot = 90.0 self.min_pot = 0.0 self.phi0() self.phi02 = abs(self.phi0)**2 self.colpot = 'yellow' self.cole = 'green' self.colphi = 'red' self.main_fig = plt.figure() self.main_fig.patch.set_facecolor('white') self.main_canvas = FigureCanvasKivyAgg(self.main_fig) self.main_canvas.bind(on_touch_up = self.control_teclat) self.box1.add_widget(self.main_canvas) self.pot_graf = plt.subplot() self.pot_graf.set_facecolor('black') self.pot_graf.axis([self.lx_min, self.lx_max, self.min_pot, self.max_pot]) self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color = self.colpot) self.e_data, = self.pot_graf.plot(self.xx,self.E_vect,color = self.color) self.ona = self.pot_graf.twinx() self.visu_ona, = self.ona.fill(self.xx,self.phi02, color = self.color) self.ona.axis([self.lx_min,self.lx_max,0.0,1.0]) #"Pantalla" on es veurè el coeficient de transmissió analític self.pant1 = plt.figure() self.pant1.patch.set_facecolor('white') self.pant1_canvas = FigureCanvasKivyAgg(self.pant1) self.box2.add_widget(self.pant1_canvas) self.T_txt = self.pant1.text(0.1, 0.5,'%.8f' % (self.T)) #"Pantalla" on es veurà la probabilotat de l'ona d'estar a l'esquerra de la barrera self.pant2 = plt.figure() self.pant2.patch.set_facecolor('white') self.pant2_canvas = FigureCanvasKivyAgg(self.pant2) self.box3.add_widget(self.pant2_canvas) self.prob_left_txt = self.pant2.text(0.1,0.5,'0.00000000') self.pant3 = plt.figure() self.pant3.patch.set_facecolor('white') self.pant3_canvas = FigureCanvasKivyAgg(self.pant3) self.box4.add_widget(self.pant3_canvas) self.norma_txt = self.pant3.text(0.1,0.5,'1.00000000') self.main_fig.tight_layout() self.main_canvas.draw() def potencial(self): #self.pot = 42.55*(np.exp(-(self.xx/self.bwidth)**2))/np.sqrt(self.bheight_gauss*np.pi) self.pot = np.zeros(len(self.xx)) for i in range(0,len(self.xx)): if -self.bwidth/2.0 < self.xx[i] < self.bwidth/2.0: self.pot[i] = self.bheight_quadrat def canvi_potencial_gauss(self): self.pot = 42.55*(np.exp(-(self.xx/self.bwidth)**2))/np.sqrt(self.bheight_gauss*np.pi) self.control_pot = 'gauss' self.pot_data.remove() self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.T_analitic() self.T_txt.remove() self.T_txt = self.pant1.text(0.1, 0.5,str(self.T)) self.main_canvas.draw() self.pant1_canvas.draw() def canvi_potencial_quadrat(self): self.pot = np.zeros(len(self.xx)) for i in range(0,len(self.xx)): if -self.bwidth/2.0 < self.xx[i] < self.bwidth/2.0: self.pot[i] = self.bheight_quadrat self.pot_data.remove() self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.T_analitic() self.T_txt.remove() self.T_txt = self.pant1.text(0.1, 0.5,str(self.T)) self.main_canvas.draw() self.pant1_canvas.draw() def phi0(self): self.phi0 = 1j*np.zeros(len(self.xx)) self.phi0 = (1.0/(2.0*np.pi)**(1.0/4.0))*np.exp((-(self.xx - 7.0)**2)/4.0)*np.exp(1j*self.xx*self.p0) self.energia() self.T_analitic() def energia(self): self.matriu_H = np.zeros((self.nx+1,self.nx+1)) k = 1.0/(self.dx**2) for i in range(0,self.nx+1): self.matriu_H[i,i] = self.pot[i] + k if i != self.nx: self.matriu_H[i,i+1] = -(k/2.0) self.matriu_H[i+1,i] = -(k/2.0) self.phihphi = (np.conjugate(self.phi0)*(np.dot(self.matriu_H,self.phi0))) self.E = self.simpson2(self.dx,self.phihphi) self.E_vect = np.zeros((self.nx+1)) for i in range(0,self.nx+1): self.E_vect[i] = self.E def simpson2(self,h,vect): #add the extrems add=(vect[0]+vect[len(vect)-1]) #add each parity its factor for i in np.arange(2,len(vect)-1,2): add+=2*vect[i] for i in np.arange(1,len(vect)-1,2): add+=4*vect[i] #add the global factor add*=(h/np.float(3)) return add def add_width(self): self.pot_data.remove() self.T_txt.remove() self.bwidth = self.bwidth + 0.05 self.potencial() self.T_analitic() self.T_txt = self.pant1.text(0.1, 0.5,str(self.T)) self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.pant1_canvas.draw() self.main_canvas.draw() def subtract_width(self): self.pot_data.remove() self.T_txt.remove() self.bwidth = self.bwidth - 0.05 self.potencial() self.T_analitic() self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.T_txt = self.pant1.text(0.1, 0.5,'%.8f' % (self.T)) self.pant1_canvas.draw() self.main_canvas.draw() def add_bheight(self): self.pot_data.remove() self.T_txt.remove() self.bheight_quadrat = self.bheight_quadrat + 0.5 self.potencial() self.T_analitic() self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.T_txt = self.pant1.text(0.1, 0.5,'%.8f' % (self.T)) self.pant1_canvas.draw() self.main_canvas.draw() def subtract_bheight(self): self.pot_data.remove() self.T_txt.remove() self.bheight_quadrat = self.bheight_quadrat - 0.5 self.potencial() self.T_analitic() self.pot_data, = self.pot_graf.fill(self.xx, self.pot,color=self.colpot) self.T_txt = self.pant1.text(0.1, 0.5,'%.8f' % (self.T)) self.pant1_canvas.draw() self.main_canvas.draw() def T_analitic(self): self.arrel = [] for i in range(0,self.nx+1): if self.pot[i] > self.E: self.arrel = np.append(self.arrel,np.sqrt(2.0*(self.pot[i]-self.E))) integral = self.simpson2(self.dx,self.arrel) #integral = (self.bwidth*np.sqrt(76.0-self.E)) self.T = np.abs((np.exp((-2.0)*integral))) def inici_evolucio(self): self.ev = Clock.schedule_interval(self.evolucio,self.dt) #Es crearan els vectors i matriu necessaris per la evolucio self.abc() self.matriuB() self.phii = 1j*np.zeros(self.nx-1) for i in range(1,self.nx-1): self.phii[i] = self.phi0[i] self.phi = 1j*np.zeros(self.nx+1) self.phi2 = np.zeros(self.nx + 1) self.t = 0 def abc(self): self.b = 1j*np.zeros(self.nx-1) self.a = 1j*np.zeros(self.nx-1) self.c = 1j*np.zeros(self.nx-1) for i in range(0,self.nx-1): self.b[i] = 2.0*(1.0 + self.r) + 1.0j*self.pot[i]*self.dt if i != 0: self.a[i] = -self.r if i != self.nx-2: self.c[i] = -self.r def stop_evolucio(self): self.ev.cancel() GlobalShared.prob = self.probleft print (GlobalShared.prob) def matriuB(self): self.matriu_B = 1j*np.zeros((self.nx -1,self.nx-1)) for i in range(0,self.nx-1): self.matriu_B[i,i] = 2.0*(1.0 -self.r) - 1.0j*self.pot[i]*self.dt if i != (self.nx-2): self.matriu_B[i,i+1] = self.r self.matriu_B[i+1,i] = self.r def prob_left(self): n = int(self.nx/2) self.probleft = self.simpson2(self.dx,self.phi2[0:n])/self.simpson2(self.dx,self.phi2) def calc_norma(self): self.norma = self.simpson2(self.dx,self.phi2) def evolucio(self,dt): self.abc() self.matriuB() self.t += 100*self.dt self.d = np.dot(self.matriu_B,self.phii) # Apliquem condicions de contorn self.d[0] = self.d[0] + 2.0*self.r*self.phi0[0] self.d[self.nx-2] = self.d[self.nx-2] + 2.0*self.r*self.phi0[self.nx] # Cridem la subrutina tridiag que ens calculi phi pel temsp següent self.tridiag() self.phi[1:self.nx] = self.phii self.phi[0] = self.phi0[0] self.phi[self.nx] = self.phi0[self.nx] for i in range(0,self.nx+1): self.phi2[i] = (np.abs(self.phi[i]))**2 #Ara per a cada temps ha de esborrar la figura anterior i #dibuixar la nova self.visu_ona.remove() self.visu_ona, = self.ona.fill(self.xx,self.phi2,color = self.color) self.main_canvas.draw() if np.mod(self.t,5.0) == 0.0: #Cridem la funció que integra la funcio d'ona a l'esquerra self.prob_left() self.prob_left_txt.remove() self.prob_left_txt = self.pant2.text(0.1,0.5,'%.8f' % (self.probleft)) #Cridem la funció que ens calcula la norma self.calc_norma() self.norma_txt.remove() self.norma_txt = self.pant3.text(0.1,0.5,'%.8f' % (self.norma)) self.pant2_canvas.draw() self.pant3_canvas.draw() if self.t == 150: self.stop_evolucio() def tridiag(self): n = np.size(self.a) cp = np.zeros(n, dtype = np.complex) dp = np.zeros(n, dtype = np.complex) cp[0] = self.c[0]/self.b[0] dp[0] = self.d[0]/self.b[0] for i in range(1,n): m = (self.b[i]-self.a[i]*cp[i-1]) cp[i] = self.c[i]/m dp[i] = (self.d[i] - self.a[i]*dp[i-1])/m self.phii[n-1] = dp[n-1] for j in range(1,n): i = (n-1)-j self.phii[i] = dp[i]-cp[i]*self.phii[i+1] def reset(self): self.stop_evolucio() self.visu_ona.remove() self.visu_ona, = self.ona.plot(self.xx,self.phi02, color = self.colphi) self.norma_txt.remove() self.prob_left_txt.remove() self.prob_left_txt = self.pant2.text(0.1,0.5,'0.00000000') self.norma_txt = self.pant3.text(0.1,0.5,'1.00000000') self.pant2.canvas.draw() self.pant3.canvas.draw() self.main_canvas.draw() def _teclat_activat(self,keyboard, keycode, text, modifiers): if keycode[1] == 'spacebar': self.inici_evolucio() self._teclat.unbind(on_hey_down = self._teclat_activat) return def control_teclat(self, *args): self._teclat = Window.request_keyboard(self._teclat_tancat,self) self._teclat.bind(on_key_down=self._teclat_activat) def _teclat_tancat(self): self._teclat.unbind(on_key_down=self._teclat_activat)
class Quantum(BoxLayout): time_label = StringProperty() but1 = StringProperty() but2 = StringProperty() but3 = StringProperty() language = StringProperty() def __init__(self, **kwargs): super(Quantum, self).__init__(**kwargs) #Language: self.language = "CA" self.time_label = "Temps" self.but1 = "Sobre el pic" self.but2 = "En el pic" self.but3 = "Sota el pic" self.energy_label = "Energia" self.prob_label = "Densitat de probabilitat" self.cabut.color = (0, 0.75, 1, 1) self.esbut.color = (1, 1, 1, 1) self.enbut.color = (1, 1, 1, 1) "Quantum definitions" self.a = -20. self.b = 20. self.N = 1000 self.deltax = (self.b - self.a) / float(self.N) te.factor = 10 #Factor for the applied potential. self.height_qua = 15 #Default self.sigma_qua = 2 * te.factor / (np.sqrt(2 * np.pi) * self.height_qua) self.mu_qua = 0 self.xarr_qua = np.arange(self.a, self.b + self.deltax * 0.1, self.deltax) self.m_qua = 1 / (2 * 3.80995) #The value contains hbar^2. te.hbar = 4.136 #eV·fs (femtosecond) self.k_qua = 0.2 #Default self.xo = -2.3 #Default te.sigma0 = 0.4 #Default. self.oldtop2_qua = self.height_qua self.oldk2_qua = self.k_qua #Clock (Quantum): Clock.schedule_interval(self.psiupdate, 1 / 60) self.dtime0_qua = 1 / 30 self.vel_qua = 1 self.dtime_qua = self.vel_qua * self.dtime0_qua self.time_qua = 0.0 self.tmax_qua = 10 self.oldtime1_qua = self.time_qua + 1 #Time self.timeslide_qua.disabled = True #It is not allowed to move the time bar. #Plots (Quantum) self.canvas_qua = FigureCanvasKivyAgg(fig_qua) self.pot_qua, = aqu.plot(self.xarr_qua, te.pot(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua), 'k--', label="V(x)") self.filled_pot_qua = aqu.fill_between(self.xarr_qua, te.pot(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua), color=(0.5, 0.5, 0.5, 0.5)) self.energy_qua, = aqu.plot([], [], '-.', color='g', label="<E>") aqu.plot([], [], 'r-', label=r'$|\Psi(x)|^{2}$') #Fake one, just for the legend. aqu.axis([-5, 5, 0, 2 * te.factor]) aqu.set_xlabel("x (" + u"\u212B" + ")") aqu.set_ylabel(self.energy_label + " (eV)", color='k') aqu.tick_params('y', colors='k') aqu.legend(loc=1) #The wavefunction is plotted in a different scale. self.psi_qua, = aqu2.plot(self.xarr_qua, np.abs(te.psi(self.xo, self.xarr_qua))**2, 'r-') self.filled_qua = aqu2.fill_between(self.xarr_qua, np.abs( te.psi(self.xo, self.xarr_qua))**2, color=(1, 0, 0, 0.2)) aqu2.axis([-5, 5, 0, 1]) aqu2.set_ylabel(self.prob_label, color='k') aqu2.tick_params('y', colors='r') self.panel2.add_widget(self.canvas_qua) #First computations: self.demo1_qua_btn() #Quantum functions: #Plotting: def plotpot(self): #It is only activated if some value changes. a = self.oldtop2_qua != self.height_qua b = self.oldk2_qua != self.k_qua if a or b: self.pot_qua.set_data( self.xarr_qua, te.pot(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua)) self.filled_pot_qua.remove() self.filled_pot_qua = aqu.fill_between( self.xarr_qua, te.pot(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua), color=(0.5, 0.5, 0.5, 0.5)) self.oldtop2_qua = self.height_qua self.oldk2_qua = self.k_qua def plotpot1(self): #It is only activated if some value changes. a = self.oldtop2_qua != self.height_qua b = self.oldk2_qua != self.k_qua if a or b: self.pot_qua.set_data( self.xarr_qua, te.pot1(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua)) self.filled_pot_qua.remove() self.filled_pot_qua = aqu.fill_between( self.xarr_qua, te.pot1(self.mu_qua, self.sigma_qua, self.k_qua, self.xarr_qua), color=(0.5, 0.5, 0.5, 0.5)) self.oldtop2_qua = self.height_qua self.oldk2_qua = self.k_qua def plotpsi(self, t): if self.oldtime1_qua != t: psit = np.abs(te.psiev(self.evalsbasis, self.coef_x_efuns, t))**2 self.psi_qua.set_data(self.xarr_qua, psit) self.filled_qua.remove() self.filled_qua = aqu2.fill_between(self.xarr_qua, psit, color=(1, 0, 0, 0.2)) self.canvas_qua.draw() self.oldtime1_qua = t #Playing: def psiupdate(self, dt): self.time_qua = self.timeslide_qua.value + self.dtime_qua if self.time_qua >= self.tmax_qua: self.time_qua = 0 self.timeslide_qua.value = self.time_qua self.plotpsi(self.time_qua) def reset(self): #Sets time to 0 self.timeslide_qua.value = 0 self.time_qua = 0 self.tmax_qua = 10 def demo1_qua_btn(self): self.reset() #This version does not compute anything. It just reads the precomputed matrices. self.coef_x_efuns = np.load("Demo1_qua/vecs.npy") self.evalsbasis = np.load("Demo1_qua/vals.npy") #Potential: self.height_qua = 40 self.sigma_qua = 2 * te.factor / (np.sqrt(2 * np.pi) * self.height_qua) self.k_cla = 0.2 self.plotpot1() #Plots the enrgy: self.energy = np.load("Demo1_qua/ene.npy") self.energy_qua.set_data(self.xarr_qua, 0 * self.xarr_qua + self.energy) self.energy_qua.set_color('g') self.energy_qua.set_label("<E>") aqu.legend(loc=1) self.canvas_qua.draw() self.demo1_button_qua.color = (0, 0.75, 1, 1) self.demo2_button_qua.color = (1, 1, 1, 1) self.demo3_button_qua.color = (1, 1, 1, 1) def demo2_qua_btn(self): self.reset() #This version does not compute anything. It just reads the precomputed matrices. self.coef_x_efuns = np.load("Demo2_qua/vecs.npy") self.evalsbasis = np.load("Demo2_qua/vals.npy") #Potential: self.height_qua = 10 self.sigma_qua = 2 * te.factor / (np.sqrt(2 * np.pi) * self.height_qua) self.k_cla = 0.2 self.plotpot() #Plots the enrgy: self.energy = np.load("Demo2_qua/ene.npy") self.energy_qua.set_data(self.xarr_qua, 0 * self.xarr_qua + self.energy) self.energy_qua.set_color('g') self.energy_qua.set_label("<E>") aqu.legend(loc=1) self.canvas_qua.draw() self.demo2_button_qua.color = (0, 0.75, 1, 1) self.demo1_button_qua.color = (1, 1, 1, 1) self.demo3_button_qua.color = (1, 1, 1, 1) def demo3_qua_btn(self): self.reset() #This version does not compute anything. It just reads the precomputed matrices. self.coef_x_efuns = np.load("Demo3_qua/vecs.npy") self.evalsbasis = np.load("Demo3_qua/vals.npy") #Potential: self.height_qua = 13 self.sigma_qua = 2 * te.factor / (np.sqrt(2 * np.pi) * self.height_qua) self.k_cla = 0.2 self.plotpot() psit = np.abs(te.psiev(self.evalsbasis, self.coef_x_efuns, 0))**2 self.psi_qua.set_data(self.xarr_qua, psit) self.filled_qua.remove() self.filled_qua = aqu2.fill_between(self.xarr_qua, psit, color=(1, 0, 0, 0.2)) self.canvas_qua.draw() #Plots the enrgy: self.energy = np.load("Demo3_qua/ene.npy") self.energy_qua.set_data(self.xarr_qua, 0 * self.xarr_qua + self.energy) self.energy_qua.set_color('g') self.energy_qua.set_label("<E>") aqu.legend(loc=1) self.canvas_qua.draw() self.demo3_button_qua.color = (0, 0.75, 1, 1) self.demo2_button_qua.color = (1, 1, 1, 1) self.demo1_button_qua.color = (1, 1, 1, 1) def changecat(self): if self.language != "CA": self.language = "CA" self.time_label = "Temps" self.but1 = "Sobre el pic" self.but2 = "En el pic" self.but3 = "Sota el pic" self.energy_label = "Energia" self.prob_label = "Densitat de probabilitat" aqu.set_ylabel(self.energy_label + " (eV)", color='k') aqu2.set_ylabel(self.prob_label, color='k') self.cabut.color = (0, 0.75, 1, 1) self.esbut.color = (1, 1, 1, 1) self.enbut.color = (1, 1, 1, 1) def changeesp(self): if self.language != "ES": self.language = "ES" self.time_label = "Tiempo" self.but1 = "Sobre el pico" self.but2 = "En el pico" self.but3 = "Bajo el pico" self.energy_label = "Energía" self.prob_label = "Densidad de probabilidad" aqu.set_ylabel(self.energy_label + " (eV)", color='k') aqu2.set_ylabel(self.prob_label, color='k') self.esbut.color = (0, 0.75, 1, 1) self.cabut.color = (1, 1, 1, 1) self.enbut.color = (1, 1, 1, 1) def changeeng(self): if self.language != "EN": self.language = "EN" self.time_label = "Time" self.but1 = "Above the peak" self.but2 = "On the peak" self.but3 = "Under the peak" self.energy_label = "Energy" self.prob_label = "Probability density" aqu.set_ylabel(self.energy_label + " (eV)", color='k') aqu2.set_ylabel(self.prob_label, color='k') self.enbut.color = (0, 0.75, 1, 1) self.esbut.color = (1, 1, 1, 1) self.cabut.color = (1, 1, 1, 1)
class TrackForm(BoxLayout): destination = ObjectProperty() my_map = ObjectProperty() txt1 = ObjectProperty() txt2 = ObjectProperty() txt3 = ObjectProperty() txt4 = ObjectProperty() txt5 = ObjectProperty() txt6 = ObjectProperty() txt7 = ObjectProperty() txt8 = ObjectProperty() txt9 = ObjectProperty() plots = ObjectProperty() file = None data_lay = None def __init__(self, **kwargs): super(TrackForm, self).__init__(**kwargs) self.my_map.map_source = "thunderforest-outdoors" self.fig = plt.figure() self.cnv = FigureCanvasKivyAgg(self.fig) self.plots.add_widget(self.cnv) def rysuj_wykres(self): self.ax1 = self.fig.add_subplot(121) #dodajemy tylko 1 wykres self.ax2 = self.fig.add_subplot(122) #dodajemy tylko 1 wykres lon, lat, el, dates = g.czytanie(self.file) distance, Vsr, dH, dHplus, dHminus, Hmax, Hmin, h, m, s, alt_dif, d, v, k, j, l, n, S = g.parametry( lon, lat, el, dates) if alt_dif != [0]: self.ax1.scatter(d[l], alt_dif[l], label='the harderst part', color='red') self.ax1.scatter(d[n], alt_dif[n], label='the easiest part', color='black') self.ax1.plot(d[::20], alt_dif[::20]) self.ax1.set_ylabel("dH[dist] [m]") if v != [0]: self.ax2.plot(d, v) self.ax2.scatter(d[k], v[k], label='the slowest part', color='red') self.ax2.scatter(d[j], v[j], label='the fastest part', color='black') self.ax2.set_ylabel("v[dis] [m/s]") self.ax1.legend() self.ax2.legend() self.cnv.draw() def open_file(self): self.txt1.text = '' self.txt2.text = '' self.txt3.text = '' self.txt4.text = '' self.txt5.text = '' self.txt6.text = '' self.txt7.text = '' self.txt8.text = '' self.txt9.text = '' self.fig.clear() self.cnv.draw() if self.data_lay is not None: self.my_map.remove_layer(self.data_lay) self.my_map.set_zoom_at(1, 0, 0, scale=None) self.my_map.center_on(0, 0) self.show_load() def analyse_file(self): if self.file == None: popup = Popup(title='Error', content=Label(text='Lack of file'), size_hint=(None, None), size=(300, 100)) popup.open() else: self.fig.clear() self.cnv.draw() self.rysuj_wykres() if self.file.endswith('.gpx'): lon, lat, el, dates = g.czytanie(self.file) self.draw_rout(lat, lon) distance, Vsr, dH, dHplus, dHminus, Hmax, Hmin, h, m, s, alt_dif, d, v, k, j, i, n, S = g.parametry( lon, lat, el, dates) self.txt1.text = str(distance) self.txt1.text += ' [m]' if dHplus != 'brak': self.txt2.text = str(dHplus) self.txt2.text += ' [m]' self.txt3.text = str(dHminus) self.txt3.text += ' [m]' self.txt4.text = str(dH) self.txt4.text += ' [m]' self.txt5.text = str(Hmax) self.txt5.text += ' [m]' self.txt6.text = str(Hmin) self.txt6.text += ' [m]' self.txt9.text = str(S) self.txt9.text += ' [m]' else: self.txt2.text = 'lack of date' self.txt3.text = 'lack of date' self.txt4.text = 'lack of date' self.txt5.text = 'lack of date' self.txt6.text = 'lack of date' self.txt9.text = 'lack of date' if Vsr != 'brak': self.txt7.text = str(Vsr) self.txt7.text += ' [m/s]' self.txt8.text = str(h) self.txt8.text += ' [h] ' self.txt8.text += str(m) self.txt8.text += ' [min] ' self.txt8.text += str(s) self.txt8.text += ' [s] ' else: self.txt7.text = 'lack of date' self.txt8.text = 'lack of date' self.my_map.set_zoom_at(8, 0, 0, scale=None) self.my_map.center_on(max(lat), max(lon)) else: popup = Popup(title='Error', content=Label(text='Incorrect file'), size_hint=(None, None), size=(300, 100)) popup.open() def draw_rout(self, lat, lon): self.data_lay = MarkerMapLayer() self.my_map.add_layer(self.data_lay) lat = lat[::10] lon = lon[::10] for point in zip(lat, lon): self.draw_marker(*point, layer=self.data_lay) def draw_marker(self, lat, lon, layer=None): markerSource = 'dot.png' if lat != None and lon != None: marker = MapMarker(lat=lat, lon=lon, source=markerSource) self.my_map.add_marker(marker, layer=layer) def load_list(self, path, filename): self.file = filename[0] os.path.join(path, filename[0]) self.dismiss_popup() def dismiss_popup(self): # zamykanie okienka self._popup.dismiss() def show_load(self): content = LoadDialog(load=self.load_list, cancel=self.dismiss_popup ) # powiazanie metod w oknie wczytywania plikow self._popup = Popup(title="Choose file", content=content, size_hint=(1, 1)) self._popup.open()
class AddLocationForm(BoxLayout): my_map = ObjectProperty() lhmax = ObjectProperty() lhmin = ObjectProperty() lnachmax = ObjectProperty() lnachmin = ObjectProperty() ldh = ObjectProperty() plots = ObjectProperty() lvmax = ObjectProperty() lvmin = ObjectProperty() lvave = ObjectProperty() lczash = ObjectProperty() lczasm = ObjectProperty() lczass = ObjectProperty() ldyst = ObjectProperty() def __init__(self, **kwargs): super(AddLocationForm, self).__init__(**kwargs) self.fig = plt.figure() self.cnv = FigureCanvasKivyAgg(self.fig) self.plots.add_widget(self.cnv) def draw_marker(self): data_lay = MarkerMapLayer() self.my_map.add_layer(data_lay) for i in range(len(self.lati)): marker = MapMarker(lat=self.lati[i], lon=self.loni[i], source="dot.png") self.my_map.add_marker(marker, layer=data_lay) self.my_map.set_zoom_at(10, self.lati[1], self.loni[1], scale=None) self.my_map.center_on(self.lati[1], self.loni[1]) def wczytaj(self): lat = [] lon = [] el = [] dates = [] gpx_file = open("2012.gpx", 'r') gpx = gpxpy.parse(gpx_file) gpx_file.close() for track in gpx.tracks: for seg in track.segments: for point in seg.points: lon.append(point.longitude) lat.append(point.latitude) vfb = getattr(point, 'elevation') if vfb == None: pass else: el.append(point.elevation) hsv = getattr(point, 'time') if hsv == None: pass else: hsv = getattr(point, 'time') hsv = str(hsv) dates.append(hsv) lat = lat[0::6] lon = lon[0::6] el = el[0::6] dates = dates[0::6] self.lati = lat self.loni = lon dh = [0] dist = [0] for i in range(len(lat)): if i == 0: pass else: aa = i - 1 bb = i d = vin(lat[aa], lon[aa], lat[bb], lon[bb]) dhcz = el[bb] - el[aa] D = math.sqrt(d**2 + dhcz**2) dh.append(dhcz) dist.append(D) n = [] for a in range(len(lat)): if i == 0: pass else: if dist[a] == 0: nach = 0 else: nach = (dh[a] / dist[a]) n.append(nach) h = [] minute = [] sec = [] tpart = [] if len(dates) > 1: ki = [] wi = [] for e in dates: e = str(e) aq = e.split("+") del aq[-1] yy = aq[0] ki.append(yy) for f in ki: f = str(f) ass = f.split(" ") ssa = ass[1] wi.append(ssa) for g in wi: g = str(g) qq = g.split(":") go = qq[0] m = qq[1] s = qq[2] h.append(go) minute.append(m) sec.append(s) czasyyy = [] if len(dates) > 1: for i in range(len(h)): czasyyy.append( float(h[i]) + float(minute[i]) / 60 + float(sec[i]) / 3600) for i in range(len(h)): if i == 0: pass else: aaa = i - 1 bbb = i dtime = czasyyy[bbb] - czasyyy[aaa] tpart.append(dtime) vparty = [] if len(tpart) > 1: del dist[0] predkosc = zip(dist, tpart) for i, j in predkosc: vvv = i / j vparty.append(vvv) vparty = [i / 1000 for i in vparty] #przeliczanie na km/h Vmax = max(vparty) Vmin = min(vparty) abba = [i / 1000 for i in dist] #przeliczanie na km Vave = sum(abba) / sum(tpart) self.lvmax.text = str("%.3f" % Vmax) self.lvmin.text = str("%.3f" % Vmin) self.lvave.text = str("%.3f" % Vave) #rozdzielanie godziny na oczekiwane wartosci timeee = math.floor(sum(tpart)) minuty = math.floor((sum(tpart) - timeee) * 60) sekundy = math.floor( ((sum(tpart) - timeee) * 60 - minuty) * 60) self.lczash.text = str(timeee) self.lczasm.text = str(minuty) self.lczass.text = str(sekundy) dist.insert(0, 0) czasyyy.insert(0, 0) vparty.insert(0, 0) hmax = max(el) hmin = min(el) #profil self.ax1 = self.fig.add_subplot(111) self.ax1.set_xlabel('Dystans [km]') self.ax1.set_ylabel('Wysokosc m.n.p.m') plt.title('Profil wysokosciowy') self.ax1.plot(dod(dist), el) self.cnv.draw() #nachylenia w procentach f = max(n) * 100 ff = min(n) * 100 self.draw_route(lat, lon) self.lhmax.text = str("%.2f" % hmax) self.lhmin.text = str("%.2f" % hmin) self.lnachmax.text = str("%.2f" % f) self.lnachmin.text = str("%.2f" % ff) self.ldyst.text = str("%.2f" % sum(dist)) self.ldh.text = str("%.2f" % sum(dh)) def draw_route(self, lat, lon): data_layer = MarkerMapLayer() for point in zip(lat, lon): self.mark_point(*point, layer=data_layer) def mark_point(self, lat, lon, layer=None): if lat != None and lon != None: self.my_map.add_marker def kas(self): self.lhmax.text = "wczytaj dane" self.lhmin.text = "wczytaj dane" self.lnachmax.text = "wczytaj dane" self.lnachmin.text = "wczytaj dane" self.ldh.text = "wczytaj dane" self.lvmax.text = "wczytaj dane" self.lvmin.text = "wczytaj dane" self.lvave.text = "wczytaj dane" self.ldyst.text = "wczytaj dane"
class AddLocationForm(BoxLayout): #stworzenie klasy txt1 = ObjectProperty() txt2 = ObjectProperty() my_map = ObjectProperty() plot = ObjectProperty() def __init__(self, **kwargs): # inicjalizacja dla klasy niedziedziczacej po App super(AddLocationForm, self).__init__(**kwargs) self.fig = plt.figure() # stworzenie pustego wykresu self.cnv = FigureCanvasKivyAgg( self.fig ) # utworzenie wykresu w aplikacji na podstawie pustego wykresu self.plot.add_widget( self.cnv) # dodanie wykresu do aplikacji do widgeta plots #----------------wykres - profil wysokosci------------------------------------- def rysuj_wykres1(self): filename = self.txt1.text #wczytanie pliku lat, lon, lat1, lat2, lon1, lon2, el, dates, elstart, elstop, datesstop, datesstart, delta, sekundy, sumdates, lat1wyk, lon1wyk = biblio.wczytaj_plik( filename) #import danych def haversine1( orig, dest ): #funkcja licząca odlegosć poziomą między punktem początkowym trasy a kolejnymi punktami trasy lat1wyk, lon1wyk = orig lat2, lon2 = dest radius = 6371000 # m dlat1 = np.radians(lat2 - lat1wyk) dlon1 = np.radians(lon2 - lon1wyk) a1 = np.sin(dlat1/2) * np.sin(dlat1/2) + np.cos(np.radians(lat1wyk)) \ * np.cos(np.radians(lat2)) * np.sin(dlon1/2) * np.sin(dlon1/2) c1 = 2 * np.arctan2(np.sqrt(a1), np.sqrt(1 - a1)) d1 = radius * c1 return d1 dist_part1 = haversine1((lat1wyk, lon1wyk), (lat2, lon2)) D = list(dist_part1) #utworzenie listy z odległosciami D.insert( 0, 0 ) #wprowadzenie odleglosci równej 0 w pierwszym punkcie trasy (aby móc zaznaczyć na wykresie wysokosć dla punktu początkowego) if el is not None: #rysowanie wykresu, jesli wysokosc istnieje self.ax1 = self.fig.add_subplot(111) self.ax1.plot(D, el) plt.xlabel('Odległość pozioma [m]') plt.ylabel('Wysokość [m]') plt.title('Profil wysokościowy') self.cnv.draw() plt.savefig("wykres_profil.png") #zapis do pliku else: pass #----------------wykres - predkosc od odleglosci------------------------------- def rysuj_wykres2(self): filename = self.txt1.text #wczytanie pliku lat, lon, lat1, lat2, lon1, lon2, el, dates, elstart, elstop, datesstop, datesstart, delta, sekundy, sumdates, lat1wyk, lon1wyk = biblio.wczytaj_plik( filename) #import danych def haversine1( orig, dest ): #funkcja licząca odlegosć poziomą między punktem początkowym trasy a kolejnymi punktami trasy lat1wyk, lon1wyk = orig lat2, lon2 = dest radius = 6371000 # m dlat1 = np.radians(lat2 - lat1wyk) dlon1 = np.radians(lon2 - lon1wyk) a1 = np.sin(dlat1/2) * np.sin(dlat1/2) + np.cos(np.radians(lat1wyk)) \ * np.cos(np.radians(lat2)) * np.sin(dlon1/2) * np.sin(dlon1/2) c1 = 2 * np.arctan2(np.sqrt(a1), np.sqrt(1 - a1)) d1 = radius * c1 return d1 dist_part1 = haversine1((lat1wyk, lon1wyk), (lat2, lon2)) D = list(dist_part1) D.insert(0, 0) #------------------predkosci--------------------------------------------------- def haversine( origin, destination ): #funkcja licząca odleglosci na pomiedzy punktami trasy lat1, lon1 = origin lat2, lon2 = destination radius = 6371000 # m dlat = np.radians(lat2 - lat1) dlon = np.radians(lon2 - lon1) a = np.sin(dlat/2) * np.sin(dlat/2) + np.cos(np.radians(lat1)) \ * np.cos(np.radians(lat2)) * np.sin(dlon/2) * np.sin(dlon/2) c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) d = radius * c return d dist_part = haversine((lat1, lon1), (lat2, lon2)) # m #obliczenie prędkosci na odcinkach if sekundy > 0: v = dist_part / sekundy #m/s V = list(v) V.insert(0, 0) self.ax1 = self.fig.add_subplot(111) self.ax1.plot(D, V) plt.xlabel('Odległość pozioma [m]') plt.ylabel('Prędkość [m/s]') plt.title('Wykres zależności prędkości od odległości poziomej') self.cnv.draw() plt.savefig("wykres_v_od_s).png") #zapis do pliku else: pass def czyszczenie(self): #funkcja czyszcząca self.txt2.text = '' #nazwę pliku self.txt1.text = '' #statystyki self.ax1.remove() #wykres self.my_map.remove_layer(self.data_lay) #znacznik na mapie #------------------analiza trasy----------------------------------------------- def analyse_file(self): filename = self.txt1.text #wczytanie pliku lat, lon, lat1, lat2, lon1, lon2, el, dates, elstart, elstop, datesstop, datesstart, delta, sekundy, sumdates, lat1wyk, lon1wyk = biblio.wczytaj_plik( filename) #---------------------HAVERSINE------------------------------------------------ def haversine(origin, destination): lat1, lon1 = origin lat2, lon2 = destination radius = 6371000 # m dlat = np.radians(lat2 - lat1) dlon = np.radians(lon2 - lon1) a = np.sin(dlat/2) * np.sin(dlat/2) + np.cos(np.radians(lat1)) \ * np.cos(np.radians(lat2)) * np.sin(dlon/2) * np.sin(dlon/2) c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) d = radius * c return d #------------------rysowanie poczatku trasy------------------------------------ self.data_lay = MarkerMapLayer() self.my_map.add_layer(self.data_lay) marker = MapMarker(lat=lat[0], lon=lon[0], source="dot.png") self.my_map.add_marker(marker, layer=self.data_lay) #-----------------------obliczenia--------------------------------------------- dist_part = haversine((lat1, lon1), (lat2, lon2)) # m sumdist = sum(dist_part) #długosć całkowita trasy - pozioma alt_part = (elstop - elstart) #przwyższenia na odcinkach trasy def przewyzszenie_dodatnie(alt_part): #całkowite przewyższenie w górę dodatnie = [] for przewyzszenie in alt_part: if przewyzszenie >= 0: dodatnie.append(przewyzszenie) return dodatnie def przewyzszenie_ujemne(alt_part): #całkowite przewyższenie w dół ujemne = [] for przewyzszenie in alt_part: if przewyzszenie < 0: ujemne.append(przewyzszenie) return ujemne altsum = sum(alt_part) #całkowite przewyższenie na trasie odl3D = np.sqrt((dist_part**2 + alt_part**2)) #odległosć skosna sum3D = sum(odl3D) #całkowita odleglosc skosna trasy #------------------predkosci--------------------------------------------------- if sekundy > 0: v = dist_part / sekundy #m/s vavg = sum(v) / len(v) p7 = str(round(vavg, 3)) else: v = 0 vavg = 0 p7 = str('Brak') #-------------wyswietlanie statystyk------------------------------------------- p1 = str(round(sumdist, 3)) p2 = str(round(sum3D, 3)) p3 = str(round(altsum, 3)) p4 = str(round(sum(np.array(przewyzszenie_dodatnie(alt_part))), 3)) p5 = str(round(sum(np.array(przewyzszenie_ujemne(alt_part))), 3)) p6 = str(sumdates) p8 = str(round(max(el), 3)) p9 = str(round(min(el), 3)) self.txt2.text = 'Statystyki:' self.txt2.text += '\nCałkowita odległość (długość) pozioma [m] ' self.txt2.text += p1 self.txt2.text += '\nCałkowita odległość skośna [m] ' self.txt2.text += p2 self.txt2.text += '\nCałkowite przewyższenie [m] ' self.txt2.text += p3 self.txt2.text += '\nw tym: w górę / w dół ' self.txt2.text += p4 self.txt2.text += ' / ' self.txt2.text += p5 self.txt2.text += '\nCzas [h:m:s] ' self.txt2.text += p6 self.txt2.text += '\nSrednia predkość [m/s] ' self.txt2.text += p7 self.txt2.text += '\nMaksymalna wysokość [m] ' self.txt2.text += p8 self.txt2.text += '\nMinimalna wysokość [m] ' self.txt2.text += p9
class KivyCamera(FloatLayout): circle_pos = ListProperty([0, 0]) # circle_y = NumericProperty(0) circle_r = NumericProperty(0) rect_pos = ListProperty([0, 0]) coords_left = ListProperty() coords_bottom = ListProperty() coords_right = ListProperty() coords_top = ListProperty() coords_center = ListProperty() widths = ListProperty() active_function = StringProperty() def __init__(self, **kwargs): super(KivyCamera, self).__init__(**kwargs) # self.start() def start(self): # self.videostream = capture self.videostream = ThreadedVideoStream(0) self.videostream.start() # args for bigger video size: , frame_width=1920, frame_height=1080 print("starting video capture") self.detector = dlib.get_frontal_face_detector() self.predictor = dlib.shape_predictor( "shape_predictor_68_face_landmarks.dat") self.hog = cv2.HOGDescriptor() self.hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # self.pos_hint = {'center_x': 0.5, 'center_y': 0.5} frame = self.videostream.read() # print("frame size; {}".format(frame.shape)) self.sec = time.time() self.last_sec = self.sec self.wait_sec = 5 self.random_s = random.randint(1, 10) self.touint8 = True # self.cam_screens = [self.original, self.original, self.sobel_cam, # self.sobel_cam, self.angle_cam, self.angle_cam, # self.mag_cam, self.mag_cam, self.hog_cam, # self.hog_cam, self.detect_faces, self.detect_faces] self.cam_screens = [ self.original, self.grey_cam, self.blur_cam, self.sobelx_cam, self.sobely_cam, self.angle_cam, self.mag_cam, self.hog_cam, self.detect_faces ] self.screen_iter = iter(self.cam_screens) self.display_func = self.original dpi = inch(1) self.h_inch = int(frame.shape[0] / dpi) self.w_inch = int(frame.shape[1] / dpi) plt.rcParams['savefig.pad_inches'] = 0 plt.style.use(['dark_background']) self.fig = plt.figure() # figsize=(self.h_inch, h_inch) # Then we set up our axes (the plot region, or the area in which we plot things). # Usually there is a thin border drawn around the axes, but we turn it off with `frameon=False`. self.ax = plt.axes([0, 0, 1, 1], frameon=False) # Then we disable our xaxis and yaxis completely. If we just say plt.axis('off'), # they are still used in the computation of the image padding. self.ax.get_xaxis().set_visible(False) self.ax.get_yaxis().set_visible(False) # Even though our axes (plot region) are set to cover the whole image with [0,0,1,1], # by default they leave padding between the plotted data and the frame. We use tigher=True # to make sure the data gets scaled to the full extents of the axes. plt.autoscale(tight=True) self.ax.imshow(frame, 'brg') self.picture = FigureCanvasKivyAgg(figure=self.fig, size_hint=(None, None)) self.picture.size = (frame.shape[1], frame.shape[0]) self.picture.center_x = Window.width / 2 self.picture.center_y = Window.height / 2 self.label = Label(text='Gesichtserkennung wird gestartet ... \n', size_hint=(None, None)) self.label.x = 100 self.label.center_y = Window.height / 2 self.layout = FloatLayout(size_hint=(None, None)) self.layout.add_widget(self.label) self.layout.add_widget(self.picture) self.add_widget(self.layout) def morphology_transform(self, img, morph_operator=2, element=1, ksize=18): morph_op_dic = { 0: cv2.MORPH_OPEN, 1: cv2.MORPH_CLOSE, 2: cv2.MORPH_GRADIENT, 3: cv2.MORPH_TOPHAT, 4: cv2.MORPH_BLACKHAT } if element == 0: morph_elem = cv2.MORPH_RECT elif element == 1: morph_elem = cv2.MORPH_CROSS elif element == 2: morph_elem = cv2.MORPH_ELLIPSE elem = cv2.getStructuringElement(morph_elem, (2 * ksize + 1, 2 * ksize + 1), (ksize, ksize)) operation = morph_op_dic[morph_operator] dst = cv2.morphologyEx(img, operation, elem) return dst def convert2uint8(self, frame, absolute=True): if absolute: frame = np.absolute(frame) return np.uint8(frame) def convert2uint32(self, frame, absolute=True): return np.uint32(frame) def original(self, frame, gray, uint8=True): self.active_function = "orig" self.wait_sec = 5 return frame def grey_cam(self, frame, gray): self.active_function = "preproc" return gray def blur_cam(self, frame, gray): self.active_function = "preproc" return cv2.medianBlur(gray, 11) def sobelx_cam(self, frame, gray, uint8=True): self.active_function = "edge" blur = cv2.medianBlur(gray, 11) sobelx = cv2.Sobel(blur, cv2.CV_64F, 1, 0, ksize=3) return sobelx def sobely_cam(self, frame, gray, uint8=True): self.active_function = "edge" blur = cv2.medianBlur(gray, 11) sobely = cv2.Sobel(blur, cv2.CV_64F, 0, 1, ksize=3) return sobely def angle_cam(self, frame, gray, uint8=True): self.active_function = "edge" blur = cv2.medianBlur(gray, 11) sobelx = cv2.Sobel(blur, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(blur, cv2.CV_64F, 0, 1, ksize=3) angle = np.arctan2(sobely, sobelx) * (180 / np.pi) return angle def mag_cam(self, frame, gray, uint8=True): self.active_function = "edge" blur = cv2.medianBlur(gray, 11) sobelx = cv2.Sobel(blur, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(blur, cv2.CV_64F, 0, 1, ksize=3) mag = np.sqrt(sobelx**2.0 + sobely**2.0) return mag def hog_cam(self, frame, gray, uint8=True): self.active_function = "hog" (H, hogImage) = feature.hog(gray, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(8, 8), transform_sqrt=True, block_norm="L1", visualize=True) hogImage = exposure.rescale_intensity(hogImage, out_range=(0, 255)) return hogImage def detect_faces(self, frame, gray, uint8=True): self.active_function = "Detected Faces" # face detection faces = self.detector(gray, 1) filtered_frame = self.morphology_transform(frame.copy()) for (i, face) in enumerate(faces): # shape = self.predictor(gray, face) # shape = face_utils.shape_to_np(shape) (x, y, w, h) = face_utils.rect_to_bb(face) # for (x, y) in shape: # cv2.circle(frame, (x, y), 1, (0, 255, 0), -1) self.circle_r = (w + w / 2) / 2 self.rect_pos = [face.right() / 2, face.top() / 2] circle_x = (x + w / 2) circle_y = (y + h / 2) rr, cc = circle(circle_y, circle_x, self.circle_r, frame.shape) filtered_frame[rr, cc] = frame[rr, cc] # morphed_frame[rr, cc] = frame[rr, cc] self.coords_left.append(frame.shape[1] - face.right()) self.coords_bottom.append(frame.shape[0] - face.bottom()) self.widths.append(face.width()) c0 = self.coords_left[i] + (int(face.width() / 2)) c1 = self.coords_bottom[i] + (int(face.width() / 2)) self.circle_c.append([c0, c1]) return filtered_frame def update(self, dt): frame = self.videostream.read() frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) self.label.texture_update() # add time value to return statements to change the time images are displayed self.sec = time.time() if (self.sec - self.last_sec) >= self.wait_sec: self.last_sec = self.sec # self.touint8 = not self.touint8 try: self.display_func = next(self.screen_iter) except StopIteration: self.screen_iter = iter(self.cam_screens) self.label.text = 'Gesichtserkennung wird gestartet ... \n' if self.display_func == self.sobelx_cam: print('1') self.label.text += 'Suche Kanten ... \n' self.label.text += 'in x-Richtung ... \n' elif self.display_func == self.sobely_cam: self.label.text += 'erledigt. \n' self.label.text += 'in y-Richtung ... \n' elif self.display_func == self.angle_cam: self.label.text += 'erledigt. \n' self.label.text += 'Berechne Stärke ... \n' elif self.display_func == self.mag_cam: self.label.text += 'erledigt. \n' self.label.text += 'Berechne Richtung ... \n' elif self.display_func == self.hog_cam: self.label.text += 'erledigt. \n' self.label.text += 'Finde Gesichter ... \n' elif self.display_func == self.detect_faces: self.label.text += 'erledigt. \n\n' self.label.texture_update() # touint8 = True if self.wait_sec > 2 else False # self.remove_widget(self.picture) new_pic = self.display_func(frame, gray) new_pic = cv2.flip(new_pic, 1) col_fmt = None if (len(new_pic.shape) > 2) else 'gray' self.ax.imshow(new_pic, col_fmt) self.picture.draw() self.layout._trigger_layout() self.coords_left = [] self.coords_bottom = [] self.widths = [] self.circle_c = [] def stop(self): print("stopping video capture") self.videostream.stop()
class DoubleSlitScreen(BoxLayout): beep= SoundLoader.load('ping.wav') #Objects binded from .kv file p_rectangle = ObjectProperty() button_1slit = ObjectProperty() button_2slits = ObjectProperty() button_large = ObjectProperty() button_medium = ObjectProperty() button_small = ObjectProperty() label_speed = ObjectProperty() speed_slider = ObjectProperty() widget_plot = ObjectProperty() #Objects created here frame = NumericProperty(0) #current frame frames = NumericProperty(0) #total number of frames texture = ObjectProperty() #texture object (initialized at create_texture) zoom = NumericProperty(1) #this value autoadjusts when calling blit_P #Drawing parameters #size and position of he heatmap wh = 0 hh = 0 xh = 0 yh = 0 #Playback status and settings clock = None speed = NumericProperty(4) playing = True normalize_each_frame = True loop = True lasttime = time() #Simulation results Pt = None times = None maxP = 1 slits = 2 slit_size = "medium" current_filename = "lastsim" language = 0 strings = { 'slit': ['1 ranura', '1 ranura', '1 slit'], 'slits': ['2 ranures', '2 ranuras', '2 slits'], 'large': ['Grans', 'Grandes', 'Large'], 'medium': ['Mitjanes', 'Medianas', 'Medium'], 'small': ['Petites', 'Pequeñas', 'Small'], 'speed': ['Velocitat', 'Velocidad', 'Speed']} measures_popup = ObjectProperty() def __init__(self, *args, **kwargs): super(DoubleSlitScreen, self).__init__(*args, **kwargs) self.canvas_qua = FigureCanvasKivyAgg(fig_qua) self.widget_plot.add_widget(self.canvas_qua) #Tries to load old simulation, in case there isn't any, it creates an #empty experiment with only psi(t=0) print("Trying to load last simulation") try: self.load_experiment() except FileNotFoundError: print("Could not find last simulation, creating new one...") self.experiment = DSexperiment() self.experiment.set_gaussian_psi0(p0x = 150/self.experiment.Lx) self.maxP = np.max(self.experiment.Pt) self.create_textures() self.clock = Clock.schedule_interval(self.update, 1.0 / 30.0) def set_language(self, lang): self.language = lang self.button_1slit.text = self.strings['slit'][self.language] self.button_2slits.text = self.strings['slits'][self.language] self.button_large.text = self.strings['large'][self.language] self.button_medium.text = self.strings['medium'][self.language] self.button_small.text = self.strings['small'][self.language] self.label_speed.text = self.strings['speed'][self.language] def load_experiment(self): self.experiment = create_experiment_from_files("{}_{}".format(self.slits, self.slit_size)) print("Simulation loaded correctly") self.computation_done(save = False) self.remove_measurements() self.experiment.compute_py(force = True) aqu.plot(np.arange(-self.experiment.Ly, self.experiment.Ly, self.experiment.dx), self.experiment.py, c = "g", lw = 4) aqu.set_xlim(-self.experiment.Ly, self.experiment.Ly) aqu.set_ylim(0,np.max(self.experiment.py)) self.canvas_qua.draw() #Drawing functions def create_textures(self): """ Creates the textures that will be used (for the wavefunction and for the potential (slits) ) """ self.texture_psi = Texture.create(size = self.experiment.Pt[0].shape[::-1], colorfmt = "luminance", bufferfmt = "uint") self.texture_V = Texture.create(size = self.experiment.Pt[0].shape[::-1], colorfmt = "rgba", bufferfmt = "uint") wall_color = (200, 0, 255) def blit_P(self, P): """ This function draws the heatmap for P centered at P is a 2d numpy array """ #Basically if white should represent the maximum value of P at each frame #or should represent the maximum value of all frames if self.normalize_each_frame: max = np.max(P) else: max = self.maxP #Stores the P matrix in the texture object #this texture is created in the method creature_texture and already has the size #It's a gray-scale texture so value must go from 0 to 255 (P/self.maxP)*255 #It must be an array of unsigned 8bit integers. And also it has to be flattened self.texture_psi.blit_buffer( ((P[:,::-1]/max)*255).astype(np.uint8).reshape(P.size), colorfmt = "luminance") #Draws walls with self.p_rectangle.canvas: #Determines the size of the box: #Full height self.zoom = self.p_rectangle.height/P.shape[0] #If full height implies cutting by the sides, it uses full width if P.shape[1]*self.zoom > self.p_rectangle.width: #Full width self.zoom = self.p_rectangle.width/P.shape[1] self.wh = P.shape[1]*self.zoom self.hh = P.shape[0]*self.zoom self.xh = self.p_rectangle.pos[0] + self.p_rectangle.width/2 - self.wh/2 self.yh = self.p_rectangle.pos[1] + self.p_rectangle.height/2 - self.hh/2 Color(self.wall_color[0]/255, self.wall_color[1]/255, self.wall_color[2]/255) #Red #box wall Rectangle(pos = (self.xh-5, self.yh-5), size = (self.wh+10, self.hh+10)) #Heatmap Color(1., 1., 1.) #White Rectangle(texture = self.texture_psi, pos = (self.xh, self.yh), size = (self.wh, self.hh)) def draw_slits(self): """ Draws the slits (heatmap of the potential energy) """ with self.p_rectangle.canvas: V = self.experiment.V[:,::-1] Vo = self.experiment.Vo M = np.zeros((V.shape[0], V.shape[1], 4), dtype = np.uint8) for i in range(3): M[:,:,i] = (self.wall_color[i]*V/Vo).astype(np.uint8) M[:,:,3] = M[:,:,0] self.texture_V.blit_buffer( M.reshape(M.size), colorfmt = "rgba") Rectangle(texture = self.texture_V, pos = (self.xh, self.yh), size = (self.wh, self.hh)) def draw_measures(self): """ Draws points representing measures in the main UI """ with self.p_rectangle.canvas: scale = self.zoom/self.experiment.dx #Measuring screen Color(0, 1., 0, 0.25) Rectangle(pos = (self.xh + self.wh - self.experiment.mp*self.zoom, self.yh), size = (self.experiment.mw*self.zoom, self.hh)) Color(0, 1., 0) for measure in self.experiment.measurements: Ellipse(pos = (self.xh + self.wh - 2*self.experiment.mp*self.zoom + measure[0]*self.zoom , self.yh + measure[1]*self.zoom), size = (self.zoom, self.zoom)) def computation_update(self, msg, x): """ This is called by the thread computing the simulation """ pass def computation_done(self, save = True): """ This is called when the simulation has been completed """ self.frames = self.experiment.Pt.shape[0] self.maxP = np.max(self.experiment.Pt) self.create_textures() if save: self.experiment.save_to_files("lastsim") def slider_moved(self, a, b): Clock.schedule_once(self.reset_speed, 5*60) def reset_speed(self, a): self.speed_slider.value = 5 #Playback functions def playpause(self): self.playing = not self.playing if self.playing: self.clock = Clock.schedule_interval(self.update, 1.0 / 30.0) self.playpause_button.text = "Pause experiment" else: self.clock.cancel() self.playpause_button.text = "Start experiment" def change_frame(self): self.playing = False def measure(self, N = 1): #self.beep.play() self.experiment.measure(N) aqu.cla() aqu.hist([-self.experiment.Ly + measure[1]*self.experiment.dx for measure in self.experiment.measurements], bins = 20, normed = True) aqu.set_xlim(-self.experiment.Ly, self.experiment.Ly) aqu.plot(np.arange(-self.experiment.Ly, self.experiment.Ly, self.experiment.dx), self.experiment.py, c="g", lw = 4) self.canvas_qua.draw() def remove_measurements(self): self.experiment.clear_measurements() def button_toggled(self, button, value): if button.group == "number": if value: self.slits = int(button.name) elif button.group == "size": if value: self.slit_size = button.name if value: self.load_experiment() print(self.slits, self.slit_size) def update(self, dt): self.speed = int(self.speed_slider.value) if self.playing: self.p_rectangle.canvas.clear() self.blit_P(self.experiment.Pt[self.frame]) self.draw_slits() self.draw_measures() self.frame = (self.frame+self.speed) if self.frame >= self.frames: if self.beep: self.beep.play() self.measure() if self.loop: self.frame = self.frame%self.frames else: self.frame = 0 else: self.p_rectangle.canvas.clear() self.blit_P(self.experiment.Pt[self.frame]) self.draw_slits() self.draw_measures()
class MainWindow(Screen): my_map = ObjectProperty() data_layer = ObjectProperty() tekst = ObjectProperty() wykres = ObjectProperty() file = ObjectProperty() def __init__(self, **kwargs): super(MainWindow, self).__init__(**kwargs) self.my_map.map_source = "thunderforest-landscape" def generuj_trase(self): if self.file is None: self.show_popup() else: dane = metody.wczytanie_pliku(self.file) self.draw_route(dane[0]) self.rysuj_wykres(dane) self.tekst.text = dane[1] fi_sr = dane[0]["lat"].mean() * 180 / pi la_sr = dane[0]["lon"].mean() * 180 / pi self.my_map.center_on(fi_sr, la_sr) self.my_map.zoom = 12 def rysuj_wykres(self, dane): self.fig = plt.figure() self.ax1 = self.fig.add_subplot(111) self.ax1.set_title("Trasa") self.ax1.scatter([dane[0]["lon"] * 180 / pi], [dane[0]["lat"] * 180 / pi], s=6) #rysowanie trasy self.cnv = FigureCanvasKivyAgg(self.fig) self.wykres.add_widget(self.cnv) self.cnv.draw() #rysowanie wykresu #rysowanie trasy def draw_route(self, df): self.data_layer = MarkerMapLayer( ) #utworzenie warstwy, creating instance of class MarkerMapLayer self.my_map.add_layer(self.data_layer) #dodanie warstwy do mapy for i in range(df.shape[0]): self.mark_point(lat=float((df.iloc[i, 0]) * 180 / pi), lon=float(df.iloc[i, 1] * 180 / pi), layer=self.data_layer) #narysowanie trasy #rysowanie znacznika - w tym przypadku kropki def mark_point(self, lat, lon, layer=None, markerSource="dot.png"): if lat != None and lon != None: marker = MapMarker(lat=lat, lon=lon, source=markerSource) #utworzenie markera self.my_map.add_marker(marker, layer=layer) #dodanie markera do mapy def usun_trase(self): if self.file is None: self.show_popup() else: self.my_map.remove_layer(self.data_layer) #usuniecie trasy def dismiss_popup(self): self._popup.dismiss() def show_popup(self): show = Okno() # Create the popup window popupWindow = Popup(title="Blad!", content=show, size_hint=(None, None), size=(400, 200)) popupWindow.open() # show the popup def load(self, path, filename): self.file = filename[0] with open(os.path.join(path, filename[0])) as stream: with open('nowyplik.gpx', 'w+') as plik: plik.write(stream.read()) self.dismiss_popup() def show_load(self): content = LoadDialog(load=self.load, cancel=self.dismiss_popup) self._popup = Popup(title="Wczytanie pliku", content=content, size_hint=(0.9, 0.9)) self._popup.open()
class QMeasures(Screen): """ Main class. The one passed to the executable class. It has acces to differents parts of the app layout (since it inherits from BoxLayout). This class consists of three main blocks: - COMPUTATION of a wave function's evolution on different potentials - PLOTTING of this evolution - GAME. A game is build on top of this problem. All functions will be organised with this structure in mind. Nevertheless, the core of this class are animation and events flow, managed only by a few functions – they actually use the functions from the main blocks. The animation (events flow) will simply consist of: - A repeatedly called function (called by Kivy's Clock) that computes and plots the evolution of the wave function: PLOTPSIEV. - A function called by the player that takes a measure of the position of the instantaneous wave function, and carries on all its consequences: MEASURE - A function that allows the player to start again after the game is over: RESTART - And finally a couple of functions that allow pausing the game and controlling its velocity: PAUSE & CHANGE_VEL These are the time FLOWING functions. Before starting the calls of plotpsiev, with Clock: - The evolution problem has to be solved - The plots have to be initialized - The game has to be set to the beggining - Clock's call So in init, all of this is done before calling Clock. """ def __init__(self, **kwargs): super(QMeasures, self).__init__(**kwargs) #Runs also the superclass #BoxLayout's __init__ function #======================== EVOLUTION PROBLEM =========================== """ Solving this problems has two parts: finding the EIGENBASIS and eigenvalues of the given hamiltonian (with a given potential), and find the COMPONENTS of the intial psi in this basis. """ #SOLVING 1ST PART #UNITS self.unit_time = 'fs' self.unit_energy = 'eV' self.unit_long = '$\AA$' self.unit_probxlong = '$\AA^{-1}$' #CONSTANTS self.hbar = 0.6582 #In these general units self.m_elec = 0.1316 #Its the m factor explained in eigenparam function self.m = self.m_elec #The name 'm' is the one used inside of eigenparam self.dirac_sigma = 0.6 #DISCRETIZATION self.a = -10. self.b = 10. self.N = 800 self.deltax = (self.b - self.a) / float(self.N) self.mesh = np.linspace(self.a, self.b, self.N + 1) #POTENTIAL INITAIL SETTINGS self.settings = open('lvl_settings.txt', 'r') self.read_settigns() #EIGENBASIS self.eigenparam() #SOLVING 2ND PART #PSI INITIAL SETTINGS #After every measure # self.p0 = 0. self.sigma0 = self.dirac_sigma #This first one (even after restarting) self.lvl = 1 #psi_init is going to use it self.psi_init(apply_cond=True) #COMPONENTS & ENERGY self.comp() self.energy = np.sum(np.abs(self.compo)**2 * self.evals) #============================ PLOTTING ================================ """ Includes the creation of all plotted objects (legend, axis, ...) but the updated data. This will happen in the plotting function. Here we should assign the canvas (created with FigureCanvasKivyAgg) to the 'box' where it will be plotted in the app with: self.box/panel_id.add_widget(self.FigureCanvasKivyAggs_name) There are four plots: background (BKG), psi (PSI), potential (POT) and a gray map for visualization (VISU). They are arranged in a (2,1) grid: first 3 plots on the top of the grid and the other bellow. Those three together share the x axis and are created in an specific order so important content don't overlap. That is: bkg, psi and pot. Moreover, pot has an extra plot, energy line. And psi as well, two arrows for visualization of the measure. """ #COLORS self.zonecol_red = '#AA3939' self.zonecol_green = '#7B9F35' self.potcol = '#226666' self.potalpha = 0.5 self.orange = '#AA6C39' self.cmap_name = 'gray' self.energycol = '#AA8439' self.b_arrow_color = '#C0C0C0' self.u_arrow_color = '#582A72' #LIMITS self.pot_tlim = 50 self.pot_blim = 0 self.psi_tlim = 1.7 self.psi_blim = 0 Dpot = self.pot_tlim - self.pot_blim Dpsi = self.psi_tlim - self.psi_blim self.dcoord_factor = Dpot / Dpsi #FIGURE self.axis_on = True # plt.show(block=False) self.main_fig = plt.figure() self.main_fig.patch.set_facecolor('black') self.main_canvas = FigureCanvasKivyAgg(self.main_fig) #Passed to kv self.box1.add_widget(self.main_canvas) self.gs = gridspec.GridSpec(2, 1, height_ratios=[7, 1], hspace=0.1, bottom=0.05, top=0.90) #Subplots grid #BACKGROUND #Their axes are going to be as psi's, since their default position #suits us. The title is going to be used as xaxis label. self.bkg_twin = plt.subplot(self.gs[0]) self.bkg_twin.axis([self.a, self.b, self.psi_blim, self.psi_tlim]) figheight = self.main_fig.get_figheight() #In inches (100 p = 1 inch) self.bkg_twin.set_title('x [' + self.unit_long + ']', color='white', pad=0.05 * figheight * 100, fontsize=10) #pad in p self.bkg_twin.set_ylabel('Probability [' + self.unit_probxlong + ']', color='white') self.bkg_twin.tick_params(axis='x', labelbottom=False, labeltop=True, bottom=False, top=True) self.bkg_twin.tick_params(colors='white') self.bkg_twin.set_facecolor('black') self.fill_bkg() #Arrows (first drawn transparent just to create the instance) self.b_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) self.u_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) #POTENTIAL self.pot_twin = self.bkg_twin.twinx() self.pot_twin.axis([self.a, self.b, self.pot_blim, self.pot_tlim]) self.pot_twin.set_ylabel('Potential [' + self.unit_energy + ']', color='white') self.pot_twin.tick_params(axis='y', colors='white') self.pot_twin.set_facecolor('black') self.pot_data, = self.pot_twin.plot(self.mesh, self.potential, color=self.potcol) #Energy self.E_data, = self.pot_twin.plot(self.mesh, np.zeros_like(self.mesh) + self.energy, color=self.energycol, ls='--', lw=2) #VISUAL self.visuax = plt.subplot(self.gs[1]) self.num_visu = len(self.mesh) #Can't be greater than the # of indices self.inter_visu = 'gaussian' self.visuax.axis('off') step = int(len(self.psi) / self.num_visu) #num_visu points in gray map self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) #FIRST DRAW #This 'tight' needs to be at the end so it considers all objects drawn self.main_fig.tight_layout() #Fills all available space self.main_canvas.draw() #============================== GAME ================================== #IMAGES path = os.path.dirname(os.path.abspath(__file__)) self.gameover_imgdata = mpimg.imread(path + str('/gameover_img.jpg')) self.heart_img = 'heart_img.jpg' self.skull_img = 'skull_img.jpg' #GAME VARIABLES self.max_lives = 10 #If changed, kv's file needs to be changed as well self.lives = self.max_lives self.lives_sources() self.lvl = 1 self.dummy = False #KEYBOARD # request_keyboard returns an instance that represents the events on # the keyboard. It can give two events (witch we can bind to functions). # Furthermore, each event comes with some input arguments: # on_key_down -- keycode, text, modifiers # on_key_up -- keycode # Using the functions bind and unbind on this instance we can bind or # unbind the instance event with a callback/function AND passing the # above arguments into the function. # When using request_keyboard a callback/function must be given. It is # going to be called when releasing/closing the keyboard (shutting the # app, or reasigning the keyboard with another request_keyboard). It # usualy unbinds everything bound. self._keyboard = Window.request_keyboard(self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) #TIME self.plt_time = 0. self.plt_dt = 1. / 30. self.plt_vel_factor = 16 #Factor in dt self.pause_state = True #Begins paused #LABELS self.label_vel.text = 'Velocity \n ' + str( self.plt_vel_factor) + 'X' #============================== CLOCK ================================= """ Here all animation will be happening. The plotting function definied in the proper section will be called several times per second. The given frame rate is going to be delayed (or not) depending on how many things happen in one frame. """ #'THE' CORE Clock.schedule_interval(self.plotpsiev, 1 / 30) ########################################################################### # 'FLOW' FUNCTIONS # ########################################################################### """ - plotpsiev - measure - restart - skip_lvl - change_vel - pause """ #PLOTPSIEV def plotpsiev(self, dt): """ Function to be called in the animation loop (clock.schedule_interval), it has to have dt as an argument. Here first is computed psi(t), then the data is updated in psi_data and finally it draws on the canvas. This parameter dt is not the actual time, its only the real time interval between calls. The time is obtained with self.plt_time. """ if not self.pause_state: #Only evolve plt_time if we are unpaused #TIME self.plt_time += self.plt_vel_factor * self.plt_dt #Time step t = self.plt_time #COMPUTE PSIEV(t). We do it with two steps (given t). #_1_. #Column vector containing the product between component and #exponential factor. 1st build array ary and then col. matrix 'mtx' ary_compexp = self.compo * \ np.exp(np.complex(0.,-1.)*self.evals*t/(50*self.hbar)) mtx_compexp = np.matrix(np.reshape(ary_compexp, (self.N + 1, 1))) #_2_. #Psi(t) col_psi = self.evect * mtx_compexp #Matrix product #UPDATE DATA. Since col_psi is a column vector (N+1,1) and we #need to pass a list, we reshape and make it an array. self.psi = np.array(np.reshape(col_psi, self.N + 1))[0] self.psi2 = np.abs(self.psi)**2 #BKG self.fill_bkg() self.b_arrow.set_alpha(np.exp(-t / 10)) self.u_arrow.set_alpha(np.exp(-t / 10)) #VISUAL PLOT self.visu_im.remove() step = int(len(self.psi) / self.num_visu) #Same as in the 1st plot self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) #DRAW #(keeps drawing even if there hasn't been an update) self.main_canvas.draw() def measure(self): """ Triggered from the kivy file. It takes the actual psi(t), generates the probability distribution and picks the new value for mu. A new initial wave function is created with a small sigma witch represents the delta post measure. The time needs to be reset to zero after measuring. Finally, calls comp() and now plotpsiev() has everything it needs to continue plotting. Schedule: - Get instant probability - Pick new mu0 - Reset time - New sigma - Check zone: OUT * Substract points AND/OR change lives !(extra with lives game mode) ! Check if any lives left ! Pauses the game ! Game over image ! Disables measures (buton and spacebar) ! Enable restart button * New psi (psi_init) * New comp (eigenbassis still the same) * Draw(data) psi and fill * Fill bkg (WITH PSI, tho still the same redzone) * Redraw visuplot IN * Add points * New level * Read new level * New pot * Eigenparam * New psi (psi_init) * New comp (eigenbassis still the same) * Draw(data) psi and fill * Fill bkg (WITH PSI, with new redzone) * Update new redzone (while filling) * Redraw visuplot - Update labels """ prob = self.deltax * self.psi2 #Get instant probability prob /= sum(prob) self.mu0 = np.random.choice(self.mesh, p=prob) #Pick new random mu0 if self.dummy: self.mu0 = self.mesh[np.argmax(prob)] self.measure_arrow() self.plt_time = 0. #Reset time self.sigma0 = self.dirac_sigma #New sigma if self.mu0 in self.redzone: #OUT self.lives -= 1 self.lives_sources() self.psi_init() self.comp() if self.lives <= 0: #GAME OVER self.pause_state = True self.pause_btn.text = 'Play' self.GMO_img = self.pot_twin.imshow(self.gameover_imgdata, aspect='auto', extent=[-7.5, 7.5, 0, 40]) self.measure_btn.disabled = True self.pause_btn.disabled = True self.restart_btn.disabled = False self._keyboard.release() self.fill_bkg() #VISUAL PLOT self.visu_im.remove() step = int(len(self.psi) / self.num_visu) #Same as in the 1st plot self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) else: #IN self.lvl += 1 #Read new lvl self.label_lvl.text = 'Level ' + str(self.lvl) self.read_settigns() self.pot_data.set_data(self.mesh, self.potential) #Eigenparam self.eigenparam() self.psi_init(apply_cond=True) self.comp() self.fill_bkg() #VISUAL PLOT self.visu_im.remove() step = int(len(self.psi) / self.num_visu) #Same as in the 1st plot self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) self.energy = np.sum(np.abs(self.compo)**2 * self.evals) self.E_data.set_data(self.mesh, self.energy) def skip_lvl(self): """ Skips the current level. Does exactly what measure does, but always passes the level. """ prob = self.deltax * self.psi2 #Get instant probability self.mu0 = np.random.choice(self.mesh, p=prob) #Pick new random mu0 if self.dummy: self.mu0 = self.mesh[np.argmax(prob)] self.b_arrow.remove() self.u_arrow.remove() self.b_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) self.u_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) self.plt_time = 0. #Reset time self.sigma0 = self.dirac_sigma #New sigma self.lvl += 1 self.label_lvl.text = 'Level ' + str(self.lvl) self.read_settigns() self.pot_data.set_data(self.mesh, self.potential) #Eigenparam self.eigenparam() self.psi_init(apply_cond=True) self.comp() self.fill_bkg() #VISUAL PLOT self.visu_im.remove() step = int(len(self.psi) / self.num_visu) #Same as in the 1st plot self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) #ENERGY self.energy = np.sum(np.abs(self.compo)**2 * self.evals) self.E_data.set_data(self.mesh, self.energy) #RESTART def restart(self): """ After the game is lost, sets everything ready to start again: - Clear game over image - Lvl 1 - Lives and its images to max_lives - Pauses again (in cas we unpaused it during game over) - Starts reading the settings file again (lvl 1) - New pot (init) - Eigenparam - New mu0 (initial mu) - New psi (sigma already dirac's) - New comp - Fill psi - Bkg fill + update redzone - Redraw visuplot - Enables measures (button and spacebar) - Disables restart - Clears arrows """ self.GMO_img.remove() self.lvl = 1 self.lives = self.max_lives self.lives_sources() self.pause_state = True self.pause_btn.text = 'Play' self.settings.close() #We close and open again to start reading again self.settings = open('lvl_settings.txt', 'r') self.read_settigns() self.pot_data.set_data(self.mesh, self.potential) self.eigenparam() self.psi_init(apply_cond=True) self.comp() self.redzone = np.array([]) self.fill_bkg() self.visu_im.remove() step = int(len(self.psi) / self.num_visu) #Same as in the 1st plot self.visu_im = self.visuax.imshow([self.psi2[::step]], aspect='auto', interpolation=self.inter_visu, cmap=self.cmap_name) self.measure_btn.disabled = False self.pause_btn.disabled = False self.request_KB() self.restart_btn.disabled = True self.energy = np.sum(np.abs(self.compo)**2 * self.evals) self.E_data.set_data(self.mesh, self.energy) self.b_arrow.remove() self.u_arrow.remove() self.b_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) self.u_arrow = self.bkg_twin.arrow(0, 0, 0, 0, alpha=0) def change_vel(self): """ Changes the factor in the plot time diferential. """ self.plt_vel_factor *= 2 if self.plt_vel_factor > 32: self.plt_vel_factor = 1 #Label in kivy file self.label_vel.text = 'Velocity \n ' + str( self.plt_vel_factor) + 'X' def pause(self): """ Changes the pause state from true to false and viceversa. """ # self.measure_btn.unbind(on_press = self.measure) if self.pause_state == True: #Unpause self.pause_state = False self.pause_btn.text = 'Pause' else: self.pause_state = True #Pause self.pause_btn.text = 'Play' ########################################################################### # COMPUTING FUNCTIONS # ########################################################################### """ - eigenparam - comp - read_setings - psi_init - shift_psi """ def eigenparam(self): """ Compute a vector with the eigenvalues(eV) and another with the eigenvectors ((Aº)**-1/2) of the quantum hamiltonian with potential [self.potential [eV]] (each column is an eigenvector with [N]+1 components). H · phi = E · phi ; H = -(1/2m)(d**2/dx**2) + poten(x) m := mass / hbar**2 [(eV·Aº**2)**-1] It solves the 1D time-independent Schrödinger equation for the given potential (self.potential) inside of a box [a(Aº), b(Aº)], with [N] intervals. """ #Dividing the ab segment in N intervals leave us with a (N+1)x(N+1) #hamiltonian, where indices 0 and N correspond to the potentials #barriers. The hamiltonian operator has 3 non-zero diagonals (the main #diagonal, and the ones next to it), with the following elements. semi_diag = np.full(self.N, -1. / (2. * self.m * self.deltax**2)) main_diag = self.potential + 1. / (self.m * self.deltax**2) #Although we keep these walls here, no change seems to happen if we #remove them (if we don't assign these values) main_diag[0] += 1000000000 #Potentials barriers main_diag[self.N] += 1000000000 self.evals, self.evect = spLA.eigh_tridiagonal(main_diag, semi_diag, check_finite=False) #Normalization. Used trapezoids method formula and that sum(evect**2)=1 factors =1/np.sqrt(self.deltax * \ (1. - np.abs(self.evect[0,:])**2/2. - \ np.abs(self.evect[-1,:])**2/2.)) #Normalized vectors (* here multiplies each factor element by each #evect column) self.evect = self.evect * factors def comp(self): """ Generates the initial wave function's components on the eigenbasis stored in self.compo. """ #Compute psi components phipsi = np.transpose(np.transpose(np.conj(self.evect)) * self.psi) self.compo = self.deltax * (np.sum(phipsi, axis = 0) \ - phipsi[0,:]/2. - phipsi[-1,:]/2.) def read_settigns(self): """ Reads file settings, assigns parameters and initializes the potentials. First element chooses potential: - If 0: HARMONIC Line: 0, mu0, dx, k, **redzone - If 1: DOUBLE WELL (20*[HARMONIC + CG*GAUSSIAN]) Line: 1, mu0, dx, k, mu, sigma, CG, **redzone - If 2: TRIPLE WELL (20*[HARMONIC + CG1*GAUSSIAN + CG2*GAUSSIAN2]) Line: 2, mu0, dx, k, mu1, sigma1, CG1, mu2, sigma2, CG2, **redzone - If 3 WOOD-SAXON Line: 3, mu0, H, R, a, **redzone - If 4: DOUBLE WOOD-SAXON Line: 4, mu0, H1, R1, a1, H2, R2, a2, **redzone Where mu0 is the position where to start the new psi. If no position wants to be specified, then mu0 = 100 (checked in psi_init) Number of arguments have to be passed to the realted variable. """ self.lvl_set = np.array(eval(self.settings.readline().strip())) #HARMONIC if self.lvl_set[0] == 0: dx, k = self.lvl_set[2:3 + 1] self.potential = 20 * 0.5 * k * (self.mesh - dx)**2 self.fill_start_i = 4 #DOUBLE WELL elif self.lvl_set[0] == 1: dx, k, mu, sigma, CG = self.lvl_set[2:6 + 1] self.potential = 20*(\ 0.5*k*(self.mesh - dx)**2 +\ CG/np.sqrt(2*np.pi*sigma**2)*\ np.exp(-(self.mesh-mu)**2/(2.*sigma**2))) self.fill_start_i = 7 #TRIPLE WELL elif self.lvl_set[0] == 2: dx, k, mu1, sigma1, CG1, mu2, sigma2, CG2 = self.lvl_set[2:9 + 1] self.potential = 20*(\ 0.5*k*(self.mesh - dx)**2 +\ CG1/np.sqrt(2*np.pi*sigma1**2)*\ np.exp(-(self.mesh-mu1)**2/(2.*sigma1**2)) +\ CG2/np.sqrt(2*np.pi*sigma2**2)*\ np.exp(-(self.mesh-mu2)**2/(2.*sigma2**2))) self.fill_start_i = 10 #WOOD-SAXON elif self.lvl_set[0] == 3: H, R, a = self.lvl_set[2:4 + 1] self.potential = -H / (1 + np.exp((abs(self.mesh) - R) / a)) + H self.fill_start_i = 5 #DOUBLE WOOD-SAXON elif self.lvl_set[0] == 4: H1, R1, a1, H2, R2, a2 = self.lvl_set[2:7 + 1] WS1 = -H1 / (1 + np.exp((abs(self.mesh) - R1) / a1)) + H1 WS2 = H2 / (1 + np.exp((abs(self.mesh) - R2) / a2)) self.potential = WS1 + WS2 self.fill_start_i = 8 else: print('ERROR: Bad code word for potential (1st element in line).') def psi_init(self, apply_cond=False): """ Creates the initial wave function, a gaussian packet in general. The output's shape is the same as mesh. If apply_cond is True, some specific conditions are checked and applied. Usually, it will be True after starting a new level for the first time. """ if apply_cond: #Conditions on the starting postiion new_mu0 = self.lvl_set[1] if new_mu0 != 100: self.mu0 = new_mu0 print('New mu0: ', new_mu0) #Other conditions if self.lvl == 10: #Starting at the middle maximum and paused self.pause_state = True self.pause_btn.text = 'Play' if self.lvl == 22: #Speeding up self.plt_vel_factor *= 1.5 self.label_vel.text = 'Velocity \n ' + \ str(int(self.plt_vel_factor)) +'X' #First we generate the shape of a gaussian, no need for norm. constants #We then normalize using the integration over the array. self.psi = np.sqrt(\ np.exp(-(self.mesh-self.mu0)**2/(2.*self.sigma0**2)))#\ # *np.exp(np.complex(0.,-1.)*self.p0*self.mesh) prob_psi = np.abs(self.psi)**2 self.psi *= 1. / np.sqrt(self.deltax*\ (np.sum(prob_psi) - prob_psi[0]/2. - prob_psi[-1]/2.)) self.psi2 = np.abs(self.psi)**2 def shift_psi(self, x): """ Makes psi a given eigenvector of the hamiltonian but shifted a certain amount x. Negative x means shift to the left and vicerversa. """ if x == 0 or x <= self.a or x >= self.b: self.psi = self.evect[:, 2] self.psi2 = np.abs(self.psi)**2 return #compute how many indices are in x: n = int(abs(x) / self.deltax) if x < 0: eigen = self.evect[:, 0] app = np.append(eigen, np.zeros(n)) self.psi = app[-(self.N + 1):] self.psi2 = np.abs(self.psi)**2 if x > 0: eigen = self.evect[:, 0] app = np.append(np.zeros(n), eigen) self.psi = app[:self.N + 1] self.psi2 = np.abs(self.psi)**2 self.psi *= 1. / np.sqrt(self.deltax*\ (np.sum(self.psi2) - self.psi2[0]/2. - self.psi2[-1]/2.)) self.psi2 = np.abs(self.psi)**2 ########################################################################### # PLOTTING FUNCTIONS # ########################################################################### """ - fill_bkg - measure_arrow """ def fill_bkg(self): """ Fills background in bkg axis, bkg_twin, with red and green zones of the current self.lvl_set. It fills above self.psi2. Keeps track of the red points in self.redzone. We take every other border from the file and fill the prev. zone(red) and the following zone (green). Last one added a side (red). """ self.bkg_twin.collections.clear( ) #Clear before so we don't draw on top self.redzone = np.array([]) prev = self.a for i in range(self.fill_start_i, len(self.lvl_set) - 1, 2): #Index prev_index = int((prev - self.a) // self.deltax) index = int((self.lvl_set[i] - self.a) // self.deltax) nxt_index = int((self.lvl_set[-1] - self.a) // self.deltax) #Red bot = (self.psi2)[prev_index:index + 1] #Psi line top = np.zeros_like(bot) + 2. redzone = self.mesh[prev_index:index + 1] #+1 due to slice potential = self.potential[prev_index:index + 1] / self.dcoord_factor self.redzone = np.append(self.redzone, redzone) self.bkg_twin.fill_between(redzone, bot, potential, where=np.less(bot, potential), facecolor=self.potcol) #Potential self.bkg_twin.fill_between(redzone, np.maximum(potential, bot), top, facecolor=self.zonecol_red) #Red #Green bot = (self.psi2)[index - 1:nxt_index + 2] top = np.zeros_like(bot) + 2. greenzone = self.mesh[index - 1:nxt_index + 2] #(") potential = self.potential[index - 1:nxt_index + 2] / self.dcoord_factor self.bkg_twin.fill_between(greenzone, bot, potential, where=np.less(bot, potential), facecolor=self.potcol) #Potential self.bkg_twin.fill_between(greenzone, np.maximum(potential, bot), top, facecolor=self.zonecol_green) #Green #Looping by giving the new prev position prev = self.mesh[int( (self.lvl_set[i + 1] - self.a) // self.deltax)] #Last zone red bot = (self.psi2)[nxt_index:] top = np.zeros_like(bot) + 2. redzone = self.mesh[nxt_index:] potential = self.potential[nxt_index:] / self.dcoord_factor self.redzone = np.append(self.redzone, redzone) self.bkg_twin.fill_between(redzone, bot, potential, where=np.less(bot, potential), facecolor=self.potcol) #Potential self.bkg_twin.fill_between(redzone, np.maximum(potential, bot), top, facecolor=self.zonecol_red) #Red def measure_arrow(self): """ Draws the annotation (line) on the measured mu0. Two annotations: line from bottom to the probilibity we got, and another from there to the max probability. """ #Clears before running self.b_arrow.remove() self.u_arrow.remove() prob = self.psi2 #%·Å^-1 m_prob = prob[int((self.mu0 - self.a) / self.deltax)] max_prob = np.max(prob) self.b_arrow = self.bkg_twin.arrow(self.mu0, 0, 0, m_prob, color=self.b_arrow_color, width=0.25, head_width=0.001, head_length=0.001) self.u_arrow = self.bkg_twin.arrow(self.mu0, m_prob, 0, max_prob - m_prob, color=self.u_arrow_color, width=0.25, head_width=0.001, head_length=0.001) ########################################################################### # GAME FUNCTIONS # ########################################################################### """ - lives_sources - _keyboard_closed - request_KB - _on_keyboard_down - dummy_mode """ def lives_sources(self): """ Replaces every live image source: having N lives, replaces live1 to liveN with 'heart_img.jpg', and live(N+1) to live(max_lives) with 'skull_img.jpg'. So, when changing the amount of lives, this has to be called. """ for live_spot in range(1, self.max_lives + 1): live_name = 'live' + str(live_spot) img = self.ids[live_name] #self.ids is a dict of all id(s) from kv if live_spot <= self.lives: #Heart img.source = self.heart_img else: img.source = self.skull_img def _keyboard_closed(self): """ Actions taken when keyboard is released/closed. Unbinding and 'removing' the _keyboard. """ print('keyboard released') self._keyboard.unbind(on_key_down=self._on_keyboard_down) #Is happening that clicking on the box (outside any button) relases the #keyboard. This can be 'fixed' adding a button that requests the #keyboard again. self._keyboard = None def request_KB(self): """ Requesting and binding keyboard again, only if it has been released. """ if self._keyboard == None: #It has been released self._keyboard = Window.request_keyboard(self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) else: pass def _on_keyboard_down(self, keyboard, keycode, text, modifiers): """ Bind to the event on_key_down, whenever keyboard is used this function will be called. So, it contains every function related to the keyboard. """ #We still want the escape to close the window, so diong the following, #pressing twice escape will close it. if keycode[1] == 'spacebar': self.measure() return def dummy_mode(self): """ Changes the game mode to picking the most probable value for x instead of randomly. Changes the controlling variable and updates button label. """ if self.dummy: # Using dummy. Change mode self.dummy = False self.dummy_btn.text = 'Helping:\n Off' else: # Not using dummy. Change mode self.dummy = True self.dummy_btn.text = 'Helping:\n On' def axis_off(self): """ Turns off or on the axis. """ if self.axis_on: #They are on, switching them off self.bkg_twin.axis('off') #Difference in dt when on or off: 0.02 self.bkg_twin.set_title(' ') self.pot_twin.axis('off') #Difference in dt when on or off: 0.01 self.axis_on = False else: self.bkg_twin.axis('on') figheight = self.main_fig.get_figheight( ) #In inches (100p = 1inch) self.bkg_twin.set_title('x [' + self.unit_long + ']', color='white', pad=0.05 * figheight * 100, fontsize=10) #pad in p self.pot_twin.axis('on') self.axis_on = True
class YoungSlitScreen(Screen): slt_number = NumericProperty(0) is_source_on = BooleanProperty(False) def __init__(self, **kwargs): super(YoungSlitScreen, self).__init__(**kwargs) def yspseudo_init(self): #temps inicial (0, evidentment) self.t = 0 self.source_on = False #recinte i discretitzat self.dt = 1 / 20 self.dl = 2 * self.dt self.Nx = 301 self.Ny = 301 global Nx_inty, Ny_inty Nx_inty = self.Nx Ny_inty = self.Ny #visualització del recinte que apareix a l'App self.h_display = int(self.Ny / 3) self.w_display = int(2 * self.Nx / 3) #variables de l'ona self.w = 2 * pi self.c = 1.4 self.amp = 2.5 self.tau = 2 * pi / self.w self.Ntau = int(1 + self.tau / self.dt) self.rao = (self.c * self.dt / self.dl)**2 #variables paret self.sgm_max = 0.02615 self.m = 1.54 #llistes de l'ona i la paret en el recinte self.a = np.zeros((self.Nx, self.Ny, 3)) self.a2 = np.zeros((self.Nx, self.Ny, self.Ntau)) self.inty = np.zeros((self.Nx, self.Ny, 3)) self.sgm = np.zeros((self.Nx, self.Ny)) self.sgm_wall = np.zeros((self.Nx, self.Ny)) self.sgm_det = np.zeros((self.Nx, self.Ny)) #font self.s = np.zeros((self.Nx, self.Ny)) #slits self.Nslt = 0 self.w_slt = 8 #gruix i posició de les parets self.x_wall = int(self.Nx / 4) self.w_wall = int(self.Nx / 30) self.w_det = int(self.Nx / 3) global w_det_ys w_det_ys = self.w_det self.slit_presence = np.zeros((self.Nx, self.Ny)) self.slit_presence[self.x_wall, :] = 1 self.separation = int(self.Ny / 10) #coef d'absorció a les parets del detector for k in range(self.w_det): self.sgm_det[self.Nx-1-k,0+k:self.Ny-1-k]=\ self.sgm_max*((self.w_det-k)/self.w_det)**self.m self.sgm_det[self.x_wall:self.Nx-k,k]=\ self.sgm_max*((self.w_det-k)/self.w_det)**self.m self.sgm_det[self.x_wall:self.Nx-k,self.Ny-1-k]=\ self.sgm_max*((self.w_det-k)/self.w_det)**self.m ##########################PRIMER DIBUIX################### #creem la figura recipient del plot imshow self.main_fig, self.axs = plt.subplots(2, sharex=True, sharey=True) #L'associem amb kivy self.main_canvas = FigureCanvasKivyAgg(self.main_fig) self.box1.add_widget(self.main_canvas, 1) #Plot de l'ona i de l'intensitat self.wave_visu = self.axs[0] self.inty_visu = self.axs[1] self.at = self.a[:, :, 2] self.it = self.inty[:, :, 2] #Dibuix de les figures self.cmap = plt.get_cmap('Reds') self.cmap.set_under('k', alpha=0) #diagrama d'ones self.wave_visu_im=self.wave_visu.imshow(\ self.at.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=4,vmin=-4,origin='lower', extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) #representació de la paret al diagrama d'ones self.wave_slit_im=self.wave_visu.imshow(\ self.slit_presence.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=1,vmin=0.5,origin='lower',cmap=self.cmap, extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) #diagrama d'intensitat self.inty_visu_im=self.inty_visu.imshow(\ self.it.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=5,origin='lower',cmap='gray', extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) #representació de la paret al diagrama d'intensitat self.inty_slit_im=self.inty_visu.imshow(\ self.slit_presence.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=1,vmin=0.5,origin='lower',cmap=self.cmap, extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) self.main_canvas.draw() self.main_canvas.mpl_connect('resize_event', partial(self.resize_kivy)) def resize_kivy(self, *largs): """Aquesta funció és trucada cada cop que la finestra canvia de tamany. Cada cop que això passa, les coordenades (en pixels) dels cantons del plot imshow canvien de lloc. Aquests són molt importants sobretot pel joc, per tant, cal tenir-nos ben localitzats.""" #Aquesta funció de matplotlib ens transforma els cantons de coordenades Data # a display (pixels) self.wave_cantonsnew = self.wave_visu.transData.transform([ (0, 0), (0, int(self.h_display * self.dl)), (int(self.w_display * self.dl), int(self.h_display * self.dl)), (int(self.w_display * self.dl), 0) ]) self.inty_cantonsnew = self.inty_visu.transData.transform([ (0, 0), (0, int(self.h_display * self.dl)), (int(self.w_display * self.dl), int(self.h_display * self.dl)), (int(self.w_display * self.dl), 0) ]) def ys_schedule_fired(self): "Ara, definim l'update, a partir d'aqui farem l'animació" self.schedule = Clock.schedule_interval(self.plotysev, self.dt) #integral per trapezis, on h és el pas, i f, una llista amb els valors de #la funció a inetgrar, és una llista 3D d'una funció 2D amb dependència temps #i com que estem integrant en el temps ens retorna una llista 2D def trapezis(self, h, f): val = (np.sum(f[:, :, 0:-1], axis=2) + np.sum(f[:, :, 1:], axis=2)) * h / 2 return val #funció de la font def p_s(self, t, amp, w): val = amp * np.sin(w * t) return val #plot young slit evolution def plotysev(self, dt): k = 2 if self.source_on == True: self.s[1, :] = self.p_s(self.t, self.amp, self.w) if self.source_on == False: self.s[:, :] = 0 """càlculs que fa el programa a cada pas""" slt_i = np.zeros((self.Nslt + 2), dtype=int) slt_f = np.zeros((self.Nslt + 2), dtype=int) slt_n = np.linspace(1, self.Nslt, self.Nslt, dtype=int) wall_presence = np.zeros((self.Ny), dtype=int) if self.Nslt == 2: #posicio del final i l'inici de cada escletxa, ara amb separació variable slt_i[1]=int(self.Ny/2)-int(self.separation/2)-\ int(self.w_slt/2) slt_i[2]=int(self.Ny/2)+int(self.separation/2)-\ int(self.w_slt/2) slt_f[1]=int(self.Ny/2)-int(self.separation/2)+\ int(self.w_slt/2) slt_f[2]=int(self.Ny/2)+int(self.separation/2)+\ int(self.w_slt/2) slt_f[0] = 0 slt_f[self.Nslt + 1] = self.Ny slt_i[self.Nslt + 1] = self.Ny else: #posicio del final i l'inici de cada escletxa slt_i[1:self.Nslt+1]=int(self.Ny/2)-int(self.h_display/2)-\ int(self.w_slt/2)+slt_n[:]*int(self.h_display/(1+self.Nslt)) slt_f[1:self.Nslt+1]=int(self.Ny/2)-int(self.h_display/2)+\ int(self.w_slt/2)+slt_n[:]*int(self.h_display/(1+self.Nslt)) slt_f[0] = 0 slt_f[self.Nslt + 1] = self.Ny slt_i[self.Nslt + 1] = self.Ny #les escletxes van de splt_i a splt_f-1, en aquests punts no hi ha paret, # a slpt_f ja hi ha paret for n in range(1, self.Nslt + 2): wall_presence[slt_f[n - 1]:slt_i[n]] = 1 wall_presence[slt_i[n]:slt_f[n]] = 0 # matriu que, amb el gruix de la paret com a nombre de files, ens diu si # hi ha paret o escletxes a cada una de les y(representades en les columnes) wall_presence = np.tile(np.array([wall_presence], dtype=int), (self.w_wall, 1)) #matriu que diu com de "dins" som a la paret wall_n = np.linspace(1, self.w_wall, self.w_wall) wall_ny = np.tile( np.array([wall_n], dtype=int).transpose(), (1, self.Ny)) #valors de coeficient d'absorció a les parets self.sgm_wall[self.x_wall-self.w_wall:self.x_wall,:]=wall_presence[:,:]\ *self.sgm_max*((wall_ny[:,:])/self.w_wall)**self.m #llista per a l'última capa de la paret, on l'amplitud d'ona és 0 self.wave_presence = np.ones((self.Nx, self.Ny)) self.wave_presence[self.x_wall, :] = (1 - wall_presence[0, :]) self.sgm = self.sgm_wall + self.sgm_det #resolució de l'equació d'ones a cada temps a l'interior del recinte self.a[1:-1,1:-1,k]=\ (self.rao*(self.a[2:,1:-1,k-1]+self.a[0:-2,1:-1,k-1]\ +self.a[1:-1,2:,k-1]+self.a[1:-1,0:-2,k-1]\ -4*self.a[1:-1,1:-1,k-1])+self.s[1:-1,1:-1]\ +2*self.a[1:-1,1:-1,k-1]-self.a[1:-1,1:-1,k-2]\ +self.sgm[1:-1,1:-1]*self.a[1:-1,1:-1,k-2]/(2*self.dt))\ /(1+self.sgm[1:-1,1:-1]/(2*self.dt))\ *self.wave_presence[1:-1,1:-1] #condicions periòdiques de contorn a les parets superior i inferior self.a[1:self.x_wall,0,k]=\ (self.rao*(self.a[2:self.x_wall+1,0,k-1]+self.a[0:self.x_wall-1,0,k-1]\ +self.a[1:self.x_wall,1,k-1]+self.a[1:self.x_wall,self.Ny-1,k-1]\ -4*self.a[1:self.x_wall,0,k-1])+self.s[1:self.x_wall,0]\ +2*self.a[1:self.x_wall,0,k-1]-self.a[1:self.x_wall,0,k-2]\ +self.sgm[1:self.x_wall,0]*self.a[1:self.x_wall,0,k-2]/(2*self.dt))\ /(1+self.sgm[1:self.x_wall,0]/(2*self.dt))\ *self.wave_presence[1:self.x_wall,0] self.a[1:self.x_wall,self.Ny-1,k]=\ (self.rao*(self.a[2:self.x_wall+1,self.Ny-1,k-1]\ +self.a[0:self.x_wall-1,self.Ny-1,k-1]\ +self.a[1:self.x_wall,0,k-1]+self.a[1:self.x_wall,self.Ny-2,k-1]\ -4*self.a[1:self.x_wall,self.Ny-1,k-1])+self.s[1:self.x_wall,self.Ny-1]\ +2*self.a[1:self.x_wall,self.Ny-1,k-1]\ -self.a[1:self.x_wall,self.Ny-1,k-2]\ +self.sgm[1:self.x_wall,self.Ny-1]\ *self.a[1:self.x_wall,self.Ny-1,k-2]/(2*self.dt))\ /(1+self.sgm[1:self.x_wall,self.Ny-1]/(2*self.dt))\ *self.wave_presence[1:self.x_wall,self.Ny-1] #calculs de la intensitat self.a2[:, :, :-1] = self.a2[:, :, 1:] self.a2[:, :, self.Ntau - 1] = self.a[:, :, k] * self.a[:, :, k] self.inty[:, :, k] = self.trapezis(self.dt, self.a2) / self.tau #preparació del següent pas self.a[:, :, :-1] = self.a[:, :, 1:] self.t = self.t + self.dt self.slit_presence = 1 - self.wave_presence """Representació a cada pas""" #eliminar l'anterior self.wave_visu_im.remove() self.wave_slit_im.remove() self.inty_visu_im.remove() self.inty_slit_im.remove() #Posar el nou self.at = self.a[:, :, 2] self.it = self.inty[:, :, 2] global intensitat_llum intensitat_llum = self.it #diagrama d'ones self.wave_visu_im=self.wave_visu.imshow(\ self.at.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=4,vmin=-4,origin='lower', extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) self.wave_slit_im=self.wave_visu.imshow(\ self.slit_presence.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=1,vmin=0.5,origin='lower',cmap=self.cmap, extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) #diagrama d'intensitat self.inty_visu_im=self.inty_visu.imshow(\ self.it.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=5,origin='lower',cmap='gray', extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) self.inty_slit_im=self.inty_visu.imshow(\ self.slit_presence.transpose()[int((self.Ny-self.h_display)/2):\ int((self.Ny+self.h_display)/2), 0:self.w_display] ,vmax=1,vmin=0.5,origin='lower',cmap=self.cmap, extent=(0,int(self.w_display*self.dl),0,int(self.h_display*self.dl))) #I utilitzar-lo self.main_canvas.draw() def ys_schedule_cancel(self): self.schedule.cancel() def add_slit(self): if self.Nslt < 5: self.Nslt += 1 else: pass def remove_slit(self): if self.Nslt > 0: self.Nslt -= 1 else: pass def inc_slt_width(self): if (self.Nslt * self.w_slt) < self.h_display: self.w_slt += 2 else: pass def dec_slt_width(self): if self.w_slt > 0: self.w_slt -= 2 else: pass def change_source_state(self): self.t = 0 if self.source_on == False: self.source_on = True else: self.source_on = False def clear_waves(self): self.a = np.zeros((self.Nx, self.Ny, 3)) def inc_separation(self): if (self.Nslt * self.w_slt + self.separation) < self.h_display: self.separation += 2 else: pass def dec_separation(self): if self.separation > 0: self.separation -= 2 else: pass
class PaquetScreen(Screen): "Això és la part més important de la app. Introduïrem la pantalla inicial" #Les propietats s'han de definir a nivell de classe (millor). Per tant, #les definim aquí. quadrat = ObjectProperty(None) position = ListProperty(None) def __init__(self, **kwargs): "Unim la clase amb la paraula self" super(PaquetScreen, self).__init__(**kwargs) #Aquesta linia uneix keyboard amb request keyboard self._keyboard = Window.request_keyboard(self._keyboard_closed, self) #self._keyboard.bind(on_key_down=self._on_keyboard_down) def gpseudo_init(self): "Iniciem el primer dibuix de l'aplicació" #Variables globals... global Vvec, avec, cvec, psi0, normavec, mode ################### PARAMETRES DE LA CAIXA,DISCRETITZAT,PARTICULA######## self.L = 3 self.xa = -self.L self.xb = self.L #Discretitzat self.tb = 0.1 self.ta = 0 self.dx = 0.05 self.dt = 0.02 self.Nx = np.int((2 * self.L) / self.dx) #particula i constants físiques self.m = 1 self.hbar = 1 self.t_total = 0. self.x0 = 0. self.y0 = 0. self.px = 0 self.py = 0 #Comptador de moments self.i = 0 #parametre del discretitzat self.r = (self.dt / (4 * (self.dx**2))) * (self.hbar / self.m) #Canvia el text del interior de la caixa 'parameters' amb els parametr #es inicials escollits self.box3.dxchange.text = "dx={}".format(self.dx) self.box3.longitudchange.text = "L={}".format(self.L) self.box3.dtchange.text = "dt={}".format(self.dt) #################### PARAMETRES NECESSARIS PER EFECTUAR ELS CALCULS###### #################### POTENCIALS #Potencial estandar(mode=0) self.Vvecestandar = np.array([[ ck.Vharm(self.xa + i * self.dx, self.xa + j * self.dx, self.xb, self.xb) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)], dtype=np.float64) #Potencial slit(mode=1) self.yposslitd = np.int(self.Nx * (4.75 / 10)) self.yposslitu = np.int(self.Nx * (5.25 / 10)) self.xposslit = np.int(self.Nx / 3) self.x0slit = self.L / 2 self.y0slit = 0. self.Vvecslit = np.copy(self.Vvecestandar) self.Vvecslit[0:self.yposslitd, self.xposslit] = 100000 self.Vvecslit[self.yposslitu:self.Nx, self.xposslit] = 100000 ##################### PAQUETS #Paquet propi del mode estandar self.psiestandar = np.array([[ ck.psi0f(-self.L + i * self.dx, -self.L + j * self.dx, 0.25, self.px, self.py, self.x0, self.y0) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)]) #dtype=np.complex128) #Paquet propi del mode slit self.psislit = np.array([[ ck.psi0f(-self.L + i * self.dx, -self.L + j * self.dx, 0.25, self.px, self.py, self.x0slit, self.y0slit) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)]) ##################### MODES #mode: 0, estandard # 1,slit # 2,disparo(encara no està fet) #definm el mode inicial tal que: self.Vvec = self.Vvecestandar self.psi0 = self.psiestandar #Ens indica en quin mode estem self.mode = 0 #Per últim, construïm les matrius molt importants per efectuar els càlculs. self.avec, self.cvec = ck.ac(self.r, self.Vvec, self.Nx) ##########################PRIMER CÀLCUL ENERGIA##### #Calculem la matriu densitat inicial self.normavec = ck.norma(self.psi0, self.Nx) #Calculem moments i energia inicials i els posem al lloc corresponent self.norma0 = ck.trapezis(self.xa, self.xb, self.dx, np.copy(self.normavec)) self.energy0 = ck.Ham(self.xa, self.xb, self.dx, np.copy(self.psi0)) self.box3.normachange.text = 'Norma={0:.3f}'.format(self.norma0) self.box3.energychange.text = 'Energia={0:.3f}'.format(self.energy0) ##########################PRIMER DIBUIX################### #creem la figura recipient del plot imshow self.main_fig = plt.figure() #L'associem amb kivy self.main_canvas = FigureCanvasKivyAgg(self.main_fig) self.box1.add_widget(self.main_canvas, 1) #Plot principal self.visu = plt.axes() self.visu_im = self.visu.imshow(self.normavec, origin={'lower'}, extent=(-self.L, self.L, -self.L, self.L)) #Posició de la figura self.visu.set_position([0, 0.15, 0.8, 0.8]) #Dibuixem tot lo dit self.main_canvas.draw() ##################################MATPLOTLIB EVENTS/RESIZING #self.main_canvas.mpl_connect('motion_notify_event', motionnotify) #Conectem l'event resize de matplotlib amb la funció resize_kivy. #Aquesta útlima ens permet saber on estan els cantons de la caixa en #coordenades de pixels de la finestra en un primer instant (ja que quan # kivy obre matplotlib per primer cop fa ja un resize), i tambe posteriorment, # cada cop que fem el resize. Això ens podria ser útil en algún moment. self.main_canvas.mpl_connect('resize_event', resize) self.main_canvas.mpl_connect('resize_event', partial(self.resize_kivy)) ################################POTENCIAL MODE/Widget de dibuix self.setcordpress = np.array([]) self.setcordrelease = np.array([]) self.paint = MyPaintWidget() #No pinta a no ser que estigui activat. self.paint.pause_paint = True self.box1.add_widget(self.paint) ###############################PROPIETATS DEL QUADRAT AMB EL QUE JUGUEM self.quadrat.pos = [800, 800] self.play_game = False ###################################BUTONS DE LA CAIXA 2################### #Aquests butons varian el menu principal del joc #Aquest activa la funció que activa,atura, o reseteja el calcul self.box2.add_widget( Button(text='Play', on_press=partial(self.compute))) self.box2.add_widget(Button(text='Pause', on_press=partial(self.pause))) self.box2.add_widget(Button(text='Reset', on_press=partial(self.reset))) self.box2.add_widget( Button(text='Standard', on_press=partial(self.standard))) self.box2.add_widget(Button(text='Slit', on_press=partial(self.slit))) self.box2.add_widget(Button(text='Game', on_press=partial(self.gameon))) #####################################PAUSESTATE self.pause_state = True ##Ara venen tot el seguït de funcions que utilitzarem conjuntament amb els #parametres definits a g_init ##############################RESIZING############################ #1.Resize_kivy #Funcions que s'ocupen del tema resize: def resize_kivy(self, *largs): """Aquesta funció és trucada cada cop que la finestra canvia de tamany. Cada cop que això passa, les coordenades (en pixels) dels cantons del plot imshow canvien de lloc. Aquests són molt importants sobretot pel joc, per tant, cal tenir-nos ben localitzats.""" #Aquesta funció de matplotlib ens transforma els cantons de coordenades Data # a display (pixels) self.cantonsnew = self.visu.transData.transform([(-3, -3), (-3, 3), (3, 3), (3, -3)]) print(self.cantonsnew) ################################FUNCIONS DE CALCUL/FLUX################## #1.g_schedule_fired #2.plotpsiev #3.compute(play) #4.pause #5.reset def g_schedule_fired(self): "Ara, definim l'update, a partir d'aqui farem l'animació" self.schedule = Clock.schedule_interval(self.plotpsiev, 1 / 60.) def plotpsiev(self, dt): "Update function that updates psi plot" if self.pause_state == False: #Primer de tot, representem el primer frame if (self.i) == 0: self.compute_parameters() #Animation #Lanimació consisteix en elimanr primer el que teniem abans self.normavec = ck.norma(self.psi0, self.Nx) self.visu_im.remove() #Posar el nou self.visu_im = self.visu.imshow(self.normavec, origin={'lower'}, extent=(-self.L, self.L, -self.L, self.L)) #I utilitzar-lo self.main_canvas.draw() #CALCUL #Tot següit fem el càlcul del següent step self.psi0 = ck.Crannk_stepm(self.psi0, self.avec, self.cvec, self.r, self.Vvec, self.dt, self.Nx, self.i) #Canviem el temps self.t_total = self.t_total + (self.dt) / 2. self.box3.tempschange.text = 'temps={0:.3f}'.format(self.t_total) #Videojoc, coses del videojoc if self.play_game == True: self.maxvalue = np.amax(self.normavec) self.llindar = self.maxvalue / 20. if self.normavec[self.pos_discret[0], self.pos_discret[1]] > self.llindar: print('Touched') #Cada 31 pasos de temps calculem el temps: self.i += 1 def compute(self, *largs): """Quan es clica el butó play, s'activa aquesta funció, que activa el calcul""" self.pause_state = False def pause(self, *largs): """Aquesta funció para el càlcul del joc""" self.pause_state = True def reset(self, *largs): """Aquesta funció reseteja el paquet i el potencial inicials. Segons el mode inicial en el que ens trobem, es resetejara un o l altre.""" if self.pause_state == True: #Segons el mode, reseteja un potencial o un paquet diferent if self.mode == 0: self.psi0 = self.psiestandar self.Vvec = self.Vvecestandar if self.mode == 1: self.psi0 = self.psislit self.Vvec = self.Vvecslit #Parametres que s'han de tornar a resetejar self.i = 0 self.px = 0 self.py = 0 self.t_toal = 0. #Rseteja la imatge self.normavec = ck.norma(self.psi0, self.Nx) self.visu_im.remove() self.visu_im = self.visu.imshow(self.normavec, origin={'lower'}, extent=(-self.L, self.L, -self.L, self.L)) self.main_canvas.draw() #Canviem els parametre en pantalla tambe self.box3.tempschange.text = 'temps=0.' self.box3.pxchange.text = 'px=0' self.box3.pychange.text = 'py=0' #####################################CHANGE PARAMETERs################## #Fucnions que s'encarregar del canvi efectiu dels parametres #1.changep def changep(self, add_px, add_py, *largs): """Funció que respon als buto + i - que varia el moment inicial del paquet. Per que aquest canvi sigui efectiu, hem de canviar tambe el propi paquet.""" #if selfpause==True #Canvi el moment en pantalla self.px += add_px self.py += add_py print(self.px, self.py) self.box3.pxchange.text = 'px={}'.format(self.px) self.box3.pychange.text = 'py={}'.format(self.py) #Canvi del moment efectiu if self.mode == 0: self.psi0 = np.array([[ ck.psi0f(-self.L + i * self.dx, -self.L + j * self.dx, 0.25, self.px, self.py, 0., 0.) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)]) if self.mode == 1: self.psi0 = np.array([[ ck.psi0f(-self.L + i * self.dx, -self.L + j * self.dx, 0.25, self.px, self.py, self.x0slit, self.y0slit) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)]) ################################# POTENCIAL MODE ######################### #Aquestes funcions juntament amb el widget MyPaintWidget porten la posibilitat #de poder dibuixar un potencial. #1.editorfun(start) #2.editorstop(stop) #3.Activatepaint(pinta només si self.paint.pause_paint==False) #4.Potpress(apunta les coordenades on es pren el potencial) #5.Potrelease(apunta les coordenades on es solta el potencial) #6.modifypot(Agafa aquests dos punts i els ajunta, tot creaunt un potencial # infinit al mig. #7.clear (reseteja el potencial que s'hagui dibuixat, amb tot el que implica) def editorfun(self, *largs): """Aquesta funció es l'encarregada d'activar el mode editor. Activa l'event de matplotlib que detecta la entrada al propi plot o la sortida, i l'enllaça amb la funció activatepaint""" #Controla que només es pogui dibuixar dins la figura self.cidactivate = self.main_canvas.mpl_connect( 'axes_enter_event', partial(self.activatepaint, 1)) self.ciddesactivate = self.main_canvas.mpl_connect( 'axes_leave_event', partial(self.activatepaint, 0)) def editorstop(self, *largs): """Aquesta funció desactiva totes les conexions activades a editorfun, i per tant, desactiva el mode editor""" self.main_canvas.mpl_disconnect(self.cidactivate) self.main_canvas.mpl_disconnect(self.ciddesactivate) def activatepaint(self, n, *largs): """Aquesta funció s'encarrega d'activar el widget Paint(que dona la capactiat de pintar en pantalla, només quan el cursor està dins del plot). També activa quatre funcions i les conecta amb les accions d'apretar i soltar el click dret del mouse per, d'aquesta manera, enregistar on s'ha apretat.""" if n == 1: self.paint.pause_paint = False self.cid1 = self.main_canvas.mpl_connect('button_press_event', press) self.cid2 = self.main_canvas.mpl_connect('button_press_event', partial(self.potpress)) self.cid3 = self.main_canvas.mpl_connect('button_release_event', release) self.cid4 = self.main_canvas.mpl_connect('button_release_event', partial(self.potrelease)) print('painting') else: self.paint.pause_paint = True self.main_canvas.mpl_disconnect(self.cid1) self.main_canvas.mpl_disconnect(self.cid2) self.main_canvas.mpl_disconnect(self.cid3) self.main_canvas.mpl_disconnect(self.cid4) def potpress(self, *largs): """Funció que s'encarrega de guardar en coordenades de data el lloc on s'ha apretat al plot""" self.setcordpress = np.append(self.setcordpress, cordpress) print(self.setcordpress) def potrelease(self, *largs): """Funció que s'encarrega de guardar en coordenades de data el lloc on s'ha soltat al plot.""" self.setcordrelease = np.append(self.setcordrelease, cordrelease) print(self.setcordrelease) def modifypot(self, *largs): """Aquesta funció s'aplica quan es clika el buto apply. Durant el període que s'ha dibuixat, totes les lineas de potencial s'han en- registrat a les variables self.csetcorpress i setcordreleas. Aquestes estan en coordenades de self. data i les hem de passar al discretitzat.""" #Variables on guardem les dates del dibuix vecpress = self.setcordpress vecrelease = self.setcordrelease #linias dibuixades=vecsize/2 vecsize = np.int(vecpress.size) #Aquí guardarem els resultats. transformvectorx = np.array([], dtype=int) transformvectory = np.array([], dtype=int) #Coloquem una guasiana al voltant del potencial que pintem. La sigma^2 farem que #sigui del mateix tamany que el pas s2vec = self.dx valorVec = 10000. #Bucle de conversió de les dades for i in range(0, vecsize, 2): #Establim noms de variables index = i x0 = vecpress[index] y0 = vecpress[index + 1] x1 = vecrelease[index] y1 = vecrelease[index + 1] Vecgaussia = self.potential_maker(x0, y0, x1, y1, valorVec, s2vec) #I el sumem... self.Vvec += Vecgaussia #Coloquem una petita gaussiana al voltant de cada punt de sigma*2=self.dx/2 #self.Vvec=Vvec #Modifiquem els respectius ac,vc #self.Vvec=Vvec print(self.Vvec) self.avec, self.cvec = ck.ac(self.r, self.Vvec, self.Nx) print('Applied!') def gaussian_maker(self, x, y, x0, y0, x1, y1, value, s2, *largs): """Introduïm aquí la gaussiana per cada x e y... x0,y0,x1,y1, son els dos punts que uneixen la recta dibuixada. Utilitzarem les rectes perpen- diculars en aquestes a cada punt per dissenyar aquest potencial.""" #Primer de tot, definim el pendent de la recta que uneix els dos punts if (x1 - x0) == 0.: x_c = x0 y_c = y else: m = (y1 - y0) / (x1 - x0) if m == 0: y_c = y0 x_c = x else: x_c = 0.5 * (x0 + x - (y0 - y) / m) y_c = m * (x_c - x0) + y0 #definim condicio per si posar-hi gaussiana o no: if x0 - self.dx < x_c < x1 + self.dx: #Obteim el punt en y #Ara només hem de calcular quant val la gaussiana: Vvecgauss = value * (1. / (np.sqrt(s2 * 2. * np.pi))) * np.exp( -(0.5 / s2) * ((x - x_c)**2 + (y - y_c)**2)) else: Vvecgauss = 0. return Vvecgauss def potential_maker(self, x0, y0, x1, y1, value, s2, *largs): Vvecgauss1 = np.array([[ self.gaussian_maker(self.xa + i * self.dx, self.xa + j * self.dx, x0, y0, x1, y1, value, s2) for i in range(self.Nx + 1) ] for j in range(self.Nx + 1)]) return Vvecgauss1 def clear(self, *largs): """Aquesta funció neteja el canvas i tot els canvis introduïts tan al potencial com a les coordenades del potencial. """ self.paint.canvas.clear() self.setcordpress = np.array([]) self.setcordrelease = np.array([]) if self.mode == 0: self.Vvec = self.Vvecestandar if self.mode == 1: self.Vvec = self.Vvecslit ############################## MODES#################################### #Aquestes funcions s'activen quan clikem self o slit i s'encarreguen de que #resetejar tot el que hi ha en pantalla (si estan en un mode difent al seu #propi) i posar el mode escollit #1.standard(mode 0) #2.slit(mode slit) def standard(self, *largs): """Funció que retorna el mode estandard en tots els aspectes: de càlcul, en pantalla, etf...""" if self.mode == 0: pass else: self.Vvec = self.Vvecestandar self.psi0 = self.psiestandar #Llevem les líneas que hi pogui haver if self.mode == 1: self.lineslit1.remove() self.lineslit2.remove() #Això es un reset, pensar fer-ho amb el reset. #Canviem la pantalla i el mode: self.i = 0 #Rseteja la imatge self.normavec = ck.norma(self.psi0, self.Nx) self.visu_im.remove() #Posar el nou self.visu_im = self.visu.imshow(self.normavec, origin={'lower'}, extent=(-self.L, self.L, -self.L, self.L)) #I utilitzar-lo self.main_canvas.draw() #Canviem el temps tambe self.t_total = 0. self.box3.tempschange.text = 'temps=0.' self.px = 0 self.py = 0 self.box3.pxchange.text = 'px=0' self.box3.pychange.text = 'py=0' self.mode = 0 def slit(self, *largs): """Quan activem aquest buto, canviem el paquet de referencia i el potencial de referència i ho deixem en el mode slit. Aquest mode correspon amb el número 1.""" self.mode = 1 self.Vvec = self.Vvecslit self.psi0 = self.psislit """Pintem tot lo dit i afegim una líniea que es correspón amb el potencial, fix en aquest mode.""" #Rseteja la imatge self.normavec = ck.norma(self.psi0, self.Nx) self.visu_im.remove() #Posar el nou self.visu_im = self.visu.imshow(self.normavec, origin={'upper'}, extent=(-self.L, self.L, -self.L, self.L)) self.lineslit1 = self.visu.axvline(x=-self.L + self.xposslit * self.dx, ymin=0, ymax=0.475, color='white') self.lineslit2 = self.visu.axvline( x=-self.L + self.xposslit * self.dx, ymin=0.525, ymax=1, color='white', ) #I utilitzar-lo self.main_canvas.draw() ################################### COMPUTE PARAMETES##################### #Aquestes funcions efectuan càlculs de diferents parametres. De moment, # només de l'energia i la norma #1.compute_parameters def compute_parameters(self, *largs): """Aquesta funció s'encarrega de calcular la norma i la energia del paquet en un cert instant t i despres l'ensenya a pantalla.""" #Calculem moments i energia inicials i els posem al lloc corresponent self.normavec = ck.norma(self.psi0, self.Nx) self.norma0 = ck.trapezis(self.xa, self.xb, self.dx, np.copy(self.normavec)) self.energy0 = ck.Ham(self.xa, self.xb, self.dx, np.copy(self.psi0)) self.box3.normachange.text = 'Norma={0:.3f}'.format(self.norma0) self.box3.energychange.text = 'Energia={0:.3f}'.format(self.energy0) ##################################### JOC ########################## #Funcions relacionades amb el propi joc #1._keyboard_closed #2._on_keyboard_down #3.on_position #4.on_game def _keyboard_closed(self): """No se ben bé que fa però es necessària""" self._keyboard.unbind(on_key_down=self._on_keyboard_down) self._keyboard = None def _on_keyboard_down(self, keyboard, keycode, text, modifiers, *largs): """Aquesta funció s'ocupa de conectar el moviment del quadrat amb el teclat. És a dir, conecta l'esdeveniment de teclejar amb el de fer que el quadrat avanci un pas. A l'hora, també imposa els limits on el quadrat es pot moure. """ #Definim els limits superior e inferior xliminf = np.int(self.cantonsnew[0, 0]) xlimsup = np.int(self.cantonsnew[2, 0]) yliminf = np.int(self.cantonsnew[0, 1]) ylimsup = np.int(self.cantonsnew[1, 1]) #defim el pas pas = 10 #definim a quina distància s'ha de parar el rectangle. w = self.quadrat.width h = self.quadrat.height #Hem de pensar que la posició es defineix a la cantonada inferior esquerre #del rectangle dist = 5 #Conexions events amb moviment quadrat if keycode[1] == 'w': if self.quadrat.y + dist + h > ylimsup: pass else: self.quadrat.y += pas self.position = self.quadrat.pos return True if keycode[1] == 's': if self.quadrat.y - dist < yliminf: pass else: self.quadrat.y -= pas self.position = self.quadrat.pos #self.position=self.quadrat.position #print(self.quadrat.position) return True if keycode[1] == 'd': if self.quadrat.x + dist + w > xlimsup: pass else: self.quadrat.x += pas self.position = self.quadrat.pos return True elif keycode[1] == 'a': if self.quadrat.x - dist < xliminf: pass else: self.quadrat.x -= pas self.position = self.quadrat.pos return True def on_position(self, quadrat, pos): """Cada cop que el quadrat canvia de posició, això es notifica aquí. Utilitzarem aquesta funció (que està anclada a una propietat) per fer el canvi de coordenades pixels matplotlib-data matplotlib. Tot seguït, sabent on es troba el paquet, podem saber a sobre de quin valor de densitat del paquet es troba i definir que passa quan es troba en segons quines situacions...""" #Utilitzem la transformació inversa que ens porta de pixels matplotlib # a dades matplotlib. inv_data = self.visu.transData.inverted() #Posició del centre del quadrat pos_data = inv_data.transform((pos[0] + self.quadrat.width / 2, pos[1] + self.quadrat.height / 2)) #Un cop tenim la posició del centre del quadrat en coordenades data, les #pasem a coord del discretitzat: self.pos_discret = np.array([(pos_data[0] + self.L) / self.dx, (pos_data[1] + self.L) / self.dx], dtype=int) #Busquem el valor màxim de normavec cada cop que es mou el paquet #definim un llindar a partir del qual el quadrat detecta el paquet self.maxvalue = np.amax(self.normavec) self.llindar = self.maxvalue / 20. if self.normavec[self.pos_discret[0], self.pos_discret[1]] > self.llindar: print('Touched') def gameon(self, *largs): """Aquesta funció es l'encarregada de posar el joc en marxa. Col·loca el quadradet a algún lloc on es pogui veure (una mica cutre però ja ho canviaras). Uneix la funció teclat amb el moviment del quadrat, i varia el mode del joc.""" if self.play_game == False: self.play_game = True self.quadrat.x = np.int( (-self.cantonsnew[0, 0] + self.cantonsnew[2, 0]) / 5. + self.cantonsnew[0, 0]) self.quadrat.y = np.int( 3 * (-self.cantonsnew[0, 1] + self.cantonsnew[1, 1]) / 4. + self.cantonsnew[0, 1]) self._keyboard.bind(on_key_down=self._on_keyboard_down) else: self.play_game = False self.quadrat.x = 800 self.quadrat.y = 600 self._keyboard.unbind(on_key_down=self._on_keyboard_down)