logInspector.py
Go to the documentation of this file.
1 #!/usr/bin/python3
2 
3 import sys, os, shutil
4 from PyQt5 import QtCore
5 from PyQt5.QtWidgets import QWidget, QDialog, QApplication, QPushButton, QVBoxLayout, QLineEdit, QTreeView, QFileSystemModel,\
6  QHBoxLayout, QGridLayout, QMainWindow, QSizePolicy, QSpacerItem, QFileDialog, QMessageBox, QLabel, QRadioButton,\
7  QAbstractItemView, QMenu, QTableWidget,QTableWidgetItem, QSpinBox, QSpacerItem
8 from PyQt5.QtGui import QMovie, QPicture, QIcon, QDropEvent, QPixmap, QImage
9 from PyQt5.Qt import QApplication, QClipboard, QStyle
10 import json
11 import io
12 
13 from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
14 from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
15 import matplotlib.pyplot as plt
16 import numpy as np
17 from threading import Thread
18 
19 from logReader import Log
20 from logPlotter import logPlot
21 import traceback
22 import yaml
23 import sys
24 
25 sys.path.append('..')
26 sys.path.append('../supernpp/')
27 sys.path.append('../ci_hdw/')
28 from pylib.data_sets import *
29 import subprocess
30 import re
31 
32 START_MODE_HOT = 0
33 START_MODE_COLD = 1
34 START_MODE_FACTORY = 2
35 
37  if sys.platform == 'darwin':
38  subprocess.check_call(['open', '--', path])
39  elif sys.platform == 'linux':
40  subprocess.check_call(['xdg-open', path])
41  elif sys.platform == 'win32':
42  # subprocess.check_call(['explorer', path]) # Not stable
43  subprocess.Popen(r'explorer '+path)
44 
45 def cleanFolder(path, toplevel=True):
46  containsDAT = False
47  containsSDAT = False
48  for fname in os.listdir(path):
49  if fname.endswith('.dat'):
50  containsDAT = True
51  if fname.endswith('.sdat'):
52  containsSDAT = True
53 
54  for fname in os.listdir(path):
55  fpath = os.path.join(path, fname)
56  if os.path.isdir( fpath ):
57  if fname == 'post_processed':
58  removeDirectory(fpath)
59  else:
60  cleanFolder(fpath, False)
61  else:
62  # Remove .csv if .dat or .sdat exist
63  if containsDAT or containsSDAT:
64  if fname.endswith('.csv'):
65  print('Deleting: ' + fpath)
66  os.remove(fpath)
67  # Remove .sdat if .dat exist
68  if containsDAT:
69  if fname.endswith('.sdat'):
70  print('Deleting: ' + fpath)
71  os.remove(fpath)
72  if toplevel:
73  print('Finished Cleaning!')
74 
75 def removeDirectory(fpath):
76  print('Removing Directory: ' + fpath)
77  shutil.rmtree(fpath)
78 
79 # startMode 0=hot, 1=cold, 2=factory
80 def setDataInformationDirectory(path, startMode=START_MODE_HOT):
81  settings_filename = os.path.expanduser("~") + '/Documents/Inertial_Sense/dataInformation.json'
82 
83  if settings_filename is not None:
84  # with open(settings_filename, 'r') as f:
85  # data = json.load(f)
86  # f.close()
87  data = {}
88  data['dataInfo'] = {}
89  data['dataInfo']['dataDirectory'] = os.path.dirname(path).replace('\\','/')
90  data['dataInfo']['subDirectories'] = [os.path.basename(path)]
91  serialnumbers = []
92  for root, dirs, files in os.walk(path):
93  for filename in files:
94  if "LOG_SN" in filename:
95  serialnum = filename[4:11]
96  if serialnum not in serialnumbers:
97  serialnumbers += [serialnum]
98 
99  data['processData'] = {}
100  data['processData']['datasets'] = [{}]
101  data['processData']['datasets'][0]['SerialNumbers'] = serialnumbers
102  data['processData']['datasets'][0]['folder'] = os.path.basename(path)
103  data['processData']['datasets'][0]['logType'] = 'DAT'
104  if startMode == START_MODE_HOT:
105  data['processData']['datasets'][0]['startMode'] = 'HOT'
106  elif startMode == START_MODE_COLD:
107  data['processData']['datasets'][0]['startMode'] = 'COLD'
108  else:
109  data['processData']['datasets'][0]['startMode'] = 'FACTORY'
110 
111  # os.remove(settings_filename)
112  with open(settings_filename, 'w') as f:
113  json.dump(data, f, indent=4)
114 
115 def verArrayToString(array):
116  return str(array[0]) + '.' + str(array[1]) + '.' + str(array[2]) #+ '.' + str(array[3])
117 
118 def dateTimeArrayToString(date, time):
119  return str(date[1]+2000) + '-' + f'{date[2]:02}' + '-' + f'{date[3]:02}' + ' ' + f'{time[0]:02}' + ':' + f'{time[1]:02}' + ':' + f'{time[2]:02}'
120 
121 class DeviceInfoDialog(QDialog):
122 
123  def __init__(self, log, parent=None):
124  super(DeviceInfoDialog, self).__init__(parent)
125  self.setWindowTitle("Device Info")
126 
127  if np.shape(log.data[0,DID_DEV_INFO])[0] == 0:
128  self.label = QLabel('No DID_DEV_INFO data available.')
129  self.mainlayout = QVBoxLayout()
130  self.mainlayout.addWidget(self.label)
131  self.setLayout(self.mainlayout)
132  self.resize(400, 200)
133  return
134 
135  self.table = QTableWidget()
136  nfields = len(log.data[0, DID_DEV_INFO].dtype.names)
137  field_names = []
138  vals = []
139 
140  self.table.setColumnCount(9)
141  self.table.setHorizontalHeaderLabels(['Serial#','Hardware','Firmware','Build','Protocol','Repo','Build Date','Manufacturer','AddInfo'])
142 
143  for d, dev in enumerate(log.data):
144  data = dev[DID_DEV_INFO][0]
145  self.table.setRowCount(d+1)
146  self.table.setItem(d, 0, QTableWidgetItem(str(data[1]))) # Serial#
147  self.table.setItem(d, 1, QTableWidgetItem(verArrayToString(data[2]))) # Hardware version
148  self.table.setItem(d, 2, QTableWidgetItem(verArrayToString(data[3]))) # Firmware version
149  self.table.setItem(d, 3, QTableWidgetItem(str(data[4]))) # Build
150  self.table.setItem(d, 4, QTableWidgetItem(verArrayToString(data[5]))) # Protocol
151  self.table.setItem(d, 5, QTableWidgetItem(str(data[6]))) # Repo
152  self.table.setItem(d, 6, QTableWidgetItem(dateTimeArrayToString(data[8], data[9]))) # Build Date & Time
153  self.table.setItem(d, 7, QTableWidgetItem(data[7].decode('UTF-8'))) # Manufacturer
154  self.table.setItem(d, 8, QTableWidgetItem(data[10].decode('UTF-8'))) # Additional Info
155 
156  self.mainlayout = QVBoxLayout()
157  self.mainlayout.addWidget(self.table)
158  self.setLayout(self.mainlayout)
159  self.resize(2000, 800)
160 
161 class FlashConfigDialog(QDialog):
162  def __init__(self, log, parent=None):
163  super(FlashConfigDialog, self).__init__(parent)
164  self.setWindowTitle("Flash Config")
165 
166  if np.shape(log.data[0,DID_FLASH_CONFIG])[0] == 0:
167  self.label = QLabel('No DID_FLASH_CONFIG data available.')
168  self.mainlayout = QVBoxLayout()
169  self.mainlayout.addWidget(self.label)
170  self.setLayout(self.mainlayout)
171  self.resize(400, 200)
172  return
173 
174  self.table = QTableWidget()
175  nfields = len(log.data[0, DID_FLASH_CONFIG].dtype.names)
176  field_names = []
177  vals = []
178 
179  for d, dev in enumerate(log.data):
180  vals.append([])
181  for f, field in enumerate(dev[DID_FLASH_CONFIG].dtype.names):
182  if isinstance(dev[DID_FLASH_CONFIG][field][0], np.ndarray):
183  length = len(dev[DID_FLASH_CONFIG][field][0])
184  if d == 0: nfields += length-1 # add extra rows for arrays in flash config
185  for i in range(length):
186  if d == 0: field_names.append(field + "[" + str(i) + "]")
187  vals[d].append(dev[DID_FLASH_CONFIG][field][0][i])
188  else:
189  if d == 0: field_names.append(field)
190  vals[d].append(dev[DID_FLASH_CONFIG][field][0])
191 
192  self.table.setRowCount(nfields)
193  self.table.setColumnCount(log.numDev)
194 
195  self.table.setHorizontalHeaderLabels([str(ser) for ser in log.serials])
196  self.table.setVerticalHeaderLabels(field_names)
197 
198  hex_fields = ['ioConfig', 'cBrdConfig', 'RTKCfgBits', 'sysCfgBits']
199  for d in range(log.numDev):
200  for f, field in enumerate(field_names):
201  if field in hex_fields:
202  self.table.setItem(f, d, QTableWidgetItem(hex(vals[d][f])))
203  else:
204  self.table.setItem(f, d, QTableWidgetItem(str(vals[d][f])))
205 
206  self.mainlayout = QVBoxLayout()
207  self.mainlayout.addWidget(self.table)
208  self.setLayout(self.mainlayout)
209  self.resize(1280, 900)
210 
211 
212 
213 
214 class LogInspectorWindow(QMainWindow):
215  def __init__(self, configFilePath, parent=None):
216  super(LogInspectorWindow, self).__init__(parent)
217  self.initMatPlotLib()
218  self.configFilePath = configFilePath
219 
220  if os.path.exists(self.configFilePath):
221  # config.yaml found. Read from file.
222  file = open(self.configFilePath, 'r')
223  self.config = yaml.load(file)
224  file.close()
225  else:
226  # config.yaml not found. Create new file.
227  self.config = {}
228  self.config['logs_directory'] = os.path.join(os.path.expanduser("~"), "Documents", "Inertial_Sense", "Logs")
229  self.config['directory'] = ""
230  self.config['serials'] = ["ALL"]
231  file = open(self.configFilePath, 'w')
232  yaml.dump(self.config, file)
233  file.close()
234 
235  self.currently_selected = 'posNEDMap'
236  self.downsample = 5
237  self.plotargs = None
238  self.log = None
239  self.plotter = None
240 
241 
242  def initMatPlotLib(self):
243  self.figure = plt.figure()
244  self.canvas = FigureCanvas(self.figure)
245  self.toolbar = NavigationToolbar(self.canvas, self)
246  self.figure.subplots_adjust(left=0.05, right=0.99, bottom=0.05, top=0.91, wspace=0.2, hspace=0.2)
247 
248  def addButton(self, name, function, multithreaded=True, layout=None):
249  setattr(self, name+"button", QPushButton(name))
250  # if multithreaded:
251  # setattr(self, name+"buttonThread", Thread(target=function))
252  # getattr(self, name+"button").pressed.connect(self.startLoadingIndicator)
253  # getattr(self, name+"button").released.connect(getattr(self, name+"buttonThread").start)
254  # else:
255  getattr(self, name + "button").clicked.connect(function)
256  # getattr(self, name + "button").setMinimumWidth(220)
257  if layout is None:
259  self.buttonLayoutRightCol.addWidget(getattr(self, name + "button"))
261  self.buttonLayoutMiddleCol.addWidget(getattr(self, name + "button"))
262  else:
263  self.buttonLayoutLeftCol.addWidget(getattr(self, name + "button"))
264  else:
265  layout.addWidget(getattr(self, name + "button"))
266 
267  def updatePlot(self):
268  self.plot(self.currently_selected, self.plotargs)
269 
270  def updateWindowTitle(self):
271  if np.shape(self.log.data[0,DID_DEV_INFO])[0] != 0:
272  info = self.log.data[0,DID_DEV_INFO][0]
273  infoStr = 'SN' + str(info[1]) + ', H:' + verArrayToString(info[2]) + ', F:' + verArrayToString(info[3]) + ' build ' + str(info[4]) + ', ' + dateTimeArrayToString(info[8], info[9]) + ', ' + info[10].decode('UTF-8')
274  self.setWindowTitle("LogInspector - " + infoStr)
275 
276  def choose_directory(self):
277  log_dir = config['logs_directory']
278  directory = QFileDialog.getExistingDirectory(parent=self, caption='Choose Log Directory', directory=log_dir)
279 
280  if directory != '':
281  try:
282  self.load(directory)
283  except Exception as e:
284  msg = QMessageBox()
285  msg.setIcon(QMessageBox.Critical)
286  msg.setText("Unable to load log: " + e.__str__())
287  msg.setDetailedText(traceback.format_exc())
288  msg.exec()
289 
290  def load(self, directory):
291  print("loading files from " + directory)
292  # if self.log is None:
293  self.log = Log()
294  self.log.load(directory)
295  print("done loading")
296  self.plotter = logPlot(False, False, 'svg', self.log)
297  self.plotter.setDownSample(self.downsample)
298  # str = ''
299  # if self.log.navMode:
300  # str += 'NAV '
301  # if self.log.rtk:
302  # str += 'RTK '
303  # if self.log.compassing:
304  # str += 'Comp '
305  # self.statusLabel.setText(str)
306  self.updatePlot()
307  self.updateWindowTitle()
308  self.stopLoadingIndicator()
309 
310  def setupUi(self):
311  self.setObjectName("LogInspector")
312  self.setWindowTitle("LogInspector")
313  self.resize(1280, 900)
314  self.setWindowFlags(self.windowFlags() |
315  QtCore.Qt.WindowSystemMenuHint |
316  QtCore.Qt.WindowMinMaxButtonsHint)
317  self.setWindowIcon(QIcon("assets/Magnifying_glass_icon.png"))
318 
319  # MainWindow.showMaximized()
320 
321  self.createFileTree()
322  self.createButtonColumn()
323  self.formatButtonColumn()
324  self.createBottomToolbar()
325 
326  self.figureLayout = QVBoxLayout()
327  self.figureLayout.addWidget(self.canvas)
328  self.figureLayout.addLayout(self.toolLayout)
329  self.figureLayout.setStretchFactor(self.canvas, 1)
330 
331  layout = QHBoxLayout()
332  layout.addLayout(self.controlLayout)
333  layout.addLayout(self.figureLayout)
334  layout.setStretch(1, 1)
335  widget = QWidget()
336  widget.setLayout(layout)
337  self.setCentralWidget(widget)
338  # self.resize(1280, 900)
339  self.resize(1450, 1000)
340  self.setAcceptDrops(True)
341 
343  self.controlLayout = QVBoxLayout()
344  self.buttonLayoutLeftCol = QVBoxLayout()
345  self.buttonLayoutMiddleCol = QVBoxLayout()
346  self.buttonLayoutRightCol = QVBoxLayout()
347  self.addButton('Pos NED Map', lambda: self.plot('posNEDMap'))
348  self.addButton('Pos NED', lambda: self.plot('posNED'))
349  self.addButton('Pos LLA', lambda: self.plot('posLLA'))
350  self.addButton('GPS LLA', lambda: self.plot('llaGps'))
351  self.addButton('Vel NED', lambda: self.plot('velNED'))
352  self.addButton('Vel UVW', lambda: self.plot('velUVW'))
353  self.addButton('Attitude', lambda: self.plot('attitude'))
354  self.addButton('Heading', lambda: self.plot('heading'))
355  self.addButton('INS Status', lambda: self.plot('insStatus'))
356  self.addButton('HDW Status', lambda: self.plot('hdwStatus'))
357  self.addButton('GPS 1 Stats', lambda: self.plot('gpsStats'))
358  self.addButton('GPS 2 Stats', lambda: self.plot('gps2Stats'))
359  self.addButton('RTK Pos Stats', lambda: self.plot('rtkPosStats'))
360  self.addButton('RTK Cmp Stats', lambda: self.plot('rtkCmpStats'))
361  self.addButton('Flash Config', lambda: self.showFlashConfig())
362  self.addButton('Device Info', lambda: self.showDeviceInfo())
363  self.addButton('IMU PQR', lambda: self.plot('imuPQR'))
364  self.addButton('IMU Accel', lambda: self.plot('imuAcc'))
365  self.addButton('PSD PQR', lambda: self.plot('gyroPSD'))
366  self.addButton('PSD Accel', lambda: self.plot('accelPSD'))
367  self.addButton('Magnetometer', lambda: self.plot('magnetometer'))
368  self.addButton('Temp', lambda: self.plot('temp'))
369 
371  self.buttonLayoutLeftCol.setAlignment(QtCore.Qt.AlignTop)
372  self.buttonLayoutMiddleCol.setAlignment(QtCore.Qt.AlignTop)
373  self.buttonLayoutRightCol.setAlignment(QtCore.Qt.AlignTop)
374  self.buttonColumnLayout = QHBoxLayout()
375  self.buttonColumnLayout.addLayout(self.buttonLayoutLeftCol)
376  self.buttonColumnLayout.addLayout(self.buttonLayoutMiddleCol)
377  self.buttonColumnLayout.addLayout(self.buttonLayoutRightCol)
378  self.controlLayout.addLayout(self.buttonColumnLayout)
379  self.controlDirLayout = QHBoxLayout();
380  self.controlDirLayout.addWidget(self.dirLineEdit)
381  self.controlLayout.addLayout(self.controlDirLayout)
382  self.controlLayout.addWidget(self.fileTree)
383  # self.buttonLayout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
384  # self.addButton('load', self.choose_directory, multithreaded=False)
385 
386 
388  self.toolLayout = QHBoxLayout()
389  self.toolLayout.addWidget(self.toolbar)
390 
391  self.loadingIndictator = QLabel()
392  self.loadingMovie = QMovie('assets/loader.gif')
393  self.emptyLoadingPicture = QPicture()
394  self.emptyLoadingPicture.load('assets/empty_loader.png')
395  self.stopLoadingIndicator()
396  self.toolLayout.addWidget(self.loadingIndictator)
397 
398  self.toolLayout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
399  # self.toolLayout.addWidget(QSpacerItem(150, 10, QSizePolicy.Expanding))
400 
401  self.copyImagePushButton = QPushButton()
402  # self.copyImagePushButton.setText("Copy")
403  # self.copyImagePushButton.setMinimumWidth(1)
404  # self.copyImagePushButton.style().standardIcon(QStyle.SP_DialogOpenButton)
405  self.copyImagePushButton.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton))
406  self.toolLayout.addWidget(self.copyImagePushButton)
407  self.copyImagePushButton.clicked.connect(self.copyPlotToClipboard)
408 
409  downsampleLabel = QLabel()
410  downsampleLabel.setText("DS")
411  self.downSampleInput = QSpinBox()
412  self.downSampleInput.setValue(self.downsample)
413  self.toolLayout.addWidget(downsampleLabel)
414  self.toolLayout.addWidget(self.downSampleInput)
415  self.downSampleInput.valueChanged.connect(self.changeDownSample)
416 
417  self.statusLabel = QLabel()
418  self.toolLayout.addWidget(self.statusLabel)
419 
420  def changeDownSample(self, val):
421  self.downsample = val
422  self.plotter.setDownSample(self.downsample)
423  self.updatePlot()
424 
426  # pixmap = QPixmap.grabWidget(self.canvas)
427  # QApplication.clipboard().setPixmap(pixmap)
428  # pixmap.save('test.png')
429 
430  # store the image in a buffer using savefig(), this has the
431  # advantage of applying all the default savefig parameters
432  # such as background color; those would be ignored if you simply
433  # grab the canvas using Qt
434  buf = io.BytesIO()
435  self.figure.savefig(buf)
436 
437  QApplication.clipboard().setImage(QImage.fromData(buf.getvalue()))
438  buf.close()
439 
441  self.loadingIndictator.setMovie(self.loadingMovie)
442  self.loadingMovie.start()
443 
444  def dragEnterEvent(self, e):
445  if (e.mimeData().hasUrls()):
446  e.acceptProposedAction()
447 
448 
449  def dropEvent(self, e):
450  try:
451  directory = e.mimeData().urls()[0].toLocalFile()
452  self.load(directory)
453  except Exception as e:
454  self.showError(e)
455 
456  def showError(self, e):
457  msg = QMessageBox()
458  msg.setIcon(QMessageBox.Critical)
459  msg.setText("Unable to load log: " + e.__str__())
460  msg.setDetailedText(traceback.format_exc())
461  msg.exec()
462 
463  def createFileTree(self):
464  self.dirModel = QFileSystemModel()
465  self.dirModel.setRootPath(self.config["logs_directory"])
466  self.dirModel.setFilter(QtCore.QDir.Dirs | QtCore.QDir.NoDotAndDotDot)
467  self.dirLineEdit = QLineEdit()
468  self.dirLineEdit.setText(self.config["logs_directory"])
469  self.dirLineEdit.setFixedHeight(25)
470  self.dirLineEdit.returnPressed.connect(self.handleTreeDirChange)
471  self.fileTree = QTreeView()
472  self.fileTree.setModel(self.dirModel)
473  self.fileTree.setRootIndex(self.dirModel.index(self.config['logs_directory']))
474  self.fileTree.setColumnHidden(1, True)
475  self.fileTree.setColumnHidden(2, True)
476  self.fileTree.setColumnHidden(3, True)
477  self.fileTree.setMinimumWidth(300)
478  self.fileTree.clicked.connect(self.handleTreeViewClick)
479  self.fileTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
480  self.fileTree.setSelectionMode(QAbstractItemView.SingleSelection)
481  self.fileTree.customContextMenuRequested.connect(self.handleTreeViewRightClick)
482  # self.populateRMSCheck(self.config['logs_directory'])
483 
484  def updateFileTree(self):
485  self.dirModel.setRootPath(self.config["logs_directory"])
486  self.fileTree.setRootIndex(self.dirModel.index(self.config['logs_directory']))
487 
488  def populateRMSCheck(self, directory):
489  for subdir in os.listdir(directory):
490  path = os.path.join(directory, subdir)
491  if os.path.isdir(path):
492  self.populateRMSCheck(path)
493  elif 'RMS' in subdir:
494  f = open(path)
495  rms_report = f.read()
496  p = re.compile(r'(?<=^PASS/FAIL).*\n', re.M)
497  line = re.search(p, rms_report).group()
498  failed = True if "FAIL" in line else False
499  if failed:
500  pass
501  else:
502  pass
503 
505  self.config["logs_directory"] = self.dirLineEdit.text()
506  self.updateFileTree()
507 
508  file = open(self.configFilePath, 'w')
509  yaml.dump(self.config, file)
510  file.close()
511 
513  selected_directory = self.fileTree.model().filePath(self.fileTree.selectedIndexes()[0])
514  for fname in os.listdir(selected_directory):
515  if fname.endswith('.dat'):
516  try:
517  self.load(selected_directory)
518  except Exception as e:
519  self.showError(e)
520  break
521 
522  def handleTreeViewRightClick(self, event):
523  selected_directory = os.path.normpath(self.fileTree.model().filePath(self.fileTree.selectedIndexes()[0]))
524  menu = QMenu(self)
525  copyAction = menu.addAction("Copy path")
526  nppActionHot = menu.addAction("Run NPP - Start Hot")
527  nppActionCold = menu.addAction("Run NPP - Start Cold")
528  nppActionFactory = menu.addAction("Run NPP - Start Factory")
529  setDataInfoDirAction = menu.addAction("Set as dataInfo.json directory")
530  openAction = menu.addAction("Open folder")
531  cleanFolderAction = menu.addAction("Clean folder")
532  deleteFolderAction = menu.addAction("Delete folder")
533  action = menu.exec_(self.fileTree.viewport().mapToGlobal(event))
534  if action == copyAction:
535  cb = QApplication.clipboard()
536  cb.clear(mode=cb.Clipboard )
537  cb.setText(selected_directory, mode=cb.Clipboard)
538  if action == nppActionHot:
539  cleanFolder(selected_directory)
540  setDataInformationDirectory(selected_directory, startMode=START_MODE_HOT)
541  sys.path.insert(1, '../../../../python/src')
542  from supernpp.supernpp import SuperNPP
543  spp = SuperNPP(selected_directory, self.config['serials'])
544  spp.run()
545  if action == nppActionCold:
546  cleanFolder(selected_directory)
547  setDataInformationDirectory(selected_directory, startMode=START_MODE_COLD)
548  sys.path.insert(1, '../../../../python/src')
549  from supernpp.supernpp import SuperNPP
550  spp = SuperNPP(selected_directory, self.config['serials'], startMode=START_MODE_COLD)
551  spp.run()
552  if action == nppActionFactory:
553  cleanFolder(selected_directory)
554  setDataInformationDirectory(selected_directory, startMode=START_MODE_FACTORY)
555  sys.path.insert(1, '../../../../python/src')
556  from supernpp.supernpp import SuperNPP
557  spp = SuperNPP(selected_directory, self.config['serials'], startMode=START_MODE_FACTORY)
558  spp.run()
559  if action == setDataInfoDirAction:
560  setDataInformationDirectory(selected_directory)
561  if action == openAction:
562  openFolderWithFileBrowser(selected_directory)
563  if action == cleanFolderAction:
564  cleanFolder(selected_directory)
565  if action == deleteFolderAction:
566  msg = QMessageBox(self)
567  msg.setIcon(QMessageBox.Question)
568  msg.setText("Are you sure you want to delete this folder?\n\n" + selected_directory)
569  msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
570  result = msg.exec()
571  if result == QMessageBox.Yes:
572  removeDirectory(selected_directory)
573 
575  self.loadingMovie.stop()
576  self.loadingIndictator.clear()
577  self.loadingIndictator.setPicture(self.emptyLoadingPicture)
578 
579  def showDeviceInfo(self):
580  dlg = DeviceInfoDialog(self.log, self)
581  dlg.show()
582  dlg.exec_()
583 
584  def showFlashConfig(self):
585  dlg = FlashConfigDialog(self.log, self)
586  dlg.show()
587  dlg.exec_()
588 
589 
590  def plot(self, func, args=None):
591  print("plotting " + func)
592  self.currently_selected = func
593  self.plotargs = args
594 
595  self.figure.clear()
596 
597  if hasattr(self, 'plotter'):
598  if args is not None:
599  getattr(self.plotter, func)(*args, self.figure)
600  else:
601  getattr(self.plotter, func)(self.figure)
602 
603  self.canvas.draw()
604  self.stopLoadingIndicator()
605  print("done plotting")
606 
607 if __name__ == '__main__':
608  app = QApplication(sys.argv)
609  MainWindow = QMainWindow()
610 
611  configFilePath = os.path.join(os.path.expanduser("~"), "Documents", "Inertial_Sense", "config.yaml")
612 
613  main = LogInspectorWindow(configFilePath, MainWindow)
614  main.setupUi()
615  # main.load(directory)
616  main.show()
617 
618  if len(sys.argv) > 1:
619  directory = sys.argv[1]
620  main.load(directory)
621 
622  app.exec_()
def dateTimeArrayToString(date, time)
size_t count(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:3206
def cleanFolder(path, toplevel=True)
Definition: logInspector.py:45
GeneratorWrapper< T > range(T const &start, T const &end, T const &step)
Definition: catch.hpp:4141
def setDataInformationDirectory(path, startMode=START_MODE_HOT)
Definition: logInspector.py:80
def __init__(self, configFilePath, parent=None)
def addButton(self, name, function, multithreaded=True, layout=None)


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:57