def getConditions(self): """Create the conditions list. The return value is a list of dicts, each dict has a key index and a min and/or max index Returns ------- list of dict the conditions """ conditions = [] for i, key_input in enumerate(self._condition_key): if i < len(self._condition_max) and i < len(self._condition_min): key = str(self._condition_key[i].itemData( self._condition_key[i].currentIndex())) min_value = self._condition_min[i].text() max_value = self._condition_max[i].text() if (key != "" and (my_utilities.is_numeric(min_value) or my_utilities.is_numeric(max_value))): cond = {"key": key} if my_utilities.is_numeric(min_value): cond["min"] = my_utilities.force_float(min_value) if my_utilities.is_numeric(max_value): cond["max"] = my_utilities.force_float(max_value) conditions.append(cond) return conditions
def updateLineData(self, xdata, ydata, plot_data_index, line_index=0): """Sets x and y data of the line with the line_index of the given plot_data_index. This will change the plot line to a new line. The plot data should normally contain only one data set for a line. This means that the line_index is (nearly) always 0. This is an update method, they can be called after the PlotData has been plotted. To commit all the updates and display them use the PlotCanvas.commitUpdate() function. Parameters ---------- xdata, ydata : list of floats The new x and y data as a list plot_data_index : int The index of the plot data line_index : int, optional The index of the line to update, default: 0 """ if my_utilities.is_numeric( plot_data_index) and my_utilities.is_numeric(line_index): try: line = self._plots[plot_data_index][line_index] except IndexError: return False else: return False line.set_data(xdata, ydata) return True
def _drawGrid(self, vertical_lines, datalist, ref_axes=None): """Draws the actual grid. Paramters --------- vertical_lines : boolean Whether to print verticale lines or horzontal lines datalist : list The x or y data depending on the vertical lines ref_axes : int, optional The index of the axes Return ------ boolean success """ ref_axes = self._getRefAxes(ref_axes) axes = self.axes[ref_axes] if not isinstance(datalist, (list, tuple)): return False for v in datalist: if my_utilities.is_numeric(v): v = my_utilities.force_float(v) if vertical_lines: axes.axvline(v, linewidth=1, color="lightgrey") else: axes.axhline(v, linewidth=1, color="lightgrey") return True
def _actionCombobox(self): """The action method for the combobox. This will change the column to contain a preview of the datacontainers values""" wizard = self.wizard() sender = self.sender() if isinstance(sender, QtWidgets.QComboBox): # the axis and the column column = sender.property("column") axis = sender.itemData(sender.currentIndex()) if my_utilities.is_numeric(column) and axis != None: column = int(column) mode = self.getMode() name = sender.currentText() # check the current mode and get the data for the mode and for # the axis if mode == 0: data, unit = wizard.result_datacontainer.getDataForExport(axis) elif mode == 1: data, unit = wizard.result_datacontainer.getDataPointDataForCSVExport(axis) data = data[0:self._preview_row_count - 1] # find exponent of the highest value d = int(math.log10(abs(max(data)))) if d < 1: d -= 1 # parse the unit unit = str(unit) # add the table items for i in range(0, self._preview_row_count - 1): # add the name and the unit in the 2nd row, in the last row # add ... if i == self._preview_row_count - 2: text = "..." align = QtCore.Qt.AlignCenter elif i == 0: text = str(name) if unit != "": text += " [" + unit + "] (rounded)" align = QtCore.Qt.AlignCenter else: if d < 1: text = str(round(data[i]* 10**(-1 * d), 3)) + "E" + str(d) else: text = str(round(data[i])) align = QtCore.Qt.AlignLeft # create and add the item item = QtWidgets.QTableWidgetItem(text) item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) item.setTextAlignment(align) self._content_table.setItem(i + 1, column, item)
def current_axes(self, current_axes): if my_utilities.is_numeric(current_axes): try: current_axes = int(current_axes) except OverflowError: return False if current_axes >= 0 and current_axes < len(self.axes): self._current_axes = current_axes
def error(self, error): """Show the given error in the error dialg. Parameters ---------- error : Exception, Warning or String The error """ self._error_count += 1 m = 100 if self._error_count == m: error = "There are more than {} errors, furhter errors will not be shown.".format( m) elif self._error_count > m: return error_text = str(error) if isinstance(error, (list, tuple)): for err in error: self.error(err) return elif isinstance(error, warnings.WarningMessage): error_text = "{} in {} in line {}".format( error.message, os.path.basename(error.filename), error.lineno) if hasattr(error, "index") and my_utilities.is_numeric( error.index): error_text += " in datapoint #{}".format(error.index) elif isinstance(sys.exc_info(), (list, tuple)) and len(sys.exc_info()) > 0: # use slice for avoiding errors, throwing an exception will cause # an infinite loop exception_type = sys.exc_info()[0] traceback = sys.exc_info()[-1] if traceback != None: error_text += ", last exception ({}) in {} in line {}".format( exception_type, os.path.split(traceback.tb_frame.f_code.co_filename)[1], traceback.tb_lineno) if error_text[-1] != ".": error_text += "." old_text = self._error_text.text() self._error_text.setText(("<b>Error:</b> " + error_text[0].upper() + error_text[1:] + "<br />" + old_text)) self._error_text.adjustSize() if not self._error_dialog.isVisible(): self._error_dialog.show()
def incrementDataPointIndex(self, increment=None): """Increments the datapoint index, ifthe increment is not given the value will be incremented by 1 Parameters ---------- increment : int The increment """ sender = self.sender() wizard = self.wizard() if not my_utilities.is_numeric(increment): if (isinstance(sender, QtCore.QObject) and my_utilities.is_numeric(sender.property("increment"))): increment = int(sender.property("increment")) else: increment = 1 index = self.getDataPointIndex() index += increment if (wizard.result_datacontainer != None and isinstance(wizard.result_datacontainer, DataHandling.DataContainer.DataContainer)): l = len(wizard.result_datacontainer.datapoints) if index < 0 or index >= l: index = index % l else: index = 0 self._datapoint_index_input.setText(str(index))
def unzipIndices(self, indices_string): """Creates an array which contains all the indices in the given indices_string. This is the inverted method for the GraphWizard.zipIndices method. Paramters --------- indices_string : String The indices in a human readable string Returns ------- list The list of indices of the datapoints """ space_regexp = re.compile("\\s+") indices_string = space_regexp.sub("", indices_string) datapoints = [] # split datapoints by ; indices_string = indices_string.split(";") for datapoint_range in indices_string: # split datapoint ranges by : datapoint_range = datapoint_range.split(":") # remove empty or non-strings datapoint_range = filter(lambda x : my_utilities.is_numeric(x), datapoint_range) # convert to int datapoint_range = list(map(lambda x: int(my_utilities.force_float(x, True)), datapoint_range)) if len(datapoint_range) == 1: # only one element so this is a single datapoint index datapoints.append(my_utilities.force_float(datapoint_range[0])) elif len(datapoint_range) > 1: # create range mi = min(datapoint_range) ma = max(datapoint_range) + 1 datapoints = datapoints + list(range(mi, ma)) return datapoints
def replaceDataContainerWidget(self, datacontainer, index=None): """Replace or add the given datacontainer to the internal list. Parameters ---------- datacontainer : DataContainer The datacontainer to add index : int, optional The index to replace, None to append """ # creating widget container_widget = View.DataContainerWidget.DataContainerWidget( datacontainer, self, self._controller) # setting widget if (my_utilities.is_numeric(index) and index >= 0 and index < self._file_list.layout().count()): self._file_list.layout().insertWidget(index, container_widget, 0) else: self._file_list.layout().addWidget(container_widget, 0)
def _getOutputMode(self, output_mode, visible_output_modes=0): """Get the ToolWizard output mode by the given output_mode parameter. This can be a list of output modes, a String or the int constant. If the visible_output_modes parameter is given the current output mode will be added to this mode Parameters ---------- output_mode : list, tuple, int or String The output mode visible_output_modes : int, optional The current output modes where to add the new ones Returns ------- int The output mode constant """ if isinstance(output_mode, (list, tuple)): for mode in output_mode: visible_output_modes = self._getOutputMode( mode, visible_output_modes) elif output_mode == "export": visible_output_modes |= ( View.ToolWizard.ToolWizard.ToolWizard. OUTPUT_MODE_EXPORT_RAW_MPMS | View.ToolWizard.ToolWizard. ToolWizard.OUTPUT_MODE_EXPORT_DAT_MPMS | View.ToolWizard.ToolWizard.ToolWizard.OUTPUT_MODE_EXPORT_CSV) elif output_mode == "plot": visible_output_modes |= ( View.ToolWizard.ToolWizard.ToolWizard.OUTPUT_MODE_PLOT_WINDOW | View.ToolWizard.ToolWizard.ToolWizard.OUTPUT_MODE_SAVE_LIST) elif my_utilities.is_numeric(output_mode): visible_output_modes |= output_mode return visible_output_modes
def showOpenDialog(self, title=None, max_file_count=1, parent=None): """Show a dialog for opening files. This emits the openedFile Signal. Parameters --------- title : String, optional The title, if not given "Open file(s)" will be used max_file_count : int, optional The maximum count of files the user can open, if the parameter is not numeric (or < 0) unlimited files can be opened parent : QWidget The parent widget Returns ------- boolean success """ if title == None or not isinstance(title, str) or len(title) <= 0: title = "Open file" if parent == None and self.isVisible(): parent = self dialog = QtWidgets.QFileDialog(parent) dialog.setWindowTitle(title) dialog.setNameFilter( "MPMS raw files (*.rw.dat);;MPMS files (*.dat);;All files (*.*)") result = dialog.exec() if result: files = dialog.selectedFiles() if my_utilities.is_iterable(files): self.log("Trying to open {0} files".format(len(files))) fs = [] for i, file in enumerate(files): filepath = os.path.dirname(file) filename = os.path.basename(file) dat_filepath = os.path.join( filepath, my_utilities.rreplace(str(filename), ".rw.dat", ".dat", 1)) if not os.path.isfile(dat_filepath): dat_filepath = self.showMissingDatfileDialog( file, dat_filepath, parent) if dat_filepath == False: self.openFileAborted.emit() self.log("Opening file(s) aborted.") return False fs.append((file, dat_filepath)) if (my_utilities.is_numeric(max_file_count) and max_file_count > 0 and len(fs) >= max_file_count): break self.openFiles(fs, parent) else: # this should never happen self.openFileAborted.emit() self._error("The file(s) cannot be received from the dialog")
def subtractBackgroundData(self, datacontainer, background_datacontainer, extend_mode = None, indices_list = None): """Subtract the backgrdound_datacontainer from the datacontainer. The actual subtracting will be done in the DataPoint Parameters ---------- datacontainer : DataContainer The datacontainer which contains the original data where the background data should be subtracted from background_datacontainer: DataContainer The datacontainer which holds the background data Returns ------- DataContainer A new datacontainer which holds the data with subtracted background """ print("Controller.subtractBackgroundData():", len(datacontainer.datapoints), len(background_datacontainer.datapoints)) if (isinstance(datacontainer, DataHandling.DataContainer.DataContainer) and isinstance(background_datacontainer, DataHandling.DataContainer.DataContainer)): # create a copy of the original datacontainer new_datacontainer = copy.deepcopy(datacontainer) new_datacontainer.setData(DataHandling.DataContainer.DataContainer.ORIGINAL_DATA, datacontainer) new_datacontainer.setData(DataHandling.DataContainer.DataContainer.BACKGROUND_DATA, background_datacontainer) new_datacontainer.addAttribute("Background removed") new_datacontainer.removed_background = True # store the errors errors = [] if len(datacontainer.datapoints) != len(background_datacontainer.datapoints): # get the extend type extend_keys = [i[1] for i in Constants.BACKGROUND_INCREASE_MODES] if extend_mode == None or extend_mode not in extend_keys: extend_mode = extend_keys[0] if not isinstance(indices_list, (list, tuple)): indices_list = self.zipFullRange(background_datacontainer.datapoints) # prepare the plain data = [] for datapoint in datacontainer.datapoints: data.append(datapoint.getPlotData( DataHandling.DataPoint.DataPoint.RAW_POSITION, DataHandling.DataPoint.DataPoint.RAW_VOLTAGE, True)) # prepare the background data background = [] for datapoint in background_datacontainer.datapoints: background.append(datapoint.getPlotData( DataHandling.DataPoint.DataPoint.RAW_POSITION, DataHandling.DataPoint.DataPoint.RAW_VOLTAGE, True)) try: # get the processed (extended) background data background_data = DataHandling.calculation.extendBackgroundData( data, background, extend_mode, indices_list, datacontainer, background_datacontainer) except Exception as e: error_loc = "" if isinstance(sys.exc_info(), (list, tuple)) and len(sys.exc_info()) > 0: # use slice for avoiding errors, throwing an exception will cause # an infinite loop exception_type = sys.exc_info()[0] traceback = sys.exc_info()[-1] if traceback != None: error_loc += "; Last exception ({}) in {} in line {}".format( exception_type, os.path.split(traceback.tb_frame.f_code.co_filename)[1], traceback.tb_lineno) errors.append(type(e).__name__ + ": " + str(e) + error_loc) else: background_data = background_datacontainer with warnings.catch_warnings(record=True) as ws: # go through all the datapoints of the original data for index, datapoint in enumerate(new_datacontainer.datapoints): print("Controller.subtractBackgroundData(): index: ", index) # perform the background removing try: new_datacontainer.datapoints[index].index = index new_datacontainer.datapoints[index].removeBackgroundData( self._getBackgroundDataPoint(background_data, index)) except Exception as e: errors.append("Datapoint #{} raised Error: ".format(index) + str(e)) # fit the datapoint again try: new_datacontainer.datapoints[index].execFit() except Exception as e: errors.append("Datapoint #{} raised Error: ".format(index) + str(e)) for w in ws: w.index = index for error in errors: if isinstance(error, warnings.WarningMessage): error = str(error.message) if hasattr(error, "index") and my_utilities.is_numeric(error.index): error += " in datapoint #{}".foramt(error.index) error += " in {} in file {}".format( error.lineno, os.path.basename(error.filename)) else: error = str(error) warnings.warn(error) return new_datacontainer return None
def highlightPosition(self, x, y, ref_axes=None, update_plot=True, text=None): """Highlight the position defined by the x and y value. The highlight point will be drawn in the ref_axes. Parameters ---------- x, y: int or list of ints The coordinates of the point(s) to highlight ref_axes : int, optional The index of the axes update_plot : boolean, optional Whether to update the plot or not, if this is False the highlight point will be displayed **after** the PlotCanvas.commitUpdate() function has been called, default: True text : String or list of Strings Some text to write on the given points """ if not isinstance(x, (list, tuple)): x = [x] if not isinstance(y, (list, tuple)): y = [y] if self.marker != "": marker = self.marker else: marker = "o" if my_utilities.is_numeric(self.markersize): markersize = my_utilities.force_float(self.markersize) + 1 else: markersize = 1 if text != None and not isinstance(text, (list, tuple)): text = [text] if isinstance(text, (list, tuple)): fig = self.getFigure() transform_matrix = fig.dpi_scale_trans.inverted() for i, t in enumerate(text): if isinstance(ref_axes, (list, tuple)) and i < len(ref_axes): axes_index = self._getRefAxes(ref_axes[i]) else: axes_index = self._getRefAxes(ref_axes) axes = self.axes[axes_index] bbox = axes.get_window_extent().transformed(transform_matrix) height = bbox.height * fig.dpi lim = axes.get_ylim() o = (self.markersize + 2) / height * abs(lim[0] - lim[1]) y_avg = my_utilities.mean_std(y) y_avg = y_avg[0] if i >= 0 and i < len(x) and i < len(y): o = (1 if y[i] >= y_avg else -1) * o self._highlights.append( axes.plot(x[i], y[i], marker=marker, linestyle="None", zorder=PlotCanvas.HIGHLIGHT_Z_ORDER, markersize=markersize, color="r")) self._highlight_texts.append( axes.annotate( str(t), xycoords='data', textcoords='data', xy=(x[i], y[i]), xytext=(x[i], y[i] + o), horizontalalignment='center', zorder=PlotCanvas.HIGHLIGHT_TEXT_Z_ORDER)) if update_plot: self.commitUpdate(False)