def addParameters(parameters): """ Add parameters specific to staying in lock. """ p = parameters.addSubSection(LockedMixin.lm_pname) p.add(params.ParameterInt(description = "Number of repeats for the lock to be considered good.", name = "buffer_length", value = 5)) p.add(params.ParameterRangeFloat(description = "Lock response gain (near target offset).", name = "lock_gain", value = 0.5, min_value = 0.0, max_value = 1.0)) p.add(params.ParameterRangeFloat(description = "Lock response maximum gain (far from target offset).", name = "lock_gain_max", value = 0.7, min_value = 0.0, max_value = 1.0)) p.add(params.ParameterFloat(description = "Maximum allowed difference to still be in lock (nm).", name = "offset_threshold", value = 20.0)) p.add(params.ParameterFloat(description = "Minimum sum to be considered locked (AU).", name = "minimum_sum", value = -1.0))
def addParameters(parameters): """ Add parameters specific to staying in lock. """ p = parameters.addSubSection(LockedMixin.lm_pname) p.add(params.ParameterInt(description = "Number of repeats for the lock to be considered good.", name = "buffer_length", value = 5)) p.add(params.ParameterFloat(description = "Maximum allowed difference to still be in lock (nm).", name = "offset_threshold", value = 20.0)) p.add(params.ParameterFloat(description = "Minimum sum to be considered locked (AU).", name = "minimum_sum", value = -1.0))
def test_parameters_3(): # Load parameters. p1 = params.parameters(test.xmlFilePathAndName("test_parameters.xml"), recurse=True) # Test sub-section creation. p2 = params.StormXMLObject() p2s = p2.addSubSection("camera1", p1.get("camera1").copy()) p2s.add(params.ParameterInt(name="test", value=5)) # p2 is different then p1 because it has 'test'. assert (params.difference(p2.get("camera1"), p1.get("camera1"))[0] == "test") # But p1 is not different from p2 because difference() only # checks p1 properties that exist in p1. assert (len(params.difference(p1.get("camera1"), p2.get("camera1"))) == 0)
def createParameters(self, cam_fn, parameters_from_file): """ Create (initial) parameters for the current feed. cam_fn - A camera / feed functionality object. parameters_from_file - The parameters that were read from the XML file. """ # Check that we are not writing over something that already exists. if (self.parameters.has(self.getFeedName())): msg = "Display parameters for " + self.getFeedName() + " already exists." raise halExceptions.HalException(msg) # Create a sub-section for this camera / feed. p = self.parameters.addSubSection(self.getFeedName()) # Add display specific parameters. p.add(params.ParameterFloat(name = "center_x", value = 0.0, is_mutable = False)) p.add(params.ParameterFloat(name = "center_y", value = 0.0, is_mutable = False)) p.add(params.ParameterSetString(description = "Color table", name = "colortable", value = self.color_tables.getColorTableNames()[0], allowed = self.color_tables.getColorTableNames())) p.add(params.ParameterInt(description = "Display maximum", name = "display_max", value = 100)) p.add(params.ParameterInt(description = "Display minimum", name = "display_min", value = 0)) p.add(params.ParameterSetBoolean(name = "initialized", value = False, is_mutable = False)) p.add(params.ParameterInt(name = "max_intensity", value = 100, is_mutable = False, is_saved = False)) p.add(params.ParameterInt(name = "scale", value = 0, is_mutable = False)) p.add(params.ParameterInt(description = "Frame to display when filming with a shutter sequence", name = "sync", value = 0)) # Set parameters with default values from feed/camera functionality if cam_fn.hasParameter("colortable"): p.setv("colortable", cam_fn.getParameter("colortable")) else: p.setv("colortable", self.default_colortable) p.setv("display_max", cam_fn.getParameter("default_max")) p.setv("display_min", cam_fn.getParameter("default_min")) p.setv("max_intensity", cam_fn.getParameter("max_intensity")) # If they exist, update with the values that we loaded from a file. # Also, some parameters files will have 'extra' parameters, typically # sub-sections for the different feeds. We skip these here as this # will be handled when we change to the feed and call the # setCameraFunctionality() method. # if parameters_from_file is not None: for attr in parameters_from_file.getAttrs(): if p.has(attr): p.setv(attr, parameters_from_file.get(attr))
def __init__(self, camera_name=None, config=None, **kwds): """ camera_name - This is the name of this camera's section in the config XML file. config - These are the values in the parameters section as a StormXMLObject(). """ super().__init__(**kwds) # This is the hardware module that will actually control the camera. self.camera = None # Sub-classes should set this to a CameraFunctionality object. self.camera_functionality = None self.camera_name = camera_name # This is a flag for whether or not the camera is in a working state. # It might not be if for example the parameters were bad. self.camera_working = True # The length of a fixed length film. self.film_length = None # The current frame number, this gets reset by startCamera(). self.frame_number = 0 # The camera parameters. self.parameters = params.StormXMLObject() # This is how we tell the thread that is handling actually talking # to the camera hardware to stop. self.running = False # This is how we know that the camera thread that is talking to the # camera actually started. self.thread_started = False # # These are the minimal parameters that every camera must provide # to work with HAL. # # The exposure time. self.parameters.add( params.ParameterFloat(description="Exposure time (seconds)", name="exposure_time", value=1.0)) # This is frames per second as reported by the camera. It is used # for hardware timed waveforms (if any). self.parameters.add( params.ParameterFloat(name="fps", value=0, is_mutable=False)) # # Chip size, ROI of the chip and the well depth. # x_size = 256 y_size = 256 self.parameters.add( params.ParameterInt(name="x_chip", value=x_size, is_mutable=False, is_saved=False)) self.parameters.add( params.ParameterInt(name="y_chip", value=y_size, is_mutable=False, is_saved=False)) self.parameters.add( params.ParameterInt(name="max_intensity", value=128, is_mutable=False, is_saved=False)) # # Note: These are all expected to be in units of binned pixels. For # example if the camera is 512 x 512 and we are binning by 2s then # the maximum value of these would 256 x 256. # self.parameters.add( params.ParameterRangeInt(description="AOI X start", name="x_start", value=1, min_value=1, max_value=x_size)) self.parameters.add( params.ParameterRangeInt(description="AOI X end", name="x_end", value=x_size, min_value=1, max_value=x_size)) self.parameters.add( params.ParameterRangeInt(description="AOI Y start", name="y_start", value=1, min_value=1, max_value=y_size)) self.parameters.add( params.ParameterRangeInt(description="AOI Y end", name="y_end", value=y_size, min_value=1, max_value=y_size)) self.parameters.add( params.ParameterInt(name="x_pixels", value=0, is_mutable=False)) self.parameters.add( params.ParameterInt(name="y_pixels", value=0, is_mutable=False)) self.parameters.add( params.ParameterRangeInt(description="Binning in X", name="x_bin", value=1, min_value=1, max_value=4)) self.parameters.add( params.ParameterRangeInt(description="Binning in Y", name="y_bin", value=1, min_value=1, max_value=4)) # Frame size in bytes. self.parameters.add( params.ParameterInt(name="bytes_per_frame", value=x_size * y_size * 2, is_mutable=False, is_saved=False)) # # How/if data from this camera is saved. # self.parameters.add( params.ParameterString( description="Camera save filename extension", name="extension", value="")) self.parameters.add( params.ParameterSetBoolean( description="Save data from this camera when filming", name="saved", value=True)) self.parameters.set("extension", config.get("extension", "")) self.parameters.set("saved", config.get("saved", True)) # # Camera display orientation. Values can only be changed by # changing the config.xml file. # self.parameters.add( params.ParameterSetBoolean(name="flip_horizontal", value=False, is_mutable=False)) self.parameters.add( params.ParameterSetBoolean(name="flip_vertical", value=False, is_mutable=False)) self.parameters.add( params.ParameterSetBoolean(name="transpose", value=False, is_mutable=False)) self.parameters.set("flip_horizontal", config.get("flip_horizontal", False)) self.parameters.set("flip_vertical", config.get("flip_vertical", False)) self.parameters.set("transpose", config.get("transpose", False)) # # Camera default display minimum and maximum. # # These are the values the display will use by default. They can # only be changed by changing the config.xml file. # self.parameters.add( params.ParameterInt(name="default_max", value=2000, is_mutable=False)) self.parameters.add( params.ParameterInt(name="default_min", value=100, is_mutable=False)) self.parameters.set("default_max", config.get("default_max", 2000)) self.parameters.set("default_min", config.get("default_min", 100)) self.finished.connect(self.handleFinished) self.newData.connect(self.handleNewData)
def __init__(self, joystick=None, joystick_gains=None, **kwds): super().__init__(**kwds) self.button_timer = QtCore.QTimer(self) self.joystick = joystick self.joystick_gains = joystick_gains # XML should be [25.0, 250.0, 2500.0] self.old_right_joystick = [0, 0] self.old_left_joystick = [0, 0] self.stage_functionality = None self.to_emit = False # The joystick parameters. self.parameters = params.StormXMLObject() self.parameters.add( params.ParameterInt(name="joystick_gain_index", value=0, is_mutable=False, is_saved=False)) self.parameters.add( params.ParameterInt(name="multiplier", value=1, is_mutable=False, is_saved=False)) self.parameters.add( params.ParameterRangeFloat( description="Step size in um for hat button press", name="hat_step", value=1.0, min_value=0.0, max_value=10.0)) self.parameters.add( params.ParameterRangeFloat( description="X button multiplier for joystick and focus lock", name="joystick_multiplier_value", value=5.0, min_value=0.0, max_value=50.0)) self.parameters.add( params.ParameterSetString(description="Response mode", name="joystick_mode", value="quadratic", allowed=["linear", "quadratic"])) self.parameters.add( params.ParameterSetFloat(description="Sign for x motion", name="joystick_signx", value=1.0, allowed=[-1.0, 1.0])) self.parameters.add( params.ParameterSetFloat(description="Sign for y motion", name="joystick_signy", value=1.0, allowed=[-1.0, 1.0])) self.parameters.add( params.ParameterRangeFloat( description="Focus lock step size in um", name="lockt_step", value=0.025, min_value=0.0, max_value=1.0)) self.parameters.add( params.ParameterRangeFloat( description="Minimum joystick offset to be non-zero", name="min_offset", value=0.1, min_value=0.0, max_value=1.0)) self.parameters.add( params.ParameterSetBoolean(description="Swap x and y axises", name="xy_swap", value=False)) self.joystick.start(self.joystickHandler) self.button_timer.setInterval(100) self.button_timer.setSingleShot(True) self.button_timer.timeout.connect(self.buttonDownHandler)
def handleResponses(self, message): if message.isType("get functionality"): assert (len(message.getResponses()) == 1) for response in message.getResponses(): self.camera_functionalities.append(response.getData()["functionality"]) self.number_fn_requested -= 1 # And we are done with the parameter change. if self.parameter_change and (self.number_fn_requested == 0): self.parameter_change = False self.sendMessage(halMessage.HalMessage(m_type = "parameters changed")) # Modules that need additional time to get ready to film should # specify at start up that they need to be waited for. elif message.isType("start film"): # No modules requested waits, so start now. if (len(self.wait_for) == 0): self.startCameras() # Modules are expected to add their current parameters as responses # to the 'stop film' message. We save them in an xml file here. elif message.isType("stop film"): self.film_state = "idle" acq_p = None notes = "" film_settings = message.getData()["film settings"] number_frames = message.getData()["number frames"] if film_settings.isSaved(): to_save = params.StormXMLObject() acq_p = to_save.addSubSection("acquisition") acq_p.add(params.ParameterString(name = "version", value = hgit.getVersion())) acq_p.add(params.ParameterInt(name = "number_frames", value = number_frames)) for response in message.getResponses(): data = response.getData() # Add general parameters 'en-bloc'. if "parameters" in data: to_save.addSubSection(response.source, svalue = data["parameters"]) # Add any acquisition parameters, these will be a list. if "acquisition" in data: for p in data["acquisition"]: acq_p.addParameter(p.getName(), p) if (p.getName() == "notes"): notes = p.getv() to_save.saveToFile(film_settings.getBasename() + ".xml") if self.logfile_fp is not None: msg = ",".join([str(datetime.datetime.now()), film_settings.getBasename(), notes]) msg += "\r\n" self.logfile_fp.write(msg) self.logfile_fp.flush() # Now that everything is complete end the filming lock out. self.setLockout(False, acquisition_parameters = acq_p)
def __init__(self, parameters = None, **kwds): """ parameters - This is just the 'feed' section of the parameters. """ super().__init__(**kwds) self.feeds = {} if parameters is None: return # Create the feeds. self.parameters = parameters for feed_name in self.parameters.getAttrs(): file_params = self.parameters.get(feed_name) # Create default feed parameters. max_value = 100000 feed_params = params.StormXMLObject() # Feeds are saved with their name as the extension. feed_params.add(params.ParameterString(name = "extension", value = feed_name, is_mutable = True)) feed_params.add(params.ParameterString(name = "feed_type", value = "", is_mutable = False)) feed_params.add(params.ParameterSetBoolean(name = "saved", value = False)) # This is the camera that drives the feed. feed_params.add(params.ParameterString(name = "source", value = "", is_mutable = False)) feed_params.add(params.ParameterRangeInt(description = "AOI X start.", name = "x_start", value = 1, min_value = 1, max_value = max_value)) feed_params.add(params.ParameterRangeInt(description = "AOI X end.", name = "x_end", value = 1, min_value = 1, max_value = max_value)) feed_params.add(params.ParameterRangeInt(description = "AOI Y start.", name = "y_start", value = 1, min_value = 1, max_value = max_value)) feed_params.add(params.ParameterRangeInt(description = "AOI Y end.", name = "y_end", value = 1, min_value = 1, max_value = max_value)) # Figure out what type of feed this is. fclass = None feed_type = file_params.get("feed_type") if (feed_type == "average"): fclass = FeedFunctionalityAverage feed_params.add(params.ParameterInt(description = "Number of frames to average.", name = "frames_to_average", value = 1)) elif (feed_type == "interval"): fclass = FeedFunctionalityInterval feed_params.add(params.ParameterInt(description = "Interval cycle length.", name = "cycle_length", value = 1)) feed_params.add(params.ParameterCustom(description = "Frames to capture.", name = "capture_frames", value = "1")) elif (feed_type == "slice"): fclass = FeedFunctionalitySlice else: raise FeedException("Unknown feed type '" + feed_type + "' in feed '" + feed_name + "'") # Update with values from the parameters file. Depending on the parameters # file it might include parameters that we don't have and which we silently # ignore. # for attr in file_params.getAttrs(): if feed_params.has(attr): feed_params.setv(attr, file_params.get(attr)) # Replace the values in the parameters that were read from a file with these values. self.parameters.addSubSection(feed_name, feed_params, overwrite = True) camera_name = feed_params.get("source") + "." + feed_name self.feeds[camera_name] = fclass(feed_name = feed_name, camera_name = camera_name, parameters = feed_params)
def processMessage(self, message): if message.isType("changing parameters"): if not message.getData()["changing"]: self.newAnalyzers() elif message.isType("configuration"): if message.sourceIs("feeds"): self.feed_names = [] for name in message.getData()["properties"]["feed names"]: self.feed_names.append(name) elif message.sourceIs("illumination"): self.shutters_info = message.getData( )["properties"]["shutters info"] for analyzer in self.analyzers: analyzer.setShuttersInfo(self.shutters_info) elif message.sourceIs("mosaic"): self.pixel_size = message.getData()["properties"]["pixel_size"] elif message.isType("configure1"): # Broadcast initial parameters. self.sendMessage( halMessage.HalMessage(m_type="initial parameters", data={"parameters": self.parameters})) self.sendMessage( halMessage.HalMessage(m_type="add to menu", data={ "item name": "Spot Counter", "item data": "spot counter" })) elif message.isType("new parameters"): # # Just record the new parameters here. Then when we get a 'configuration' message # from feeds.feeds we'll get the names of the new feeds. And finally when we get # the 'changing parameters' message we'll update the analyzers. # message.addResponse( halMessage.HalMessageResponse( source=self.module_name, data={"old parameters": self.parameters.copy()})) self.parameters = message.getData()["parameters"].get( self.module_name) message.addResponse( halMessage.HalMessageResponse( source=self.module_name, data={"new parameters": self.parameters})) elif message.isType("show"): if (message.getData()["show"] == "spot counter"): self.view.show() elif message.isType("start"): self.newAnalyzers() if message.getData()["show_gui"]: self.view.showIfVisible() elif message.isType("start film"): film_settings = message.getData()["film settings"] if film_settings.isSaved(): self.basename = film_settings.getBasename() for analyzer in self.analyzers: analyzer.startFilm(film_settings) elif message.isType("stop film"): total_spots = 0 for analyzer in self.analyzers: analyzer.stopFilm() total_spots += analyzer.getCounts() if self.basename is not None: analyzer.savePicture(self.basename) self.basename = None message.addResponse( halMessage.HalMessageResponse( source=self.module_name, data={"parameters": self.parameters.copy()})) counts_param = params.ParameterInt(name="spot_counts", value=total_spots) message.addResponse( halMessage.HalMessageResponse( source=self.module_name, data={"acquisition": [counts_param]}))
def __init__(self, parameters, joystick, parent=None): QtCore.QObject.__init__(self, parent) halModule.HalModule.__init__(self, parent) self.button_timer = QtCore.QTimer(self) self.jstick = joystick self.old_right_joystick = [0, 0] self.old_left_joystick = [0, 0] self.to_emit = False # Add joystick specific parameters. js_params = parameters.addSubSection("joystick") js_params.add( "joystick_gain_index", params.ParameterInt("", "joystick_gain_index", 0, is_mutable=False, is_saved=False)) js_params.add( "multiplier", params.ParameterInt("", "multiplier", 1, is_mutable=False, is_saved=False)) js_params.add( "hat_step", params.ParameterRangeFloat("Step size in um for hat button press", "hat_step", 1.0, 0.0, 10.0)) js_params.add("joystick_gain", [25.0, 250.0, 2500.0]) js_params.add( "joystick_multiplier_value", params.ParameterRangeFloat( "X button multiplier for joystick and focus lock", "joystick_multiplier_value", 5.0, 0.0, 50.0)) js_params.add( "joystick_mode", params.ParameterSetString("Response mode", "joystick_mode", "quadratic", ["linear", "quadratic"])) js_params.add( "joystick_signx", params.ParameterSetFloat("Sign for x motion", "joystick_signx", 1.0, [-1.0, 1.0])) js_params.add( "joystick_signy", params.ParameterSetFloat("Sign for y motion", "joystick_signy", 1.0, [-1.0, 1.0])) js_params.add( "lockt_step", params.ParameterRangeFloat("Focus lock step size in um", "lockt_step", 0.025, 0.0, 1.0)) js_params.add( "min_offset", params.ParameterRangeFloat( "Minimum joystick offset to be non-zero", "min_offset", 0.1, 0.0, 1.0)) js_params.add( "xy_swap", params.ParameterSetBoolean("Swap x and y axises", "xy_swap", False)) self.parameters = js_params self.jstick.start(self.joystickHandler) self.button_timer.setInterval(100) self.button_timer.setSingleShot(True) self.button_timer.timeout.connect(self.buttonDownHandler)