def test_D_scalar(self): D_scalar = 1 * um * um / ms D_tensor = [ 1 * um * um / ms, 0 * um * um / ms, 0 * um * um / ms, 0 * um * um / ms, 1 * um * um / ms, 0 * um * um / ms, 0 * um * um / ms, 0 * um * um / ms, 1 * um * um / ms ] species = sycomore.Species(1 * ms, 100 * ms, D_scalar) self.assertSequenceEqual(species.D, D_tensor) species = sycomore.Species(1 * ms, 100 * ms) species.D = D_scalar self.assertSequenceEqual(species.D, D_tensor)
def test_diffusion(self): model = sycomore.como.Model( sycomore.Species(0 * Hz, 0 * Hz, 1 * um * um / ms), sycomore.Magnetization(0, 0, 1), [["foo", sycomore.TimeInterval(500 * ms, 0.1 * rad / um)]]) model.apply_pulse(sycomore.Pulse(40 * deg, 0 * deg)) model.apply_time_interval("foo") grid = model.magnetization() for index, _ in sycomore.GridScanner(grid.origin(), grid.shape()): if index == sycomore.Index(-1): self.assertEqual(grid[index].p, 0) self.assertEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0 + 0.003062528150606j) elif index == sycomore.Index(0): self.assertEqual(grid[index].p, 0) self.assertAlmostEqual(grid[index].z, 0.766044443118978) self.assertEqual(grid[index].m, 0) elif index == sycomore.Index(1): self.assertAlmostEqual(grid[index].p, 0 - 0.003062528150606j) self.assertEqual(grid[index].z, 0) self.assertEqual(grid[index].m, 0) else: self.assertEqual(grid[index].p, 0) self.assertAlmostEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0)
def test_gradient_multiple(self): species = sycomore.Species(1000*ms, 100*ms, 3*um**2/ms) model = sycomore.epg.Regular(species, unit_gradient_area=1*mT/m*ms) model.apply_pulse(47*deg, 23*deg) model.shift(1*ms, 1*mT/m) self._test_model( model, [ [0, 0, 0.6819983600624985], [0.2857626571584661-0.6732146319308543j, 0, 0]]) model.shift(2*ms, 1*mT/m) self._test_model( model, [ [0, 0, 0.6819983600624985], [0, 0, 0], [0, 0, 0], [0.2857626571584661-0.6732146319308543j, 0, 0]]) model.shift(1*ms, -1*mT/m) self._test_model( model, [ [0, 0, 0.6819983600624985], [0, 0, 0], [0.2857626571584661-0.6732146319308543j, 0, 0]]) with self.assertRaises(Exception): model.shift(1.5*ms, 1*mT/m)
def test_gradient_default(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species) model.apply_pulse(47 * deg, 23 * deg) model.shift() self._test_model(model, [[0, 0, 0.6819983600624985], [0.2857626571584661 - 0.6732146319308543j, 0, 0]])
def test_relaxation(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species) model.apply_pulse(47 * deg, 23 * deg) model.shift() model.relaxation(10 * ms) self._test_model(model, [[0, 0, 0.6851625292479138], [0.2585687448743616 - 0.6091497893403431j, 0, 0]])
def test_apply_time_interval_field_off_resonance(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species, unit_gradient_area=10 * mT / m * ms) model.delta_omega = 10 * Hz model.apply_pulse(47 * deg, 23 * deg) model.apply_time_interval(10 * ms, 2 * mT / m) self._test_model(model, [[0, 0, 0.6851625292479138], [0, 0, 0], [0.56707341067384409 - 0.34073208057155585j, 0, 0]])
def test_off_resonance(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species) model.delta_omega = 10 * Hz model.apply_pulse(47 * deg, 23 * deg) model.shift() model.off_resonance(10 * ms) self._test_model(model, [[0, 0, 0.6819983600624985], [0.6268924782754024 - 0.37667500256027975j, 0, 0]])
def test_quantity_constructor_partial(self): species = sycomore.Species(1 * ms, 0.01 * kHz, R2_prime=1. / (15 * ds)) self.assertEqual(species.R1, 1. * kHz) self.assertEqual(species.T1, 1. * ms) self.assertEqual(species.R2, 10. * Hz) self.assertEqual(species.T2, 0.1 * s) self.assertEqual(species.D[0], 0 * m * m / s) self.assertEqual(species.R2_prime, (1 / 1.5) * Hz) self.assertEqual(species.T2_prime, 1.5 * s) self.assertEqual(species.delta_omega, 0 * rad / s) self.assertEqual(species.w, 1)
def test_quantity_constructor_full(self): species = sycomore.Species(1 * ms, 0.01 * kHz, 3 * um * um / ms, 1. / (15 * ds), 0.9 * rad / s, 1.1) self.assertEqual(species.R1, 1. * kHz) self.assertEqual(species.T1, 1. * ms) self.assertEqual(species.R2, 10. * Hz) self.assertEqual(species.T2, 0.1 * s) self.assertEqual(species.D[0], 3e-9 * m * m / s) self.assertEqual(species.R2_prime, (1 / 1.5) * Hz) self.assertEqual(species.T2_prime, 1.5 * s) self.assertEqual(species.delta_omega, 0.9 * rad / s) self.assertEqual(species.w, 1.1)
def test_D_tensor(self): D = [ 1 * um * um / ms, 4 * um * um / ms, 7 * um * um / ms, 2 * um * um / ms, 5 * um * um / ms, 8 * um * um / ms, 3 * um * um / ms, 6 * um * um / ms, 9 * um * um / ms ] species = sycomore.Species(1 * ms, 100 * ms, sycomore.Array[sycomore.Quantity](D)) self.assertSequenceEqual(species.D, D) species = sycomore.Species(1 * ms, 100 * ms, D) self.assertSequenceEqual(species.D, D) species = sycomore.Species(1 * ms, 100 * ms) species.D = sycomore.Array[sycomore.Quantity](D) self.assertSequenceEqual(species.D, D) species.D = D self.assertSequenceEqual(species.D, D)
def test_apply_time_interval_species_off_resonance(self): model = sycomore.epg.Discrete( sycomore.Species(self.species.R1, self.species.R2, self.species.D, delta_omega=10 * Hz)) model.apply_pulse(47 * deg, 23 * deg) model.apply_time_interval(10 * ms, 2 * mT / m) self._test_model(model, [0 * rad / m, 5350 * rad / m], [[0, 0, 0.6851625292479138], [0.56707341067384409 - 0.34073208057155585j, 0, 0]])
def test_diffusion(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species, unit_gradient_area=20 * mT / m * ms) model.apply_pulse(47 * deg, 23 * deg) model.shift() model.relaxation(10 * ms) model.diffusion(10 * ms, 2 * mT / m) self._test_model(model, [[0, 0, 0.6851625292479138], [0.25805111586158685 - 0.60793033180597855j, 0, 0]])
def test_apply_time_interval_species_off_resonance(self): species = sycomore.Species(1000*ms, 100*ms, 3*um**2/ms, delta_omega=10*Hz) model = sycomore.epg.Regular(species, unit_gradient_area=10*mT/m*ms) model.delta_omega = -10*Hz model.apply_pulse(47*deg, 23*deg) model.apply_time_interval(10*ms, 2*mT/m) self._test_model( model, [ [0, 0, 0.6851625292479138], [0, 0, 0], [0.2584947343504123-0.6089754314724013j, 0, 0]])
def test_apply_time_interval_both_off_resonance(self): model = sycomore.epg.Discrete( sycomore.Species(self.species.R1, self.species.R2, self.species.D, delta_omega=10 * Hz)) model.delta_omega = -10 * Hz model.apply_pulse(47 * deg, 23 * deg) model.apply_time_interval(10 * ms, 2 * mT / m) self._test_model(model, [0 * rad / m, 5350 * rad / m], [[0, 0, 0.6851625292479138], [0.2584947343504123 - 0.6089754314724013j, 0, 0]])
def setUp(self): self.species = sycomore.Species(1000*ms, 100*ms, 0.89*um*um/ms) self.m0 = sycomore.Magnetization(0, 0, 1) self.flip_angle = 40*deg self.pulse_duration = 1*ms self.pulse_support_size = 101 self.zero_crossings = 2 self.TR = 500*ms self.slice_thickness = 1*mm self.TR_count = 10
def test_time_interval(self): species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms) model = sycomore.epg.Regular(species, unit_gradient_area=10 * mT / m * ms) model.apply_pulse(47 * deg, 23 * deg) model.apply_time_interval(10 * ms, 2 * mT / m) self._test_model(model, [[0, 0, 0.6851625292479138], [0, 0, 0], [0.2584947343504123 - 0.6089754314724013j, 0, 0]]) model.apply_time_interval(10 * ms, -2 * mT / m) self._test_model(model, [[ 0.23382875968307784 - 0.5508660366970124j, 0.23382875968307784 + 0.5508660366970124j, 0.6882952144238884 ]])
def test_off_resonance(self): species = sycomore.Species(0 * Hz, 0 * Hz, 0 * um * um / ms) m0 = sycomore.Magnetization(0, 0, 1) pulse = sycomore.Pulse(90 * deg, math.pi * rad) pulse_duration = 1 * ms pulse_support_size = 101 zero_crossings = 2 # NOTE: in the absence of relaxation and diffusion, the TR is meaningless TR = 500 * ms slice_thickness = 1 * mm t0 = pulse_duration / (2 * zero_crossings) sinc_pulse = sycomore.HardPulseApproximation( pulse, sycomore.linspace(pulse_duration, pulse_support_size), sycomore.sinc_envelope(t0), 1 / t0, slice_thickness, "rf") refocalization = sycomore.TimeInterval( (TR - pulse_duration) / 2., -sinc_pulse.get_gradient_moment() / 2) model = sycomore.como.Model( species, m0, [["rf", sinc_pulse.get_time_interval()], ["refocalization", refocalization]]) model.apply_pulse(sinc_pulse) model.apply_time_interval("refocalization") frequencies = sycomore.linspace(60. * rad / ms, 201) magnetization = [ model.isochromat(set(), sycomore.Point(), f) for f in frequencies ] root = os.environ["SYCOMORE_TEST_DATA"] with open(os.path.join(root, "baseline", "off_resonance.dat"), "rb") as fd: contents = fd.read() baseline = struct.unpack((int(len(contents) / 8)) * "d", contents) self.assertEqual(len(baseline), 2 * len(magnetization)) for i in range(len(magnetization)): self.assertAlmostEqual(sycomore.transversal(magnetization[i]), baseline[2 * i]) self.assertAlmostEqual(magnetization[i][2], baseline[2 * i + 1])
def test_pulse(self): model = sycomore.como.Model( sycomore.Species(1 * s, 0.1 * s), sycomore.Magnetization(0, 0, 1), [["dummy", sycomore.TimeInterval(0 * s)]]) model.apply_pulse(sycomore.Pulse(41 * deg, 27 * deg)) grid = model.magnetization() for index, _ in sycomore.GridScanner(grid.origin(), grid.shape()): if index == sycomore.Index(0): self.assertAlmostEqual(grid[index].p, 0.210607912662250 - 0.413341301933443j) self.assertAlmostEqual(grid[index].z, 0.754709580222772) self.assertAlmostEqual(grid[index].m, 0.210607912662250 + 0.413341301933443j) else: self.assertEqual(grid[index].p, 0) self.assertAlmostEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0)
def update(): start = time.time() slice_thickness = 1 * mm document = bokeh.plotting.curdoc() T1 = document.get_model_by_id("T1").value * ms T2 = document.get_model_by_id("T2").value * ms flip_angle = document.get_model_by_id("flip_angle").value * deg TE = document.get_model_by_id("TE").value * ms TR = document.get_model_by_id("TR").value * ms species = sycomore.Species(T1, T2) repetitions = int(4 * species.T1 / TR) phase_steps = sycomore.linspace(0 * deg, 180 * deg, 100) steady_states = [ rf_spoiling(sycomore.epg.Regular(species), flip_angle, TE, TR, slice_thickness, phase_step, repetitions)[-1] for phase_step in phase_steps ] magnitude_data = document.get_model_by_id("magnitude_data") magnitude_data.data = { "x": [x.convert_to(deg) for x in phase_steps], "y": [numpy.abs(x) for x in steady_states] } ideal_spoiling = compute_ideal_spoiling(species, flip_angle, TR) ideal_spoiling_data = document.get_model_by_id("ideal_spoiling_data") ideal_spoiling_data.data = { "x": (phase_steps[0].convert_to(deg), phase_steps[-1].convert_to(deg)), "y": (ideal_spoiling, ideal_spoiling) } stop = time.time() document.get_model_by_id("runtime").text = "Runtime: {}".format( utils.to_eng_string(stop - start, "s", 3))
def test_time_interval(self): species = sycomore.Species(1000*ms, 100*ms, 3*um**2/ms) model = sycomore.epg.Regular(species, unit_gradient_area=10*mT/m*ms) model.apply_pulse(47*deg, 23*deg) model.apply_time_interval(10*ms, 2*mT/m) self._test_model( model, [ [0, 0, 0.6851625292479138], [0, 0, 0], [0.2584947343504123-0.6089754314724013j, 0, 0]]) model.apply_time_interval(10*ms, -2*mT/m) self._test_model( model, [ [ 0.23262696138115807-0.5480347773241918j, 0.23262696138115807+0.5480347773241918j, 0.6882952144238884]])
def update(): start = time.time() slice_thickness = 1*mm document = bokeh.plotting.curdoc() T1 = document.get_model_by_id("T1").value*ms T2 = document.get_model_by_id("T2").value*ms flip_angle = document.get_model_by_id("flip_angle").value*deg TE = document.get_model_by_id("TE").value*ms TR = document.get_model_by_id("TR").value*ms phase_step = document.get_model_by_id("phase_step").value*deg species = sycomore.Species(T1, T2) model = sycomore.epg.Regular(species) repetitions = int(4*species.T1/TR) echoes = rf_spoiling( model, flip_angle, TE, TR, slice_thickness, phase_step, repetitions) magnitude_data = document.get_model_by_id("magnitude_data") magnitude_data.data = { "x": range(repetitions), "y": numpy.abs(echoes) } ideal_spoiling = compute_ideal_spoiling(species, flip_angle, TR) ideal_spoiling_data = document.get_model_by_id("ideal_spoiling_data") ideal_spoiling_data.data = { "x": (0, repetitions), "y": (ideal_spoiling, ideal_spoiling) } stop = time.time() document.get_model_by_id("runtime").text = "Runtime: {}".format( utils.to_eng_string(stop-start, "s", 1))
def test_pulse_profile(self): species = sycomore.Species(0*Hz, 0*Hz, 0*um*um/ms) m0 = sycomore.Magnetization(0, 0, 1) pulse = sycomore.Pulse(90*deg, math.pi*rad) pulse_duration = 1*ms pulse_support_size = 101 zero_crossings = 2 # NOTE: in the absence of relaxation and diffusion, the TR is meaningless TR = 500*ms; slice_thickness = 1*mm; sampling_support_size = 501 t0 = pulse_duration/(2*zero_crossings) sinc_pulse = sycomore.HardPulseApproximation( pulse, sycomore.linspace(pulse_duration, pulse_support_size), sycomore.sinc_envelope(t0), 1/t0, slice_thickness, "rf") refocalization = sycomore.TimeInterval( (TR-pulse_duration)/2., -sinc_pulse.get_gradient_moment()/2) sampling_locations = sycomore.linspace( sycomore.Point(0*m, 0*m, 2*slice_thickness), sampling_support_size) model = sycomore.como.Model( species, m0, [ ["rf", sinc_pulse.get_time_interval()], ["refocalization", refocalization]]) model.apply_pulse(sinc_pulse) before_refocalization = [ model.isochromat(set(), p) for p in sampling_locations] model.apply_time_interval("refocalization") after_refocalization = [ model.isochromat(set(), p) for p in sampling_locations] root = os.environ["SYCOMORE_TEST_DATA"] with open(os.path.join(root, "baseline", "pulse_profile.dat"), "rb") as fd: contents = fd.read() baseline = struct.unpack((int(len(contents)/8))*"d", contents) self.assertEqual(len(baseline), 2*3*len(sampling_locations)) for i in range(len(sampling_locations)): m_test = before_refocalization[i] m_baseline = baseline[3*i:3*(i+1)] self.assertAlmostEqual(m_test[0], m_baseline[0]) self.assertAlmostEqual(m_test[1], m_baseline[1]) self.assertAlmostEqual(m_test[2], m_baseline[2]) for i in range(len(sampling_locations)): m_test = after_refocalization[i] m_baseline = baseline[ 3*(i+len(sampling_locations)):3*(i+len(sampling_locations)+1)] self.assertAlmostEqual(m_test[0], m_baseline[0]) self.assertAlmostEqual(m_test[1], m_baseline[1]) self.assertAlmostEqual(m_test[2], m_baseline[2])
def test_empty(self): species = sycomore.Species(1000*ms, 100*ms) model = sycomore.epg.Regular(species) self._test_model(model, [[0,0,1]])
def update(): start = time.time() document = bokeh.plotting.curdoc() T1 = document.get_model_by_id("T1").value * ms T2 = document.get_model_by_id("T2").value * ms excitation = document.get_model_by_id("excitation").value * deg TE = document.get_model_by_id("TE").value * ms refocalization = document.get_model_by_id("refocalization").value * deg train_length = document.get_model_by_id("train_length").value TR = document.get_model_by_id("TR").value * ms repetitions = document.get_model_by_id("repetitions").value species = sycomore.Species(T1, T2) m0 = [0., 0., 1., 1.] voxel_size = 1 * mm positions_count = 192 steps = 1 + int(repetitions * TR / time_step) times = sycomore.linspace(0 * s, repetitions * TR, steps) excitation = sycomore.bloch.pulse(excitation, 90 * deg) refocalization = sycomore.bloch.pulse(refocalization, 0 * rad) positions = sycomore.linspace(voxel_size, positions_count) gradient = ( 2 * numpy.pi * rad / sycomore.gamma # T*s / voxel_size # T*s/m / (TE / 2)) time_intervals = numpy.asarray([ sycomore.bloch.time_interval(species, time_step, gradient_amplitude=gradient, position=position) for position in positions ]) magnetizations = numpy.full((positions_count, steps, 4), m0) # WARNING: floating-point modulo arithmetic is not reliable (pulses are # missed). Switch to integer arithmetic in ms; this assumes that # time_step >= 2*ms. TE_ms = int(numpy.round(TE.convert_to(ms))) TR_ms = int(numpy.round(TR.convert_to(ms))) for step, t in enumerate(times[:-1]): t_in_TR = int(numpy.round(t.convert_to(ms))) % TR_ms t_in_TE = t_in_TR % TE_ms if t_in_TR == 0 and step != len(times) - 1: pulse = excitation elif t_in_TE == TE_ms // 2: echo = (t_in_TR - TE_ms // 2) // TE_ms if echo < train_length: pulse = refocalization else: pulse = numpy.identity(4) else: pulse = numpy.identity(4) magnetizations[:, step + 1] = numpy.einsum("ij,oj->oi", pulse, magnetizations[:, step]) magnetizations[:, step + 1] = numpy.einsum("oij,oj->oi", time_intervals, magnetizations[:, step + 1]) signals = [m[:, 0] + 1j * m[:, 1] for m in magnetizations] phases = numpy.angle(signals) times_ms = [x.convert_to(ms) for x in times] magnitude_data = document.get_model_by_id("magnitude_data") magnitude_data.data = { "x": times_ms, "y": numpy.abs(numpy.mean(signals, axis=0)) } phase_data = document.get_model_by_id("phase_data") phase_data.data = { "x": times_ms, "y_min": numpy.min(phases, axis=0), "y_max": numpy.max(phases, axis=0) } stop = time.time() document.get_model_by_id("runtime").text = "Runtime: {}".format( utils.to_eng_string(stop - start, "s", 1))
def update(): start = time.time() slice_thickness = 1 * mm document = bokeh.plotting.curdoc() pulse_support_size = 101 T1 = document.get_model_by_id("T1").value * ms T2 = document.get_model_by_id("T2").value * ms flip_angle = document.get_model_by_id("flip_angle").value * deg duration = document.get_model_by_id("duration").value * ms zero_crossings = document.get_model_by_id("zero_crossings").value t0 = duration / (2 * zero_crossings) support = sycomore.linspace(duration, pulse_support_size) envelope = sycomore.sinc_envelope(t0) bandwidth = 1 / t0 sinc_pulse = sycomore.HardPulseApproximation( sycomore.Pulse(flip_angle, 0 * deg), support, envelope, bandwidth, slice_thickness, "") gradient_duration = sinc_pulse.get_time_interval().duration gradient_amplitude = (sinc_pulse.get_time_interval().gradient_moment[2] / (2 * numpy.pi * sycomore.gamma) / sinc_pulse.get_time_interval().duration) species = sycomore.Species(T1, T2) model = sycomore.epg.Discrete3D(species) for index, hard_pulse in enumerate(sinc_pulse.get_pulses()): model.apply_pulse(hard_pulse.angle, hard_pulse.phase) model.apply_time_interval(gradient_duration, [0 * T / m, 0 * T / m, gradient_amplitude]) # Unfold the F and the Z states: create an array for all orders, including # empty ones. max_order = numpy.max(model.orders, axis=0)[2] max_bin = int(max_order / model.bin_width) F = numpy.zeros(2 * max_bin + 1, model.states.dtype) Z = numpy.zeros(2 * max_bin + 1, model.states.dtype) for order, state in zip(model.orders, model.states): bin = int(order[2] / model.bin_width) # WARNING: since we de-bin the orders, we need to scale the population F[bin] = F.shape[0] * state[0] Z[bin] = F.shape[0] * state[2] if order != 0: F[-bin] = F.shape[0] * state[1].conj() Z[-bin] = F.shape[0] * state[2] # Perform iFFT, and shift it since the spatial axis must be centered on zero. M_transversal = numpy.fft.fftshift(numpy.fft.ifft(F)) M_longitudinal = numpy.fft.fftshift(numpy.fft.ifft(Z)) # Frequency ranges from -max_order to +max_order: the spatial step size # is then given by the following expression. step = (1 / (2 * max_order)).convert_to(mm) x_axis = step * numpy.arange(len(M_transversal)) x_axis -= 0.5 * (x_axis[0] + x_axis[-1]) # Crop between [-slice_thickness, +slice_thickness] slice_ = ( numpy.searchsorted(x_axis, -slice_thickness.convert_to(mm), "left"), numpy.searchsorted(x_axis, +slice_thickness.convert_to(mm), "right"), ) x_axis = x_axis[slice_[0]:slice_[1]] M_transversal = M_transversal[slice_[0]:slice_[1]] M_longitudinal = M_longitudinal[slice_[0]:slice_[1]] transversal_data = document.get_model_by_id("transversal_data") transversal_data.data = {"x": x_axis, "y": numpy.abs(M_transversal)} longitudinal_data = document.get_model_by_id("longitudinal_data") longitudinal_data.data = {"x": x_axis, "y": numpy.abs(M_longitudinal)} stop = time.time() document.get_model_by_id("runtime").text = "Runtime: {}".format( utils.to_eng_string(stop - start, "s", 3))
def test_time_interval(self): model = sycomore.como.Model( sycomore.Species(math.log(2) * Hz, math.log(2) * Hz), sycomore.Magnetization(0, 0, 1), [["foo", sycomore.TimeInterval(1 * s)], ["bar", sycomore.TimeInterval(1 * s)]]) model.apply_pulse(sycomore.Pulse(45 * deg, 90 * deg)) model.apply_time_interval("foo") grid = model.magnetization() for index, _ in sycomore.GridScanner(grid.origin(), grid.shape()): if index == sycomore.Index(-1, 0): self.assertEqual(grid[index].p, 0) self.assertEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0.25) elif index == sycomore.Index(0, 0): self.assertEqual(grid[index].p, 0) self.assertEqual(grid[index].z, 0.5 * (1 + math.sqrt(2) / 2)) self.assertEqual(grid[index].m, 0) elif index == sycomore.Index(1, 0): self.assertAlmostEqual(grid[index].p, 0.25) self.assertEqual(grid[index].z, 0) self.assertEqual(grid[index].m, 0) else: self.assertEqual(grid[index].p, 0) self.assertAlmostEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0) model.apply_time_interval("bar") grid = model.magnetization() for index, _ in sycomore.GridScanner(grid.origin(), grid.shape()): if index == sycomore.Index(-1, -1): self.assertEqual(grid[index].p, 0) self.assertEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0.125) elif index == sycomore.Index(0, 0): self.assertEqual(grid[index].p, 0) self.assertEqual(grid[index].z, 0.5 + 0.25 * (1 + math.sqrt(2) / 2)) self.assertEqual(grid[index].m, 0) elif index == sycomore.Index(1, 1): self.assertAlmostEqual(grid[index].p, 0.125) self.assertEqual(grid[index].z, 0) self.assertEqual(grid[index].m, 0) else: self.assertEqual(grid[index].p, 0) self.assertAlmostEqual(grid[index].z, 0) self.assertAlmostEqual(grid[index].m, 0) isochromat = model.isochromat() self.assertAlmostEqual(isochromat[0], 0.125 * math.sqrt(2)) self.assertAlmostEqual(isochromat[1], 0) self.assertAlmostEqual(isochromat[2], 0.5 + 0.25 * (1 + math.sqrt(2) / 2)) isochromat = model.isochromat( {sycomore.Index(0, 0), sycomore.Index(-1, -1)}) self.assertAlmostEqual(isochromat[0], 0.125 * math.sqrt(2) / 2) self.assertAlmostEqual(isochromat[1], 0) self.assertAlmostEqual(isochromat[2], 0.5 + 0.25 * (1 + math.sqrt(2) / 2))
def setUp(self): self.species = sycomore.Species(1000 * ms, 100 * ms, 3 * um**2 / ms)