csvdatawriterbackend.cpp \
gui/exportgraphtoimagedialog.cpp \
imagedrawer.cpp \
- signaldrawer.cpp
+ signaldrawer.cpp \
+ jsonserializable.cpp
HEADERS += \
datafilesloader.h \
gui/exportgraphtoimagedialog.h \
imagedrawer.h \
signaldrawer.h \
- enumflags.h
+ enumflags.h \
+ jsonserializable.h
FORMS += \
gui/mainwindow.ui \
E_FATAL
};
- explicit DataFilesLoader(QObject* parent = 0);
+ explicit DataFilesLoader(QObject* parent = nullptr);
ReturnCode loadSingleRun(const QDir& path, std::vector<std::shared_ptr<AGRE_MeasurementInfo>>& dataFiles);
private:
#include "logger.h"
#include "gui/exportgraphtoimagedialog.h"
#include "gui/exportrawdatadialog.h"
+#include <QtCore/QJsonDocument>
#include <QtWidgets/QMessageBox>
#include <QDebug>
_c = std::shared_ptr<SignalController>(new SignalController(_s));
+ /* Try to read saved user data from JSON file */
+ QFile jsonFile(dir.path() + "/" + "ank_" + QString::fromStdString(_s->descriptiveName()) + ".json");
+ if (jsonFile.exists()) {
+ if (jsonFile.open(QFile::ReadOnly)) {
+ QByteArray bytes = jsonFile.readAll();
+ QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes);
+ QJsonObject jso = jsonDoc.object();
+
+ if (!_c->deserialize(jso)) {
+ llog->log(Logger::Level::WARNING, ME_SENDER_STR, "Failed to deserialize saved user data for " + QString::fromStdString(_s->descriptiveName()));
+ QMessageBox::warning(nullptr, "Load single run", "Saved user data for signal " + QString::fromStdString(_s->descriptiveName()) +
+ "could not have been read properly.");
+ }
+ } else
+ llog->log(Logger::Level::WARNING, ME_SENDER_STR, "Cannot open saved user data file " + QString::fromStdString(_s->descriptiveName()) +
+ " for reading.");
+ } else
+ llog->log(Logger::Level::DEBUG, ME_SENDER_STR, "No user data file for " + QString::fromStdString(_s->descriptiveName()));
+
sigs[_s->descriptiveName()] = _s;
ctrls[_s->descriptiveName()] = _c;
}
}
singleRun = std::shared_ptr<SingleRunData>(new SingleRunData(methodNames.at(0), operatorNames.at(0), sampleInfos.at(0), dates.at(0), times.at(0), sigs, ctrls,
- dir.dirName(), this));
+ dir.dirName(), dir.absolutePath(), this));
Logger::log(Logger::DEBUG, ME_SENDER_STR, "Single run successfully parsed");
emit setActiveSequenceIndex(0);
}
+void DataManager::onSaveChanges()
+{
+ std::shared_ptr<SingleRunData> sr = m_activeSequence->selectedRun();
+ std::unordered_map<std::string, std::shared_ptr<SignalController>>::const_iterator cit;
+
+ if (m_activeSequence == nullptr)
+ return;
+
+ const std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls = sr->allControllers();
+ cit = ctrls.cbegin();
+
+ while (cit != ctrls.cend()) {
+ QJsonValue val = cit->second->serialize();
+ QJsonDocument doc(val.toObject());
+ QFile f(sr->absPath() + "/" + "ank_" + QString::fromStdString(cit->first) + ".json");
+ QByteArray bytes = doc.toJson();
+
+ f.open(QFile::WriteOnly);
+ f.write(bytes.data(), bytes.size());
+
+ qDebug() << val;
+ f.close();
+ ++cit;
+ }
+
+}
+
void DataManager::onSequenceSelected(const QString& key)
{
if (m_sequenceRejected) {
void onExportRawData();
void onLoadSequence(const QString& dir);
void onLoadSingleRun(const QString& dir);
+ void onSaveChanges();
void onSequenceSelected(const QString& key);
void onSingleRunSelected(const QString& key);
/* DATA menu */
connect(ui->actionLoad_single_run, SIGNAL(triggered()), this, SLOT(onLoadSingleRun()));
connect(ui->actionLoad_sequence, SIGNAL(triggered()), this, SLOT(onLoadSequence()));
+ connect(ui->actionSave_changes, SIGNAL(triggered()), this, SLOT(onSaveChanges()));
/* EXPORT menu */
connect(ui->actionRaw_values, SIGNAL(triggered()), this, SLOT(onExportRawData()));
connect(ui->actionIntegration_results, SIGNAL(triggered()), this, SLOT(onExportPeaks()));
void onIntegrateSelected();
void onLoadSequence();
void onLoadSingleRun();
+ void onSaveChanges() { emit saveChanges(); }
void onSequenceSelected(const QString& str);
void onSingleRunSelected(const QString& str);
void onSWFullSizeToggle();
void exportRawData();
void loadSequence(const QString& dir);
void loadSingleRun(const QString& dir);
+ void saveChanges();
void sequenceSelected(const QString& str);
void singleRunSelected(const QString& str);
};
</property>
<addaction name="actionLoad_single_run"/>
<addaction name="actionLoad_sequence"/>
+ <addaction name="separator"/>
+ <addaction name="actionSave_changes"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Graph as image</string>
</property>
</action>
+ <action name="actionSave_changes">
+ <property name="text">
+ <string>Save changes</string>
+ </property>
+ </action>
</widget>
<resources/>
<connections/>
*/
#include "integratedpeak.h"
+#include <QtCore/QJsonObject>
-IntegratedPeak::IntegratedPeak(IntegratedPeak::Type type, double auc, size_t peakIdx, double peakTime, double peakVal,
+const QString IntegratedPeak::KEY_AUC("auc");
+const QString IntegratedPeak::KEY_FROMIDX("fromIdx");
+const QString IntegratedPeak::KEY_FROMTIME("fromTime");
+const QString IntegratedPeak::KEY_FROMY("fromY");
+const QString IntegratedPeak::KEY_PEAKIDX("peakIdx");
+const QString IntegratedPeak::KEY_PEAKTIME("peakTime");
+const QString IntegratedPeak::KEY_PEAKY("peakY");
+const QString IntegratedPeak::KEY_TOIDX("toIdx");
+const QString IntegratedPeak::KEY_TOTIME("toTime");
+const QString IntegratedPeak::KEY_TOY("toY");
+const QString IntegratedPeak::KEY_TYPE("type");
+
+IntegratedPeak::IntegratedPeak(IntegratedPeak::Type type, double auc, size_t peakIdx, double peakTime, double peakY,
size_t fromIdx, size_t toIdx, double fromTime, double toTime, double fromY, double toY, QObject* parent) :
QObject(parent),
+ JSONSerializable(),
m_auc(auc),
m_fromIdx(fromIdx),
m_fromTime(fromTime),
m_fromY(fromY),
m_peakIdx(peakIdx),
m_peakTime(peakTime),
- m_peakVal(peakVal),
+ m_peakY(peakY),
m_toIdx(toIdx),
m_toTime(toTime),
m_toY(toY),
return (m_toY - m_fromY) / (m_toIdx - m_fromIdx);
}
+bool IntegratedPeak::deserialize(const QJsonValue& value)
+{
+ QJsonObject jso;
+ QString type;
+
+ if (!value.isObject())
+ return false;
+
+ jso = value.toObject();
+
+ if (!jso.contains(KEY_AUC))
+ return false;
+ m_auc = jso.value(KEY_AUC).toDouble();
+ if (!jso.contains(KEY_FROMIDX))
+ return false;
+ m_fromIdx = jso.value(KEY_FROMIDX).toDouble();
+ if (!jso.contains(KEY_FROMTIME))
+ return false;
+ m_fromTime = jso.value(KEY_FROMTIME).toDouble();
+ if (!jso.contains(KEY_FROMY))
+ return false;
+ m_fromY = jso.value(KEY_FROMY).toDouble();
+
+ if (!jso.contains(KEY_PEAKIDX))
+ return false;
+ m_peakIdx = jso.value(KEY_PEAKIDX).toDouble();
+ if (!jso.contains(KEY_PEAKTIME))
+ return false;
+ m_peakTime = jso.value(KEY_PEAKTIME).toDouble();
+ if (!jso.contains(KEY_PEAKY))
+ return false;
+ m_peakY = jso.value(KEY_PEAKY).toDouble();
+
+ if (!jso.contains(KEY_TOIDX))
+ return false;
+ m_toIdx = jso.value(KEY_TOIDX).toDouble();
+ if (!jso.contains(KEY_TOTIME))
+ return false;
+ m_toTime = jso.value(KEY_TOTIME).toDouble();
+ if (!jso.contains(KEY_TOY))
+ return false;
+ m_toY = jso.value(KEY_TOY).toDouble();
+
+ if (!jso.contains(KEY_TYPE))
+ return false;
+ type = jso.value(KEY_TYPE).toString();
+ if (type.compare("PEAK") == 0)
+ m_type = Type::PEAK;
+ else
+ m_type = Type::VALLEY;
+
+ return true;
+}
+
double IntegratedPeak::height() const
{
- return fabs(m_peakVal - (baselineSlope() * (m_peakIdx - m_fromIdx) + m_fromY));
+ return fabs(m_peakY - (baselineSlope() * (m_peakIdx - m_fromIdx) + m_fromY));
+}
+
+QJsonValue IntegratedPeak::serialize() const
+{
+ QJsonObject jso;
+ QString type = (m_type == Type::PEAK) ? "PEAK" : "VALLEY";
+
+ jso.insert(KEY_AUC, QJsonValue(m_auc));
+ jso.insert(KEY_FROMIDX, QJsonValue(static_cast<qint64>(m_fromIdx)));
+ jso.insert(KEY_FROMTIME, QJsonValue(m_fromTime));
+ jso.insert(KEY_FROMY, QJsonValue(m_fromY));
+ jso.insert(KEY_PEAKIDX, QJsonValue(static_cast<qint64>(m_peakIdx)));
+ jso.insert(KEY_PEAKTIME, QJsonValue(m_peakTime));
+ jso.insert(KEY_PEAKY, QJsonValue(m_peakY));
+ jso.insert(KEY_TOIDX, QJsonValue(static_cast<qint64>(m_toIdx)));
+ jso.insert(KEY_TOTIME, QJsonValue(m_toTime));
+ jso.insert(KEY_TOY, QJsonValue(m_toY));
+ jso.insert(KEY_TYPE, QJsonValue(type));
+
+ return jso;
}
#ifndef INTEGRATEDPEAK_H
#define INTEGRATEDPEAK_H
+#include "jsonserializable.h"
#include <QtCore/QObject>
-class IntegratedPeak : public QObject
+class IntegratedPeak : public QObject, public JSONSerializable
{
Q_OBJECT
public:
enum class Type {
+ INVALID,
PEAK,
VALLEY
};
- explicit IntegratedPeak(Type type, double auc, size_t peakIdx, double peakTime, double peakVal, size_t fromIdx, size_t toIdx, double fromTime, double toTime,
+ explicit IntegratedPeak() : m_type(Type::INVALID) {}
+ explicit IntegratedPeak(Type type, double auc, size_t peakIdx, double peakTime, double peakY, size_t fromIdx, size_t toIdx, double fromTime, double toTime,
double fromY, double toY, QObject* parent = nullptr);
double auc() const { return m_auc; }
double baselineSlope() const;
double height() const;
size_t peakIdx() const { return m_peakIdx; }
double peakTime() const { return m_peakTime; }
+ double peakY() const { return m_peakY; }
size_t toIdx() const { return m_toIdx; }
double toTime() const { return m_toTime; }
double toY() const { return m_toY; }
Type type() const { return m_type; }
double width() const { return m_toTime - m_fromTime; }
+ virtual bool deserialize(const QJsonValue& value);
+ virtual QJsonValue serialize() const;
+
private:
- const double m_auc;
- const size_t m_fromIdx;
- const double m_fromTime;
- const double m_fromY;
- const size_t m_peakIdx;
- const double m_peakTime;
- const double m_peakVal;
- const size_t m_toIdx;
- const double m_toTime;
- const double m_toY;
- const Type m_type;
+ double m_auc;
+ size_t m_fromIdx;
+ double m_fromTime;
+ double m_fromY;
+ size_t m_peakIdx;
+ double m_peakTime;
+ double m_peakY;
+ size_t m_toIdx;
+ double m_toTime;
+ double m_toY;
+ Type m_type;
+
+ static const QString KEY_AUC;
+ static const QString KEY_FROMIDX;
+ static const QString KEY_FROMTIME;
+ static const QString KEY_FROMY;
+ static const QString KEY_PEAKIDX;
+ static const QString KEY_PEAKTIME;
+ static const QString KEY_PEAKY;
+ static const QString KEY_TOIDX;
+ static const QString KEY_TOTIME;
+ static const QString KEY_TOY;
+ static const QString KEY_TYPE;
+
public slots:
signals:
m_signal(signal)
{}
+void Integrator::addPeak(std::shared_ptr<IntegratedPeak> peak)
+{
+ emit addingPeak(m_peaksList.count());
+ m_peaksList.append(peak);
+ emit peakAdded();
+}
+
std::shared_ptr<const IntegratedPeak> Integrator::deletePeak(size_t idx)
{
size_t ctr = 0;
};
explicit Integrator(std::shared_ptr<Signal> signal, QObject* parent = nullptr);
+ void addPeak(std::shared_ptr<IntegratedPeak> peak);
std::shared_ptr<const IntegratedPeak> deletePeak(size_t idx);
std::vector<std::shared_ptr<const IntegratedPeak>> allPeaks();
ReturnCode integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak);
--- /dev/null
+#include "jsonserializable.h"
+
+JSONSerializable::JSONSerializable()
+{
+}
--- /dev/null
+#ifndef JSONSERIALIZABLE_H
+#define JSONSERIALIZABLE_H
+
+#include <QtCore/QJsonValue>
+
+class JSONSerializable
+{
+public:
+ JSONSerializable();
+ virtual QJsonValue serialize() const = 0;
+ virtual bool deserialize(const QJsonValue& value) = 0;
+};
+
+#endif // JSONSERIALIZABLE_H
QObject::connect(mWin.get(), SIGNAL(exportGraphToImage()),dMgr.get(), SLOT(onExportGraphToImage()));
QObject::connect(mWin.get(), SIGNAL(exportPeaks()), dMgr.get(), SLOT(onExportPeaks()));
QObject::connect(mWin.get(), SIGNAL(exportRawData()), dMgr.get(), SLOT(onExportRawData()));
+ QObject::connect(mWin.get(), SIGNAL(saveChanges()), dMgr.get(), SLOT(onSaveChanges()));
QObject::connect(mWin.get(), SIGNAL(loadSingleRun(QString)), dMgr.get(), SLOT(onLoadSingleRun(QString)));
QObject::connect(mWin.get(), SIGNAL(loadSequence(QString)), dMgr.get(), SLOT(onLoadSequence(QString)));
QObject::connect(mWin.get(), SIGNAL(sequenceSelected(QString)), dMgr.get(), SLOT(onSequenceSelected(QString)));
#include "logger.h"
#include <cfloat>
#include <utility>
-
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
#include <QDebug>
const double SignalController::RELATIVE_MAX = 100.0;
const double SignalController::RELATIVE_MIN = 0.0;
const QString SignalController::ME_SENDER_STR("SignalController");
+const QString SignalController::KEY_PEAKS("peaks");
+
SignalController::SignalController(std::shared_ptr<Signal> signal, QObject* parent) :
QObject(parent),
+ JSONSerializable(),
m_signal(signal)
{
m_integrator = std::shared_ptr<Integrator>(new Integrator(signal));
return genPeakDrawData(peak);
}
+bool SignalController::deserialize(const QJsonValue& value)
+{
+ QJsonObject jso;
+ QJsonArray jsPeakArray;
+
+ if (!value.isObject()) {
+ Logger::log(Logger::Level::WARNING, ME_SENDER_STR, "JSON value is notan object");
+ return false;
+ }
+ jso = value.toObject();
+
+ /* Add peaks */
+ if (!jso.contains(KEY_PEAKS)) {
+ Logger::log(Logger::Level::WARNING, ME_SENDER_STR, "JSON object does not contain \"peaks\" array");
+ return false;
+ }
+ jsPeakArray = jso.value(KEY_PEAKS).toArray();
+ for (QJsonValueRef ref : jsPeakArray) {
+ std::shared_ptr<IntegratedPeak> peak(new IntegratedPeak());
+
+ peak->deserialize(ref);
+ m_integrator->addPeak(peak);
+ }
+
+ return true;
+}
+
std::shared_ptr<GraphDrawData> SignalController::getGraphDrawData(const double fromX, const double toX)
{
size_t fromIdx, toIdx;
return PeakDrawData();
}
+QJsonValue SignalController::serialize() const
+{
+ QJsonObject jso;
+ QJsonArray jsPeakArray;
+
+ for (std::shared_ptr<const IntegratedPeak> peak : m_integrator->allPeaks()) {
+ QJsonValue val = peak->serialize();
+ jsPeakArray.append(val);
+ }
+
+ jso.insert("peaks", jsPeakArray);
+ return jso;
+}
+
/** Private methods **/
PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<const IntegratedPeak> peak)
#include "integrationtablemodel.h"
#include "integrator.h"
+#include "jsonserializable.h"
#include "signal.h"
#include "signaldatatablemodel.h"
#include <memory>
const double relStep;
};
-class SignalController : public QObject
+class SignalController : public QObject, public JSONSerializable
{
Q_OBJECT
public:
~SignalController();
SignalDataTableModel* dataTableModel() { return m_dtblModel; }
PeakDrawData deletePeak(const double x);
+ virtual bool deserialize(const QJsonValue& value);
Signal::TimeValuePair getXYValues(const double x);
std::shared_ptr<GraphDrawData> getGraphDrawData(const double fromX, const double toX);
std::vector<PeakDrawData> getPeaksDrawData(const double fromX, const double fromY, const double toX, const double toY);
PeakDrawData integratePeak(const double fromX, const double fromY, const double toX, const double toY);
IntegrationTableModel* integrationTableModel() { return m_integTblModel;}
void setGUIViewport(const double fromX, const double fromY, const double toX, const double toY);
+ virtual QJsonValue serialize() const;
const std::shared_ptr<Signal> signal() const { return m_signal; }
const std::shared_ptr<Integrator> cIntegrator() const { return m_integrator; }
static const QString ME_SENDER_STR;
+ static const QString KEY_PEAKS;
+
public slots:
signals:
SingleRunData::SingleRunData(const QString& methodName, const QString& operatorName, const QString& sampleInfo, const QDate date, const QTime time,
std::unordered_map<std::string, std::shared_ptr<Signal>>& sigs, std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls,
- const QString& dirname, QObject *parent) :
+ const QString& dirname, const QString& absPath, QObject *parent) :
QObject(parent),
+ m_absPath(absPath),
m_date(date),
m_dirName(dirname),
m_methodName(methodName),
public:
explicit SingleRunData(const QString& methodName, const QString& operatorName, const QString& sampleInfo, const QDate date, const QTime time,
std::unordered_map<std::string, std::shared_ptr<Signal>>& sigs, std::unordered_map<std::string, std::shared_ptr<SignalController>>& ctrls,
- const QString& dirname, QObject* parent = nullptr);
+ const QString& dirname, const QString& absPath, QObject* parent = nullptr);
+ QString absPath() const { return m_absPath; }
const std::unordered_map<std::string, std::shared_ptr<SignalController>>& allControllers() const { return m_ctrls; }
std::vector<std::string> allKeys() const;
const std::unordered_map<std::string, std::shared_ptr<Signal>>& allSignals() const { return m_signals; }
QTime time() const { return m_time; }
private:
+ const QString m_absPath;
const QDate m_date;
const QString m_dirName;
const QString m_methodName;