Initial Commit
commit
3e2a0416cc
|
@ -0,0 +1,141 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# Local stuff to exclude
|
||||||
|
.vscode/
|
|
@ -0,0 +1,14 @@
|
||||||
|
import sys
|
||||||
|
from PyQt5 import QtGui, QtWidgets, uic
|
||||||
|
from memdb import mem
|
||||||
|
|
||||||
|
class AppWindow(QtWidgets.QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super(AppWindow, self).__init__()
|
||||||
|
uic.loadUi('app.ui', self)
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
window = AppWindow()
|
||||||
|
sys.exit(app.exec_())
|
|
@ -0,0 +1,586 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1091</width>
|
||||||
|
<height>580</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>CRDS Time Analyzer</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QGroupBox: {font-style: bold; font-size: 8px }</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<widget class="graph_tab" name="tabWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>260</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>821</width>
|
||||||
|
<height>561</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="raw_data">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Raw Data</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="rawdata_graph" name="widget" native="true">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>-1</x>
|
||||||
|
<y>-1</y>
|
||||||
|
<width>811</width>
|
||||||
|
<height>531</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="groups">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Groups</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="peaks_graph" name="widget_2" native="true">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>651</width>
|
||||||
|
<height>531</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="time_constant">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Time Constant</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="timeconstant_graph" name="widget_3" native="true">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>651</width>
|
||||||
|
<height>531</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>70</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>141</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Grouping Config</string>
|
||||||
|
</property>
|
||||||
|
<widget class="config_area" name="stackedWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>111</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page">
|
||||||
|
<widget class="QWidget" name="formLayoutWidget_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Minimum voltage out</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="spin_min_voltage" name="doubleSpinBox_5">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.001000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<widget class="QWidget" name="formLayoutWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>101</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Estimated pass time</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="spin_group_len" name="spin_group_len">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.000600000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min peak height</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="spin_min_peakheight" name="spin_min_peakheight">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.000400000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min peak prominence</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="spin_min_peakprominence" name="spin_min_peakprominence">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<double>0.001200000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Moving average size</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="spin_moving_average_denom" name="spin_moving_average_denom">
|
||||||
|
<property name="value">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="correlate_button" name="compute_button">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>220</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>28</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>-1</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {font-size: 13px}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Correlate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>320</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>171</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Initial Fit Config</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="formLayoutWidget_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>80</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>89</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_3">
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_14">
|
||||||
|
<property name="text">
|
||||||
|
<string>τ value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_2">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>y0 value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>a value</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_3">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="equation_view" name="graphicsView">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="fit_button" name="compute_button_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>500</y>
|
||||||
|
<width>151</width>
|
||||||
|
<height>28</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>-1</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">* {font-size: 13px}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Fit</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Grouping Algorithm</string>
|
||||||
|
</property>
|
||||||
|
<widget class="combo_grouping_algo" name="comboBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>VThreshold (V column required)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>SpacedGroups</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>260</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>8</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Peak Isolation Config</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="formLayoutWidget_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>9</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>221</width>
|
||||||
|
<height>25</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Individual Peak Range</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="doubleSpinBox_4">
|
||||||
|
<property name="decimals">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1091</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="file_menu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="help_menu" name="menuhelp">
|
||||||
|
<property name="title">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuhelp"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<action name="actionOpen_CSV">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open CSV File</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+O</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionQuit">
|
||||||
|
<property name="text">
|
||||||
|
<string>Quit</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionExport">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+E</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionGithub_repository">
|
||||||
|
<property name="text">
|
||||||
|
<string>GitHub Repo</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionOpen_LabView_Binary">
|
||||||
|
<property name="text">
|
||||||
|
<string>Open LabView File</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>spin_group_len</class>
|
||||||
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>spin_min_peakheight</class>
|
||||||
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>spin_min_peakprominence</class>
|
||||||
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>spin_moving_average_denom</class>
|
||||||
|
<extends>QSpinBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>correlate_button</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>equation_view</class>
|
||||||
|
<extends>QGraphicsView</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>fit_button</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>rawdata_graph</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>peaks_graph</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>timeconstant_graph</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>combo_grouping_algo</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>file_menu</class>
|
||||||
|
<extends>QMenu</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>help_menu</class>
|
||||||
|
<extends>QMenu</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>graph_tab</class>
|
||||||
|
<extends>QTabWidget</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>config_area</class>
|
||||||
|
<extends>QStackedWidget</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>spin_min_voltage</class>
|
||||||
|
<extends>QDoubleSpinBox</extends>
|
||||||
|
<header>widgets</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,13 @@
|
||||||
|
echo WARNING: THIS WILL OVERWRITE app.py WITH A CONVERTED VERSION OF THE .UI FILE.
|
||||||
|
|
||||||
|
set /p INPUT=Continue? [y/n]
|
||||||
|
|
||||||
|
If %INPUT%=="y" goto yes
|
||||||
|
If %INPUT%=="n" goto no
|
||||||
|
|
||||||
|
:yes
|
||||||
|
pyuic5.exe -x .\app.ui -o app.py
|
||||||
|
exit
|
||||||
|
|
||||||
|
:no
|
||||||
|
exit
|
|
@ -0,0 +1,112 @@
|
||||||
|
import numpy as np
|
||||||
|
from scipy.signal import find_peaks, correlate
|
||||||
|
|
||||||
|
def spaced_groups(
|
||||||
|
x_data: np.array,
|
||||||
|
y_data: np.array,
|
||||||
|
group_len: float,
|
||||||
|
peak_minheight: float,
|
||||||
|
peak_prominence: float,
|
||||||
|
sma_denom: int
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Use SpacedGroups algo to separate groups
|
||||||
|
|
||||||
|
Returns 2D array of raw data; every other group
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Helpers
|
||||||
|
def t2i(t): # STATIC time to index
|
||||||
|
delta_t = abs(x_data[0] - t)
|
||||||
|
timestep = abs(x_data[1] - x_data[0])
|
||||||
|
return int(delta_t / timestep)
|
||||||
|
|
||||||
|
def t2i_range(t): # time to index RANGE (just get the delta)
|
||||||
|
timestep = abs(x_data[1] - x_data[0])
|
||||||
|
return int(t / timestep)
|
||||||
|
|
||||||
|
def moving_average(x, w):
|
||||||
|
return np.convolve(x, np.ones(w), 'valid') / w
|
||||||
|
|
||||||
|
def isolate_group(i):
|
||||||
|
i_min = i - t2i_range(group_len)
|
||||||
|
i_max = i + t2i_range(group_len)
|
||||||
|
return y_data.tolist()[i_min:i_max]
|
||||||
|
|
||||||
|
# Detect peaks w/ averaged data
|
||||||
|
x_data_av = np.delete(x_data, [range(int(sma_denom / 2))])
|
||||||
|
x_data_av = np.delete(x_data_av, [range(len(x_data)-int((sma_denom / 2) - 1), len(x_data_av))])
|
||||||
|
y_data_av = moving_average(y_data, sma_denom)
|
||||||
|
peak_indices = find_peaks(y_data_av, height=peak_minheight, prominence=peak_prominence) # Get indices of all peaks
|
||||||
|
|
||||||
|
peaks = []
|
||||||
|
for p in peak_indices[0]: # Get x-values of all peaks
|
||||||
|
peaks.append(x_data[p])
|
||||||
|
|
||||||
|
|
||||||
|
# Group peaks together
|
||||||
|
peak_groups = [[]]
|
||||||
|
group_index = 0
|
||||||
|
for i in range(len(peaks)):
|
||||||
|
item = peaks[i]
|
||||||
|
next_item = 0
|
||||||
|
prev_item = item-10
|
||||||
|
try:
|
||||||
|
next_item = peaks[i+1]
|
||||||
|
prev_item = peaks[i-1]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
peak_groups[group_index].append(item)
|
||||||
|
|
||||||
|
# Removed overlapping peak checks; don't really need that anymore
|
||||||
|
if abs(next_item - item) >= group_len: # Check if far enough away for new group
|
||||||
|
peak_groups.append([])
|
||||||
|
group_index += 1
|
||||||
|
|
||||||
|
for g in peak_groups: # empty group check
|
||||||
|
if len(g) == 0:
|
||||||
|
peak_groups.remove(g)
|
||||||
|
|
||||||
|
peaks_init = [] # Get peaks[0] for every group
|
||||||
|
for g in peak_groups:
|
||||||
|
peaks_init.append(g[0])
|
||||||
|
|
||||||
|
# Isolate group data
|
||||||
|
|
||||||
|
groups_raw = [] # NOTE: Only contains every other group
|
||||||
|
for p in peaks_init:
|
||||||
|
if peaks_init.index(p) % 2 == 0:
|
||||||
|
groups_raw.append(isolate_group(t2i(p)))
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return groups_raw
|
||||||
|
|
||||||
|
def correlate_groups(groups_raw):
|
||||||
|
"""
|
||||||
|
Overlay groups using `scipy.correlate`.
|
||||||
|
|
||||||
|
Returns 2D array of overlayed groups
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Compare groups (scipy correlate)
|
||||||
|
|
||||||
|
group_base = np.array(groups_raw[0])
|
||||||
|
groups_adjusted = [group_base]
|
||||||
|
for x in groups_raw[1:len(groups_raw)-1]:
|
||||||
|
# calculate how much to shift
|
||||||
|
corr = correlate(group_base, np.array(x))
|
||||||
|
shift = corr.tolist().index(max(corr))
|
||||||
|
|
||||||
|
# adjust alignment to fit on top of base group
|
||||||
|
diff = shift - len(x)
|
||||||
|
if diff < 0:
|
||||||
|
for i in range(abs(diff)):
|
||||||
|
x.pop(0)
|
||||||
|
elif diff > 0:
|
||||||
|
x = [0 for i in range(abs(diff))] + x
|
||||||
|
|
||||||
|
groups_adjusted.append(x)
|
||||||
|
|
||||||
|
return groups_adjusted
|
|
@ -0,0 +1,10 @@
|
||||||
|
from sqlitedict import SqliteDict
|
||||||
|
|
||||||
|
class ModSqliteDict(SqliteDict):
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
# Initialize in-memory db
|
||||||
|
self.filename = ':memory:'
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
mem = ModSqliteDict()
|
|
@ -0,0 +1,243 @@
|
||||||
|
import numpy as np
|
||||||
|
from pandas import read_csv
|
||||||
|
import matplotlib
|
||||||
|
matplotlib.use('Qt5Agg')
|
||||||
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg, NavigationToolbar2QT as NavigationToolbar
|
||||||
|
from matplotlib.figure import Figure
|
||||||
|
import crds_calc
|
||||||
|
import PyQt5
|
||||||
|
from PyQt5 import QtWidgets, QtCore
|
||||||
|
from memdb import mem
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
|
||||||
|
def display_warning(message: str):
|
||||||
|
msg = QtWidgets.QMessageBox()
|
||||||
|
msg.setIcon(QtWidgets.QMessageBox.warning)
|
||||||
|
msg.setText("Warning")
|
||||||
|
msg.setInformativeText(message)
|
||||||
|
msg.setWindowTitle("Warning")
|
||||||
|
msg.exec_()
|
||||||
|
|
||||||
|
def display_error(message: str):
|
||||||
|
msg = QtWidgets.QMessageBox()
|
||||||
|
msg.setIcon(QtWidgets.QMessageBox.Critical)
|
||||||
|
msg.setText("Error")
|
||||||
|
msg.setInformativeText(message)
|
||||||
|
msg.setWindowTitle("Error")
|
||||||
|
msg.exec_()
|
||||||
|
|
||||||
|
# Create global object to send signals
|
||||||
|
|
||||||
|
class Global(QtWidgets.QWidget):
|
||||||
|
grouping_algo_changed = QtCore.pyqtSignal()
|
||||||
|
csv_selected = QtCore.pyqtSignal()
|
||||||
|
correlation_complete = QtCore.pyqtSignal()
|
||||||
|
fitting_complete = QtCore.pyqtSignal()
|
||||||
|
globj = Global()
|
||||||
|
|
||||||
|
# Menu definitions
|
||||||
|
|
||||||
|
class file_menu(QtWidgets.QMenu):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
open_csv = QtWidgets.QAction("Open CSV File", self)
|
||||||
|
open_csv.setShortcut("Ctrl+O")
|
||||||
|
open_csv.triggered.connect(self.select_csv)
|
||||||
|
self.addAction(open_csv)
|
||||||
|
|
||||||
|
def select_csv(self):
|
||||||
|
filename, _ = QtWidgets.QFileDialog.getOpenFileName(self)
|
||||||
|
data = read_csv(filename, comment="%", delimiter=";").to_numpy()
|
||||||
|
mem['x_data'] = data.transpose()[0]
|
||||||
|
mem['y_data'] = data.transpose()[1]
|
||||||
|
try:
|
||||||
|
mem['v_data'] = data[2].transpose()
|
||||||
|
except IndexError:
|
||||||
|
display_error('No voltage column detected. Functionality will be limited.')
|
||||||
|
|
||||||
|
globj.csv_selected.emit()
|
||||||
|
|
||||||
|
class help_menu(QtWidgets.QMenu):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
visit_repo = QtWidgets.QAction("Go to GitHub Repo", self)
|
||||||
|
visit_repo.triggered.connect(self.go_to_repo)
|
||||||
|
self.addAction(visit_repo)
|
||||||
|
|
||||||
|
def go_to_repo(self):
|
||||||
|
PyQt5.QtGui.QDesktopServices.openUrl(QtCore.QUrl('https://github.com/turtlebasket/crds-time-analyzer'))
|
||||||
|
|
||||||
|
# Inputs / Parameter boxes
|
||||||
|
|
||||||
|
class combo_grouping_algo(QtWidgets.QComboBox):
|
||||||
|
def change(self):
|
||||||
|
mem['grouping_algo'] = self.currentIndex()
|
||||||
|
globj.grouping_algo_changed.emit()
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
self.currentIndexChanged.connect(self.change)
|
||||||
|
|
||||||
|
class config_area(QtWidgets.QStackedWidget):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
self.setCurrentIndex(0)
|
||||||
|
globj.grouping_algo_changed.connect(lambda: self.setCurrentIndex(mem['grouping_algo']))
|
||||||
|
|
||||||
|
class spin_min_voltage(QtWidgets.QDoubleSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['min_voltage'] = float(val)
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['min_voltage'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class spin_group_len(QtWidgets.QDoubleSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['group_len'] = float(val)
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['group_len'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class spin_peak_len(QtWidgets.QDoubleSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['peak_len'] = float(val)
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['peak_len'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class spin_min_peakheight(QtWidgets.QDoubleSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['peak_minheight'] = float(val)
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['peak_minheight'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class spin_min_peakprominence(QtWidgets.QDoubleSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['peak_prominence'] = float(val)
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['peak_prominence'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class spin_moving_average_denom(QtWidgets.QSpinBox):
|
||||||
|
def changeVal(self, val):
|
||||||
|
mem['moving_avg_denom'] = int(val)
|
||||||
|
print(isinstance(val, str))
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
mem['moving_avg_denom'] = float(self.value())
|
||||||
|
self.textChanged.connect(self.changeVal)
|
||||||
|
|
||||||
|
class equation_view(QtWidgets.QGraphicsView):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
pix = PyQt5.QtGui.QPixmap(f"{pathlib.Path(__file__).parent.resolve()}/assets/eq2.png")
|
||||||
|
item = QtWidgets.QGraphicsPixmapItem(pix)
|
||||||
|
item.setScale(0.15)
|
||||||
|
scene = QtWidgets.QGraphicsScene()
|
||||||
|
scene.addItem(item)
|
||||||
|
self.setScene(scene)
|
||||||
|
|
||||||
|
class correlate_button(QtWidgets.QPushButton):
|
||||||
|
def calc(self):
|
||||||
|
groups_raw = None
|
||||||
|
try:
|
||||||
|
if (mem['grouping_algo'] == 0):
|
||||||
|
display_error('VThreshold not yet implemented.')
|
||||||
|
elif (mem['grouping_algo'] == 1):
|
||||||
|
groups_raw = crds_calc.spaced_groups(
|
||||||
|
mem['x_data'],
|
||||||
|
mem['y_data'],
|
||||||
|
mem['group_len'],
|
||||||
|
mem['peak_minheight'],
|
||||||
|
mem['peak_prominence'],
|
||||||
|
mem['moving_avg_denom']
|
||||||
|
)
|
||||||
|
|
||||||
|
mem['groups_correlated'] = crds_calc.correlate_groups(groups_raw)
|
||||||
|
globj.correlation_complete.emit()
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
display_error('Failed to correlate. Did you import a data file & set parameters?')
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
self.pressed.connect(self.calc)
|
||||||
|
|
||||||
|
class fit_button(QtWidgets.QPushButton):
|
||||||
|
def fit(self):
|
||||||
|
print("hi")
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
self.pressed.connect(self.fit)
|
||||||
|
|
||||||
|
|
||||||
|
# Graph stuff
|
||||||
|
|
||||||
|
class graph_tab(QtWidgets.QTabWidget):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
globj.csv_selected.connect(lambda: self.setCurrentIndex(0))
|
||||||
|
globj.correlation_complete.connect(lambda: self.setCurrentIndex(1))
|
||||||
|
globj.fitting_complete.connect(lambda: self.setCurrentIndex(2))
|
||||||
|
|
||||||
|
class MplCanvas(FigureCanvasQTAgg):
|
||||||
|
def __init__(self, parent=None, width=5, height=4, dpi=100):
|
||||||
|
fig = Figure(figsize=(width, height), dpi=dpi)
|
||||||
|
self.axes = fig.add_subplot(111)
|
||||||
|
fig.tight_layout()
|
||||||
|
super(MplCanvas, self).__init__(fig)
|
||||||
|
|
||||||
|
class base_graph(QtWidgets.QWidget):
|
||||||
|
"""
|
||||||
|
Widget with embedded matplotlib graph & navigation toolbar
|
||||||
|
|
||||||
|
Reference: https://www.mfitzp.com/tutorials/plotting-matplotlib/
|
||||||
|
"""
|
||||||
|
|
||||||
|
canv = None
|
||||||
|
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
self.canv = MplCanvas(self)
|
||||||
|
# Example
|
||||||
|
# canv.axes.plot([0,1,2,3,4], [10,1,20,3,40])
|
||||||
|
toolbar = NavigationToolbar(self.canv, self)
|
||||||
|
layout = QtWidgets.QVBoxLayout()
|
||||||
|
layout.addWidget(toolbar)
|
||||||
|
layout.addWidget(self.canv)
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def plot(self):
|
||||||
|
self.canv.axes.plot(mem['x_data'], mem['y_data'])
|
||||||
|
|
||||||
|
def plot_full(self):
|
||||||
|
self.canv.axes.clear()
|
||||||
|
self.plot()
|
||||||
|
self.canv.draw()
|
||||||
|
print("attempted plot")
|
||||||
|
|
||||||
|
class rawdata_graph(base_graph):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
globj.csv_selected.connect(self.plot_full)
|
||||||
|
|
||||||
|
class peaks_graph(base_graph):
|
||||||
|
def __init__(self, x):
|
||||||
|
super().__init__(x)
|
||||||
|
globj.correlation_complete.connect(self.plot_full)
|
||||||
|
|
||||||
|
def plot(self):
|
||||||
|
for i in mem['groups_correlated']:
|
||||||
|
self.canv.axes.plot(i)
|
||||||
|
|
||||||
|
|
||||||
|
class timeconstant_graph(base_graph):
|
||||||
|
pass
|
Loading…
Reference in New Issue