def test_get_instance_stream(self): instance_manager = get_test_pipeline_manager_with_real_cam() instance_manager.stop_all_instances() self.assertTrue( len(instance_manager.get_info()["active_instances"]) == 0, "There should be no running instances.") pipeline_id = "test_pipeline" pipeline_config = PipelineConfig( pipeline_id, parameters={"camera_name": "simulation"}) instance_manager.config_manager.save_pipeline_config( pipeline_id, pipeline_config.get_configuration()) instance_stream_1 = instance_manager.get_instance_stream(pipeline_id) self.assertTrue( instance_manager.get_info()["active_instances"][pipeline_id] ["read_only"], "Instance should be read only.") with self.assertRaisesRegex( ValueError, "Cannot set config on a read only instance."): instance_manager.get_instance(pipeline_id).set_parameter({}) instance_stream_2 = instance_manager.get_instance_stream(pipeline_id) self.assertEqual(instance_stream_1, instance_stream_2, "Only one instance should be present.") instance_manager.stop_all_instances()
def test_both_rois(self): pipeline_config = PipelineConfig("test_pipeline") simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() parameters = pipeline_config.get_configuration() camera_name = simulated_camera.get_name() parameters["roi_signal"] = [0, 200, 0, 200] parameters["roi_background"] = [0, 200, 0, 200] for i in range(10): result = process_image(image=image, pulse_id=i, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) required_fields_in_result = [ camera_name + ".processing_parameters", camera_name + '.roi_signal_x_profile', # camera_name + '.edge_position', # camera_name + '.cross_correlation_amplitude', camera_name + '.roi_background_x_profile' ] self.assertSetEqual(set(required_fields_in_result), set(result.keys()), "Not all required keys are present in the result")
def test_noop_pipeline(self): pipeline_config = PipelineConfig("test_pipeline") simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() parameters = pipeline_config.get_configuration() result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) required_fields_in_result = ['x_center_of_mass', 'x_axis', 'y_axis', 'x_profile', 'y_fit_standard_deviation', 'y_rms', 'timestamp', 'y_profile', 'image', 'max_value', 'x_fit_offset', 'x_fit_gauss_function', 'y_center_of_mass', 'min_value', 'y_fit_mean', 'x_fit_mean', 'x_rms', 'y_fit_amplitude', 'x_fit_amplitude', 'y_fit_gauss_function', 'x_fit_standard_deviation', 'y_fit_offset', "processing_parameters", "intensity"] self.assertSetEqual(set(required_fields_in_result), set(result.keys()), "Not all required keys are present in the result") self.assertTrue(numpy.array_equal(result["image"], image), "The input and output image are not the same, but the pipeline should not change it.") self.assertDictEqual(parameters, json.loads(result["processing_parameters"]), "The passed and the received processing parameters are not the same.")
def test_background_roi(self): pipeline_config = PipelineConfig("test_pipeline") simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() parameters = pipeline_config.get_configuration() camera_name = simulated_camera.get_name() parameters["roi_background"] = [0, 200, 0, 200] result = process_image(image=image, pulse_id=0, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) required_fields_in_result = [ camera_name + ".processing_parameters", camera_name + '.roi_background_x_profile' ] self.assertSetEqual(set(required_fields_in_result), set(result.keys()), "Not all required keys are present in the result")
def test_collect_background(self): instance_manager = get_test_pipeline_manager_with_real_cam() instance_manager.background_manager = BackgroundImageManager( self.background_folder) pipeline_id = "test_pipeline" number_of_images = 10 pipeline_config = PipelineConfig( pipeline_id, parameters={"camera_name": "simulation"}) instance_manager.config_manager.save_pipeline_config( pipeline_id, pipeline_config.get_configuration()) pipeline_stream_address = instance_manager.get_instance_stream( pipeline_id) pipeline_host, pipeline_port = get_host_port_from_stream_address( pipeline_stream_address) # Collect from the pipeline. with source(host=pipeline_host, port=pipeline_port, mode=SUB) as stream: data = stream.receive() self.assertIsNotNone(data, "This should really not happen anymore.") camera_name = instance_manager.get_instance( pipeline_id).get_info()["camera_name"] background_id = instance_manager.collect_background( camera_name, number_of_images) self.assertTrue(background_id.startswith("simulation"), "Background id not as expected.") host, port = get_host_port_from_stream_address( instance_manager.cam_server_client.get_instance_stream( "simulation")) # Collect from the camera. with source(host=host, port=port, mode=SUB) as stream: data = stream.receive() self.assertIsNotNone(data, "This should really not happen anymore.") self.assertEqual( instance_manager.background_manager.get_background( background_id).shape, data.data.data["image"].value.shape, "Background and image have to be of the same shape.") self.assertEqual( instance_manager.background_manager.get_background( background_id).dtype, data.data.data["image"].value.dtype, "Background and image have to be of the same dtype.") instance_manager.stop_all_instances()
def test_invalid_pipeline_type(self): configuration = {"camera_name": "simulation"} expanded_configuration = PipelineConfig.expand_config(configuration) PipelineConfig.validate_pipeline_config(expanded_configuration) expanded_configuration["pipeline_type"] = "invalid" with self.assertRaisesRegex( ValueError, "pipeline_type 'invalid' not present in mapping. Available:"): PipelineConfig.validate_pipeline_config(expanded_configuration)
def test_invalid_number_of_slices(self): configuration = { "camera_name": "simulation", "image_slices": { "number_of_slices": 1.2 } } expanded_configuration = PipelineConfig.expand_config(configuration) with self.assertRaisesRegex(ValueError, "number_of_slices must be an integer"): PipelineConfig.validate_pipeline_config(expanded_configuration)
def test_wrong_background_size(self): pipeline_parameters = { "camera_name": "simulation", "image_background": "white_background" } simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() background_provider = MockBackgroundManager() # Invalid background size. background_provider.save_background("white_background", numpy.zeros(shape=(100, 100)), append_timestamp=False) parameters = PipelineConfig("test_pipeline", pipeline_parameters).get_configuration() image_background_array = background_provider.get_background("white_background") with self.assertRaisesRegex(RuntimeError, "Invalid background_image size "): process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters, image_background_array=image_background_array)
def test_store_pipeline_with_simulated_camera(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() self.client.stop_all_instances() pipeline_config = PipelineConfig("test_pipeline") def send(): store_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12003, MockBackgroundManager()) thread = Thread(target=send) thread.start() sleep(0.5) with source(host="127.0.0.1", port=12003, mode=PULL, receive_timeout=3000) as stream: data = stream.receive() self.assertIsNotNone(data, "Receiving timeout.") required_keys = set(["simulation" + config.EPICS_PV_SUFFIX_IMAGE]) self.assertSetEqual( required_keys, set(data.data.data.keys()), "Missing required keys in pipeline output bsread message.") stop_event.set() thread.join()
def create_pipeline(self, pipeline_name=None, configuration=None, instance_id=None): """ Create the pipeline stream address. Either pass the pipeline name, or the configuration. :param pipeline_name: Name of the pipeline to load from config. :param configuration: Configuration to load the pipeline with. :param instance_id: Name to assign to the instace. It must be unique. :return: instance_id, Pipeline stream address. """ # User specified or random uuid as the instance id. if not instance_id: instance_id = str(uuid.uuid4()) if self.is_instance_present(instance_id): raise ValueError("Instance with id '%s' is already present and running. " "Use another instance_id or stop the current instance " "if you want to reuse the same instance_id." % instance_id) if (not pipeline_name) and (not configuration): raise ValueError("You must specify either the pipeline name or the configuration for the pipeline.") if pipeline_name: pipeline_config = self.config_manager.load_pipeline(pipeline_name) if configuration is not None: pipeline_config.update( configuration ) else: pipeline_config = PipelineConfig(instance_id, configuration) self._create_and_start_pipeline(instance_id, pipeline_config, read_only_pipeline=False) pipeline_instance = self.get_instance(instance_id) return pipeline_instance.get_instance_id(), pipeline_instance.get_stream_address()
def test_expand_pipeline_config(self): configuration = { "camera_name": "simulation", "image_slices": { "number_of_slices": None, "scale": 7 } } expanded_configuration = PipelineConfig.expand_config(configuration) self.assertEqual( expanded_configuration["image_slices"]["number_of_slices"], PipelineConfig.DEFAULT_IMAGE_SLICES["number_of_slices"], "Default not applied.") self.assertEqual(expanded_configuration["pipeline_type"], PipelineConfig.DEFAULT_CONFIGURATION["pipeline_type"], "Default not applied.") configuration = {"camera_name": "simulation", "image_slices": None} expanded_configuration = PipelineConfig.expand_config(configuration) self.assertIsNone(expanded_configuration["image_slices"], "It should still be None.") configuration = {"camera_name": "simulation", "image_slices": {}} expanded_configuration = PipelineConfig.expand_config(configuration) self.assertDictEqual(expanded_configuration["image_slices"], PipelineConfig.DEFAULT_IMAGE_SLICES, "Image slices defaults not applied.") configuration = { "camera_name": "simulation", "image_background_enable": None } expanded_configuration = PipelineConfig.expand_config(configuration) self.assertEqual( expanded_configuration["image_background_enable"], PipelineConfig.DEFAULT_CONFIGURATION["image_background_enable"], "Default value not applied. It should not be None.")
def run_the_pipeline(configuration, simulated_image=None): parameters = PipelineConfig("test_pipeline", configuration).get_configuration() simulated_camera = CameraSimulation(CameraConfig("simulation")) if simulated_image is None: simulated_image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() return process_image(image=simulated_image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters)
def test_default_config(self): configuration = { "camera_name": "simulation", "image_background": "test_background", "image_good_region": {} } configuration = PipelineConfig("test", configuration) complete_config = configuration.get_configuration() self.assertIsNone(complete_config["image_slices"], "This section should be None.") self.assertSetEqual(set(complete_config["image_good_region"].keys()), set(["threshold", "gfscale"])) configuration = { "camera_name": "simulation", "image_good_region": {}, "image_slices": {} } configuration = PipelineConfig("test", configuration) complete_config = configuration.get_configuration() self.assertSetEqual(set(complete_config["image_good_region"].keys()), set(["threshold", "gfscale"]), "Missing keys in camera calibration.") self.assertSetEqual(set(complete_config["image_slices"].keys()), set(["number_of_slices", "scale", "orientation"]), "Missing keys in camera calibration.")
def test_image_threshold(self): simulated_camera = get_simulated_camera() image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() x_size, y_size = simulated_camera.get_geometry() pipeline_parameters = { "camera_name": "simulation", "image_threshold": 9999999 } pipeline_config = PipelineConfig("test_pipeline", pipeline_parameters) parameters = pipeline_config.get_configuration() result = process_image(image, 0, time.time(), x_axis, y_axis, parameters) expected_image = numpy.zeros(shape=(y_size, x_size), dtype="uint16") self.assertTrue(numpy.array_equal(result["image"], expected_image), "An image of zeros should have been produced.") pipeline_parameters = { "camera_name": "simulation", "image_threshold": 0 } pipeline_config = PipelineConfig("test_pipeline", pipeline_parameters) parameters = pipeline_config.get_configuration() result = process_image(image, 0, time.time(), x_axis, y_axis, parameters) self.assertTrue(numpy.array_equal(result["image"], image), "The image should be the same as the original image.")
def create_pipeline(self, pipeline_name=None, configuration=None, instance_id=None): """ If both pipeline_name and configuration are set, pipeline is create from name and configuration field added as additional config parameters """ status = self.get_status() if (not pipeline_name) and (not configuration): raise ValueError("You must specify either the pipeline name or the configuration for the pipeline.") if pipeline_name is not None: cfg = self.config_manager.get_pipeline_config(pipeline_name) elif configuration is not None: cfg = PipelineConfig.expand_config(configuration) PipelineConfig.validate_pipeline_config(cfg) server,port = None,None if instance_id is not None: server = self.get_server(instance_id, status) if server is None: (server,port) = self.get_server_for_pipeline(pipeline_name, cfg, status) if port: if not configuration: configuration = {} configuration["port"] = port self._check_background(server, cfg) self._check_script(server, cfg) if pipeline_name is not None: server.save_pipeline_config(pipeline_name, cfg) _logger.info("Creating stream from name %s at %s" % (pipeline_name, server.get_address())) instance_id, stream_address = server.create_instance_from_name(pipeline_name, instance_id, configuration) elif cfg is not None: _logger.info("Creating stream from config to camera %s at %s" % (str(cfg.get("camera_name")), server.get_address())) instance_id, stream_address = server.create_instance_from_config(cfg, instance_id) else: raise Exception("Invalid parameters") return instance_id, stream_address
def test_image_background(self): pipeline_parameters = { "camera_name": "simulation", "image_background": "white_background" } simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() background_provider = MockBackgroundManager() x_size, y_size = simulated_camera.get_geometry() background_provider.save_background("white_background", numpy.zeros(shape=(y_size, x_size)), append_timestamp=False) pipeline_config = PipelineConfig("test_pipeline", pipeline_parameters) parameters = pipeline_config.get_configuration() image_background_array = background_provider.get_background(parameters.get("image_background")) result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters, image_background_array=image_background_array) self.assertTrue(numpy.array_equal(result["image"], image), "A zero background should not change the image.") max_value_in_image = result["max_value"] pipeline_parameters = { "camera_name": "simulation", "image_background": "max_background", "image_threshold": 0 } max_background = numpy.zeros(shape=(y_size, x_size), dtype="uint16") max_background.fill(max_value_in_image) background_provider.save_background("max_background", max_background, append_timestamp=False) pipeline_config = PipelineConfig("test_pipeline", pipeline_parameters) parameters = pipeline_config.get_configuration() image_background_array = background_provider.get_background(parameters.get("image_background")) expected_image = numpy.zeros(shape=(y_size, x_size)) result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters, image_background_array=image_background_array) self.assertTrue(numpy.array_equal(result["image"], expected_image), "The image should be all zeros - negative numbers are not allowed.")
def test_pipeline_background_manager(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() pipeline_config = PipelineConfig("test_pipeline", parameters={ "camera_name": "simulation", "image_background": "full_background", "image_background_enable": True, "image_threshold": 0 }) background_manager = MockBackgroundManager() with self.assertRaises(Exception): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12000, background_manager) simulated_camera_shape = (960, 1280) background_array = numpy.zeros(shape=simulated_camera_shape) background_array.fill(99999) background_manager.save_background("full_background", background_array, append_timestamp=False) def send(): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12000, background_manager) thread = Thread(target=send) thread.start() with source(host="127.0.0.1", port=12000, mode=SUB) as stream: data = stream.receive() self.assertIsNotNone(data, "Received None message.") self.assertTrue( numpy.array_equal(data.data.data["image"].value, numpy.zeros(shape=simulated_camera_shape))) stop_event.set() thread.join()
def get_instance_stream_from_config(self, configuration): pipeline_config = PipelineConfig(None, parameters=configuration) instance_id = self._find_instance_id_with_config(pipeline_config) if self.is_instance_present(instance_id): return instance_id, self.get_instance(instance_id).get_stream_address() else: # If the instance is not present, it was deleted because it was stopped. instance_id = None if instance_id is None: instance_id = str(uuid.uuid4()) self._create_and_start_pipeline(instance_id, pipeline_config, read_only_pipeline=True) return instance_id, self.get_instance(instance_id).get_stream_address()
def test_intensity(self): simulated_camera = get_simulated_camera() image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() parameters = PipelineConfig("test_pipeline", { "camera_name": "simulation" }).get_configuration() result = process_image(image, 0, time.time(), x_axis, y_axis, parameters) x_sum = result["x_profile"].sum() y_sum = result["y_profile"].sum() # The sums of X and Y profile should always give us the same result as the intensity. self.assertAlmostEqual(x_sum, result["intensity"], delta=10000) self.assertAlmostEqual(y_sum, result["intensity"], delta=10000)
def test_system_exit(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() pipeline_config = PipelineConfig("test_pipeline", parameters={ "camera_name": "simulation", "image_background": "full_background", "image_background_enable": True, "image_threshold": 0 }) background_manager = MockBackgroundManager() with self.assertRaises(SystemExit): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12001, background_manager)
def test_profiles(self): height = 10 width = 10 square_start = 4 square_end = 6 n_pixels = square_end - square_start pixel_value = 10000 image = numpy.zeros((height, width), dtype="uint16") x_axis = numpy.linspace(0, width - 1, width, dtype='f') y_axis = numpy.linspace(0, height - 1, height, dtype='f') parameters = PipelineConfig("test_pipeline", { "camera_name": "simulation" }).get_configuration() # Add signal in the center image[square_start:square_end, square_start:square_end] = 10000 result = process_image(image, 0, time.time(), x_axis, y_axis, parameters) x_profile = result["x_profile"] y_profile = result["y_profile"] numpy.testing.assert_array_equal(x_profile[0:square_start], numpy.zeros(shape=square_start)) numpy.testing.assert_array_equal( x_profile[square_start:square_end], numpy.zeros(shape=n_pixels) + (n_pixels * pixel_value)) numpy.testing.assert_array_equal(x_profile[square_end], numpy.zeros(shape=width - square_end)) numpy.testing.assert_array_equal(y_profile[0:square_start], numpy.zeros(shape=square_start)) numpy.testing.assert_array_equal( y_profile[square_start:square_end], numpy.zeros(shape=n_pixels) + (n_pixels * pixel_value)) numpy.testing.assert_array_equal( y_profile[square_end], numpy.zeros(shape=height - square_end))
def test_pipeline_with_simulation_camera(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() pipeline_config = PipelineConfig("test_pipeline") def send(): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12000, MockBackgroundManager()) thread = Thread(target=send) thread.start() with source(host="127.0.0.1", port=12000, mode=SUB, receive_timeout=3000) as stream: data = stream.receive() self.assertIsNotNone(data, "Received None message.") required_keys = set([ 'x_fit_standard_deviation', 'x_axis', 'y_fit_standard_deviation', 'x_center_of_mass', 'x_fit_amplitude', 'y_fit_mean', 'processing_parameters', 'timestamp', 'y_fit_gauss_function', 'y_profile', 'y_center_of_mass', 'x_fit_gauss_function', 'x_rms', 'y_rms', 'y_fit_amplitude', 'image', 'y_axis', 'min_value', 'x_fit_mean', 'max_value', 'x_fit_offset', 'x_profile', 'y_fit_offset', 'width', 'height', 'intensity', "x_fwhm", "y_fwhm" ]) self.assertSetEqual( required_keys, set(data.data.data.keys()), "Missing required keys in pipeline output bsread message.") stop_event.set() thread.join()
def test_transparent_pipeline(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() pipeline_config = PipelineConfig("test_pipeline", parameters={ "camera_name": "simulation", "function": "transparent" }) def send(): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12004, MockBackgroundManager()) thread = Thread(target=send) thread.start() with source(host="127.0.0.1", port=12004, mode=SUB, receive_timeout=3000) as stream: data = stream.receive() self.assertIsNotNone(data, "Received None message.") required_keys = set([ "image", "timestamp", "width", "height", "x_axis", "y_axis", "processing_parameters" ]) self.assertSetEqual( required_keys, set(data.data.data.keys()), "Missing required keys in pipeline output bsread message.") stop_event.set() thread.join(5.0)
def test_region_of_interest_default_values(self): simulated_camera = CameraSimulation(CameraConfig("simulation")) image = simulated_camera.get_image() x_axis, y_axis = simulated_camera.get_x_y_axis() parameters = PipelineConfig("test_pipeline", { "camera_name": "simulation" }).get_configuration() good_region_keys = set(["good_region", "gr_x_axis", "gr_y_axis", "gr_x_fit_gauss_function", "gr_x_fit_offset", "gr_x_fit_amplitude", "gr_x_fit_standard_deviation", "gr_x_fit_mean", "gr_y_fit_gauss_function", "gr_y_fit_offset", "gr_y_fit_amplitude", "gr_y_fit_standard_deviation", "gr_y_fit_mean", "gr_intensity", "gr_x_profile", "gr_y_profile"]) slices_key_formats = set(["slice_%s_center_x", "slice_%s_center_y", "slice_%s_standard_deviation", "slice_%s_intensity"]) result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) self.assertFalse(any((x in result for x in good_region_keys)), 'There should not be good region keys.') parameters = PipelineConfig("test_pipeline", { "camera_name": "simulation", "image_good_region": { "threshold": 99999 } }).get_configuration() result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) self.assertTrue(all((x in result for x in good_region_keys)), 'There should be good region keys.') self.assertTrue(all((result[x] is None for x in good_region_keys)), 'All values should be None.') number_of_slices = 7 parameters = PipelineConfig("test_pipeline", { "camera_name": "simulation", "image_good_region": { "threshold": 99999 }, "image_slices": { "number_of_slices": number_of_slices } }).get_configuration() result = process_image(image=image, timestamp=time.time(), x_axis=x_axis, y_axis=y_axis, parameters=parameters) self.assertTrue(all((x in result for x in good_region_keys)), 'There should be good region keys.') self.assertTrue(all((x in result for x in (x % counter for x in slices_key_formats for counter in range(number_of_slices)))))
# Stream configuration. cam_server uses PUB for the output stream. output_stream_port = 9999 output_stream_mode = PUB # output_stream_mode = PUSH simulated_camera = CameraSimulation(camera_config=CameraConfig("simulation"), size_x=image_size_x, size_y=image_size_y) x_axis, y_axis = simulated_camera.get_x_y_axis() x_size, y_size = simulated_camera.get_geometry() # Documentation: https://github.com/datastreaming/cam_server#pipeline_configuration pipeline_parameters = { "camera_name": "simulation" } pipeline_config = PipelineConfig("test_pipeline", pipeline_parameters) parameters = pipeline_config.get_configuration() image_number = 0 with sender(port=output_stream_port, mode=output_stream_mode) as output_stream: # Get simulated image. image = simulated_camera.get_image() # Generate timestamp. timestamp = time.time() # Pass data to processing pipeline. processed_data = process_image(image, 0, timestamp, x_axis, y_axis, pipeline_parameters) # Set height and width.
def test_update_pipeline_config(self): configuration = {"camera_name": "simulation"} old_config = PipelineConfig("test", configuration).get_configuration() config_updates = {"image_good_region": {}} updated_config = update_pipeline_config(old_config, config_updates) self.assertIsNotNone(updated_config["image_good_region"]) configuration = { "camera_name": "simulation", "image_slices": { "number_of_slices": 98 } } old_config = PipelineConfig("test", configuration).get_configuration() config_updates = {"image_slices": {"scale": 99}} updated_config = update_pipeline_config(old_config, config_updates) self.assertEqual(updated_config["image_slices"]["scale"], 99, "New value not updated.") self.assertEqual(updated_config["image_slices"]["number_of_slices"], 98, "Old value changed.") configuration = { "camera_name": "name 1", "image_background": "test", "image_threshold": 1, "image_region_of_interest": [0, 1, 2, 3], "image_good_region": { "threshold": 0.3, "gfscale": 1.8 }, "image_slices": { "number_of_slices": 1, "scale": 2 } } old_config = PipelineConfig("test", configuration).get_configuration() config_updates = { "camera_name": "name 2", "image_background_enable": True, "image_background": "test_2", "image_threshold": 2, "image_region_of_interest": [3, 4, 5, 6], "image_good_region": { "threshold": 0.9, "gfscale": 3.6 }, "image_slices": { "number_of_slices": 6, "scale": 7 }, "pipeline_type": "processing" } updated_config = update_pipeline_config(old_config, config_updates) self.assertDictEqual(updated_config["image_good_region"], config_updates["image_good_region"], "Everything was not updated properly.") self.assertDictEqual(updated_config["image_slices"], config_updates["image_slices"], "Everything was not updated properly.") self.assertDictEqual(updated_config, config_updates, "Everything was not updated properly.") # Try removing element by element from the config - negative update. updated_config = update_pipeline_config(updated_config, {"camera_name": None}) self.assertEqual(updated_config["camera_name"], None) updated_config = update_pipeline_config(updated_config, {"image_background": None}) self.assertEqual(updated_config["image_background"], None) updated_config = update_pipeline_config( updated_config, {"image_region_of_interest": None}) self.assertEqual(updated_config["image_region_of_interest"], None) updated_config = update_pipeline_config( updated_config, {"image_good_region": { "threshold": None }}) self.assertEqual(updated_config["image_good_region"]["threshold"], None) self.assertEqual(updated_config["image_good_region"]["gfscale"], 3.6) updated_config = update_pipeline_config(updated_config, {"image_good_region": None}) self.assertEqual(updated_config["image_good_region"], None) updated_config = update_pipeline_config( updated_config, {"image_slices": { "number_of_slices": None }}) self.assertEqual(updated_config["image_slices"]["number_of_slices"], None) self.assertEqual(updated_config["image_slices"]["scale"], 7) updated_config = update_pipeline_config(updated_config, {"image_slices": None}) self.assertEqual(updated_config["image_slices"], None) updated_config = update_pipeline_config(updated_config, {"image_threshold": None}) self.assertEqual(updated_config["image_threshold"], None) updated_config = update_pipeline_config( updated_config, {"image_background_enable": None}) self.assertEqual(updated_config["image_background_enable"], None) updated_config = update_pipeline_config(updated_config, {"pipeline_type": None}) self.assertEqual(updated_config["pipeline_type"], None) self.assertTrue(all(value is None for value in updated_config.values()))
def test_store_pipeline_port_requirement(self): configuration = {"camera_name": "simulation", "pipeline_type": "store"} expanded_configuration = PipelineConfig.expand_config(configuration) with self.assertRaisesRegex(ValueError, "stream_port"): PipelineConfig.validate_pipeline_config(expanded_configuration) configuration = { "camera_name": "simulation", "pipeline_type": "store", "stream_port": "test" } expanded_configuration = PipelineConfig.expand_config(configuration) with self.assertRaisesRegex(ValueError, "must be an integer"): PipelineConfig.validate_pipeline_config(expanded_configuration) configuration = { "camera_name": "simulation", "pipeline_type": "store", "stream_port": config.PIPELINE_STREAM_PORT_RANGE[0] } expanded_configuration = PipelineConfig.expand_config(configuration) with self.assertRaisesRegex(ValueError, "must be outside of"): PipelineConfig.validate_pipeline_config(expanded_configuration) configuration = { "camera_name": "simulation", "pipeline_type": "store", "stream_port": config.PIPELINE_STREAM_PORT_RANGE[1] + 1 } expanded_configuration = PipelineConfig.expand_config(configuration) PipelineConfig.validate_pipeline_config(expanded_configuration)
def test_rotate_camera(self): manager = multiprocessing.Manager() stop_event = multiprocessing.Event() statistics = manager.Namespace() parameter_queue = multiprocessing.Queue() self.client.set_camera_config( "simulation_temp", self.client.get_camera_config("simulation")) pipeline_config = PipelineConfig( "test_pipeline", parameters={"camera_name": "simulation_temp"}) background_manager = MockBackgroundManager() x_size, y_size = get_simulated_camera().get_geometry() simulated_camera_shape = (y_size, x_size) def send(): processing_pipeline(stop_event, statistics, parameter_queue, self.client, pipeline_config, 12002, background_manager) thread = Thread(target=send) thread.start() with source(host="127.0.0.1", port=12002, mode=SUB, receive_timeout=3000) as stream: data = stream.receive() self.assertIsNotNone(data, "Received None message.") x_size = data.data.data["width"].value y_size = data.data.data["height"].value x_axis = data.data.data["x_axis"].value y_axis = data.data.data["y_axis"].value image_shape = data.data.data["image"].value.shape self.assertEqual(x_size, simulated_camera_shape[1]) self.assertEqual(y_size, simulated_camera_shape[0]) # Sanity checks. self.assertEqual(x_size, len(x_axis)) self.assertEqual(y_size, len(y_axis)) self.assertEqual(image_shape, (y_size, x_size)) # Rotate the image by 90 degree. camera_config = self.client.get_camera_config("simulation_temp") camera_config["rotate"] = 1 self.client.set_camera_config("simulation_temp", camera_config) # Make a few frames pass. for _ in range(5): data = stream.receive() self.assertIsNotNone(data, "Received None message.") x_size = data.data.data["width"].value y_size = data.data.data["height"].value x_axis = data.data.data["x_axis"].value y_axis = data.data.data["y_axis"].value image_shape = data.data.data["image"].value.shape # X and Y size should be inverted. self.assertEqual(x_size, simulated_camera_shape[0]) self.assertEqual(y_size, simulated_camera_shape[1]) # Sanity checks. self.assertEqual(x_size, len(x_axis)) self.assertEqual(y_size, len(y_axis)) self.assertEqual(image_shape, (y_size, x_size)) self.client.delete_camera_config("simulation_temp") stop_event.set() thread.join()