diff --git a/.gitignore b/.gitignore
index 0e398a2..70cbc7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ brent_test
tasmet
tasmet_automoc.dir
tasmet_solvemodel
+tasmet_autogen
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 64ac6f8..ccadf03 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
# CMakeList.txt for TaSMET
-cmake_minimum_required (VERSION 3.6)
+cmake_minimum_required (VERSION 2.8.5)
project(TaSMET)
set(PACKAGE_VERSION 0.1)
message("Running Cmake for TaSMET version ${PACKAGE_VERSION}")
diff --git a/Doxyfile b/Doxyfile
index dad1477..b93776d 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -51,14 +51,14 @@ PROJECT_BRIEF = "Thermoacoustic System Modeling Environment"
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO = /home/anne/wip/tasmet/src/gui/images/tasmet_small.png
+PROJECT_LOGO = src/gui/images/tasmet_small.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = /home/anne/wip/tasmet/doc
+OUTPUT_DIRECTORY = doc
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
diff --git a/doc/fig/tasys_artist.eps b/doc/fig/tasys_artist.eps
old mode 100755
new mode 100644
diff --git a/doc/fig/tasys_artist.png b/doc/fig/tasys_artist.png
old mode 100755
new mode 100644
diff --git a/gui/__init__.py b/gui/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/gui/about_dialog.py b/gui/about_dialog.py
new file mode 100644
index 0000000..10a541b
--- /dev/null
+++ b/gui/about_dialog.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'about_dialog.ui'
+#
+# Created by: PyQt4 UI code generator 4.12
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui
+
+try:
+ _fromUtf8 = QtCore.QString.fromUtf8
+except AttributeError:
+ def _fromUtf8(s):
+ return s
+
+try:
+ _encoding = QtGui.QApplication.UnicodeUTF8
+ def _translate(context, text, disambig):
+ return QtGui.QApplication.translate(context, text, disambig, _encoding)
+except AttributeError:
+ def _translate(context, text, disambig):
+ return QtGui.QApplication.translate(context, text, disambig)
+
+class Ui_about_dialog(object):
+ def setupUi(self, about_dialog):
+ about_dialog.setObjectName(_fromUtf8("about_dialog"))
+ about_dialog.resize(318, 582)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(about_dialog.sizePolicy().hasHeightForWidth())
+ about_dialog.setSizePolicy(sizePolicy)
+ self.verticalLayout = QtGui.QVBoxLayout(about_dialog)
+ self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
+ self.label = QtGui.QLabel(about_dialog)
+ font = QtGui.QFont()
+ font.setFamily(_fromUtf8("DejaVu Sans Mono"))
+ font.setPointSize(14)
+ font.setBold(True)
+ font.setWeight(75)
+ self.label.setFont(font)
+ self.label.setAlignment(QtCore.Qt.AlignCenter)
+ self.label.setObjectName(_fromUtf8("label"))
+ self.verticalLayout.addWidget(self.label)
+ self.label_4 = QtGui.QLabel(about_dialog)
+ self.label_4.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_4.setObjectName(_fromUtf8("label_4"))
+ self.verticalLayout.addWidget(self.label_4)
+ self.label_5 = QtGui.QLabel(about_dialog)
+ self.label_5.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_5.setObjectName(_fromUtf8("label_5"))
+ self.verticalLayout.addWidget(self.label_5)
+ self.label_2 = QtGui.QLabel(about_dialog)
+ self.label_2.setMinimumSize(QtCore.QSize(300, 433))
+ self.label_2.setMaximumSize(QtCore.QSize(300, 433))
+ self.label_2.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 255)"))
+ self.label_2.setFrameShape(QtGui.QFrame.Box)
+ self.label_2.setText(_fromUtf8(""))
+ self.label_2.setPixmap(QtGui.QPixmap(_fromUtf8("images/tasmet.png")))
+ self.label_2.setScaledContents(True)
+ self.label_2.setObjectName(_fromUtf8("label_2"))
+ self.verticalLayout.addWidget(self.label_2)
+ self.label_3 = QtGui.QLabel(about_dialog)
+ self.label_3.setAlignment(QtCore.Qt.AlignCenter)
+ self.label_3.setObjectName(_fromUtf8("label_3"))
+ self.verticalLayout.addWidget(self.label_3)
+ self.pushButton = QtGui.QPushButton(about_dialog)
+ self.pushButton.setObjectName(_fromUtf8("pushButton"))
+ self.verticalLayout.addWidget(self.pushButton)
+
+ self.retranslateUi(about_dialog)
+ QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), about_dialog.accept)
+ QtCore.QMetaObject.connectSlotsByName(about_dialog)
+
+ def retranslateUi(self, about_dialog):
+ about_dialog.setWindowTitle(_translate("about_dialog", "About TaSMET", None))
+ self.label.setText(_translate("about_dialog", "TaSMET", None))
+ self.label_4.setText(_translate("about_dialog", "Thermoacoustic System", None))
+ self.label_5.setText(_translate("about_dialog", "Modeling Environment Twente", None))
+ self.label_3.setText(_translate("about_dialog", "Copyright (c) 2017 Anne de Jong", None))
+ self.pushButton.setText(_translate("about_dialog", "OK", None))
+
diff --git a/gui/about_dialog.ui b/gui/about_dialog.ui
new file mode 100644
index 0000000..7899116
--- /dev/null
+++ b/gui/about_dialog.ui
@@ -0,0 +1,130 @@
+
+
+ about_dialog
+
+
+
+ 0
+ 0
+ 318
+ 582
+
+
+
+
+ 0
+ 0
+
+
+
+ About TaSMET
+
+
+ -
+
+
+
+ DejaVu Sans Mono
+ 14
+ 75
+ true
+
+
+
+ TaSMET
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Thermoacoustic System
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Modeling Environment Twente
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 300
+ 433
+
+
+
+
+ 300
+ 433
+
+
+
+ background-color: rgb(255, 255, 255)
+
+
+ QFrame::Box
+
+
+
+
+
+ images/tasmet.png
+
+
+ true
+
+
+
+ -
+
+
+ Copyright (c) 2017 Anne de Jong
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ OK
+
+
+
+
+
+
+
+
+ pushButton
+ clicked()
+ about_dialog
+ accept()
+
+
+ 158
+ 562
+
+
+ 158
+ 290
+
+
+
+
+
diff --git a/images/document-new.png b/images/document-new.png
new file mode 100644
index 0000000..61db97a
Binary files /dev/null and b/images/document-new.png differ
diff --git a/images/document-open.png b/images/document-open.png
new file mode 100644
index 0000000..3432ed2
Binary files /dev/null and b/images/document-open.png differ
diff --git a/images/document-save-as.png b/images/document-save-as.png
new file mode 100644
index 0000000..ed2453d
Binary files /dev/null and b/images/document-save-as.png differ
diff --git a/images/document-save.png b/images/document-save.png
new file mode 100644
index 0000000..cc380a0
Binary files /dev/null and b/images/document-save.png differ
diff --git a/images/tasmet.png b/images/tasmet.png
new file mode 100644
index 0000000..a4b2f1d
Binary files /dev/null and b/images/tasmet.png differ
diff --git a/images/tasmet_small.png b/images/tasmet_small.png
new file mode 100644
index 0000000..6a5c9ed
Binary files /dev/null and b/images/tasmet_small.png differ
diff --git a/images/tasmet_transparent.png b/images/tasmet_transparent.png
new file mode 100644
index 0000000..91e3124
Binary files /dev/null and b/images/tasmet_transparent.png differ
diff --git a/src/gui/images/tasmet.png b/src/gui/images/tasmet.png
old mode 100755
new mode 100644
diff --git a/src/gui/images/tasmet_small.png b/src/gui/images/tasmet_small.png
old mode 100755
new mode 100644
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 59f9173..b03a61c 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -11,14 +11,6 @@
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
#include "tasmet_config.h"
#include "tasmet_tracer.h"
#include "tasmet_assert.h"
@@ -31,6 +23,16 @@
#include "solver_dialog.h"
#include "message_tools.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
const QString default_model_name = QString("Unsaved TaSMET Model") +
constants::model_fileext;
const QString default_segment_name = "Unnamed segment";
@@ -38,6 +40,7 @@ const QString start_file_location = QStandardPaths::
writableLocation(QStandardPaths::DocumentsLocation);
const QString filetype = QString("TaSMET Model files (*") + constants::model_fileext + ")";
const QString window_title_part = "TaSMET Model Builder - ";
+
namespace {
int saveFileFirstQuestion(QWidget* parent) {
@@ -55,6 +58,7 @@ namespace {
TaSMETMainWindow::TaSMETMainWindow():
_window(new Ui::MainWindow()),
_model(pb::Model::default_instance()),
+ _saved_model(_model),
_system(*_model.mutable_system())
{
@@ -120,6 +124,7 @@ TaSMETMainWindow::~TaSMETMainWindow(){
void TaSMETMainWindow::newModel() {
TRACE(15,"newModel");
_model = pb::Model::default_instance();
+ _saved_model = _model;
_filepath = "";
set(_model);
}
@@ -148,7 +153,11 @@ void TaSMETMainWindow::loadModel(const string* filepath_s) {
try {
TRACE(15,"Setting loaded model");
_filepath = *filepath_s;
- set(loadMessage(*filepath_s));
+ _model = loadMessage(*filepath_s);
+ _saved_model = _model;
+ _system = *_model.mutable_system();
+ set(_model);
+
}
catch(TaSMETError &e) {
_filepath = "";
@@ -172,6 +181,7 @@ void TaSMETMainWindow::saveModel(string* filepath) {
}
try {
saveMessage(*filepath,_model);
+ _saved_model = _model;
_filepath = *filepath;
changed();
}
@@ -282,8 +292,6 @@ void TaSMETMainWindow::set(const pb::Model& model) {
_window->backlog->setPlainText(QString::fromStdString(model.backlog()));
- _model = model;
- _system = *_model.mutable_system();
_init = false;
changed();
@@ -311,6 +319,9 @@ void TaSMETMainWindow::closeEvent(QCloseEvent *event) {
}
}
+ // If we are here, the model is not dirty anymore. We can savely
+ // close the application.
+
// Save window configuration to settings
QSettings settings(company,appname);
settings.setValue("geometry", saveGeometry());
@@ -470,10 +481,12 @@ void TaSMETMainWindow::on_actionSolve_triggered() {
void TaSMETMainWindow::on_actionPostprocess_model_triggered() {
try {
+
TaSystem sys(_model.system());
if(_model.solution_size() == 0)
throw TaSMETError("No solution found");
vd sol(_model.solution_size());
+
for(us i=0;istartDetached(command,params);
}
catch(TaSMETError &e) {
e.show_user("Postprocessing failed");
@@ -491,18 +519,7 @@ void TaSMETMainWindow::on_actionPostprocess_model_triggered() {
}
bool TaSMETMainWindow::isDirty() const {
TRACE(15,"isDirty()");
- if(_filepath.size()==0) return true;
-
- try {
- pb::Model filemodel = loadMessage(_filepath);
- bool dirty = !compareMessage(filemodel,_model);
- VARTRACE(15,dirty);
- return dirty;
- }
- catch(TaSMETError& e) {
- TRACE(15,"Files could not be compared");
- return true;
- }
+ return !compareMessage(_model,_saved_model);
}
void TaSMETMainWindow::on_actionAbout_triggered(){
diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h
index fbf97fd..4bf3116 100644
--- a/src/gui/mainwindow.h
+++ b/src/gui/mainwindow.h
@@ -26,6 +26,10 @@ class TaSMETMainWindow: public QMainWindow {
// In-memory model
pb::Model _model;
+ pb::Model _saved_model; /**< Last saved state of the model, to
+ compare with to check whether we
+ are dirty yes or no */
+
pb::System& _system; /**< In constructor set to the
_model.mutable_system() */
diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui
index 4a690d1..6d07851 100644
--- a/src/gui/mainwindow.ui
+++ b/src/gui/mainwindow.ui
@@ -348,7 +348,7 @@
0
0
683
- 18
+ 21
diff --git a/src/sys/tasmet_variable.h b/src/sys/tasmet_variable.h
index 7000c62..e44c7b5 100644
--- a/src/sys/tasmet_variable.h
+++ b/src/sys/tasmet_variable.h
@@ -96,7 +96,7 @@ public:
// add two Variableiables
Variable operator+(const Variable& other) const;
//Subtract two Variableiables
- Variable operator-(const Variable& Variable2) const;
+ Variable operator-(const Variable& other) const;
// with Note multiplication is defined outside of the class
// If we need to multiply two numbers in frequency domain, this
diff --git a/src/sys/tasystem.cpp b/src/sys/tasystem.cpp
index 473b118..393bf8a 100644
--- a/src/sys/tasystem.cpp
+++ b/src/sys/tasystem.cpp
@@ -457,10 +457,11 @@ void TaSystem::exportHDF5(const string& filename) const {
// H5Eset_auto(error_stack, old_func, old_client_data); /// Disable HDF5 error printing
if(file_id < 0)
- throw TaSMETError("Creation of export file failed. "
- "This could mean that the file is blocked "
- "by another program, or the user has insufficient "
- "privileges to create the file at the given path."
+ throw TaSMETError("Creation of export file failed. This is probably "
+ "because the postprocessor is already running. "
+ "However, this could also mean that the file is blocked "
+ "by another program, or you have insufficient "
+ "privileges to create the postprocessing file."
);
/// Enable HDF5 error printing
diff --git a/tasmet_postprocessor.py b/tasmet_postprocessor.py
old mode 100755
new mode 100644
index 0ac3341..4cbe35b
--- a/tasmet_postprocessor.py
+++ b/tasmet_postprocessor.py
@@ -5,17 +5,26 @@ Created on Thu Feb 2 08:33:53 2017
@author: anne
"""
-
+qt = 5
# Here we provide the necessary imports.
# The basic GUI widgets are located in QtGui module.
import sys, h5py
import numpy as np
-from PyQt5.QtCore import *
-from PyQt5.QtWidgets import *
-from PyQt5.QtGui import QIcon,QDoubleValidator
-from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
-from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar
+if qt==4:
+ from PyQt4.QtCore import *
+ from PyQt4.QtGui import *
+ from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+ from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar
+else:
+ from PyQt5.QtWidgets import *
+ from PyQt5.QtGui import QIcon,QDoubleValidator
+ from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
+ from matplotlib.backends.backend_qt5 import NavigationToolbar2QT as NavigationToolbar
+
from matplotlib.figure import Figure
+
+import time
+from matplotlib.animation import FuncAnimation
from gui.about_dialog import Ui_about_dialog
scale = [('nano',-9,'n'),
@@ -68,7 +77,7 @@ class TaSMETFigure(Figure):
def __init__(self, width=5, height=4, dpi=100):
- Figure.__init__(self,figsize=(width, height), dpi=dpi)
+ Figure.__init__(self, figsize=(width, height), dpi=dpi)
self._axes = self.add_subplot(111)
@@ -76,6 +85,9 @@ class TaSMETFigure(Figure):
self._plots = []
self._grid = False
+ def setCanvas(self,canvas):
+ self._canvas = canvas
+
def addPlot(self,plot,one):
if one:
self._plots = [plot]
@@ -94,7 +106,8 @@ class TaSMETFigure(Figure):
self._axes.grid(self._grid,'both')
- self.canvas.draw_idle()
+ self.canvas.draw()
+
def setGrid(self,grid):
self._grid = grid
self.rePlot()
@@ -107,7 +120,44 @@ class TaSMETFigure(Figure):
self._plots = []
self.rePlot()
+ def animate(self, data):
+ line = self._axes.get_lines()[0]
+ max_val = np.max(data)
+ min_val = np.min(data)
+
+ self._axes.set_ylim((min_val,max_val))
+
+ # Number of frames available in a period
+ frames_per_period = data.shape[1]
+
+ # Time to pass to show one period
+ time_per_period = 1.0
+
+ # interval in seconds
+ interval = time_per_period/frames_per_period
+
+ # We need a max, here because due to a bug intervals lower than 200
+ # are going plain wrong in matplotlib
+ interval_ms = max(int(interval*1000),200)
+
+ def animate_i(i):
+ line.set_ydata(data[:,i%frames_per_period])
+ return line,
+
+ ani = FuncAnimation(self,
+ animate_i,
+ interval = max(200,interval_ms),
+ frames = frames_per_period,
+ blit=True,
+ repeat = True,
+ save_count = 300 # High value here as animate_i repeats itself
+ )
+ self.canvas.draw()
+# for i in range(100):
+# print(i)
+# animate_i(i)
+#
class TaSMETCanvas(FigureCanvas):
def __init__(self, parent, figure):
@@ -120,7 +170,7 @@ class TaSMETCanvas(FigureCanvas):
QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
-
+ figure.setCanvas(self)
class MainWindow(QMainWindow):
@@ -277,7 +327,7 @@ class MainWindow(QMainWindow):
# Plot menu
plot_menu = QMenu('&Plot', self)
- self._grid_option = QAction('Enable grid')
+ self._grid_option = QAction('Enable grid',plot_menu)
self._grid_option.setCheckable(True)
self._grid_option.triggered.connect(self._figure.setGrid)
plot_menu.addAction(self._grid_option)
@@ -335,8 +385,28 @@ class MainWindow(QMainWindow):
def output(self):
print('output')
+ def disableAll(self):
+ self._seg_box.setEnabled(False)
+ self._qty_box.setEnabled(False)
+ self._vspos.setEnabled(False)
+ self._vstime.setEnabled(False)
+ self._vs_instance.setEnabled(False)
+ self._plot_button.setEnabled(False)
+ self._output_button.setEnabled(False)
+ self._animate_button.setEnabled(False)
+
def animate(self):
- print('animate')
+ self.disableAll()
+ self._hold_button.setChecked(False)
+ self.plot()
+ try:
+ data,datatype = self.getCurrentData()
+ except:
+ return
+
+ self._figure.animate(data[:,:])
+
+ self.qtyItemChanged()
def getCurrentData(self):
"""
@@ -353,13 +423,12 @@ class MainWindow(QMainWindow):
datatype = data.attrs['datatype'].decode('utf-8')
return data,datatype
-
-
-
- def segItemChanged(self,item):
+
+ def segItemChanged(self,item=None):
"""
Update the combobox with quantities
"""
+
self._suppressed = True
self._qty_box.clear()
one = False
@@ -373,14 +442,14 @@ class MainWindow(QMainWindow):
self._suppressed = False
self._qty_box.setCurrentIndex(0)
- self.qtyItemChanged(0)
+ self.qtyItemChanged()
- def qtyItemChanged(self,item):
+ def qtyItemChanged(self,item=None):
"""
The quantity item has been changed
"""
-
if self._suppressed: return
+
try:
data,datatype = self.getCurrentData()
except:
@@ -388,16 +457,15 @@ class MainWindow(QMainWindow):
segitemno = self._seg_box.currentText()
- if data is None:
- self._vstime.setChecked(False)
- self._vspos.setEnabled(False)
- self._vstime.setEnabled(False)
- self._vs_instance.setEnabled(False)
- self._plot_button.setEnabled(False)
- self._output_button.setEnabled(False)
- self._animate_button.setEnabled(False)
- return
+ self.disableAll()
+ self._seg_box.setEnabled(True)
+ self._qty_box.setEnabled(True)
+
+ if data is None:
+ return
+
+
self._plot_button.setEnabled(True)
self._output_button.setEnabled(True)
@@ -405,9 +473,6 @@ class MainWindow(QMainWindow):
if datatype == 'time':
self._vstime.setChecked(True)
self._vspos.setEnabled(False)
- self._vstime.setEnabled(False)
- self._vs_instance.setEnabled(False)
- self._animate_button.setEnabled(False)
elif datatype == 'pos':
self._vspos.setChecked(True)
@@ -429,6 +494,7 @@ class MainWindow(QMainWindow):
self._vspos.setEnabled(True)
self._vstime.setEnabled(True)
self._vs_instance.setEnabled(True)
+ self._animate_button.setEnabled(True)
def initGui(self):
self.defaultOutput()
@@ -552,8 +618,7 @@ def usage():
if __name__ == '__main__':
if(len(sys.argv) < 2):
usage()
- file_ = '../second_duct_sinomgt.tasmet.h5'
-# return -1
+ exit(-1)
else:
file_ = sys.argv[1]
@@ -573,4 +638,4 @@ if __name__ == '__main__':
w.show() # The show() method displays the widget on the screen.
- sys.exit(app.exec_()) # Finally, we enter the mainloop of the application.
\ No newline at end of file
+ sys.exit(app.exec_()) # Finally, we enter the mainloop of the application.