def create_viz(): global state, G, basis scene = vp.canvas(background=vp.color.white) n = len(state.dims[0]) colors = [vp.color.red, vp.color.green, vp.color.blue] if n == 3 else\ [vp.vector(*np.random.random(3)) for i in range(n)] vpts = {} for i in range(n): pov_state = take_pov(state, 0, i, G, basis=basis) vp.label(text="pov: %d" % i,\ pos=vp.vector(3*i-n,-1.5,0),\ color=colors[i]) vp.sphere(color=colors[i],\ opacity=0.1,\ pos=vp.vector(3*i-n, 0, 0)) for k in range(n): partial = pov_state.ptrace(k) xyz = np.array([qt.expect(qt.sigmax(), partial),\ qt.expect(qt.sigmay(), partial),\ qt.expect(qt.sigmaz(), partial)]) vpts[(i,k)] = vp.arrow(opacity=0.3,\ pos=vp.vector(3*i-n, 0, 0)+0.01*vp.vector(*np.random.randn(3)),\ color=colors[k],\ axis=vp.vector(*xyz),\ visible=not np.isclose(np.linalg.norm(xyz), 0)) return vpts
def tidy_all(): cubic_meter = ex.width * ex2.width * ex.length while 1: rate(100) velocity = 0.05 if purplebox.pos.z > 0.25: purplebox.pos.z -= velocity if bluebox.pos.x > 0.25: bluebox.pos.x -= velocity if yellowbox.pos.x > -0.25 and yellowbox.pos.z > -0.25: yellowbox.pos.x -= velocity yellowbox.pos.z -= velocity if purplebox.pos.z < 0.25 and bluebox.pos.x < 0.25 and yellowbox.pos.x < -0.25 and yellowbox.pos.z < -0.25: cubic_meter = cubic_meter - ( yellowbox_cubic_meter + bluebox_cubic_meter + purplebox_cubic_meter + greenbox_cubic_meter) label( pos=vector(0, 2, 0), text= "Available cubic meter : {} m3 \r\n yellowbox : {} m3 \r\n bluebox: {} m3 \r\n purplebox: {} m3" .format(cubic_meter, yellowbox_cubic_meter, bluebox_cubic_meter, purplebox_cubic_meter)) if cubic_meter == 0: for o in [bluebox, purplebox, yellowbox, orangebox]: o.color = color.green elif cubic_meter < 0: for o in [bluebox, purplebox, yellowbox, orangebox]: o.color = color.red break
def create_viz(): global state, G scene = vp.canvas(background=vp.color.white) n = len(state.dims[0]) d = state.dims[0][0] coords = [ vp.vector(root.real, root.imag, 0) for root in [np.exp(1j * 2 * np.pi * i / d) for i in range(d)] ] colors = [vp.color.red, vp.color.green, vp.color.blue] if n == 3 else\ [vp.vector(*np.random.random(3)) for i in range(n)] vpts = {} for i in range(n): pov_state = take_pov(state, 0, i, G) vp.label(text="pov: %d" % i,\ pos=vp.vector(3*i-n,-1.5,0),\ color=colors[i]) vp.ring(color=colors[i],\ radius=1,\ axis=vp.vector(0,0,1),\ thickness=0.01,\ pos=vp.vector(3*i-n, 0, 0)) for k in range(n): partial = pov_state.ptrace(k).full() for j in range(d): vpts[(i, k, j)] = vp.sphere(opacity=0.5,\ pos=vp.vector(3*i-n,np.random.randn()/25,0)+coords[j],\ color=colors[k],\ radius=partial[j,j].real/4) return vpts
def draw_axis(Figures, max_coord): Figures.append( arrow( pos=vector(0,0,0), axis=vector(0,0,max_coord), shaftwidth=0.1)) Figures.append( label( pos=vector(0,0,max_coord/2), text='Z' )) #Z axis Figures.append( arrow( pos=vector(0,0,0), axis=vector(0,max_coord,0), shaftwidth=0.1)) Figures.append( label( pos=vector(0,max_coord/2,0), text='Y' )) #Y axis Figures.append( arrow( pos=vector(0,0,0), axis=vector(max_coord,0,0), shaftwidth=0.1)) Figures.append( label( pos=vector(max_coord/2,0,0), text='X' )) #X axis
def __init__(self, bodies = []): # Register the solar system bodies self.bodies = bodies # Make some visual objects to display in the scene self.time_label = vis.label(pixel_pos = vec(0, 0, 0), xoffset = 100, yoffset = -1 * (scene.height - 30), align = "left", box = True, line = False) self.controls_label = vis.label(pixel_pos = vec(0, 0, 0), xoffset = 300, yoffset = -1 * (scene.height - 71), text = "Controls\nScroll: zoom camera\nRight click + drag: orbit camera", align = "left", box = True, line = False, visible = False)
def _make_labels(theta, omega, dampening_coeff, acceleration_from_gravity, rod_length): """ Makes the VPython labels. """ equation_label = 'Angular Acceleration (\u03b1): \n\u03b1 = - D\u03c9 - (g/L)sin(\u03b8)' theta_label = f'Starting Theta (\u03b8) = {theta} \u00b0' omega_label = f'Starting Omega (\u03c9) = {omega} \u00b0/s' dampening_label = f'Damping Coeff (D) = {dampening_coeff}' gravity_label = f'Gravity (g) = {acceleration_from_gravity} m/s\u00b2' rod_label = f'Rod Length (L) = {rod_length} m' combined_label = '\n'.join((equation_label, '', theta_label, omega_label, dampening_label, gravity_label, rod_label)) label(pos=vector(0, rod_length / 2, 0), text=combined_label)
def __init__(self, radius=10.0, bodies=[]): self.radius = radius self.bodies = bodies self.base = vis.cylinder(pos=vec(0, 0, -2), axis=vec(0, 0, 1), radius=self.radius, color=vis.color.gray(0.6)) self.top_plate = vis.box(pos=vec(0, .5, -1), length=20, height=.25, width=1, color=vis.color.red) self.bottom_plate = vis.box(pos=vec(0, -.5, -1), length=20, height=.25, width=1, color=vis.color.blue) self.polarity = "up" self.e_field = vec(0, E_mag, 0) self.e_indicator = vis.arrow(pos=vec(-11, 0, 0), axis=vec(0, 2, 0), color=vis.color.yellow) self.b_field = vec(0, 0, -B_mag) # 1 mT in -z direction self.time_label = vis.label(pixel_pos=vec(0, 0, 0), xoffset=100, yoffset=-1 * (scene.height - 30), align="left", box=True, line=False)
def __init__(self, v, v_label, v_label_pos, v_color, v_pos): self.v = v # Vector self.v_label = v_label # Label for the vector self.v_color = v_color # Vector colour # Position of vector i.e. where its tail is. self.v_pos = v_pos # Axis of the cone; same as the vector's self.cone_axis = 0.1 * vp.norm(self.v) self.rod_radius = 0.02 # Absolute radius of the rod self.cone_radius = 0.06 # Absolute radius of the rod # Reduce the size of the rod by the axial size of the cone self.rod = vp.cylinder(pos=v_pos, axis=self.v - self.cone_axis, radius=self.rod_radius, color=v_color) # Place the base of the cone at the end of rod # which has been reduced by the cone's axial length self.cone = vp.cone(pos=self.v - self.cone_axis + v_pos, axis=self.cone_axis, radius=self.cone_radius, color=v_color) # Note where the tip of the cone is, # which will define the starting point of # of the axis line self.cone_tip = self.v + v_pos + 0.1 * vp.norm(self.v) self.axis_text = vp.label(text=v_label, pos=v_pos + v_label_pos * (self.cone_tip - v_pos), color=v_color, xoffset=3, yoffset=3, box=False)
def __init__( self, name="Electron", q=1.6e-19, # charge of the body in coulomb mass=9.109e-31, # mass of body in kg pos=vec(1, 0.0, 0.0), # x, y, z coordinates of the body in meters vel=vec(0.0, 0.0, 0.0), # vx, vy, vz of the body in m/s color=(1.0, 1.0, 1.0) # color of the body ): # Register properties of the body self.name = name self.q = q self.mass = mass self.pos = pos self.vel = vel self.color = color # Make vpython visual objects self.visual = vis.sphere(pos=pos, color=color, radius=0.01, axis=vec(0, 0, 1), make_trail=True, trail_type="curve", retain=500) self.info = vis.label(pos=self.visual.pos, xoffset=50, yoffset=-25, height=9, align="left", opacity=0.0, visible=True)
def dibujar_coordenada(self): cordenadas = label(pos=(self.Robot.pos + self.altura), text=str(self.Robot.pos), color=self.text_color, height=8, opacity=0.1) return cordenadas
def __init__(self, pos, mass, orbitalParentmass, orbitalParentpos, orbitalParentv): self.age = 0 self.mass = mass self.planet = sphere(pos=pos, radius=((3 * self.mass) / (4 * pi * 3000))**(1 / 3), make_trail=True, retain=5000) self.colorMe() self.G = 6.7e-11 r = orbitalParentpos.x - self.planet.pos.x rmag = abs(r) inner = self.G * orbitalParentmass / rmag self.v = vector( orbitalParentv.x, 0, orbitalParentv.z + (random.choice([-1, 1]) * math.sqrt(inner)) + random.randint(0, 100)) self.p = self.mass * self.v self.Vol = (4 * pi * (self.planet.radius**3)) / 3 self.name = (''.join( [random.choice(string.ascii_letters) for n in range(4)])).lower() self.name = self.name.capitalize() self.label = label(pos=self.planet.pos, height=16, yoffset=5, text=self.name + "\n" + str(int(mag(self.v))) + "m/s", line=False) print("New Planet " + self.name)
def __init__(self, name = "Orbital Body", mass = 1.0, # mass of the body in kg x = 0.0, y = 0.0, z = 0.0, # x, y, z coordinates of the body in meters vx = 0.0, vy = 0.0, vz = 0.0, # vx, vy, vz of the body in m/s radius = 1e8, # radius of the body in meters color = (1.0, 1.0, 1.0) # color of the body ): # Register properties of the body self.name = name self.mass = mass self.x = x self.y = y self.z = z self.vx = vx self.vy = vy self.vz = vz self.color = color self.radius = radius # Make vpython visual objects self.visual = vis.sphere(pos = vec(x, y, z), color = color, radius = radius, axis = vec(0, 0, 1), make_trail = True, trail_type = "curve", retain = 500) self.info = vis.label(pos = self.visual.pos, xoffset = 50, yoffset = -25, height = 9, align = "left", opacity = 0.0, visible = True)
def __make_label(self): self.label = label(text=self.__label_text(), align='left', height=20, pixel_pos=True, pos=vector(20, self.canvas.height - 100, 0), box=False)
def processClick(event): global seltile, tlabel, scene try: # Key pressed: s = event.key if s == 'c': for ob in simplist: ob.visible = False for ob in complist: ob.visible = True elif s == 's': for ob in complist: ob.visible = False for ob in simplist: ob.visible = True except AttributeError: # Mouse clicked: clickedpos = scene.mouse.project(normal=v( 0, 0, 1), d=0) # Mouse position projected onto XY plane if clickedpos: scene.center = clickedpos # Change the camera centre position ob = scene.mouse.pick try: name = ob.name if seltile is not None: seltile.color = color.green tlabel.visible = False del tlabel seltile = ob seltile.color = color.red tlabel = vpython.label(pos=v(seltile.pos.x, seltile.pos.y, seltile.pos.z + 10), text=name, height=15) except AttributeError: pass
def draw_label(label_text, label_position, scene): # pragma nocover """ Display a label at a given position, with borders and lines :param label_text: String of text to be written on the label. :type label_text: `str` :param label_position: 3D vector position to draw the label at. :type label_position: class:`vpython.vector` :param scene: The scene in which to draw the object :type scene: class:`vpython.canvas` :return: The created label object. :rtype: class:`vpython.label` """ # Custom settings for the label label_height = 10 label_xoffset = 0 label_yoffset = 50 label_space = 20 label_font = 'serif' label_text_colour = color.black label_line_color = color.black the_label = label(canvas=scene, pos=label_position, text=label_text, height=label_height, xoffset=label_xoffset, yoffset=label_yoffset, space=label_space, font=label_font, color=label_text_colour, linecolor=label_line_color) return the_label
def axes(frame, colour, sz, posn): # Make axes visible (of world or frame). # Use None for world. directions = [ vs.vector(sz, 0, 0), vs.vector(0, sz, 0), vs.vector(0, 0, sz) ] texts = ["X", "Y", "Z"] posn = vs.vector(posn) for i in range(3): # EACH DIRECTION vs.curve(frame=frame, color=colour, pos=[posn, posn + directions[i]]) vs.label(frame=frame, color=colour, text=texts[i], pos=posn + directions[i], opacity=0, box=False)
def __init__(self, draw_state: PhysicsState, *, title: str, running_as_mirror: bool) -> None: assert len(draw_state) >= 1 self._state = draw_state # create a vpython canvas, onto which all 3D and HTML drawing happens. self._scene = self._init_canvas(title) self._map_mode = False self._show_label: bool = True self._show_trails: bool = DEFAULT_TRAILS self._paused: bool = False self._removed_saveload_hint: bool = False self._origin: Entity self.texture_path: Path = Path('data', 'textures') self._commands: List[Request] = [] self._paused_label = vpython.label( text="Simulation paused; saving and loading enabled.\n" "When finished, unpause by setting a time acceleration.", xoffset=0, yoffset=200, line=False, height=25, border=20, opacity=1, visible=False) self._3dobjs: Dict[str, ThreeDeeObj] = {} # Remove vpython ambient lighting: self._scene.lights = [] # This line shouldn't be removed. self._set_origin(common.DEFAULT_CENTRE) # When very zoomed out, we only draw planets, scaled so that the # smallest planet is radius 1. self._map_scale_factor = np.inf for entity in draw_state: self._3dobjs[entity.name] = self._build_threedeeobj(entity) if entity.r < self._map_scale_factor: self._map_scale_factor = entity.r self._orbit_projection = OrbitProjection() self._sidebar = Sidebar(self, running_as_mirror) self._scene.bind('keydown', self._handle_keydown) # Add an animation when launching the program to describe the solar # system and the current location while self._scene.range > 600000: vpython.rate(100) self._scene.range = self._scene.range * 0.92 self._landing_graphic = LandingGraphic() self._landing_graphic.draw(self._3dobjs[draw_state.reference]) self.recentre_camera(common.DEFAULT_CENTRE)
def __init__(self, v_auf, v_orient, txt, p, *args, **kwargs): super(Vector_stat, self).__init__(*args, **kwargs) self.p = p if not v_auf == 0: x1 = get_v_arg(v_auf,0)*self.p y1 = get_v_arg(v_auf,1)*self.p z1 = get_v_arg(v_auf,2)*self.p else: x1 = 0. y1 = 0. z1 = 0. x2 = get_v_arg(v_orient,0)*self.p y2 = get_v_arg(v_orient,1)*self.p z2 = get_v_arg(v_orient,2)*self.p self.pos.x = x1 self.pos.y = y1 self.pos.z = z1 self.axis = vis.vector(x2,y2,z2) vis.label(pos=vis.vector(x1+x2-0.75, y1+y2-0.75,z1+z2-0.75), text=txt)
def mouseclick(m): global lab pickobj = scene.mouse.pick if pickobj: if lab: lab.visible = 0 lab = vpython.label(pos=pickobj.pos, xoffset=20, yoffset=20, text=pickobj.name) else: if lab: lab.visible = 0
def __init__(self, entity: Entity, origin: Entity, texture_path: Path) -> None: texture_path = texture_path / (entity.name + '.jpg') texture = str(texture_path) if texture_path.is_file() else None self._obj = self._create_obj(entity, origin, texture) assert self._obj is not None self._small_landing_graphic: Optional[vpython.compound] = None self._large_landing_graphic: Optional[vpython.compound] = None self._label = vpython.label( pos=self._obj.pos, xoffset=10, yoffset=10, border=4, font='sans', text=self._label_text(entity))
def __init__(self, entity: Entity, origin: Entity, texture_path: Path) -> None: texture_path = texture_path / (entity.name + '.jpg') texture = str(texture_path) if texture_path.is_file() else None self._obj = self._create_obj(entity, origin, texture) assert self._obj is not None self._label = vpython.label(pos=self._obj.pos, xoffset=10, yoffset=10, border=4, font='sans', text=entity.name)
def __axes(self): arrows = { 'pos': self.pos, 'length': 1.5 * self.radius, 'shaftwidth': self.radius / 100, 'headwidth': self.radius / 30, 'headlength': self.radius / 30, 'color': color.red } self._xarrow = arrow(axis=self._xaxis, **arrows) self._yarrow = arrow(axis=self._yaxis, **arrows) self._zarrow = arrow(axis=self._zaxis, **arrows) labels = {'box': False, 'opacity': 0} self._xarrow_label = label(text='X', pos=self.pos + self._xarrow.axis, **labels) self._yarrow_label = label(text='Y', pos=self.pos + self._yarrow.axis, **labels) self._zarrow_label = label(text='Z', pos=self.pos + self._zarrow.axis, **labels)
def __init__(self, entity: Entity, origin: Entity, texture_path: Path) -> None: texture_path = texture_path / (entity.name + '.jpg') texture = str(texture_path) if texture_path.is_file() else None self._obj = self._create_obj(entity, origin, texture) assert self._obj is not None self._label = vpython.label( pos=self._obj.pos, xoffset=10, yoffset=10, border=4, font='sans', text=self._label_text(entity)) # The object is made smaller by greater values of this. # The use of _scale_factor is when OrbitX goes into map mode. self._scale_factor = 1
def __init__(self, physicalEnvironment): self.logger = logging.getLogger(name='Quadsim.Visualizer') self.physEnv = physicalEnvironment self.obj = set() self.simFrames = 0 self.objUpdates = 0 self.canvas = v.display(title='Simulation', width=1024, height=768, background=(0.2,0.2,0.2)) self.canvas.select() self.controls = vc.controls(x=640, y=0, range=20) self.infoLabel = v.label(display=self.controls.display,pos=(-10,-10), text='Click simulation to start', line=False) self.lastFPSCheckTime = None self.lastFPS = 0.0 self.simTime = 0.0 self.fpsValues = [] self.geomLookup = {}
def draw_text(label_text, label_position, scene): """ Display a label at a given position, without borders or lines. :param label_text: String of text to be written on the label. :type label_text: `str` :param label_position: 3D vector position to draw the label at. :type label_position: class:`vpython.vector` :param scene: The scene in which to draw the object :type scene: class:`vpython.canvas` :return: The created label object. :rtype: class:`vpython.label` """ # Distance of camera from focus point to determine text size distance_from_center = mag(scene.center - scene.camera.pos) # Far away = smaller text, closer = larger text (up to a min (20) and max (40)) # Typically 5->20 units away # (eqn and limits modified to suit display better) = -1.3333 * distance_from_center + 46.6667 label_height = -1.3333 * distance_from_center + 36.6667 # Calculate label height label_height = max(min(label_height, 35), 10) # Limit to 10->35 label_xoffset = 0 label_yoffset = 0 label_space = 0 label_font = 'serif' label_text_colour = color.black label_line_color = color.white label_bg_opacity = 0 label_linewidth = 0.1 the_label = label(canvas=scene, pos=label_position, text=label_text, height=label_height, xoffset=label_xoffset, yoffset=label_yoffset, space=label_space, font=label_font, color=label_text_colour, linecolor=label_line_color, opacity=label_bg_opacity, linewidth=label_linewidth) return the_label
def test2(): from random import randint Rows = 10 Cols = 10 boxMat = dict() for row in range(Rows): for col in range(Cols): rand = randint(0, 10) boxMat[row, col] = label(pos=vec(row, col, 0), text=str(rand), value=rand) def metricFunc(listOfCells): """ metric function must return a list scalars based on a list of objects """ return [l.value for l in listOfCells] sortRectangle(boxMat, Rows, Cols, metricFunc)
def draw(lattice): lattice.logger.info("Hook6: Display water molecules with VPython.") lattice.logger.info(" Total number of atoms: {0}".format(len(lattice.atoms))) cellmat = lattice.repcell.mat offset = (cellmat[0] + cellmat[1] + cellmat[2]) / 2 # prepare the reverse dict waters = defaultdict(dict) for atom in lattice.atoms: resno, resname, atomname, position, order = atom if "O" in atomname: waters[order]["O"] = position - offset elif "H" in atomname: if "H0" not in waters[order]: waters[order]["H0"] = position - offset else: waters[order]["H1"] = position - offset for order, water in waters.items(): O = water["O"] H0 = water["H0"] H1 = water["H1"] lattice.vpobjects['w'].add(vp.simple_sphere(radius=0.03, pos=vp.vector(*O), color=vp.vector(1,0,0))) lattice.vpobjects['w'].add(vp.simple_sphere(radius=0.02, pos=vp.vector(*H0), color=vp.vector(0,1,1))) lattice.vpobjects['w'].add(vp.simple_sphere(radius=0.02, pos=vp.vector(*H1), color=vp.vector(0,1,1))) lattice.vpobjects['w'].add(vp.cylinder(radius=0.015, pos=vp.vector(*O), axis=vp.vector(*(H0-O)))) lattice.vpobjects['w'].add(vp.cylinder(radius=0.015, pos=vp.vector(*O), axis=vp.vector(*(H1-O)))) lattice.vpobjects['l'].add(vp.label(pos=vp.vector(*O), xoffset=30, text="{0}".format(order), visible=False)) for i,j in lattice.spacegraph.edges(data=False): if i in waters and j in waters: # edge may connect to the dopant O = waters[j]["O"] H0 = waters[i]["H0"] H1 = waters[i]["H1"] d0 = H0 - O d1 = H1 - O rr0 = np.dot(d0,d0) rr1 = np.dot(d1,d1) if rr0 < rr1 and rr0 < 0.27**2: lattice.vpobjects['a'].add(vp.arrow(shaftwidth=0.015, pos=vp.vector(*H0), axis=vp.vector(*(O-H0)), color=vp.vector(1,1,0))) if rr1 < rr0 and rr1 < 0.245**2: lattice.vpobjects['a'].add(vp.arrow(shaftwidth=0.015, pos=vp.vector(*H1), axis=vp.vector(*(O-H1)), color=vp.vector(1,1,0))) lattice.logger.info(" Tips: use keys to draw/hide layers. [3 4 5 6 7 8 a w l]") lattice.logger.info(" Tips: Type ctrl-C twice at the terminal to stop.") lattice.logger.info("Hook6: end.")
def draw_text(label_text, label_position, scene): # pragma nocover """ Display a label at a given position, without borders or lines. :param label_text: String of text to be written on the label. :type label_text: `str` :param label_position: 3D vector position to draw the label at. :type label_position: class:`vpython.vector` :param scene: The scene in which to draw the object :type scene: class:`vpython.canvas` :return: The created label object. :rtype: class:`vpython.label` """ label_height = get_text_size(scene) label_xoffset = 0 label_yoffset = 0 label_space = 0 label_font = 'serif' label_text_colour = color.black label_line_color = color.white label_bg_opacity = 0 label_linewidth = 0.1 the_label = label( canvas=scene, pos=label_position, text=label_text, height=label_height, xoffset=label_xoffset, yoffset=label_yoffset, space=label_space, font=label_font, color=label_text_colour, linecolor=label_line_color, opacity=label_bg_opacity, linewidth=label_linewidth ) return the_label
def __init__(self, posicion, velocidad, masa, radio, nombre, conversion: dict): self.posicion = posicion self.velocidad = velocidad self.etiqueta = vp.label(pos=posicion, text=nombre, color=vp.vector(0.1, 1, 0.7), opacity=0.7, height=15, box=0) self.masa = masa self.radio = radio self.conversion = conversion #Se crea a esfera en VPython que representa a la particula self.esfera = vp.sphere(pos=posicion, radius=radio, color=vp.vector(*conversion[str(380)]), make_trail=True, shininess=0, masa=masa, velocidad=velocidad, trail_radius=(0.02))
def __init__( self, mass=1, GM=1, radius=1, velocity=vector(0, 0, 0), position=vector(0, 0, 0), color=color.white, trail=True, name="Body", scale=True, index=0, ): self.mass = mass self.GM = GM self.velocity = velocity self.position = position self.temp_position = position self.k = [] self.xv = conVec(0, 0) # self.sum_forces = vector(0,0,0) self.color = color self.radius = radius self.acc = vector( 0, 0, 0 ) # gravitational_acc(self.position) # approximate the initial acceleration for Verlet self.name = name self.label = label(pos=self.position, text=self.name, height=10) self.index = index self.sphere = sphere( pos=self.position, color=self.color, radius=self.radius, make_trail=trail, retain=200, index=self.index, ) self.scale = scale
def __simulate_scenario(self): """ Simulates the given scenario. """ self._scene.height = self._screen_height - self._controls.scene_height_sub if self._controls.start_time == 'now': self._start_time = datetime.datetime.utcnow() self._start_time -= datetime.timedelta(microseconds=self._start_time.microsecond) else: self._start_time = self._controls.start_time self._time = self._start_time self._time_stamp = label(text=f'Datetime: {self._time} UTC', align='left', height=20, pixel_pos=True, box=False, pos=vector(20, self._scene.height-28, 0)) while self._controls.scenario_running: self._spheres = self._controls.spheres self._dt = self._controls.dt self._collisions = self._controls.collisions # According to .../vpython/rate_control.py line 19: # Unresolved bug: rate(X) yields only about 0.8X iterations per second. rate(self._controls.time_rate_seconds/(0.8*self._dt)) if self._scene.height != self._screen_height - self._controls.scene_height_sub: self._scene.height = self._screen_height - self._controls.scene_height_sub self._time_stamp.pos = vector(20, self._scene.height-28, 0) if self._controls.labelled_sphere: self._controls.labelled_sphere.label.pos = vector(20, self._scene.height-100, 0) if self._controls.running: self._massives = [sph for sph in self._spheres if sph.massive] self.__update_spheres() self._time += datetime.timedelta(seconds=self._dt) self._time_stamp.text = f'Datetime: {self._time} UTC'