def __init__(self, inputTab): super().__init__() self.input = inputTab # initialize the map for locating sections canvas = LineMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.locateSections = QAction('Locate sections\non map', self, icon=self.style().standardIcon(QStyle.SP_DialogHelpButton), triggered=self.locateSectionsEvent) self.locateSections_short = QAction('Locate sections\non map', self, icon=self.style().standardIcon(QStyle.SP_DialogHelpButton), triggered=self.locateSectionsEvent) self.map.closeEvent = self.enable_locate self.cumulativeFluxAct = QAction('Show\ncumulative flux', self, checkable=True, icon=self.style().standardIcon(QStyle.SP_DialogApplyButton)) self.cumulativeFluxAct.toggled.connect(self.changeFluxType) self.toolBar.addAction(self.locateSections) self.toolBar.addSeparator() self.toolBar.addAction(self.selectColumnsAct) self.toolBar.addAction(self.editColumnNamesAct) self.toolBar.addAction(self.editColumColorAct) self.toolBar.addSeparator() self.toolBar.addAction(self.convertTimeAct) self.toolBar.addAction(self.changeDateAct) self.toolBar.addSeparator() self.toolBar.addAction(self.cumulativeFluxAct) self.mapMenu = QMenu('&Map', self) self.mapMenu.addAction(self.locateSections_short) self.menuBar.addMenu(self.mapMenu) self.menuBar.addMenu(self.poly_menu)
def __init__(self, inputTab): super().__init__() self.input = inputTab # initialize the map for locating polygons canvas = PolygonMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.locatePolygons = QAction('Locate polygons\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.locatePolygonsEvent) self.locatePolygons_short = QAction('Locate polygons on map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.locatePolygonsEvent) self.map.closeEvent = self.enable_locate self.toolBar.addAction(self.locatePolygons) self.toolBar.addSeparator() self.toolBar.addAction(self.selectColumnsAct) self.toolBar.addAction(self.editColumnNamesAct) self.toolBar.addAction(self.editColumColorAct) self.toolBar.addSeparator() self.toolBar.addAction(self.convertTimeAct) self.toolBar.addAction(self.changeDateAct) self.mapMenu = QMenu('&Map', self) self.mapMenu.addAction(self.locatePolygons_short) self.menuBar.addMenu(self.mapMenu) self.menuBar.addMenu(self.poly_menu)
def __init__(self, inputTab): super().__init__() self.input = inputTab self.has_map = False canvas = MapCanvas() self.map = MapViewer(canvas) self.var_IDs = [] self.current_var = '' self.openAttributes = QAction('Attributes\nTable', self, icon=self.style().standardIcon( QStyle.SP_FileDialogListView), triggered=self.openAttributesEvent) self.openAttributes_short = QAction('Attributes Table', self, icon=self.style().standardIcon( QStyle.SP_FileDialogListView), triggered=self.openAttributesEvent) self.locatePoints = QAction('Locate points\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.map_event) self.locatePoints_short = QAction('Locate points on map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.map_event) self.input.map.closeEvent = self.enable_locate self.input.attribute_table.closeEvent = self.enable_attribute self.toolBar.addAction(self.locatePoints) self.toolBar.addAction(self.openAttributes) self.toolBar.addSeparator() self.toolBar.addAction(self.select_variable) self.toolBar.addAction(self.selectColumnsAct) self.toolBar.addAction(self.editColumnNamesAct) self.toolBar.addAction(self.editColumColorAct) self.toolBar.addSeparator() self.toolBar.addAction(self.convertTimeAct) self.toolBar.addAction(self.changeDateAct) self.mapMenu = QMenu('&Map', self) self.mapMenu.addAction(self.locatePoints) self.pointsMenu = QMenu('&Data', self) self.pointsMenu.addAction(self.openAttributes_short) self.pointsMenu.addSeparator() self.pointsMenu.addAction(self.select_variable_short) self.pointsMenu.addAction(self.selectColumnsAct_short) self.pointsMenu.addAction(self.editColumnNamesAct_short) self.pointsMenu.addAction(self.editColumColorAct_short) self.menuBar.addMenu(self.mapMenu) self.menuBar.addMenu(self.pointsMenu)
def __init__(self, parent): super().__init__(parent) canvas = LineMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.data = None self.mesh = None self.lines = [] self.line_interpolators = [] self.line_interpolators_internal = [] # without intersection points self._initWidgets() # some instance attributes will be set there self._setLayout() self._bindEvents()
def __init__(self, parent): super().__init__(parent) self.ref_data = None self.test_data = None self.ref_mesh = None self.polygons = [] self.selected_polygon = None self.ref_mesh = None self.polygon_added = False # is the intersection between the mesh and the selected polygon calculated? # initialize the map for locating polygons canvas = PolygonMapCanvas() self.map = MapViewer(canvas) self.has_map = False self._initWidgets() self._setLayout() self._bindEvents()
def __init__(self, parent): super().__init__(parent) self.old_frequency = '1' canvas = MapCanvas() self.map = MapViewer(canvas) self.has_map = False self.data = None self.mesh = None self.points = [] self.point_interpolators = [] self.fields = [] self.attributes = [] self.attribute_table = PointAttributeTable() self._initWidgets() # some instance attributes will be set there self._setLayout() self._bindEvents()
class ImageTab(VolumePlotViewer): def __init__(self, inputTab): super().__init__() self.input = inputTab # initialize the map for locating polygons canvas = PolygonMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.locatePolygons = QAction('Locate polygons\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.locatePolygonsEvent) self.locatePolygons_short = QAction('Locate polygons on map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.locatePolygonsEvent) self.map.closeEvent = self.enable_locate self.toolBar.addAction(self.locatePolygons) self.toolBar.addSeparator() self.toolBar.addAction(self.selectColumnsAct) self.toolBar.addAction(self.editColumnNamesAct) self.toolBar.addAction(self.editColumColorAct) self.toolBar.addSeparator() self.toolBar.addAction(self.convertTimeAct) self.toolBar.addAction(self.changeDateAct) self.mapMenu = QMenu('&Map', self) self.mapMenu.addAction(self.locatePolygons_short) self.menuBar.addMenu(self.mapMenu) self.menuBar.addMenu(self.poly_menu) def enable_locate(self, event): self.locatePolygons.setEnabled(True) self.locatePolygons_short.setEnabled(True) def getData(self): # get the new data csv_file = self.input.csvNameBox.text() self.data, headers = read_csv(csv_file, self.input.parent.csv_separator) self.var_ID = self.input.var_ID self.second_var_ID = self.input.second_var_ID if self.input.data.header.date is not None: year, month, day, hour, minute, second = self.input.data.header.date self.start_time = datetime.datetime(year, month, day, hour, minute, second) else: self.start_time = datetime.datetime(1900, 1, 1, 0, 0, 0) self.datetime = list( map(lambda x: self.start_time + datetime.timedelta(seconds=x), self.data['time'])) self.str_datetime = list( map(lambda x: x.strftime('%Y/%m/%d\n%H:%M'), self.datetime)) self.str_datetime_bis = list( map(lambda x: x.strftime('%d/%m/%y\n%H:%M'), self.datetime)) self.columns = headers[1:] self.column_labels = {x: x for x in self.columns} self.column_colors = { column: color for column, color in zip(self.columns, cycle(self.defaultColors)) } # initialize the plot self.time = [ self.data['time'], self.data['time'], self.data['time'], self.data['time'] / 60, self.data['time'] / 3600, self.data['time'] / 86400 ] self.language = self.input.data.language self.current_xlabel = self._defaultXLabel() self.current_ylabel = self._defaultYLabel() self.current_title = '' self.replot() def locatePolygonsEvent(self): if not self.has_map: self.map.canvas.reinitFigure( self.input.mesh, self.input.polygons, map(self.column_labels.get, [ 'Polygon %d' % (i + 1) for i in range(len(self.input.polygons)) ])) self.has_map = True self.locatePolygons.setEnabled(False) self.locatePolygons_short.setEnabled(False) self.map.show() def reset(self): self.has_map = False self.map.close() super().reset() self.current_columns = ('Polygon 1', )
class InputTab(SerafinInputTab): def __init__(self, parent): super().__init__(parent) self.ref_data = None self.test_data = None self.ref_mesh = None self.polygons = [] self.selected_polygon = None self.ref_mesh = None self.polygon_added = False # is the intersection between the mesh and the selected polygon calculated? # initialize the map for locating polygons canvas = PolygonMapCanvas() self.map = MapViewer(canvas) self.has_map = False self._initWidgets() self._setLayout() self._bindEvents() def _initWidgets(self): # create the button open the reference file self.btnOpen.setText('Load\nReference') # create the button open the test file self.btnOpenTest = QPushButton('Load\nTest', self, icon=self.style().standardIcon( QStyle.SP_DialogOpenButton)) self.btnOpenTest.setToolTip('<b>Open</b> a Serafin file') self.btnOpenTest.setFixedSize(105, 50) self.btnOpenTest.setEnabled(False) # create the button open the polygon file self.btnOpenPolygon = QPushButton('Load polygons\n(optional)', self, icon=self.style().standardIcon( QStyle.SP_DialogOpenButton)) self.btnOpenPolygon.setToolTip('<b>Open</b> a .i2s or .shp file') self.btnOpenPolygon.setFixedSize(135, 50) self.btnOpenPolygon.setEnabled(False) # create the button for locating polygons on map self.locatePolygons = QPushButton('Locate polygons\non map', icon=self.style().standardIcon( QStyle.SP_DialogHelpButton)) self.locatePolygons.setToolTip('<b>Open</b> a map with polygons') self.locatePolygons.setFixedSize(135, 50) self.locatePolygons.setEnabled(False) # create some text fields displaying the IO files info self.testNameBox = QLineEdit() self.testNameBox.setReadOnly(True) self.testNameBox.setFixedHeight(30) self.testNameBox.setMinimumWidth(600) self.testSummaryTextBox = QPlainTextEdit() self.testSummaryTextBox.setReadOnly(True) self.testSummaryTextBox.setMinimumHeight(40) self.testSummaryTextBox.setMaximumHeight(50) self.testSummaryTextBox.setMinimumWidth(600) self.polygonNameBox = QPlainTextEdit() self.polygonNameBox.setReadOnly(True) self.polygonNameBox.setFixedHeight(50) self.polygonNameBox.setMinimumWidth(600) # create combo box widgets for choosing the variable self.varBox = QComboBox() self.varBox.setFixedSize(400, 30) # create combo box widgets for choosing the polygon self.polygonBox = QComboBox() self.polygonBox.setFixedSize(400, 30) def _bindEvents(self): self.btnOpen.clicked.connect(self.btnOpenRefEvent) self.btnOpenTest.clicked.connect(self.btnOpenTestEvent) self.btnOpenPolygon.clicked.connect(self.btnOpenPolygonEvent) self.locatePolygons.clicked.connect(self.locatePolygonsEvent) self.polygonBox.currentTextChanged.connect(self.selectPolygonEvent) self.map.closeEvent = lambda event: self.locatePolygons.setEnabled(True ) def _setLayout(self): mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 20)) mainLayout.setSpacing(15) hlayout = QHBoxLayout() hlayout.setAlignment(Qt.AlignLeft) hlayout.addItem(QSpacerItem(50, 1)) hlayout.addWidget(self.btnOpen) hlayout.addWidget(self.btnOpenTest) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.langBox) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnOpenPolygon) hlayout.addWidget(self.locatePolygons) hlayout.setSpacing(10) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(10, 10)) glayout = QGridLayout() glayout.addWidget(QLabel(' Reference'), 1, 1) glayout.addWidget(self.inNameBox, 1, 2) glayout.addWidget(QLabel(' Summary'), 2, 1) glayout.addWidget(self.summaryTextBox, 2, 2) glayout.addWidget(QLabel(' Test'), 3, 1) glayout.addWidget(self.testNameBox, 3, 2) glayout.addWidget(QLabel(' Summary'), 4, 1) glayout.addWidget(self.testSummaryTextBox, 4, 2) glayout.addWidget(QLabel(' Polygons'), 5, 1) glayout.addWidget(self.polygonNameBox, 5, 2) glayout.setAlignment(Qt.AlignLeft) glayout.setVerticalSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(10, 10)) glayout = QGridLayout() glayout.addWidget(QLabel(' Select the variable to compare'), 1, 1) glayout.addWidget(self.varBox, 1, 2) glayout.addWidget(QLabel(' Select the comparison domain'), 2, 1) glayout.addWidget(self.polygonBox, 2, 2) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.setAlignment(glayout, Qt.AlignTop | Qt.AlignLeft) mainLayout.addItem(QSpacerItem(30, 15)) mainLayout.addWidget(QLabel(' Message logs')) mainLayout.addWidget(self.logTextBox.widget) self.setLayout(mainLayout) self.setLayout(mainLayout) def _reinitRef(self): self.reset() self.ref_mesh = None self.ref_data = None self.polygon_added = False self.selected_polygon = None self.polygons = [] self.test_data = None self.testSummaryTextBox.clear() self.testNameBox.clear() self.polygonNameBox.clear() self.varBox.clear() self.polygonBox.clear() self.btnOpenTest.setEnabled(False) self.btnOpenPolygon.setEnabled(False) self.locatePolygons.setEnabled(False) self.map.hide() self.has_map = False self.parent.reset() def _reinitTest(self, filename): self.test_data = None self.testNameBox.setText(filename) self.testSummaryTextBox.clear() self.varBox.clear() def locatePolygonsEvent(self): if not self.has_map: self.map.canvas.reinitFigure( self.ref_mesh, self.polygons, ['Polygon %d' % (i + 1) for i in range(len(self.polygons))]) self.has_map = True self.locatePolygons.setEnabled(False) self.map.show() def selectPolygonEvent(self, text): if not text: return elif text == 'Entire mesh': self.selected_polygon = None else: polygon_index = int(text.split()[1]) - 1 self.selected_polygon = self.polygons[polygon_index] self.polygon_added = False def btnOpenRefEvent(self): canceled, filename = super().open_event() if canceled: return self._reinitRef() success, data = self.read_2d(filename) if not success: return self.ref_data = data # record the mesh self.parent.inDialog() meshLoader = LoadMeshDialog('comparison', self.ref_data.header) self.ref_mesh = meshLoader.run() self.parent.outDialog() if meshLoader.thread.canceled: self.summaryTextBox.clear() self.ref_data = None return self.parent.add_reference() self.btnOpenTest.setEnabled(True) self.btnOpenPolygon.setEnabled(True) self.polygonBox.addItem('Entire mesh') def btnOpenTestEvent(self): canceled, filename = super().open_event() if canceled: return self._reinitTest(filename) success, data = self.read_2d(filename, update=False) if not success: return # check if the mesh is identical to the reference if not np.all(self.ref_data.header.x == data.header.x) or \ not np.all(self.ref_data.header.y == data.header.y) or \ not np.all(self.ref_data.header.ikle == data.header.ikle): QMessageBox.critical( self, 'Error', 'The mesh is not identical to the reference.', QMessageBox.Ok) return # check if the test file has common variables with the reference file common_vars = [(var_ID, var_names) for var_ID, var_names in zip( self.ref_data.header.var_IDs, self.ref_data.header.var_names) if var_ID in data.header.var_IDs] if not common_vars: QMessageBox.critical( self, 'Error', 'No common variable with the reference file.', QMessageBox.Ok) return self.test_data = data self.testNameBox.setText(filename) self.testSummaryTextBox.appendPlainText( self.test_data.header.summary()) self.parent.add_test() for var_ID, var_name in common_vars: self.varBox.addItem(var_ID + ' (%s)' % var_name.decode('utf-8').strip()) def btnOpenPolygonEvent(self): success, filename, polygons = open_polygons() if not success: return self.polygons = polygons self.map.close() self.map.has_figure = False self.polygonNameBox.clear() self.polygonNameBox.appendPlainText( filename + '\n' + 'The file contains {} polygon{}.'.format( len(self.polygons), 's' if len(self.polygons) > 1 else '')) self.polygonBox.clear() self.polygonBox.addItem('Entire mesh') for i in range(len(self.polygons)): self.polygonBox.addItem('Polygon %d' % (i + 1)) self.locatePolygons.setEnabled(True)
def __init__(self, inputTab): super().__init__() self.input = inputTab self.ewsd = None self.xlim = None self.ylim = None # set up a custom plot viewer self.plotViewer = PlotViewer() self.plotViewer.exitAct.setEnabled(False) self.plotViewer.menuBar.setVisible(False) self.XLimitsAct = QAction('Change X limits', self, triggered=self.changeXlimits, enabled=False, icon=self.style().standardIcon( QStyle.SP_DialogNoButton)) self.YLimitsAct = QAction('Change Y limits', self, triggered=self.changeYlimits, enabled=False, icon=self.style().standardIcon( QStyle.SP_DialogNoButton)) self.plotViewer.toolBar.addAction(self.XLimitsAct) self.plotViewer.toolBar.addAction(self.YLimitsAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.xLabelAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.yLabelAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.titleAct) # put it in a group box to get a nice border gb = QGroupBox() ly = QHBoxLayout() ly.addWidget(self.plotViewer) gb.setLayout(ly) gb.setStyleSheet( 'QGroupBox {border: 8px solid rgb(108, 122, 137); border-radius: 6px }' ) gb.setMinimumWidth(600) # create the reference time selection widget self.timeSelection = DoubleTimeSelection() # create the compute button self.btnCompute = QPushButton('Compute', icon=self.style().standardIcon( QStyle.SP_DialogApplyButton)) self.btnCompute.setFixedSize(105, 50) self.btnCompute.clicked.connect(self.btnComputeEvent) # create the color map button self.btnColorMap = QPushButton('2D View', icon=self.style().standardIcon( QStyle.SP_DialogHelpButton)) self.btnColorMap.setFixedSize(105, 50) self.btnColorMap.clicked.connect(self.btnColorMapEvent) self.btnColorMap.setEnabled(False) # initialize the map for 2D view canvas = ColorMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.map.closeEvent = lambda event: self.btnColorMap.setEnabled(True) # create the stats box self.resultBox = QPlainTextEdit() self.resultBox.setMinimumWidth(400) self.resultBox.setMaximumWidth(600) # set layout mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.addWidget(self.timeSelection) vlayout = QVBoxLayout() hlayout = QHBoxLayout() hlayout.addWidget(self.btnColorMap) hlayout.addWidget(self.btnCompute) hlayout.setSpacing(10) vlayout.addLayout(hlayout) vlayout.setAlignment(hlayout, Qt.AlignTop | Qt.AlignRight) vlayout.addItem(QSpacerItem(10, 10)) vlayout.addWidget(self.resultBox) vlayout.setAlignment(Qt.AlignHCenter) hlayout = QHBoxLayout() hlayout.addLayout(vlayout) hlayout.addWidget(gb, Qt.AlignHCenter) hlayout.setSpacing(10) mainLayout.addLayout(hlayout) self.setLayout(mainLayout) # template for text output self.template = '=== EWSD distribution between Ref (frame {}) and Test (frame {}) ===\n'\ 'Mean \t{:<30}\n' \ 'Variance \t{:<30}\n' \ 'Min \t{:<30}\n' \ 'Quartile 25 \t{:<30}\n' \ 'Median \t{:<30}\n' \ 'Quartile 75 \t{:<30}\n' \ 'Max \t{:<30}\n'
class ErrorDistributionTab(QWidget): def __init__(self, inputTab): super().__init__() self.input = inputTab self.ewsd = None self.xlim = None self.ylim = None # set up a custom plot viewer self.plotViewer = PlotViewer() self.plotViewer.exitAct.setEnabled(False) self.plotViewer.menuBar.setVisible(False) self.XLimitsAct = QAction('Change X limits', self, triggered=self.changeXlimits, enabled=False, icon=self.style().standardIcon( QStyle.SP_DialogNoButton)) self.YLimitsAct = QAction('Change Y limits', self, triggered=self.changeYlimits, enabled=False, icon=self.style().standardIcon( QStyle.SP_DialogNoButton)) self.plotViewer.toolBar.addAction(self.XLimitsAct) self.plotViewer.toolBar.addAction(self.YLimitsAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.xLabelAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.yLabelAct) self.plotViewer.toolBar.addSeparator() self.plotViewer.toolBar.addAction(self.plotViewer.titleAct) # put it in a group box to get a nice border gb = QGroupBox() ly = QHBoxLayout() ly.addWidget(self.plotViewer) gb.setLayout(ly) gb.setStyleSheet( 'QGroupBox {border: 8px solid rgb(108, 122, 137); border-radius: 6px }' ) gb.setMinimumWidth(600) # create the reference time selection widget self.timeSelection = DoubleTimeSelection() # create the compute button self.btnCompute = QPushButton('Compute', icon=self.style().standardIcon( QStyle.SP_DialogApplyButton)) self.btnCompute.setFixedSize(105, 50) self.btnCompute.clicked.connect(self.btnComputeEvent) # create the color map button self.btnColorMap = QPushButton('2D View', icon=self.style().standardIcon( QStyle.SP_DialogHelpButton)) self.btnColorMap.setFixedSize(105, 50) self.btnColorMap.clicked.connect(self.btnColorMapEvent) self.btnColorMap.setEnabled(False) # initialize the map for 2D view canvas = ColorMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.map.closeEvent = lambda event: self.btnColorMap.setEnabled(True) # create the stats box self.resultBox = QPlainTextEdit() self.resultBox.setMinimumWidth(400) self.resultBox.setMaximumWidth(600) # set layout mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.addWidget(self.timeSelection) vlayout = QVBoxLayout() hlayout = QHBoxLayout() hlayout.addWidget(self.btnColorMap) hlayout.addWidget(self.btnCompute) hlayout.setSpacing(10) vlayout.addLayout(hlayout) vlayout.setAlignment(hlayout, Qt.AlignTop | Qt.AlignRight) vlayout.addItem(QSpacerItem(10, 10)) vlayout.addWidget(self.resultBox) vlayout.setAlignment(Qt.AlignHCenter) hlayout = QHBoxLayout() hlayout.addLayout(vlayout) hlayout.addWidget(gb, Qt.AlignHCenter) hlayout.setSpacing(10) mainLayout.addLayout(hlayout) self.setLayout(mainLayout) # template for text output self.template = '=== EWSD distribution between Ref (frame {}) and Test (frame {}) ===\n'\ 'Mean \t{:<30}\n' \ 'Variance \t{:<30}\n' \ 'Min \t{:<30}\n' \ 'Quartile 25 \t{:<30}\n' \ 'Median \t{:<30}\n' \ 'Quartile 75 \t{:<30}\n' \ 'Max \t{:<30}\n' def add_reference(self): self.timeSelection.initRef(self.input.ref_data.header.nb_frames) def add_test(self): self.timeSelection.initTest(self.input.test_data.header.nb_frames) def reset(self): self.ewsd = None self.xlim = None self.ylim = None self.has_map = False self.timeSelection.clearText() self.resultBox.clear() self.plotViewer.defaultPlot() self.plotViewer.current_title = 'Distribution of EWSD (element-wise signed deviation)' self.plotViewer.current_ylabel = 'Frequency' self.plotViewer.current_xlabel = 'EWSD' self.XLimitsAct.setEnabled(False) self.YLimitsAct.setEnabled(False) self.btnColorMap.setEnabled(False) def changeXlimits(self): value, ok = QInputDialog.getText( self, 'Change X limits', 'Enter the new X limits', text=', '.join( map(lambda x: '{:+f}'.format(x), self.plotViewer.canvas.axes.get_xlim()))) if not ok: return try: xmin, xmax = map(float, value.split(',')) except ValueError: QMessageBox.critical(self, 'Error', 'Invalid input.', QMessageBox.Ok) return self.xlim = xmin, xmax self.updateHistogram() self.has_map = False def changeYlimits(self): value, ok = QInputDialog.getText( self, 'Change Y limits', 'Enter the new Y limits', text=', '.join( map(lambda x: '{:+f}'.format(x), self.plotViewer.canvas.axes.get_ylim()))) if not ok: return try: self.ylim = tuple(map(float, value.split(','))) except ValueError: QMessageBox.critical(self, 'Error', 'Invalid input.', QMessageBox.Ok) return self.plotViewer.canvas.axes.set_ylim(self.ylim) self.plotViewer.canvas.draw() def updateStats(self, ref_time, test_time): ewsd = np.array(list(self.ewsd.values())) quantile25, median, quantile75 = np.percentile(ewsd, [25, 50, 75]) self.resultBox.appendPlainText( self.template.format(ref_time + 1, test_time + 1, np.mean(ewsd), np.var(ewsd, ddof=1), np.min(ewsd), quantile25, median, quantile75, np.max(ewsd))) def updateHistogram(self): ewsd = list(self.ewsd.values()) if self.xlim is not None: ewsd = list( filter(lambda x: self.xlim[0] <= x <= self.xlim[1], ewsd)) weights = np.ones_like( ewsd ) / self.input.ref_mesh.nb_triangles_inside # make frequency histogram self.plotViewer.canvas.axes.clear() self.plotViewer.canvas.axes.grid(linestyle='dotted') self.plotViewer.canvas.axes.hist(ewsd, weights=weights, histtype='bar', color='g', edgecolor='k', alpha=0.5) self.plotViewer.canvas.axes.set_xlabel(self.plotViewer.current_xlabel) self.plotViewer.canvas.axes.set_ylabel(self.plotViewer.current_ylabel) self.plotViewer.canvas.axes.set_title(self.plotViewer.current_title) if self.ylim is not None: self.plotViewer.canvas.axes.set_ylim(self.ylim) self.plotViewer.canvas.draw() self.btnColorMap.setEnabled(True) self.XLimitsAct.setEnabled(True) self.YLimitsAct.setEnabled(True) def btnComputeEvent(self): self.xlim = None self.ylim = None self.has_map = False ref_time = int(self.timeSelection.refIndex.text()) - 1 test_time = int(self.timeSelection.testIndex.text()) - 1 selected_variable = self.input.varBox.currentText().split('(')[0][:-1] with Serafin.Read(self.input.ref_data.filename, self.input.ref_data.language) as input_stream: input_stream.header = self.input.ref_data.header input_stream.time = self.input.ref_data.time ref_values = input_stream.read_var_in_frame( ref_time, selected_variable) with Serafin.Read(self.input.test_data.filename, self.input.test_data.language) as input_stream: input_stream.header = self.input.test_data.header input_stream.time = self.input.test_data.time test_values = input_stream.read_var_in_frame( test_time, selected_variable) values = test_values - ref_values self.ewsd = self.input.ref_mesh.element_wise_signed_deviation(values) self.updateStats(ref_time, test_time) self.updateHistogram() def btnColorMapEvent(self): if not self.has_map: reply = QMessageBox.question( self, 'Show distribution in 2D', 'This may take some time. Are you sure to proceed?', QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: return self.map.canvas.reinitFigure(self.input.ref_mesh, self.ewsd, self.xlim, self.input.ref_mesh.polygon) self.has_map = True self.btnColorMap.setEnabled(False) self.map.show()
class InputTab(SerafinInputTab): def __init__(self, parent): super().__init__(parent) canvas = LineMapCanvas() self.map = MapViewer(canvas) self.has_map = False self.data = None self.mesh = None self.lines = [] self.line_interpolators = [] self.line_interpolators_internal = [] # without intersection points self._initWidgets() # some instance attributes will be set there self._setLayout() self._bindEvents() def _initWidgets(self): # create the button open lines self.btnOpenLines = QPushButton('Load\nLines', self, icon=self.style().standardIcon( QStyle.SP_DialogOpenButton)) self.btnOpenLines.setToolTip('<b>Open</b> a .i2s or .shp file') self.btnOpenLines.setFixedSize(105, 50) self.btnOpenLines.setEnabled(False) # create some text fields displaying the IO files info self.linesNameBox = QPlainTextEdit() self.linesNameBox.setReadOnly(True) self.linesNameBox.setFixedHeight(50) # create the map button self.btnMap = QPushButton('Locate lines\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton)) self.btnMap.setFixedSize(135, 50) self.btnMap.setEnabled(False) def _bindEvents(self): self.btnOpen.clicked.connect(self.btnOpenSerafinEvent) self.btnOpenLines.clicked.connect(self.btnOpenLinesEvent) self.btnMap.clicked.connect(self.btnMapEvent) def _setLayout(self): mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.setSpacing(15) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.setAlignment(Qt.AlignLeft) hlayout.addWidget(self.btnOpen) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.langBox) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnOpenLines) hlayout.addWidget(self.btnMap) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(10, 10)) glayout = QGridLayout() glayout.addWidget(QLabel(' Input file'), 1, 1) glayout.addWidget(self.inNameBox, 1, 2) glayout.addWidget(QLabel(' Summary'), 2, 1) glayout.addWidget(self.summaryTextBox, 2, 2) glayout.addWidget(QLabel(' Lines file'), 3, 1) glayout.addWidget(self.linesNameBox, 3, 2) glayout.setAlignment(Qt.AlignLeft) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.addWidget(QLabel(' Message logs')) mainLayout.addWidget(self.logTextBox.widget) self.setLayout(mainLayout) def _reinitInput(self): self.reset() self.data = None self.has_map = False self.btnMap.setEnabled(False) self.mesh = None self.btnOpenLines.setEnabled(False) self.parent.reset() def _resetDefaultOptions(self): nb_nonempty = 0 self.line_interpolators = [] self.line_interpolators_internal = [] for line in self.lines: line_interpolators, distances, \ line_interpolators_internal, distances_internal = self.mesh.get_line_interpolators(line) if line_interpolators: nb_nonempty += 1 self.line_interpolators.append((line_interpolators, distances)) self.line_interpolators_internal.append( (line_interpolators_internal, distances_internal)) if nb_nonempty == 0: self.lines = [] self.line_interpolators = [] self.line_interpolators_internal = [] self.linesNameBox.clear() self.parent.reset() else: old_filename = self.linesNameBox.toPlainText().split('\n')[0] self.linesNameBox.clear() self.linesNameBox.appendPlainText( old_filename + '\n' + 'The file contains {} open polyline{}.' '{} line{} the mesh continuously.'.format( len(self.lines), 's' if len(self.lines) > 1 else '', nb_nonempty, 's intersect' if nb_nonempty > 1 else ' intersects')) self.has_map = False self.btnMap.setEnabled(True) self.parent.getInput() def btnOpenSerafinEvent(self): canceled, filename = super().open_event() if canceled: return self._reinitInput() success, data = self.read_2d(filename) if not success: return # record the mesh for future visualization and calculations self.parent.inDialog() meshLoader = LoadMeshDialog('interpolation', data.header) self.mesh = meshLoader.run() self.parent.outDialog() if meshLoader.thread.canceled: self.linesNameBox.clear() self.parent.reset() return self.data = data self.btnOpenLines.setEnabled(True) self._resetDefaultOptions() def btnOpenLinesEvent(self): success, filename, polylines = open_polylines() if not success: return self.lines = polylines logging.info('Finished reading the lines file %s' % filename) nb_nonempty, indices_nonempty, \ self.line_interpolators, self.line_interpolators_internal = self.mesh.get_line_interpolators(self.lines) if nb_nonempty == 0: QMessageBox.critical(self, 'Error', 'No line intersects the mesh continuously.', QMessageBox.Ok) return logging.info('Finished reading the lines file %s' % filename) self.linesNameBox.clear() self.linesNameBox.appendPlainText( filename + '\n' + 'The file contains {} open polyline{}.' '{} line{} the mesh continuously.'.format( len(self.lines), 's' if len(self.lines) > 1 else '', nb_nonempty, 's intersect' if nb_nonempty > 1 else ' intersects')) self.has_map = False self.btnMap.setEnabled(True) self.parent.getInput() def btnMapEvent(self): if not self.has_map: self.map.canvas.reinitFigure( self.mesh, self.lines, ['Line %d' % (i + 1) for i in range(len(self.lines))], list( islice( cycle(['b', 'r', 'g', 'y', 'k', 'c', '#F28AD6', 'm']), len(self.lines)))) self.has_map = True self.map.canvas.draw() self.has_map = True self.map.show()
class InputTab(SerafinInputTab): def __init__(self, parent): super().__init__(parent) self.old_frequency = '1' canvas = MapCanvas() self.map = MapViewer(canvas) self.has_map = False self.data = None self.mesh = None self.points = [] self.point_interpolators = [] self.fields = [] self.attributes = [] self.attribute_table = PointAttributeTable() self._initWidgets() # some instance attributes will be set there self._setLayout() self._bindEvents() def _initWidgets(self): # create the button open points self.btnOpenPoints = QPushButton('Load\nPoints', self, icon=self.style().standardIcon( QStyle.SP_DialogOpenButton)) self.btnOpenPoints.setToolTip('<b>Open</b> a .shp file') self.btnOpenPoints.setFixedSize(105, 50) self.btnOpenPoints.setEnabled(False) self.btnOpenAttributes = QPushButton('Attributes\nTable', self, icon=self.style().standardIcon( QStyle.SP_FileDialogListView)) self.btnOpenAttributes.setToolTip('<b>Open</b> the attribute table') self.btnOpenAttributes.setFixedSize(105, 50) self.btnOpenAttributes.setEnabled(False) # create some text fields displaying the IO files info self.pointsNameBox = QPlainTextEdit() self.pointsNameBox.setReadOnly(True) self.pointsNameBox.setFixedHeight(50) # create two 3-column tables for variables selection self.firstTable = VariableTable() self.secondTable = VariableTable() self.timeSampling = QLineEdit('1') self.timeSampling.setFixedWidth(50) # create the map button self.btnMap = QPushButton('Locate points\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton)) self.btnMap.setFixedSize(135, 50) self.btnMap.setEnabled(False) # create the submit button self.btnSubmit = QPushButton('Submit\nto .csv', self, icon=self.style().standardIcon( QStyle.SP_DialogSaveButton)) self.btnSubmit.setToolTip('<b>Write</b> output to .csv') self.btnSubmit.setFixedSize(105, 50) self.btnSubmit.setEnabled(False) # create the output file name box self.csvNameBox = QLineEdit() self.csvNameBox.setReadOnly(True) self.csvNameBox.setFixedHeight(30) def _bindEvents(self): self.btnOpen.clicked.connect(self.btnOpenSerafinEvent) self.btnOpenPoints.clicked.connect(self.btnOpenPointsEvent) self.btnOpenAttributes.clicked.connect(self.btnOpenAttributesEvent) self.btnMap.clicked.connect(self.btnMapEvent) self.btnSubmit.clicked.connect(self.btnSubmitEvent) self.timeSampling.editingFinished.connect(self._checkSamplingFrequency) def _setLayout(self): mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.setSpacing(15) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.setAlignment(Qt.AlignLeft) hlayout.addWidget(self.btnOpen) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.langBox) hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnOpenPoints) hlayout.addWidget(self.btnOpenAttributes) hlayout.addWidget(self.btnMap) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(10, 10)) glayout = QGridLayout() glayout.addWidget(QLabel(' Input file'), 1, 1) glayout.addWidget(self.inNameBox, 1, 2) glayout.addWidget(QLabel(' Summary'), 2, 1) glayout.addWidget(self.summaryTextBox, 2, 2) glayout.addWidget(QLabel(' Points file'), 3, 1) glayout.addWidget(self.pointsNameBox, 3, 2) glayout.setAlignment(Qt.AlignLeft) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(10, 10)) glayout = QGridLayout() hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) vlayout = QVBoxLayout() lb = QLabel('Available variables') vlayout.addWidget(lb) vlayout.setAlignment(lb, Qt.AlignHCenter) vlayout.addWidget(self.firstTable) hlayout.addLayout(vlayout) hlayout.addItem(QSpacerItem(15, 1)) vlayout = QVBoxLayout() lb = QLabel('Output variables') vlayout.addWidget(lb) vlayout.setAlignment(lb, Qt.AlignHCenter) vlayout.addWidget(self.secondTable) hlayout.addLayout(vlayout) hlayout.addItem(QSpacerItem(30, 1)) glayout.addLayout(hlayout, 1, 1) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(QLabel('Time sampling frequency')) hlayout.addWidget(self.timeSampling) hlayout.setAlignment(self.timeSampling, Qt.AlignLeft) hlayout.addStretch() glayout.addLayout(hlayout, 2, 1) glayout.setAlignment(Qt.AlignLeft) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(30, 10)) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnSubmit) hlayout.addWidget(self.csvNameBox) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(30, 15)) mainLayout.addWidget(QLabel(' Message logs')) mainLayout.addWidget(self.logTextBox.widget) self.setLayout(mainLayout) def _reinitInput(self): self.reset() self.data = None self.has_map = False self.firstTable.setRowCount(0) self.secondTable.setRowCount(0) self.btnMap.setEnabled(False) self.btnOpenAttributes.setEnabled(False) self.mesh = None self.btnOpenPoints.setEnabled(False) self.old_frequency = self.timeSampling.text() self.timeSampling.setText('1') self.btnSubmit.setEnabled(False) self.csvNameBox.clear() self.parent.tab.setTabEnabled(1, False) def _resetDefaultOptions(self): if int(self.old_frequency) <= len(self.data.time): self.timeSampling.setText(self.old_frequency) is_inside, self.point_interpolators = self.mesh.get_point_interpolators( self.points) nb_inside = sum(map(int, is_inside)) if nb_inside == 0: self.pointsNameBox.clear() self.points = [] self.point_interpolators = [] else: self.attribute_table.getData(self.points, is_inside, self.fields, self.attributes) old_filename = self.pointsNameBox.toPlainText().split('\n')[0] self.pointsNameBox.clear() self.pointsNameBox.appendPlainText( old_filename + '\n' + 'The file contains {} point{}.' '{} point{} inside the mesh.'.format( len(self.points), 's' if len(self.points) > 1 else '', nb_inside, 's are' if nb_inside > 1 else ' is')) self.btnSubmit.setEnabled(True) self.btnOpenAttributes.setEnabled(True) self.btnMap.setEnabled(True) def _initVarTables(self): self.firstTable.fill(self.data.header) def _checkSamplingFrequency(self): try: sampling_frequency = int(self.timeSampling.text()) except ValueError: QMessageBox.critical(self, 'Error', 'The sampling frequency must be a number!', QMessageBox.Ok) self.timeSampling.setText('1') return if sampling_frequency < 1 or sampling_frequency > len(self.data.time): QMessageBox.critical( self, 'Error', 'The sampling frequency must be in the range [1; nbFrames]!', QMessageBox.Ok) self.timeSampling.setText('1') return def getSelectedVariables(self): return self.secondTable.get_selected() def btnOpenSerafinEvent(self): canceled, filename = super().open_event() if canceled: return self._reinitInput() success, data = self.read_2d(filename) if not success: return # record the mesh for future visualization and calculations self.parent.inDialog() meshLoader = LoadMeshDialog('interpolation', data.header) self.mesh = meshLoader.run() self.parent.outDialog() if meshLoader.thread.canceled: self.pointsNameBox.clear() self.summaryTextBox.clear() return self.data = data self.btnOpenPoints.setEnabled(True) self._resetDefaultOptions() self.parent.imageTab.reset() # displaying the available variables self._initVarTables() def btnOpenPointsEvent(self): success, filename, points, attributes, fields = open_points() if not success: return logging.info('Finished reading the points file %s' % filename) is_inside, point_interpolators = self.mesh.get_point_interpolators( points) nb_inside = sum(map(int, is_inside)) if nb_inside == 0: QMessageBox.critical(self, 'Error', 'No point inside the mesh.', QMessageBox.Ok) return self.points = points self.attributes = attributes self.fields = fields self.attribute_table.getData(self.points, is_inside, self.fields, self.attributes) self.point_interpolators = point_interpolators self.pointsNameBox.clear() self.pointsNameBox.appendPlainText( filename + '\n' + 'The file contains {} point{}.' '{} point{} inside the mesh.'.format( len(self.points), 's' if len(self.points) > 1 else '', nb_inside, 's are' if nb_inside > 1 else ' is')) self.has_map = False self.btnMap.setEnabled(True) self.btnOpenAttributes.setEnabled(True) self.btnSubmit.setEnabled(True) self.csvNameBox.clear() self.parent.imageTab.reset() self.parent.tab.setTabEnabled(1, False) def btnOpenAttributesEvent(self): self.attribute_table.show() def btnMapEvent(self): if not self.has_map: self.map.canvas.initFigure(self.mesh) self.map.canvas.axes.scatter(*zip(*self.points)) labels = ['%d' % (i + 1) for i in range(len(self.points))] for label, (x, y) in zip(labels, self.points): self.map.canvas.axes.annotate( label, xy=(x, y), xytext=(-20, 20), fontsize=8, textcoords='offset points', ha='right', va='bottom', bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5), arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0')) self.map.canvas.draw() self.has_map = True self.map.show() def btnSubmitEvent(self): selected_var_IDs = self.getSelectedVariables() if not selected_var_IDs: QMessageBox.critical( self, 'Error', 'Choose at least one output variable before submit!', QMessageBox.Ok) return canceled, filename = save_dialog('CSV') if canceled: return self.csvNameBox.setText(filename) logging.info('Writing the output to %s' % filename) self.parent.inDialog() sampling_frequency = int(self.timeSampling.text()) selected_time = self.data.time[::sampling_frequency] indices_inside = [ i for i in range(len(self.points)) if self.point_interpolators[i] is not None ] # initialize the progress bar process = WriteCSVProcess(self.parent.csv_separator, self.parent.digits, self.mesh) progressBar = OutputProgressDialog() with Serafin.Read(self.data.filename, self.data.language) as input_stream: input_stream.header = self.data.header input_stream.time = self.data.time progressBar.setValue(1) QApplication.processEvents() with open(filename, 'w') as output_stream: progressBar.connectToThread(process) process.write_csv( input_stream, selected_time, selected_var_IDs, output_stream, indices_inside, [self.points[i] for i in indices_inside], [self.point_interpolators[i] for i in indices_inside]) if not process.canceled: progressBar.outputFinished() progressBar.exec_() self.parent.outDialog() if process.canceled: self.csvNameBox.clear() return self.parent.imageTab.getData(selected_var_IDs, indices_inside) self.parent.tab.setTabEnabled(1, True)
class ImageTab(PointPlotViewer): def __init__(self, inputTab): super().__init__() self.input = inputTab self.has_map = False canvas = MapCanvas() self.map = MapViewer(canvas) self.var_IDs = [] self.current_var = '' self.openAttributes = QAction('Attributes\nTable', self, icon=self.style().standardIcon( QStyle.SP_FileDialogListView), triggered=self.openAttributesEvent) self.openAttributes_short = QAction('Attributes Table', self, icon=self.style().standardIcon( QStyle.SP_FileDialogListView), triggered=self.openAttributesEvent) self.locatePoints = QAction('Locate points\non map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.map_event) self.locatePoints_short = QAction('Locate points on map', self, icon=self.style().standardIcon( QStyle.SP_DialogHelpButton), triggered=self.map_event) self.input.map.closeEvent = self.enable_locate self.input.attribute_table.closeEvent = self.enable_attribute self.toolBar.addAction(self.locatePoints) self.toolBar.addAction(self.openAttributes) self.toolBar.addSeparator() self.toolBar.addAction(self.select_variable) self.toolBar.addAction(self.selectColumnsAct) self.toolBar.addAction(self.editColumnNamesAct) self.toolBar.addAction(self.editColumColorAct) self.toolBar.addSeparator() self.toolBar.addAction(self.convertTimeAct) self.toolBar.addAction(self.changeDateAct) self.mapMenu = QMenu('&Map', self) self.mapMenu.addAction(self.locatePoints) self.pointsMenu = QMenu('&Data', self) self.pointsMenu.addAction(self.openAttributes_short) self.pointsMenu.addSeparator() self.pointsMenu.addAction(self.select_variable_short) self.pointsMenu.addAction(self.selectColumnsAct_short) self.pointsMenu.addAction(self.editColumnNamesAct_short) self.pointsMenu.addAction(self.editColumColorAct_short) self.menuBar.addMenu(self.mapMenu) self.menuBar.addMenu(self.pointsMenu) def enable_attribute(self, event): self.openAttributes.setEnabled(True) self.openAttributes_short.setEnabled(True) def enable_locate(self, event): self.locatePoints.setEnabled(True) self.locatePoints_short.setEnabled(True) def map_event(self): self.locatePoints.setEnabled(False) self.locatePoints_short.setEnabled(False) self.input.btnMapEvent() def _to_column(self, point): point_index = int(point.split()[1]) - 1 x, y = self.input.points[point_index] return 'Point %d %s (%.4f|%.4f)' % (point_index + 1, self.current_var, x, y) def editColumns(self): msg = PointLabelEditor( self.column_labels, self.column_name, self.input.points, [ self.input.point_interpolators[i] is not None for i in range(len(self.input.points)) ], self.input.fields, self.input.attributes) value = msg.exec_() if value == QDialog.Rejected: return msg.getLabels(self.column_labels) self.replot() def getData(self, var_IDs, point_indices): self.var_IDs = var_IDs self.current_var = var_IDs[0] # get the new data csv_file = self.input.csvNameBox.text() self.data, headers = read_csv(csv_file, self.input.parent.csv_separator) if self.input.data.header.date is not None: year, month, day, hour, minute, second = self.input.data.header.date self.start_time = datetime.datetime(year, month, day, hour, minute, second) else: self.start_time = datetime.datetime(1900, 1, 1, 0, 0, 0) self.datetime = list( map(lambda x: self.start_time + datetime.timedelta(seconds=x), self.data['time'])) self.str_datetime = list( map(lambda x: x.strftime('%Y/%m/%d\n%H:%M'), self.datetime)) self.str_datetime_bis = list( map(lambda x: x.strftime('%d/%m/%y\n%H:%M'), self.datetime)) self.columns = ['Point %d' % (i + 1) for i in point_indices] self.current_columns = self.columns[0:1] self.column_labels = {x: x for x in self.columns} self.column_colors = { column: color for column, color in zip(self.columns, cycle(self.defaultColors)) } # initialize the plot self.time = [ self.data['time'], self.data['time'], self.data['time'], self.data['time'] / 60, self.data['time'] / 3600, self.data['time'] / 86400 ] self.language = self.input.data.language self.current_xlabel = self._defaultXLabel() self.current_ylabel = self._defaultYLabel() self.current_title = '' self.replot() def openAttributesEvent(self): self.openAttributes.setEnabled(False) self.openAttributes_short.setEnabled(False) self.input.attribute_table.show() def replot(self): self.canvas.axes.clear() for point in self.current_columns: self.canvas.axes.plot(self.time[self.timeFormat], self.data[self._to_column(point)], '-', color=self.column_colors[point], linewidth=2, label=self.column_labels[point]) self.canvas.axes.legend() self.canvas.axes.grid(linestyle='dotted') self.canvas.axes.set_xlabel(self.current_xlabel) self.canvas.axes.set_ylabel(self.current_ylabel) self.canvas.axes.set_title(self.current_title) if self.timeFormat in [1, 2]: self.canvas.axes.set_xticklabels( self.str_datetime if self.timeFormat == 1 else self.str_datetime_bis) for label in self.canvas.axes.get_xticklabels(): label.set_rotation(45) label.set_fontsize(8) self.canvas.draw() def reset(self): self.has_map = False self.map.close() self.input.attribute_table.close() # reinitialize old graphical parameters super().reset() self.current_columns = ('Point 1', )