def test_init_with_override(self): line = geom.Line(geom.STVector(0, 1, precision=7), geom.STVector(2, 3, precision=7), precision=5, tag='test') self.assertEqual(line.precision(), 5) self.assertEqual(line.tag, 'test')
def test_copy_ctor(self): stvec = geom.STVector(2, 3, tag='test', precision=4, draw_options={'color': 'red'}) stvec_cpy = geom.STVector(stvec) self.assertEqual(stvec.t, stvec_cpy.t) self.assertEqual(stvec.x, stvec_cpy.x) self.assertEqual(stvec.tag, 'test') self.assertEqual(stvec.precision, stvec_cpy.precision) self.assertEqual(stvec.draw_options, {'color': 'red'})
def test_draw_in_bounds(self): p = _MockSTPlotter() geom.STVector(3, 4, tag='test', draw_options={'color': 'red'}).draw(p) self.assertEqual(len(p.points), 1) self.assertEqual(len(p.segments), 0) self.assertEqual(len(p.polygons), 0) self.assertEqual(p.points[0], ((3, 4), 'test', {'color': 'red'})) self.assertEqual(p.tlim, (3, 3)) self.assertEqual(p.xlim, (4, 4))
def test_in_bounds_exact_equality(self): self.assertTrue(geom.STVector(2, 3)._in_bounds((2, 2), (3, 3)))
def setUp(self): self.original = geom.STVector(2, 3) self.transformed = geom.lorentz_transformed(self.original, 3 / 5)
#!/usr/bin/env python3 import sys sys.path.append('..') import specrel.geom as geom import specrel.visualize as vis # Set up "simultaneous events" xvals = [-0.5, 0, 0.5] colors = ['red', 'green', 'blue'] points = geom.PointGroup([ geom.STVector(0, x, draw_options={'color': c}) for x, c in zip(xvals, colors) ]) # Compare spacetime diagrams in different frames v = 4 / 5 # Relative velocity between frames tlim = (-0.75, 0.75) xlim = (-1, 1) markersize = 20 title = '"Simultaneous" events in different frames' plotters = vis.compare_frames(points, v, tlim=tlim, xlim=xlim, title=title, markersize=markersize) p = plotters[0] p.save('4-simultaneity.png') p.show()
def test_str(self): self.assertEqual(str(geom.STVector(2, 3)), 'STVector(2, 3)')
def test_eq(self): self.assertEqual(geom.STVector(2, 3), (2, 3))
import sys sys.path.append('..') import specrel.geom as geom import specrel.spacetime.physical as phy import specrel.visualize as vis # Plot a spacetime grid tlim = (-5, 5) xlim = (-5, 5) stgrid = phy.stgrid(tlim, xlim) plotter = vis.stplot( stgrid, title= 'Spacetime diagram\n(Also known as "Minkowski" or "Worldline" diagram)', lim_padding=0) plotter.save('1-spacetime_grid.png') plotter.show() # Plot a spacetime event tlim = (0, 2) xlim = (-2, 2) event = geom.STVector(1, 1, draw_options={'label': 'Event'}) p = vis.stplot(event, title='An event in spacetime', tlim=tlim, xlim=xlim, grid=True, legend=True) p.save('1-spacetime_event.png') p.show()
def test_lorentz_transform_origin_1_1(self): stvec = geom.STVector(3, 4) stvec.lorentz_transform(3 / 5, origin=(1, 1)) self.assertAlmostEqual(stvec.t, 1 / 4 + 1) self.assertAlmostEqual(stvec.x, 9 / 4 + 1)
def test_init_from_timepos(self): stvec = geom.STVector(2, 3) self.assertEqual(stvec.t, 2) self.assertEqual(stvec.x, 3)
def test_abs(self): self.assertEqual(abs(geom.STVector(2, 3)), 5)
def test_lorentz_transform(self): stvec = geom.STVector(2, 3) stvec.lorentz_transform(3 / 5) self.assertAlmostEqual(stvec.t, 1 / 4) self.assertAlmostEqual(stvec.x, 9 / 4)
def test_add(self): self.assertEqual(geom.STVector(2, 3) + geom.STVector(3, 3), (5, 6))
def test_neg(self): self.assertEqual(-geom.STVector(2, 3), geom.STVector(-2, -3))
def test_eq_within_precision(self): self.assertEqual(geom.STVector(2, 3, precision=3), (2.0001, 3)) self.assertNotEqual(geom.STVector(2, 3, precision=3), (2.001, 3))
def test_append(self): self.collection.append(geom.STVector(5, 5)) self.assertEqual(len(self.collection), 4) self.assertEqual(self.collection[3], (5, 5))
def test_init_from_iterable(self): stvec = geom.STVector((2, 3)) self.assertEqual(stvec.t, 2) self.assertEqual(stvec.x, 3)
def test_str_within_precision(self): self.assertEqual(str(geom.STVector(2.001, 2.999, precision=3)), 'STVector(2.001, 2.999)') self.assertEqual(str(geom.STVector(2.0001, 2.9999, precision=3)), 'STVector(2.0, 3.0)')
def test_copy_ctor_with_override(self): stvec = geom.STVector(2, 3, precision=4) stvec_cpy = geom.STVector(stvec, precision=6, tag='test') self.assertEqual(stvec_cpy.precision, 6) self.assertEqual(stvec_cpy.tag, 'test')
def test_cannot_append(self): self.assertRaises(TypeError, geom.Line((0, 1), (2, 3)).append, geom.STVector(1, 1))
def test_iter(self): for cmp, answer in zip(geom.STVector(2, 3), [2, 3]): self.assertEqual(cmp, answer)
def test_draw_out_of_bounds(self): p = _MockSTPlotter() geom.STVector(3, 4).draw(p, tlim=(4, 5)) self.assertEqual(len(p.points), 0) self.assertEqual(len(p.segments), 0) self.assertEqual(len(p.polygons), 0)
def test_auto_draw_lims(self): self.assertEqual( geom.STVector(2, 3)._auto_draw_lims(), ((2, 2), (3, 3)))
def test_getitem(self): stvec = geom.STVector(2, 3) self.assertEqual(stvec[0], 2) self.assertEqual(stvec[1], 3)
def test_in_bounds(self): stvec = geom.STVector(2, 3) self.assertTrue(stvec._in_bounds((0, 3), (2, 4))) self.assertFalse(stvec._in_bounds((3, 4), (1, 2)))
draw_options=closed_draw_options) # Exact event of closing/opening each door close_event_draw_options = { 'color': 'red', 'marker': 'v', 'markersize': 10, 'label': 'Close door', } open_event_draw_options = { 'color': 'limegreen', 'marker': '^', 'markersize': 10, 'label': 'Open door', } left_close_event = geom.STVector(t_transition, garage.left_pos(t_transition), draw_options=close_event_draw_options) right_open_event = geom.STVector(t_transition, garage.right_pos(t_transition), draw_options=open_event_draw_options) # Synthesize the scene scene = geom.Collection([ garage, ladder, left_closed, right_closed, left_close_event, right_open_event, ]) tlim = (t_start, t_end) xlim = (ladder_left_start - ladder_length, ladder.right_pos(t_end)) # Plot the frames legend = True
def test_in_bounds_within_precision(self): stvec1 = geom.STVector(2.0001, 3.0001, precision=3) self.assertTrue(stvec1._in_bounds((0, 2), (2, 3))) stvec2 = geom.STVector(2.001, 3.001, precision=3) self.assertFalse(stvec2._in_bounds((0, 2), (2, 3)))
t_return = rocket_backward_alltime.time_for_left_pos(origin) rocket_backward = geom.line_segment((t_turnaround, x_planet), (t_return, 0), draw_options={ 'color': 'darkorange', 'marker': '<', 'markersize': 5, 'linestyle': ':', 'label': 'Traveler (backward)', } ) # Mark events turnaround_event = geom.STVector(t_turnaround, x_planet, draw_options={ 'color': 'green', 'marker': '*', 'markersize': 10, 'label': 'Turning around', } ) return_event = geom.STVector(t_return, origin, draw_options={ 'color': 'red', 'marker': '*', 'markersize': 10, 'label': 'Arrive home', } ) # Collect scene scene = geom.Collection([ earth, planet,
def gradient_line(point1, point2, color1, color2, divisions=100, extrapolate_color=True, draw_options=geom.geomrc['draw_options']): """A line with a color gradient. The gradient transition will happen over a finite range in spacetime, and be monochromatic at either end. Args: point1 (specrel.geom.STVector or iterable): Starting point of the gradient. point2 (specrel.geom.STVector or iterable): Ending point of the gradient. color1 (color): A Matplotlib color for the gradient starting color. color2 (color): A Matplotlib color for the gradient ending color. divisions (int, optional): The number of line segment divisions in the gradient. More divisions means a smoother gradient. extrapolate_color (bool, optional): Flag for whether or not to extrapolate the color gradient across the line past the specified endpoints so that the color change spans as far as possible across the line. draw_options (dict, optional): See `specrel.geom.LorentzTransformable`. Returns: specrel.geom.Collection: Collection containing the color gradient increments, in the order: 1. `specrel.geom.Ray` before `point1` with `color1`. 2. Line segments changing color from `point1` to `point2`. 3. `specrel.geom.Ray` after `point2` with `color2`. """ # Copy draw_options and remove color if it's there draw_options = dict(draw_options) draw_options.pop('color', None) # If extrapolating color, calculate the color gradient extremes if extrapolate_color: point1, point2, color1, color2, divisions = _colorgrad_extremes( point1, point2, color1, color2, divisions) # Color gradient calculator for the given points and colors def this_colorgrad(x): return _calc_colorgrad(x, point1, point2, color1, color2) # Line direction vector direc = geom.STVector(point2) - geom.STVector(point1) grad = geom.Collection() # Monochromatic ray at the tail end of the gradient line grad.append( geom.Ray(-direc, point1, draw_options={ 'color': color1, **draw_options })) # The line segments comprising the color gradient for i in range(divisions): start_point, _ = this_colorgrad(i / divisions) end_point, _ = this_colorgrad((i + 1) / divisions) _, grad_color = this_colorgrad((i + 1 / 2) / divisions) grad.append( geom.line_segment(start_point, end_point, draw_options={ 'color': grad_color, **draw_options })) # Monochromatic ray at the head end of the gradient line grad.append( geom.Ray(direc, point2, draw_options={ 'color': color2, **draw_options })) return grad