Пример #1
0
 def test_init(self):
     c = RunnableController("mri", "/tmp")
     c.add_part(self.o)
     self.process.add_controller(c)
     b = c.block_view()
     assert list(b.configure.takes.elements) == [
         'generator', 'fileDir', 'axesToMove', 'formatName', 'fileTemplate'
     ]
Пример #2
0
 def setUp(self):
     self.o = SimultaneousAxesPart(value=["x", "y"])
     self.process = Process("proc")
     self.process.start()
     self.addCleanup(self.process.stop, 2)
     c = RunnableController("mri", "/tmp")
     c.add_part(self.o)
     self.process.add_controller(c)
     self.b = c.block_view()
Пример #3
0
 def setUp(self):
     self.o = UnrollingPart(name="Unroll")
     self.process = Process("proc")
     self.process.start()
     self.addCleanup(self.process.stop, 2)
     c = RunnableController("mri", "/tmp")
     c.add_part(self.o)
     self.process.add_controller(c)
     self.b = c.block_view()
Пример #4
0
 def setUp(self):
     self.o = UnrollingPart(name="Unroll",
                            mri="mri",
                            initial_visibility=True)
     self.process = Process("proc")
     self.process.start()
     self.addCleanup(self.process.stop, 2)
     self.config_dir = tmp_dir("config_dir")
     c = RunnableController("mri", self.config_dir.value)
     c.add_part(self.o)
     self.process.add_controller(c)
     self.b = c.block_view()
Пример #5
0
    def test_real(self):
        c = RunnableController(mri="top", config_dir="/tmp")
        c.add_part(self.o)

        class ValidatePart(Part):
            data = []

            def setup(self, registrar):
                super(ValidatePart, self).setup(registrar)
                self.register_hooked(ValidateHook, self.validate)

            @add_call_types
            def validate(self, part_info):
                # type: (APartInfo) -> None
                self.data.append(part_info)

        c.add_part(ValidatePart("validate"))
        self.process.add_controller(c)
        c.block_view().validate(CompoundGenerator([], [], []))
        assert len(ValidatePart.data) == 1
        assert list(ValidatePart.data[0]) == ["scan"]
        assert len(ValidatePart.data[0]["scan"]) == 1
Пример #6
0
 def test_init(self):
     self.o = HDFWriterPart(name="m", mri="BLOCK:HDF5")
     self.context.set_notify_dispatch_request(
         self.o.notify_dispatch_request)
     c = RunnableController("mri", self.config_dir.value)
     c.add_part(self.o)
     self.process.add_controller(c)
     b = c.block_view()
     assert list(b.configure.meta.takes.elements) == [
         "generator",
         "fileDir",
         "axesToMove",
         "breakpoints",
         "formatName",
         "fileTemplate",
     ]
Пример #7
0
class TestPandaPulseTriggerPart(ChildTestCase):
    def setUp(self):
        self.process = Process("Process")
        self.context = Context(self.process)

        # Create a fake PandA with a pulse block
        self.panda = ManagerController("PANDA", "/tmp")
        controller = BasicController("PANDA:PULSE3")
        self.pulse_part = PulsePart("part")
        controller.add_part(self.pulse_part)
        self.process.add_controller(controller)
        self.panda.add_part(
            ChildPart("PULSE3",
                      "PANDA:PULSE3",
                      initial_visibility=True,
                      stateful=False))
        self.process.add_controller(self.panda)

        # And the detector
        self.config_dir = tmp_dir("config_dir")
        for c in detector_block("DET", config_dir=self.config_dir.value):
            self.process.add_controller(c)

        # Make the child block holding panda and pmac mri
        self.child = self.create_child_block(
            panda_pulse_trigger_block,
            self.process,
            mri="SCAN:PULSE",
            panda="PANDA",
            detector="DET",
        )

        # And our part under test
        self.o = PandAPulseTriggerPart("detTrigger", "SCAN:PULSE")

        # Add in a scan block
        self.scan = RunnableController("SCAN", "/tmp")
        self.scan.add_part(DetectorChildPart("det", "DET", True))
        self.scan.add_part(self.o)
        self.process.add_controller(self.scan)

        # Now start the process off and tell the panda which sequencer tables
        # to use
        self.process.start()
        exports = ExportTable.from_rows([
            ("PULSE3.width", "detTriggerWidth"),
            ("PULSE3.step", "detTriggerStep"),
            ("PULSE3.delay", "detTriggerDelay"),
            ("PULSE3.pulses", "detTriggerPulses"),
        ])
        self.panda.set_exports(exports)
        self.tmpdir = tempfile.mkdtemp()

    def tearDown(self):
        self.process.stop(timeout=2)
        shutil.rmtree(self.tmpdir)
        shutil.rmtree(self.config_dir.value)

    def check_pulse_mocks(self, width, step, delay, pulses):
        self.pulse_part.mocks["width"].assert_called_once_with(
            pytest.approx(width))
        self.pulse_part.mocks["step"].assert_called_once_with(
            pytest.approx(step))
        self.pulse_part.mocks["delay"].assert_called_once_with(
            pytest.approx(delay))
        self.pulse_part.mocks["pulses"].assert_called_once_with(pulses)

    def test_configure_multiple_no_exposure(self):
        xs = LineGenerator("x", "mm", 0.0, 0.3, 4)
        ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
        generator = CompoundGenerator([ys, xs], [], [], 1.0)
        generator.prepare()
        detectors = DetectorTable.from_rows([[True, "det", "DET", 0.0, 5]])
        self.o.on_configure(self.context, generator, detectors)
        assert self.o.generator_duration == 1.0
        assert self.o.frames_per_step == 5
        # Detector would normally be configured by DetectorChildPart
        detector = self.process.block_view("DET")
        spg = StaticPointGenerator(5, axes=["det_frames_per_step"])
        ex = SquashingExcluder(axes=["det_frames_per_step", "x"])
        generatormultiplied = CompoundGenerator([ys, xs, spg], [ex], [], 0.2)
        detector.configure(generatormultiplied, self.tmpdir)

        self.o.on_post_configure()

        self.check_pulse_mocks(0.19899, 0.2, 0.000505, 5)

    def test_configure_multiple_no_exposure_with_zero_delay(self):
        xs = LineGenerator("x", "mm", 0.0, 0.3, 4)
        ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
        generator = CompoundGenerator([ys, xs], [], [], 1.0)
        generator.prepare()
        detectors = DetectorTable.from_rows([[True, "det", "DET", 0.0, 5]])
        # Set delay to zero (normally done in constructor)
        self.o.zero_delay = True
        self.o.on_configure(self.context, generator, detectors)
        assert self.o.generator_duration == 1.0
        assert self.o.frames_per_step == 5
        # Detector would normally be configured by DetectorChildPart
        detector = self.process.block_view("DET")
        spg = StaticPointGenerator(5, axes=["det_frames_per_step"])
        ex = SquashingExcluder(axes=["det_frames_per_step", "x"])
        generatormultiplied = CompoundGenerator([ys, xs, spg], [ex], [], 0.2)
        detector.configure(generatormultiplied, self.tmpdir)

        self.o.on_post_configure()

        self.check_pulse_mocks(0.19899, 0.2, 0.0, 5)

    def test_system(self):
        xs = LineGenerator("x", "mm", 0.0, 0.3, 4)
        ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
        generator = CompoundGenerator([ys, xs], [], [], 1.0)
        generator.prepare()
        detectors = DetectorTable.from_rows([[True, "det", "DET", 0.0, 5]])

        b = self.scan.block_view()
        b.configure(generator, self.tmpdir, detectors=detectors)

        self.check_pulse_mocks(0.19899, 0.2, 0.000505, 5)

    def test_system_defined_exposure(self):
        xs = LineGenerator("x", "mm", 0.0, 0.3, 4)
        ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
        generator = CompoundGenerator([ys, xs], [], [], 1.0)
        generator.prepare()
        detectors = DetectorTable.from_rows([[True, "det", "DET", 0.1, 5]])

        b = self.scan.block_view()
        b.configure(generator, self.tmpdir, detectors=detectors)

        self.check_pulse_mocks(0.1, 0.2, 0.05, 5)

    def test_on_validate_tweaks_zero_duration(self):
        points = StaticPointGenerator(10)
        generator = CompoundGenerator([points], [], [], 0.0)
        generator.prepare()
        # Disable the detector
        detectors = DetectorTable.from_rows([[False, "det", "DET", 0.0, 5]])
        # Expected duration is 2 clock cycles
        expected_duration = 2 * 8.0e-9

        b = self.scan.block_view()
        params = b.validate(generator, self.tmpdir, detectors=detectors)

        self.assertEqual(expected_duration, params["generator"]["duration"])

    def test_on_validate_raises_AssertionError_for_negative_duration(self):
        xs = LineGenerator("x", "mm", 0.0, 0.3, 4)
        ys = LineGenerator("y", "mm", 0.0, 0.1, 2)
        generator = CompoundGenerator([ys, xs], [], [], -1.0)
        generator.prepare()
        # Disable the detector
        detectors = DetectorTable.from_rows([[False, "det", "DET", 0.0, 5]])

        b = self.scan.block_view()
        self.assertRaises(AssertionError,
                          b.validate,
                          generator,
                          self.tmpdir,
                          detectors=detectors)