def _createRunningDialog(self) -> None: """Create and show the running dialog in another thread. Note: Make sure to set the `DMView.progress_max` before calling this function! Notes ----- This function creates a dialog that is running in the current dm-script main thread. UI components always run in the main thread! """ path = os.path.join(self._rel_path, "dm_view_progress_dialog.s") sv = { "max_progress": self.progress_max, "progress_tn": self._progress_dialog_progress_tagname, "text_tn": self._progress_dialog_text_tagname, "success_tn": self._progress_dialog_success_tagname, "kill_tn": self._progress_dialog_kill_tagname } self._created_tagnames.add(self._progress_dialog_progress_tagname) self._created_tagnames.add(self._progress_dialog_success_tagname) self._created_tagnames.add(self._progress_dialog_text_tagname) log_debug(self._logger, ("Showing running dialog by executing " + "dmscript '{}' with setvars '{}'").format(path, sv)) with execdmscript.exec_dmscript(path, setvars=sv, debug=self._exec_debug): pass
def _createKillDialog(self) -> None: """A dialog that shows the kill button only.""" id_ = int(time.time() * 100) dmscript = "\n".join(( "class handler_{} : UIFrame {{".format(id_), "void killTaks(object self){", "if(!GetPersistentTagGroup().TagGroupDoesTagExist(\"{}\")){{". format(self._progress_dialog_kill_tagname), "GetPersistentTagGroup().TagGroupCreateNewLabeledTag(\"{}\");". format(self._progress_dialog_kill_tagname), "}", "GetPersistentTagGroup().TagGroupSetTagAsBoolean(\"{}\", 1);". format(self._progress_dialog_kill_tagname), "}", "}", "TagGroup Dialog = DLGCreateDialog(\"Kill task\");", "TagGroup kill_button = DLGCreatePushButton(\"Kill Task\", \"killTaks\");", "Dialog.DLGAddElement(kill_button);", "object kill_dialog = alloc(handler_{}).init(Dialog)".format(id_), "kill_dialog.display(\"Kill task\");", )) self._created_tagnames.add(self._progress_dialog_kill_tagname) log_debug(self._logger, "Creating kill dialg by executing dmscript '{}'") with execdmscript.exec_dmscript(dmscript, debug=self._exec_debug): pass
def showError(self, error: typing.Union[str, Exception], how_to_fix: typing.Optional[str] = None) -> None: """Show the user a hint. Raises ------ StopProgram When the user clicks the cancel button. Parameters ---------- hint : str The text to show how_to_fix : str, optional A text that helps the user to interpret and avoid this error, default: None """ msg = "" if isinstance(error, Exception): try: msg = type(error).__name__ except: pass if msg == "": msg = "Error" msg += ": " + str(error) print(msg) print(" Fix:", how_to_fix) self.print(msg) self.print(" Fix:", how_to_fix) if isinstance(error, Exception): traceback.print_exc() log_error(self._logger, error) elif do_log(self._logger, logging.ERROR): self._logger.error(msg) if isinstance(how_to_fix, str) and how_to_fix != "": msg += "\n\nPossible Fix:\n{}".format(how_to_fix) dmscript = "showAlert(msg, 0);" setvars = setvars = {"msg": msg} log_debug( self._logger, "Executing dmscript '{}' with setvars '{}'".format( dmscript, setvars)) with execdmscript.exec_dmscript(dmscript, setvars=setvars, debug=self._exec_debug): pass
def _createNewWorkspace( self, name: typing.Optional[str] = None, activate: typing.Optional[bool] = True) -> typing.Tuple[int, str]: """Create a new workspace and save the workspace id. Parameters ---------- name : str, optional The workspace name, if not given the `config.PROGRAM_NAME` with a trailing number is used, default: None activate : bool, optional Whether to set the new workspace as the active one, default: True Returns ------- int, str The id of the new workspace and the name """ from pylo.config import PROGRAM_NAME if not isinstance(name, str) or name == "": name = "{} {}".format(PROGRAM_NAME, DMCamera.workspace_number + 1) dmscript = [ "number wsid = WorkspaceAdd(0);", "WorkspaceSetName(wsid, \"{}\");".format( execdmscript.escape_dm_string(name)), ] if activate: dmscript.append("WorkspaceSetActive(wsid);") dmscript = "\n".join(dmscript) readvars = {"wsid": int} logginglib.log_debug(self._logger, ("Creating new workspace by " + "executing dmscript '{}' with " + "readvars '{}'").format(dmscript, readvars)) with execdmscript.exec_dmscript(dmscript, readvars=readvars) as script: self._workspace_id = script["wsid"] DMCamera.workspace_number += 1 logginglib.log_debug(self._logger, ("New workspace with id '{}' and " + "name '{}'.").format(self._workspace_id, name)) return self._workspace_id, name
def _ensureWorkspace(self, name: typing.Optional[str] = None, activate_new: typing.Optional[bool] = True, force_active: typing.Optional[bool] = False) -> None: """Ensure that the `DMCamera._workspace_id` exists. If the workspace does not exist, it is created. Parameters ---------- name : str, optional The workspace name, if not given the `config.PROGRAM_NAME` with a trailing number is used, default: None activate_new : bool, optional Whether to set the workspace new as the active one, default: True force_active : bool, optional Whether to set the workspace as active also if it already exists, default: False """ logginglib.log_debug(self._logger, ("Checking if workspace id '{}' " + "is valid").format(self._workspace_id)) if (not isinstance(self._workspace_id, int) or DM.WorkspaceCountWindows(self._workspace_id) == 0): # either the workspace id does not exist or it exists but the user # closed the workspace already logginglib.log_debug(self._logger, ("Workspace with id '{}' does " + "not exist, creating a new " + "one.").format(self._workspace_id)) self._createNewWorkspace(activate_new) # reset shown images if a new workspace is created DMImage.shown_images_counter = 0 elif force_active: setvars = {"wsid": self._workspace_id} dmscript = "WorkspaceSetActive(wsid);" logginglib.log_debug( self._logger, ("Forcing workspace to be " + "active by executing " + "dmscript '{}' with setvars " + "'{}'").format( dmscript, setvars)) with execdmscript.exec_dmscript(dmscript, setvars=setvars): pass
def _getWorkspaceRect(self) -> typing.Tuple[int, int, int, int]: """Get the available workspace area in GMS. Raises ------ LookupError When the workspace area could not be detected Returns ------- tuple of int A tuple containing the *top*, *left*, *bottom* and *right* coordinates of the available space for images in the stated order """ log_debug(self._logger, "Trying to get the workspace rect") readvars = {"top": int, "left": int, "bottom": int, "right": int} dmscript = "\n".join( ("number top, left, bottom, right;", "GetMaximalDocumentWindowRect(1+2+240, top, left, bottom, right);" )) log_debug( self._logger, "Executing dm-script '{}' with readvars '{}'".format( dmscript, readvars)) workspace_rect = None with execdmscript.exec_dmscript(dmscript, readvars=readvars) as script: workspace_rect = (script["top"], script["left"], script["bottom"], script["right"]) log_debug(self._logger, ("Found workspace rect to be " + "'{}'").format(workspace_rect)) if not isinstance(workspace_rect, tuple): err = LookupError("Could not detect the workspace area in GMS.") log_error(self._logger, err) raise err return workspace_rect
def showHint(self, hint: str) -> None: """Show the user a hint. Raises ------ StopProgram When the user clicks the cancel button. Parameters ---------- hint : str The text to show """ dmscript = "showAlert(msg, 2);" setvars = {"msg": hint} log_debug(self._logger, ("Showing alert by executing dmscript '{}' " + "with setvars '{}'").format(dmscript, setvars)) with execdmscript.exec_dmscript(dmscript, setvars=setvars, debug=self._exec_debug): pass
def getNumberOfWorkspaces() -> int: """Get the number of 'Pylo <number>' workspaces Returns ------- int The number of workspaces whose name starts with the program name and ends with a number """ from pylo.config import PROGRAM_NAME dmscript = "\n".join( ( "number workspace_number = 0;", "for(number i = 0; i < WorkspaceGetCount(); i++){", "number wsid = WorkspaceGetFromIndex(i);", "string name = WorkspaceGetName(wsid);", "if(name.left({}) == \"{}\"){{".format( len(PROGRAM_NAME), execdmscript.escape_dm_string(PROGRAM_NAME)), "name = name.right(name.len() - 1 - {});".format( len(PROGRAM_NAME)), "if(name.val() > workspace_number){", "workspace_number = name.val()", "}", "}", "}", )) readvars = {"workspace_number": int} with execdmscript.exec_dmscript(dmscript, readvars=readvars) as script: return script["workspace_number"] return 0
import execdmscript # set the text in python world_text = "Hello World!" # create an executable dm-script code dmscript = """ OKDialog(text); result(text); """ # save which variables should be passed from python to dm-script and how they should be # called setvars = { "text": world_text } # execute the script with execdmscript.exec_dmscript(dmscript, setvars=setvars): pass
import execdmscript # Tell the dm-script the variables it should know setvars = {"variable1": 1, "variable2": "B", "variable3": False} # Get the list of headlines readvars = {"variable4": str, "variable5": int} # set your filepath, needs to be the complete path, not just the name! path = r"C:\testdmscript3.s" with execdmscript.exec_dmscript(path, setvars=setvars, readvars=readvars, debug=True, debug_file=r"C:\debugfile.s") as script: pass
def _show( self, image_doc: DM.Py_ImageDocument, workspace_id: typing.Optional[int] = None, file_path: typing.Optional[typing.Union[pathlib.PurePath, str]] = None ) -> DM.Py_ImageDocument: """Show the given image document. If the `workspace_id` is given, the image will be shown in this workspace. Parameters ---------- image_doc : DigitalMicrograph.Py_ImageDocument The image document to show workspace_id: int, optional The workspace id to show in, if not an int the image will be shown in the current workspace, default: None file_path : str or pathlib.PurePath, optional The path where the image is Returns ------- DigitalMicrograph.Py_ImageDocument The image document that shows the image """ log_debug( self._logger, ("Showing image with " + "DigitalMicrograph.Py_ImageDocument '{}'").format(image_doc)) if (isinstance(workspace_id, int) and DM.WorkspaceCountWindows(workspace_id) > 0): log_debug( self._logger, "Moving image document '{}' to workspace '{}'".format( image_doc, workspace_id)) # check if the workspace exists (if not it does not have windows), # if the workspace does not exist and ImageDocument.MoveToWorkspace() # is called, a RuntimeError is raised image_doc.MoveToWorkspace(workspace_id) # calculate position depending on the available size and the # number of columns from .config import DEFAULT_DM_SHOW_IMAGES_ROW_COUNT rows = DEFAULT_DM_SHOW_IMAGES_ROW_COUNT length = round( (self.workspace_rect[2] - self.workspace_rect[0]) / rows) cols = math.floor( (self.workspace_rect[3] - self.workspace_rect[1]) / length) row_index = (DMImage.shown_images_counter // cols) % rows col_index = (DMImage.shown_images_counter % cols) pos = (self.workspace_rect[0] + row_index * length, self.workspace_rect[1] + col_index * length, self.workspace_rect[0] + (row_index + 1) * length, self.workspace_rect[1] + (col_index + 1) * length) log_debug(self._logger, "Setting image document to position '{}'".format(pos)) # show in the workspace image_doc.ShowAtRect(*pos) from .config import DM_IMAGE_DISABLE_PYTHON_ANNOTATIONS # link to file and/or add annotations if (isinstance(file_path, str) or isinstance(file_path, pathlib.PurePath) or (DM_IMAGE_DISABLE_PYTHON_ANNOTATIONS and isinstance(self.annotations, (list, tuple)))): if isinstance(workspace_id, int): wsid = workspace_id else: wsid = "" dmscript = [] if (DM_IMAGE_DISABLE_PYTHON_ANNOTATIONS and isinstance(self.annotations, (list, tuple))): # do not link to file because annotations are missing in the # file, force user to save the workspace log_debug(self._logger, ("Adding annotations in dm-script " + "after showing the file, not " + "linking to file because in file " + "the annotations are missing.")) from .config import DM_IMAGE_ANNOTATION_COLOR from .config import DM_IMAGE_ANNOTATION_PADDING_FRACTION from .config import DM_IMAGE_ANNOTATION_SCALEBAR_LENGTH_FRACTION from .config import DM_IMAGE_ANNOTATION_HEIGHT_FRACTION if (not isinstance(self.annotations_height_fraction, float) or self.annotations_height_fraction <= 0 or math.isclose( self.annotations_height_fraction, 0, abs_tol=1e-10) or self.annotations_height_fraction > 1): self.annotations_height_fraction = DM_IMAGE_ANNOTATION_HEIGHT_FRACTION dmscript += [ "if(img_doc.ImageDocumentCountImages() > 0){", "Image img := img_doc.ImageDocumentGetImage(0);", "ImageDisplay display;", "if(img.ImageCountImageDisplays() == 0){", "display = img_doc.ImageDocumentAddImageDisplay(img, -2);", "}", "else{", "display = img.ImageGetImageDisplay(0);", "}", "Component annotation;", "number image_width = img.ImageGetDimensionSize(0);", "number image_height = img.ImageGetDimensionSize(1);", "number top, left, bottom, right, font_size, t, l, b, r;", "top = (1 - {ah} - {ap}) * image_height".format( ah=self.annotations_height_fraction, ap=DM_IMAGE_ANNOTATION_PADDING_FRACTION), "left = {ap} * image_width".format( ap=DM_IMAGE_ANNOTATION_PADDING_FRACTION), "font_size = {ah} * image_height".format( ah=self.annotations_height_fraction) ] for annotation in self.annotations: log_debug(self._logger, ("Trying to add annotation " + "'{}'").format(annotation)) if annotation == "scalebar": dmscript += [ "bottom = (1 - {ap}) * image_height".format( ap=DM_IMAGE_ANNOTATION_PADDING_FRACTION), "right = left + {sl} * image_width".format( sl=DM_IMAGE_ANNOTATION_SCALEBAR_LENGTH_FRACTION ), "annotation = NewComponent(31, top, left, bottom, right);" ] else: dmscript += [ "annotation = NewTextAnnotation(left, top, \"{}\", font_size);" .format(execdmscript.escape_dm_string(annotation)) ] dmscript += [ "annotation.ComponentSetForegroundColor({r}, {g}, {b})" .format(r=DM_IMAGE_ANNOTATION_COLOR[0], g=DM_IMAGE_ANNOTATION_COLOR[1], b=DM_IMAGE_ANNOTATION_COLOR[2]), "display.ComponentAddChildAtEnd(annotation);", "annotation.ComponentGetBoundingRect(t, l, b, r);", "left = r + {ap} * image_width;".format( ap=DM_IMAGE_ANNOTATION_PADDING_FRACTION) ] dmscript += ["}"] else: log_debug(self._logger, "Trying to link image document to the file") dmscript = [ "if(path != \"\"){", "img_doc.ImageDocumentSetCurrentFile(path);", "if(format != \"\"){", "img_doc.ImageDocumentSetCurrentFileSaveFormat(format);", "}", "img_doc.ImageDocumentClean();", "}" ] dmscript = "\n".join([ "number wsid = {}".format( "WorkspaceGetActive();" if wsid == "" else wsid), "if(WorkspaceGetIndex(wsid) >= 0){", "for(number i = CountImageDocuments(wsid) - 1; i >= 0; i--){", "ImageDocument img_doc = GetImageDocument(i, wsid);", "if(img_doc.ImageDocumentGetName() == name){" ] + dmscript + ["break;", "}", "}", "}"]) if (isinstance(file_path, str) or isinstance(file_path, pathlib.PurePath)): _, extension = os.path.splitext(file_path) if extension in DMImage.gatan_file_types: file_format = DMImage.gatan_file_types[extension] else: file_format = "" else: file_path = "" file_format = "" svars = { "name": image_doc.GetName(), "path": file_path, "format": file_format } log_debug( self._logger, "Executing dmscript '{}' with setvars '{}'".format( dmscript, svars)) with execdmscript.exec_dmscript(dmscript, setvars=svars): pass DMImage.shown_images_counter += 1 return image_doc
import execdmscript import urllib.request import html.parser import re # get the text of example.com content = str(urllib.request.urlopen("https://www.example.com/").read()) # get all headlines matches = re.findall(r"<h([\d])>([^<]+)</h\1>", content) if matches is not None: headlines = [x[1] for x in matches] text = "Headlines:\n- " + "\n- ".join(headlines) else: headlines = [] text = "*No headlines found*" # Tell the dm-script the variables it should know setvars = {"text": text} # set your filepath, needs to be the complete path, not just the name! path = r"C:\testdmscript.s" with execdmscript.exec_dmscript(path, setvars=setvars): pass
def _showDialog( self, measurement_variables: typing.Optional[ typing.List["MeasurementVariable"]] = None, series: typing.Optional[dict] = None, start: typing.Optional[dict] = None, configuration: typing.Optional[AbstractConfiguration] = None, ask_for_values: typing.Optional[typing.Sequence[AskInput]] = None, ask_for_msg: typing.Optional[str] = "", custom_tags: typing.Optional[dict] = {}, dialog_type: typing.Optional[int] = 0b11): """Show the dm-script dialog. The base dialog is the same for all dialogs. The `dialog_type` shows which dialog is created in the dm-script code. Only the parameters for this dialog are required, the others can be omitted Parameters ---------- measurement_variables : list of MeasurementVariable The measurement variables that the current microscope supports, required for 'series' dialog (`0b0010`) series : dict The series dict that defines the series that is shown on startup with uncalibrated and parsed values, if not given the default values are used, optional for 'series' dialog (`0b0010`), default: None start : dict The series start definition that is shown on startup with uncalibrated and parsed values, if not given the default values are used, optional for 'series' dialog (`0b0010`), default: None configuration : AbstractConfiguration The configuration to get the values of, required for 'configuration' dialog (`0b0001`) ask_for_values : sequence of dicts A sequence of dicts where the dict contains the "datatype" and the "name" index and an optional "description" defining the values to ask the user for, required for 'ask_for' dialog (`0b0100`) ask_for_msg : str The message to show in the ask for dialog, optional for 'ask_for' dialog (`0b0100`) custom_tags : dict of dicts The tags dict where the keys are the tag names and the values are dicts with the "value" and "save" indices, required for 'custom_tags' dialog (`0b1000`) dialog_type : int, optional Define which dialog to show, use - `0b01` for showing the configuration dialog - `0b10` for showing the series dialog - `0b01 | 0b10 | 0b1000 = 0b1011` for showing the series dialog but the user can switch to the configuration dialog and the custom tags dialog and back - `0b100` for showing the ask for dialog - `0b1000` for showing the custom tags dialog """ if (dialog_type & 0b01) > 0 and (dialog_type & 0b10) > 0: dialog_startup = "" elif (dialog_type & 0b01) > 0: dialog_startup = "configuration" elif (dialog_type & 0b100) > 0: dialog_startup = "ask_for" elif (dialog_type & 0b1000) > 0: dialog_startup = "custom_tags" else: dialog_startup = "series" log_debug(self._logger, ("Showing dialog with mode '{:b}' which is " + "converted to '{}' as a string value").format( dialog_type, dialog_startup)) if isinstance(measurement_variables, dict): measurement_variables = list(measurement_variables.values()) m_vars = [] series_def = [] # add all measurement variables if there are some if isinstance(measurement_variables, list): var_keys = ("unique_id", "name", "unit", "min_value", "max_value", "start", "end", "step") cal_keys = ("name", "unit") num_keys = ("start", "step", "end", "min_value", "max_value") if not isinstance(series, dict): series = {} if not isinstance(start, dict): start = {} series, *_ = MeasurementSteps.formatSeries(measurement_variables, series, add_default_values=True, parse=False, uncalibrate=False, start=start) start, *_ = MeasurementSteps.formatStart(measurement_variables, start, series, add_default_values=True, parse=False, uncalibrate=False) series_nests = list(MeasurementSteps.getSeriesNests(series)) series_def = list(map(lambda s: s["variable"], series_nests)) for var in measurement_variables: m_var = {} if var.unique_id in series_def: i = series_def.index(var.unique_id) fake_series = series_nests[i] if "on-each-point" in fake_series: # not used and just more formatting overhead del fake_series["on-each-point"] else: fake_series = {"variable": var.unique_id} if var.unique_id in start: fake_series["start"] = start[var.unique_id] defaults, *_ = MeasurementSteps.formatSeries( measurement_variables, fake_series, add_default_values=True, parse=False, uncalibrate=False) for name in var_keys: val = None if name == "step": key = "step-width" else: key = name if var.has_calibration and name in cal_keys: n = "calibrated_{}".format(name) if hasattr(var, n) and getattr(var, n) != None: val = getattr(var, n) if val is None and key in defaults: val = defaults[key] if val is None and hasattr(var, name): val = getattr(var, name) if name in num_keys and val != "": if var.has_calibration: val = var.ensureCalibratedValue(float(val)) if (var.calibrated_format is not None and isinstance(var.calibrated_format, Datatype)): m_var["formatted_{}".format(name)] = ( var.calibrated_format.format(val)) elif (var.format is not None and isinstance(var.format, Datatype)): m_var["formatted_{}".format(name)] = ( var.format.format(val)) if val == None: val = "" elif not isinstance(val, (bool, str, float, int)): val = str(val) m_var[name] = val if var.has_calibration: if isinstance(var.calibrated_format, OptionDatatype): m_var["format"] = "options" m_var["options"] = var.calibrated_format.options elif var.has_calibration and var.calibrated_format is not None: m_var["format"] = get_datatype_name( var.calibrated_format) elif isinstance(var.format, OptionDatatype): m_var["format"] = "options" m_var["options"] = var.format.options elif var.format is not None: m_var["format"] = get_datatype_name(var.format) m_vars.append(m_var) config_vars = {} if isinstance(configuration, AbstractConfiguration): for group in configuration.getGroups(): if (not group in config_vars or not isinstance(config_vars[group], dict)): config_vars[group] = {} for key in configuration.getKeys(group): try: val = configuration.getValue(group, key) except KeyError: val = "" try: var_type = configuration.getDatatype(group, key) except KeyError: var_type = str if isinstance(var_type, OptionDatatype): var_type_name = "options" else: var_type_name = get_datatype_name(var_type) # make sure the vaue is valid, parse it and then format it # again val = parse_value(var_type, val) val = format_value(var_type, val) try: default_value = configuration.getDefault(group, key) except KeyError: default_value = "" try: description = configuration.getDescription(group, key) except KeyError: description = "" try: ask_if_not_present = configuration.getAskIfNotPresent( group, key) except KeyError: ask_if_not_present = False try: restart_required = configuration.getRestartRequired( group, key) except KeyError: restart_required = False config_vars[group][key] = { "value": val, "default_value": default_value, "datatype": var_type_name, "description": str(description), "ask_if_not_present": ask_if_not_present, "restart_required": restart_required, } if isinstance(var_type, OptionDatatype): config_vars[group][key]["options"] = var_type.options ask_vals = [] if isinstance(ask_for_values, (tuple, list)): for input_definition in ask_for_values: input_definition = input_definition.copy() if "datatype" in input_definition: if isinstance(input_definition["datatype"], OptionDatatype): input_definition["options"] = input_definition[ "datatype"].options input_definition["datatype"] = "options" elif not isinstance(input_definition["datatype"], str): if hasattr(input_definition["datatype"], "name"): input_definition["datatype"] = input_definition[ "datatype"].name elif hasattr(input_definition["datatype"], "__name__"): input_definition["datatype"] = input_definition[ "datatype"].__name__ else: input_definition["datatype"] = str( input_definition["datatype"]) else: input_definition["datatype"] = "string" else: input_definition["datatype"] = "string" ask_vals.append(input_definition) variables = { "m_vars": m_vars, "series_def": series_def, "config_vars": config_vars, "ask_vals": ask_vals, "message": ask_for_msg, "dialog_startup": dialog_startup, "custom_tag_vals": custom_tags } path = os.path.join(self._rel_path, "dm_view_dialog.s") sync_vars = { "start": dict, "series": dict, "configuration": dict, "ask_for": list, "custom_tags": dict, "success": bool } libs = (os.path.join(self._rel_path, "pylolib.s"), ) start = None series = None config = None ask_for_values = None custom_tags = None success = None log_debug(self._logger, ("Executing dm libs '{}' and dmscript '{}' " + "with readvars '{}' and setvars '{}'").format( libs, path, sync_vars, variables)) # shows the dialog (as a dm-script dialog) in dm_view_series_dialog.s # and sets the start and series variables with execdmscript.exec_dmscript(*libs, path, readvars=sync_vars, setvars=variables, debug=self._exec_debug) as script: try: success = bool(script["success"]) except KeyError: success = False if isinstance(measurement_variables, list): try: series = script["series"] except KeyError: series = None if series is not None: series = MeasurementSteps.formatSeries( measurement_variables, series, add_default_values=False, parse=True, uncalibrate=True) else: series = None if isinstance(measurement_variables, list): try: start = script["start"] except KeyError: start = None if start is not None and series is not None: start = MeasurementSteps.formatStart( measurement_variables, start, series, add_default_values=False, parse=True, uncalibrate=True) else: start = None try: config = script["configuration"] except KeyError: config = None try: ask_for_values = script["ask_for"] except KeyError: ask_for_values = None try: custom_tags = script["custom_tags"] except KeyError: custom_tags = None if success and ((start is not None and series is not None) or config is not None or ask_for_values is not None or custom_tags is not None): log_debug(self._logger, ("Returning start '{}', series '{}', " + "config '{}', ask_for_values '{}' and " + "custom_tags '{}'").format(start, series, config, ask_for_values, custom_tags)) return start, series, config, ask_for_values, custom_tags else: err = StopProgram() log_debug(self._logger, "Stopping program", exc_info=err) raise err
def askForDecision( self, text: str, options: typing.Optional[typing.Sequence[str]] = ("Ok", "Cancel") ) -> int: """Ask for a decision between the given `options`. The `options` are shown to the user depending on the view implementation. In most of the times this are the buttons shown on a dialog. The selected index will be returned. Raises ------ ValueError When the `options` is empty StopProgram When the view is closed in another way (e.g. the close icon of a dialog is clicked) Parameters ---------- text : str A text that is shown to the users to explain what they are deciding options : sequence of str The texts to show to the users they can select from Returns ------- int The selected index """ if len(options) == 0: raise ValueError("The options must not be empty.") elif len(options) == 2: dmscript = "number index = TwoButtonDialog(text, button0, button1);" readvars = {"index": int} setvars = { "text": text, "button0": options[0], "button1": options[1] } log_debug(self._logger, ("Asking for decision by executing " + "dmscript '{}' with setvars '{}' and " + "readvars '{}'").format(dmscript, setvars, readvars)) with execdmscript.exec_dmscript(dmscript, setvars=setvars, readvars=readvars, debug=self._exec_debug) as script: index = script["index"] # for dm-script the buttons are the "confirm" and the "cancel" # buttons, so the left button (button0 in this case) is always # true, the right button (button1 in this case) is always false # which are, converted to int, 0 and 1 in the exact other way # than this function is retunring its values if index == 0: index = 1 elif index == 1: index = 0 else: id_ = "__pylo_pressed_button_{}".format(int(time.time() * 100)) setvars = { "text": text, "persistent_tag_name": id_, "title": "Please select" } self._created_tagnames.add(id_) dmscript_button_pressed_handlers = [] dmscript_button_creations = [] for i, o in enumerate(options): setvars["button{}".format(i)] = o dmscript_button_pressed_handlers.append( ("void button{i}_pressed(object self){{" + "self.button_pressed({i});" + "}}").format(i=i)) dmscript_button_creations.append(( "b = DLGCreatePushButton(button{i}, \"button{i}_pressed\");" + "b.DLGWidth(80);" + "wrapper.DLGAddElement(b);").format(i=i)) dmscript = "\n".join([ "class ButtonDialog : UIFrame{", "void button_pressed(object self, number i){", "if(GetPersistentTagGroup().TagGroupDoesTagExist(persistent_tag_name)){", "GetPersistentTagGroup().TagGroupDeleteTagWithLabel(persistent_tag_name);", "}", "GetPersistentTagGroup().TagGroupCreateNewLabeledTag(persistent_tag_name);", "GetPersistentTagGroup().TagGroupSetTagAsShort(persistent_tag_name, i);", "self.close();", "exit(0);", "}", "" ] + dmscript_button_pressed_handlers + [ "" "object init(object self){", "TagGroup dlg, dlg_items, wrapper, label, b;", "dlg = DLGCreateDialog(title, dlg_items);", "", "dlg_items.DLGAddElement(DLGCreateLabel(text));", "", "wrapper = DLGCreateGroup();", "wrapper.DLGTableLayout({}, 1, 1);".format(len( options)), "dlg_items.DLGAddElement(wrapper);", "" ] + dmscript_button_creations + [ "", "self.super.init(dlg);", "return self;", "}", "}", "alloc(ButtonDialog).init().display(title);" ]) log_debug(self._logger, ("Asking for decision by executing " + "dmscript '{}' with setvars '{}' and " + "readvars '{}'").format(dmscript, setvars, readvars)) log_debug( self._logger, "Deleting persistent tag with label " + "'{}'".format(id_)) DM.GetPersistentTagGroup().DeleteTagWithLabel(id_) with execdmscript.exec_dmscript(dmscript, setvars=setvars, debug=self._exec_debug): # wait for dm-script to show the dialog, the user takes longer # to react anyway time.sleep(0.5) log_debug(self._logger, ("Repetitively checking persistent tag " + "'{}' as a short").format(id_)) while DM is not None: s, v = DM.GetPersistentTagGroup().GetTagAsShort(id_) if s: index = v DM.GetPersistentTagGroup().DeleteTagWithLabel(id_) log_debug(self._logger, ("Found tag '{}' with value '{}', " + "deleted it now.").format(id_, v)) break time.sleep(0.1) if 0 <= index and index < len(options): log_debug( self._logger, "User was asked '{}' and clicked '{}'".format( text, options[index])) return index else: err = StopProgram() log_debug(self._logger, "Stopping program", exc_info=err) raise err
setvars = { "b": -193.3288, "tg4": { "test-key 1": 1, "test-key 2": { "test-key 3": False, "test-key 4": None } }, "tl6": ["A", "B", ["U", "V"], (-101, -120)] } with execdmscript.exec_dmscript(script1, script2, script3, readvars=readvars, setvars=setvars, separate_thread=False, debug=False, debug_file=None) as script: for key in script.synchronized_vars.keys(): print("Variable '", key, "'") pprint.pprint(script[key]) # wrapper = execdmscript.DMScriptWrapper(script1, script2, script3, # readvars=readvars, setvars=setvars) # # exec_script = wrapper.getExecDMScriptCode() # # print("The following script is being executed:") # print(exec_script) except Exception as e:
self.super.init(Dialog); return self; } } // do not move this in the thread part, this will not work anymore object progress_dlg = alloc(ProgressDialog).init(); """ exec_script = """ if(!GetPersistentTagGroup().TagGroupDoesTagExist("__progress")){ GetPersistentTagGroup().TagGroupCreateNewLabeledTag("__progress"); GetPersistentTagGroup().TagGroupSetTagAsLong("__progress", 0); } progress_dlg.pose(); if(GetPersistentTagGroup().TagGroupDoesTagExist("__progress")){ GetPersistentTagGroup().TagGroupDeleteTagWithLabel("__progress"); } RemoveMainThreadTask(update_task); """ with exec_dmscript(dialog_script, separate_thread=(exec_script, ), debug=False) as script: pass thread.join() except Exception as e: # dm-script error messages are very bad, use this for getting the error text and the # correct traceback print("Exception: ", e) import traceback traceback.print_exc()
import execdmscript dmscript1 = "number c = a + b;" dmscript2 = "number d = c + a;" dmscript3 = r"C:\testdmscript5.s" setvars = {"a": 1, "b": 2} readvars = {"c": int, "d": int, "e": int} with execdmscript.exec_dmscript(dmscript1, dmscript2, dmscript3, setvars=setvars, readvars=readvars) as script: print("c:", script["c"]) print("d:", script["d"]) print("e:", script["e"])
# whether to add another tag add_tag = True while add_tag: # ask for the tag name and value tag_name = input("Please enter a tag name to add to the image") tag_value = input( "Please enter the value for the tag '{}'".format(tag_name)) tags[tag_name] = tag_value tag_str = execdmscript.escape_dm_string(pprint.pformat(tags)) print(tag_str) # ask whether to add another tag add_tag = False with execdmscript.exec_dmscript(dm_code.format(tag_str), readvars={"add_tag": int}) as script: add_tag = script["add_tag"] # convert the tags to a tag group object tags = execdmscript.convert_to_taggroup(tags) # apply the tag group object to the image img.GetTagGroup().DeleteAllTags() img.GetTagGroup().CopyTagsFrom(tags) img.ShowImage() except Exception as e: # dm-script error messages only show the error type but not the message print("Exception: ", e) import traceback traceback.print_exc()
import execdmscript # `a` and `b` are given in python a = 10 b = 20 # This is the dm-script to execute dmscript = "number c = a + b;" # This are the variables the upper dm-script will know setvars = {"a": a, "b": b} # This are the variables this python script will know after the execution readvars = {"c": int} with execdmscript.exec_dmscript(dmscript, setvars=setvars, readvars=readvars) as script: # now we can access `c` because it is set in the `readvars` print(script["c"])