def setDataSet(self, data_set): ''' Save previous data to the older data set name Then load data from the existing global data dictionary ''' # First save data with the old data set key if self.current_data_set is not None: logger.info('Saving data set %s'%(self.current_data_set)) self.all_tables[self.current_data_set] = self.sonicViewer.table self.all_geo_indices[self.current_data_set] = self.geo_indices self.all_indices[self.current_data_set] = self.indices self.sonicViewer.plot_arrival_times_flag = False self.all_times[self.current_data_set] = self.times # get sonic table for the current data set if data_set in self.all_tables.keys(): logger.info("found data: %s"%(data_set)) self.current_data_set = data_set self.sonicViewer.setSonicTable(self.all_tables[data_set]) self.geo_indices = self.all_geo_indices[data_set] self.indices = self.all_indices[data_set] self.times = self.all_times[data_set] self.sonicViewer.setIndices(self.indices, self.geo_indices) # self.sonicViewer.plot_arrival_times_flag = False length = self.parent.props['length'] self.interpretationSettings.lengthLine.setValue(length) # moduli action disabled cause arrival times not stored self.moduliAction.setEnabled(False) self.sonicViewer.arrivalsPicked = False self.setEnabled() self.sonicViewer.plot() else: self.setEnabled(False)
def setCurrentDataSet(self, dataSetName): ''' Store old data in the dictionary. Load new data from the dictionary. ''' logger.info('New data set is chosen') self.sigSaveDataSet.emit(copy(self.currentDataSetName)) # if we switch to a different data set (if it's not the first), # remember cursors for the old one if self.currentDataSetName: logger.debug('Saving old data') self.allIndices[self.currentDataSetName] = self.indices # self.allCursors[self.currentDataSetName] = self.cursors self.allComments[self.currentDataSetName] = self.comments self.allProps[self.currentDataSetName] = self.props logger.debug('Setting new data') # set current data dictionaries to new values self.currentDataSetName = dataSetName self.data = self.allData[dataSetName] self.units = self.allUnits[dataSetName] self.props = self.allProps[dataSetName] self.indices = self.allIndices[dataSetName] self.dataSetMenu.setDefaultAction(self.dataSetButtons[dataSetName]) self.sigLoadDataSet.emit(dataSetName) self.comments = self.allComments[dataSetName] # fill the data tree widget with data keys self.setTreeParameters() self.connectParameters() self.updatePlot()
def setDataSet(self, data_set): ''' Save previous data to the older data set name Then load data from the existing global data dictionary ''' # First save data with the old data set key if self.current_data_set is not None: logger.info('Saving data set %s' % (self.current_data_set)) self.all_tables[self.current_data_set] = self.sonicViewer.table self.all_geo_indices[self.current_data_set] = self.geo_indices self.all_indices[self.current_data_set] = self.indices self.sonicViewer.plot_arrival_times_flag = False self.all_times[self.current_data_set] = self.times # get sonic table for the current data set if data_set in self.all_tables.keys(): logger.info("found data: %s" % (data_set)) self.current_data_set = data_set self.sonicViewer.setSonicTable(self.all_tables[data_set]) self.geo_indices = self.all_geo_indices[data_set] self.indices = self.all_indices[data_set] self.times = self.all_times[data_set] self.sonicViewer.setIndices(self.indices, self.geo_indices) # self.sonicViewer.plot_arrival_times_flag = False length = self.parent.props['length'] self.interpretationSettings.lengthLine.setValue(length) # moduli action disabled cause arrival times not stored self.moduliAction.setEnabled(False) self.sonicViewer.arrivalsPicked = False self.setEnabled() self.sonicViewer.plot() else: self.setEnabled(False)
def getFourrierTransforms(self): if not self.hasData(): return 0 # if no data pass logger.info('Building Fourrier matrix') self.fft = {} # fourrier transform self.fftamp = {} # power self.fftph = {} # phase for wave in WaveTypes: x = self.table[wave][0,:,:] y = self.table[wave][1,:,:] [self.fft[wave], self.fftamp[wave], self.fftph[wave]] = get_fft(x, y)
def setMode(self, mode): ''' takes string arguments: WaveForms and Contours ''' self.mode = mode if mode == 'WaveForms': logger.info('Setting mode to Wave Forms') # self.modeMenu.setDefaultAction(self.waveFormButton) elif mode == 'Contours': logger.info('Setting mode to Contours') # self.modeMenu.setDefaultAction(self.contourButton) else: raise ValueError("This mode is not available: %s"%(mode))
def exportModuli(self, fname): logger.info('Saving moduli to %s' % (fname)) data = [] keys = [] # get experimental plot parameter keys.append(self.moduliWidget.parameter()) data.append(self.moduliWidget.getGeoArray()) # get moduli mod = self.moduliWidget.getActiveModuli() for key in mod.keys(): keys.append(key) data.append(mod[key]) write_csv(keys, data, fname)
def exportModuli(self, fname): logger.info('Saving moduli to %s'%(fname)) data = [] keys = [] # get experimental plot parameter keys.append(self.moduliWidget.parameter()) data.append(self.moduliWidget.getGeoArray()) # get moduli mod = self.moduliWidget.getActiveModuli() for key in mod.keys(): keys.append(key) data.append(mod[key]) write_csv(keys, data, fname)
def exportArrivals(self, fname): logger.info('Saving arrivals to %s' % (fname)) data = [] keys = [] sv = self.sonicViewer for k, wave in enumerate(sv.getActivePlots()): if wave in sv.arrival_times.keys(): keys.append("time_" + wave) keys.append(wave) arrivals = sv.arrival_times[wave][sv.indices[wave]] exp_times = self.sonicViewer.getYArray(wave) data.append(exp_times) data.append(arrivals) write_csv(keys, data, fname)
def exportArrivals(self, fname): logger.info('Saving arrivals to %s'%(fname)) data = [] keys = [] sv = self.sonicViewer for k, wave in enumerate(sv.getActivePlots()): if wave in sv.arrival_times.keys(): keys.append("time_" + wave) keys.append(wave) arrivals = sv.arrival_times[wave][sv.indices[wave]] exp_times = self.sonicViewer.getYArray(wave) data.append(exp_times) data.append(arrivals) write_csv(keys, data, fname)
def createTable(self): ''' store all data in one 3D np-array 1st dimension - time or amplitude 2nd dimension - number of file 3rd dimension - datapoints ''' if not self.hasData(): return 0 # if no data pass logger.info('Building sonic matrix') ### add some function that checks for constant dt # if dt is not uniform, interpolate data and add some points self.table = {} for wave in WaveTypes: self.table[wave] = get_table(self.data[wave]) self.y[wave] = np.arange(self.table[wave].shape[1])
def setData(self,data, keys): ''' data is a dictionary with np array values ''' logger.info('Calculator: Setting data') self.data = data self.keys = keys someKey = keys[0] npoints = len(self.findData(someKey)) if self.parent: self.indices = self.parent.indices else: self.indices = np.arange(npoints) self.applyButton.setDisabled(False) # in case if some expression already entered self.getData()
def setData(self, data, keys): ''' data is a dictionary with np array values ''' logger.info('Calculator: Setting data') self.data = data self.keys = keys someKey = keys[0] npoints = len(self.findData(someKey)) if self.parent: self.indices = self.parent.indices else: self.indices = np.arange(npoints) self.applyButton.setDisabled(False) # in case if some expression already entered self.getData()
def getData(self): logger.info('Calculator: interpreting input') for key in self.names: # interpret x xText = self.xTextBoxes[key].text() x = self.parseExpression(xText) if isinstance(x, np.ndarray): self.plotItems[key]['x'] = x self.xTexts[key] = xText # interpret y yText = self.yTextBoxes[key].text() y = self.parseExpression(yText) if isinstance(y, np.ndarray): self.plotItems[key]['y'] = y self.yTexts[key] = yText self.plot()
def setTreeParameters(self): logger.info( 'Modifying GUI: adding parameters to plot') # Modify parameter tree (i.r. plotting trend etc.) self.modparamlist = ModifyingParameters self.modparamlist[1]['values'] = self.keys # Parameter # self.modparamlist[2]['values'] = self.data.keys() # Interval self.modparamlist[5]['children'][1]['values'] = self.keys # Trend parameter # create parameter class instances() self.modparams = Parameter.create(name='Options', type='group', children=self.modparamlist) # modify main tree self.tree.clear() self.tree.addItems(self.keys, DATA_VIEWER_TREE_COLORS) self.modtree.setParameters(self.modparams, showTop=True) self.assignAttributes() # to get shorter names
def getData(self): logger.info('Calculator: interpreting input') for key in self.names: # interpret x xText = self.xTextBoxes[key].text() x = self.parseExpression(xText) if isinstance(x,np.ndarray): self.plotItems[key]['x'] = x self.xTexts[key] = xText # interpret y yText = self.yTextBoxes[key].text() y = self.parseExpression(yText) if isinstance(y,np.ndarray): self.plotItems[key]['y'] = y self.yTexts[key] = yText self.plot()
def setYAxisParameters(self,parameters): # we use setLimits because of weird implementation # in pyqtgraph self.allParameters = parameters self.yAxisMenu.clear() self.yAxisButtons = {} self.yAxisButtons['Track #'] = QtGui.QAction('Track #',self,checkable=True) self.yAxisButtons['Track #'].setActionGroup(self.yAxisGroup) self.yAxisMenu.addAction(self.yAxisButtons['Track #']) for p in parameters: if self.mode == 'Contours' and p!='Time': continue self.yAxisButtons[p] = QtGui.QAction(p,self,checkable=True) self.yAxisButtons[p].setActionGroup(self.yAxisGroup) self.yAxisMenu.addAction(self.yAxisButtons[p]) pass try: logger.info('Setting y axis to: Time') self.yAxisButtons['Time'].setChecked(True) self.yAxis = 'Time' except: logger.warning('setting was not successful')
def togglePlotVisibility(self): logger.info('changing layout') for wave in WaveTypes: try: # self.sublayout.removeItem(self.plots[wave]) self.plotWidget.sublayout.removeItem(self.plots[wave]) # self.fWidget.sublayout.removeItem(self.fWidget.plots[wave]) self.fftWidget.sublayout.removeItem(self.fftWidget.plots[wave]) except: pass for wave in self.getActivePlots(): if wave: self.plotWidget.sublayout.addItem(self.plots[wave]) # self.fWidget.sublayout.addItem(self.fWidget.plots[wave]) self.fftWidget.sublayout.addItem(self.fftWidget.plots[wave]) # self.sublayout.nextRow() # self.fWidget.sublayout.nextRow() self.plot()
def setYParameters(self): default_active_action = self.parent.timeParam mode = self.sonicViewer.mode assert mode in VIEW_MODES last_active_action = self.yAxisGroup.checkedAction() self.yAxisMenu.clear() if mode == VIEW_MODES[0]: # contours assert self.parent.timeParam in self.yAxisActions.keys() self.yAxisMenu.addAction(self.yAxisActions[self.parent.timeParam]) self.yAxisMenu.addAction(self.yAxisActions[TRACK_NUMBER_LABEL]) elif mode == VIEW_MODES[1]: # wave forms for key, action in self.yAxisActions.items(): self.yAxisMenu.addAction(action) if last_active_action is not None: default_active_action = last_active_action.text() try: logger.info('Setting y axis to: %s'%(default_active_action)) self.yAxisActions[default_active_action].setChecked(True) except: logger.warning('setting was not successful')
def addCursor(self, posx=None, posy = None): logger.info('adding a Cursor') viewrange = self.parent.plt.viewRange() # this is a weird way to scale a new cursor initially rangeX = [viewrange[0][0], viewrange[0][1]] rangeY = [viewrange[1][0], viewrange[1][1]] if posx is None and posy is None: pos = [(rangeX[0] + rangeX[1])/2, (rangeY[0] + rangeY[1])/2] else: pos = [posx, posy] xSize = (rangeX[1]-rangeX[0])/50*800/self.parent.plt.width() ySize = (rangeY[1]-rangeY[0])/50*800/self.parent.plt.height() cursor = CursorItem(pos, [xSize,ySize], pen=(4, 9)) self.cursors.append(cursor) self.allCursors[self.parent.currentDataSetName] = self.cursors # bind cursor if there is something to plot if len(self.parent.activeEntries()) > 0: self.bindCursors() self.drawCursors()
def setYParameters(self): default_active_action = self.parent.timeParam mode = self.sonicViewer.mode assert mode in VIEW_MODES last_active_action = self.yAxisGroup.checkedAction() self.yAxisMenu.clear() if mode == VIEW_MODES[0]: # contours assert self.parent.timeParam in self.yAxisActions.keys() self.yAxisMenu.addAction(self.yAxisActions[self.parent.timeParam]) self.yAxisMenu.addAction(self.yAxisActions[TRACK_NUMBER_LABEL]) elif mode == VIEW_MODES[1]: # wave forms for key, action in self.yAxisActions.items(): self.yAxisMenu.addAction(action) if last_active_action is not None: default_active_action = last_active_action.text() try: logger.info('Setting y axis to: %s' % (default_active_action)) self.yAxisActions[default_active_action].setChecked(True) except: logger.warning('setting was not successful')
def addCursor(self, posx=None, posy=None): logger.info('adding a Cursor') viewrange = self.parent.plt.viewRange() # this is a weird way to scale a new cursor initially rangeX = [viewrange[0][0], viewrange[0][1]] rangeY = [viewrange[1][0], viewrange[1][1]] if posx is None and posy is None: pos = [(rangeX[0] + rangeX[1]) / 2, (rangeY[0] + rangeY[1]) / 2] else: pos = [posx, posy] xSize = (rangeX[1] - rangeX[0]) / 50 * 800 / self.parent.plt.width() ySize = (rangeY[1] - rangeY[0]) / 50 * 800 / self.parent.plt.height() cursor = CursorItem(pos, [xSize, ySize], pen=(4, 9)) self.cursors.append(cursor) self.allCursors[self.parent.currentDataSetName] = self.cursors # bind cursor if there is something to plot if len(self.parent.activeEntries()) > 0: self.bindCursors() self.drawCursors()
def pickArrivals(self,wave): logger.info('Computing arrival times for %s wave'%(wave)) win = [0,0,0] mpoint = self.params[wave].param('Arrival times').param('Mpoint').value() win[0] = self.params[wave].param('Arrival times').param('BTA').value() win[1] = self.params[wave].param('Arrival times').param('ATA').value() win[2] = self.params[wave].param('Arrival times').param('DTA').value() x = self.table[wave][0,:,:] y = self.table[wave][1,:,:] h = x[0,1] - x[0,0] r = multi_window(y,win) rx = np.arange(r.shape[1])*h + x[0,win[0]] mind = abs(rx-mpoint).argmin() #index of middle point sInd = r[:,:mind].argmax(axis=1) # sender indices sTimes = rx[sInd] # sender times rInd = r[:,mind:].argmax(axis=1) # receiver indices rTimes = rx[mind+rInd] self.aTimes[wave] = rTimes - sTimes # shift initial data so if self.autoShift[wave]: shift = np.mean(sTimes) self.table[wave][0,:,:] -= shift self.autoShift[wave] = False
def bindData(self): ''' bind wave tracks to the time of experiment the were measured. it essentially implies parsing comments and comparing it to sonic data names Algorithm: - find times for non-empty comments - throw out repeated comments (take last occurrence) - compare comments with sonic file names Result: times - when waves were recorded geo_indices - indices of times in geomechanical dataset indices - indices of wave forms to be truncated ''' logger.info('Binding sonic data') self.current_data_set = self.parent.currentDataSetName # times are when sonic waves were recorded self.times = {} self.indices = {} # self.geo_indices = {} comments = self.parent.comments geo_times = self.parent.findData(self.parent.timeParam) # filter out empty comments non_empty = [i for i, c in enumerate(comments) if c != b'' and c!=''] comments = comments[non_empty] filtered_times = geo_times[non_empty] # check if there are any duplicates comments, ind = remove_duplicates(comments) filtered_times = filtered_times[ind] # idk why but these values are not sorted yet # but they should be filtered_times.sort() # find same strings in sonic file names for wave in WAVE_TYPES: wave_files = list(self.sonicViewer.data[wave].keys()) # natural keys is a function from lib.functions # wave_files.sort(key=natural_keys) indices = compare_arrays(comments, wave_files) # which items wave_keys are not in comments spurious_entries = array_diff(wave_files, comments) for e in spurious_entries: del self.sonicViewer.data[wave][wave_files[e]] # this is what we really need self.times[wave] = filtered_times[indices] self.indices[wave] = np.arange(len(filtered_times[indices])) self.geo_indices[wave] = compare_arrays(geo_times, self.times[wave]) # rebuild sonic table if spurious_entries != []: self.sonicViewer.createTable() self.sonicViewer.setIndices(self.indices, self.geo_indices) # we don't need those anymore self.sonicViewer.data = {} # set initial length for moduli calculation length = float(self.parent.props['length']) self.interpretationSettings.lengthLine.setValue(length)
def addEnvelope(self, etype='Coulomb', name='Env'): logger.info("Adding %s failure envelope: name %s"%(etype, name)) # envelope_item = EnvelopeEntry(etype, name, parent=self) # self.tree.addTopLevelItem(envelope_item.treeItem) # envelope_item.colorButton.sigColorChanged.connect(self.plot) # envelope_item.frictionBox.sigValueChanged.connect(self.plot) # envelope_item.cohesionBox.sigValueChanged.connect(self.plot) item = pg.TreeWidgetItem([name]) self.envelopes.addChild(item) self.eNames.append(name) self.eTypes[name] = etype typeLabel = QtGui.QLabel(etype) item.setWidget(2,typeLabel) colorButton = ColorButton.ColorButton() self.eCButtons[name] = colorButton color = get_color() colorButton.setColor(color) item.setExpanded(True) self.eBoxes[name] = {} colorItem = pg.TreeWidgetItem(['Color']) if etype == 'Coulomb': item1 = pg.TreeWidgetItem(['Friction Angle']) item2 = pg.TreeWidgetItem(['Cohesion']) step1 = 1 step2 = 50 elif etype == 'Brown': item1 = pg.TreeWidgetItem(['m']) item2 = pg.TreeWidgetItem(['UCS']) step1 = 1 step2 = 1 else: logger.error("Envelope type unknows: %s"%(etype)) # raise NotImplementedError("Envelope type unknows: %s"%(etype)) return 0 item.addChild(colorItem) item.addChild(item1) item.addChild(item2) frictionBox = pg.SpinBox(value=50, step=step1) cohesionBox = pg.SpinBox(value=1e3, step=step2) frictionBox.sigValueChanged.connect(self.plot) cohesionBox.sigValueChanged.connect(self.plot) colorItem.setWidget(2, colorButton) item1.setWidget(2, frictionBox) item2.setWidget(2, cohesionBox) self.fBoxes[name] = frictionBox self.cBoxes[name] = cohesionBox for dname in self.datasets: child = pg.TreeWidgetItem([dname]) item.addChild(child) box = CheckBox.CheckBox() child.setWidget(2, box) self.eBoxes[name][dname] = box box.click() box.clicked.connect(lambda: self.getEnvelope(name)) removeEnvelopeItem = pg.TreeWidgetItem(['']) item.addChild(removeEnvelopeItem) removeButton = QtGui.QPushButton('Remove') removeEnvelopeItem.setWidget(2, removeButton) removeButton.clicked.connect(lambda: self.removeEnvelope(item)) colorButton.sigColorChanged.connect(self.plot) self.nEnvelopes += 1 self.getEnvelope(eName=name)
def modifyParentMenu(self): logger.info("adding Calculator to menu") self.activateAction = QtGui.QAction('Calculator', self.parent) self.activateAction.setDisabled(True) self.parent.viewMenu.addAction(self.activateAction) self.activateAction.triggered.connect(self.run)
def modifyParentMenu(self): logger.info("adding Calculator to menu") self.activateAction = QtGui.QAction('Calculator',self.parent) self.activateAction.setDisabled(True) self.parent.viewMenu.addAction(self.activateAction) self.activateAction.triggered.connect(self.run)
def bindData(self): ''' bind wave tracks to the time of experiment the were measured. it essentially implies parsing comments and comparing it to sonic data names Algorithm: - find times for non-empty comments - throw out repeated comments (take last occurrence) - compare comments with sonic file names Result: times - when waves were recorded geo_indices - indices of times in geomechanical dataset indices - indices of wave forms to be truncated ''' logger.info('Binding sonic data') self.current_data_set = self.parent.currentDataSetName # times are when sonic waves were recorded self.times = {} self.indices = {} # self.geo_indices = {} comments = self.parent.comments geo_times = self.parent.findData(self.parent.timeParam) # filter out empty comments non_empty = [i for i, c in enumerate(comments) if c != b'' and c != ''] comments = comments[non_empty] filtered_times = geo_times[non_empty] # check if there are any duplicates comments, ind = remove_duplicates(comments) filtered_times = filtered_times[ind] # idk why but these values are not sorted yet # but they should be filtered_times.sort() # find same strings in sonic file names for wave in WAVE_TYPES: wave_files = list(self.sonicViewer.data[wave].keys()) # natural keys is a function from lib.functions # wave_files.sort(key=natural_keys) indices = compare_arrays(comments, wave_files) # which items wave_keys are not in comments spurious_entries = array_diff(wave_files, comments) for e in spurious_entries: del self.sonicViewer.data[wave][wave_files[e]] # this is what we really need self.times[wave] = filtered_times[indices] self.indices[wave] = np.arange(len(filtered_times[indices])) self.geo_indices[wave] = compare_arrays(geo_times, self.times[wave]) # rebuild sonic table if spurious_entries != []: self.sonicViewer.createTable() self.sonicViewer.setIndices(self.indices, self.geo_indices) # we don't need those anymore self.sonicViewer.data = {} # set initial length for moduli calculation length = float(self.parent.props['length']) self.interpretationSettings.lengthLine.setValue(length)
def addEnvelope(self, etype='Coulomb', name='Env'): logger.info("Adding %s failure envelope: name %s" % (etype, name)) # envelope_item = EnvelopeEntry(etype, name, parent=self) # self.tree.addTopLevelItem(envelope_item.treeItem) # envelope_item.colorButton.sigColorChanged.connect(self.plot) # envelope_item.frictionBox.sigValueChanged.connect(self.plot) # envelope_item.cohesionBox.sigValueChanged.connect(self.plot) item = pg.TreeWidgetItem([name]) self.envelopes.addChild(item) self.eNames.append(name) self.eTypes[name] = etype typeLabel = QtGui.QLabel(etype) item.setWidget(2, typeLabel) colorButton = ColorButton.ColorButton() self.eCButtons[name] = colorButton color = get_color() colorButton.setColor(color) item.setExpanded(True) self.eBoxes[name] = {} colorItem = pg.TreeWidgetItem(['Color']) if etype == 'Coulomb': item1 = pg.TreeWidgetItem(['Friction Angle']) item2 = pg.TreeWidgetItem(['Cohesion']) step1 = 1 step2 = 50 elif etype == 'Brown': item1 = pg.TreeWidgetItem(['m']) item2 = pg.TreeWidgetItem(['UCS']) step1 = 1 step2 = 1 else: logger.error("Envelope type unknows: %s" % (etype)) # raise NotImplementedError("Envelope type unknows: %s"%(etype)) return 0 item.addChild(colorItem) item.addChild(item1) item.addChild(item2) frictionBox = pg.SpinBox(value=50, step=step1) cohesionBox = pg.SpinBox(value=1e3, step=step2) frictionBox.sigValueChanged.connect(self.plot) cohesionBox.sigValueChanged.connect(self.plot) colorItem.setWidget(2, colorButton) item1.setWidget(2, frictionBox) item2.setWidget(2, cohesionBox) self.fBoxes[name] = frictionBox self.cBoxes[name] = cohesionBox for dname in self.datasets: child = pg.TreeWidgetItem([dname]) item.addChild(child) box = CheckBox.CheckBox() child.setWidget(2, box) self.eBoxes[name][dname] = box box.click() box.clicked.connect(lambda: self.getEnvelope(name)) removeEnvelopeItem = pg.TreeWidgetItem(['']) item.addChild(removeEnvelopeItem) removeButton = QtGui.QPushButton('Remove') removeEnvelopeItem.setWidget(2, removeButton) removeButton.clicked.connect(lambda: self.removeEnvelope(item)) colorButton.sigColorChanged.connect(self.plot) self.nEnvelopes += 1 self.getEnvelope(eName=name)