]> Devoid-pointer.net GitWeb - anyanka.git/commitdiff
Add feature to integrate peak by baseline
authorMichal Malý <madcatxster@devoid-pointer.net>
Thu, 31 Jul 2014 07:58:39 +0000 (09:58 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Thu, 31 Jul 2014 07:58:39 +0000 (09:58 +0200)
18 files changed:
datafilesloader.cpp
datamanager.cpp
gui/graphview.cpp
gui/graphview.h
gui/mainwindow.cpp
gui/mainwindow.h
gui/mainwindow.ui
helpers.h
integratedpeak.cpp
integratedpeak.h
integrator.cpp
integrator.h
metatypes.h
signal.cpp
signal.h
signalcontroller.cpp
signalcontroller.h
signaldrawer.cpp

index 0d1f1b8ae35869dbad46dfab6d30b8ed354e6b69..b5fdfd8f65704d4c2bf3e12fb65a296ad7ede277 100644 (file)
@@ -34,7 +34,7 @@ DataFilesLoader::DataFilesLoader(QObject *parent) :
   m_supportedFileTypes << "*.ch";
 }
 
-DataFilesLoader::ReturnCode DataFilesLoader::loadSingleRun(const QDir& path, std::vector<struct HPCS_MeasuredData*>& loadedData)
+DataFilesLoader::ReturnCode DataFilesLoader::loadSingleRun(const QDir& path, std::vector<struct HPCS_MeasuredData* >& loadedData)
 {
   ReturnCode ret = ReturnCode::SUCCESS;
 
@@ -57,8 +57,6 @@ DataFilesLoader::ReturnCode DataFilesLoader::loadSingleRun(const QDir& path, std
       QMessageBox::warning(nullptr, "Error reading file '" + s + "'", errDesc);
 
       hpcs_free(mdata);
-      ret = ReturnCode::E_READ_ERROR;
-      break;
     }
   }
 
@@ -72,5 +70,5 @@ DataFilesLoader::ReturnCode DataFilesLoader::loadSingleRun(const QDir& path, std
 
   Logger::log(Logger::Level::DEBUG, ME_SENDER_STR, QString::number(loadedData.size()) + " files were found and successfully parsed");
 
-  return ret;
+  return ReturnCode::SUCCESS;
 }
index f80786df38ab0bf54cde10865100ccebd237964d..010e23e6f3e083edb80508d7193574ea457ca572 100644 (file)
@@ -349,7 +349,8 @@ std::shared_ptr<SingleRunData> DataManager::loadSingleRun(QDir& dir)
       Signal::TimeValuePair stvp(md->data[idx].time, md->data[idx].value);
       values.push_back(stvp);
     }
-    _s = std::shared_ptr<Signal>(new Signal(eqp, res, samplingRate, yu, md->dad_wavelength_msr, md->dad_wavelength_ref, values));
+    _s = std::shared_ptr<Signal>(new Signal(eqp, res, samplingRate, yu, md->dad_wavelength_msr.wavelength, md->dad_wavelength_msr.interval,
+                                            md->dad_wavelength_ref.wavelength, md->dad_wavelength_ref.interval, values));
 
     if (!date.isValid()) {
       llog->log(Logger::WARNING, ME_SENDER_STR, QString("Date ") + date.toString() + QString("is invalid."));
@@ -424,8 +425,8 @@ void DataManager::showOneSignal(std::shared_ptr<SignalController> ctrl)
   swp->setDataTableModel(ctrl->dataTableModel());
   swp->setIntegrationTableModel(ctrl->integrationTableModel());
   if (ctrl->signal()->resource() == Signal::Resource::CE_DAD)
-    swp->setTypeText(ctrl->signal()->resourceAsString() + " Sig: " + QString::number(ctrl->signal()->wavelengthAbsorbed()) + " nm, Ref: " +
-                     QString::number(ctrl->signal()->wavelengthReference()) + " nm");
+    swp->setTypeText(ctrl->signal()->resourceAsString() + " Sig: " + QString::number(ctrl->signal()->wavelengthMeasured().wavelength) + " nm, Ref: " +
+                     QString::number(ctrl->signal()->wavelengthReference().wavelength) + " nm");
   else
     swp->setTypeText(ctrl->signal()->resourceAsString());
   swp->setXUnits(ctrl->signal()->xunitAsString());
index 9f7c3fc12a8be4f76032d4efe25599d8e4b8e05b..5b9a64385dad1764e64a25e186a87739fe3977ea 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 
+#include "helpers.h"
 #include "gui/graphview.h"
 #include "logger.h"
 #include <QtGui/QPainter>
@@ -120,14 +121,19 @@ void GraphView::mousePressEvent(QMouseEvent* ev)
     case Qt::LeftButton:
       switch (m_mouseMode) {
         case GraphView::MouseMode::CROSSHAIR:
-          if (m_graphCtrlMode == GraphControlModes::ZOOM) {
+          switch (m_graphCtrlMode) {
+          case GraphControlModes::ZOOM:
             m_zoomRectStartXPix = ev->x();
             m_zoomRectStartYPix = ev->y();
             m_zoomRectLastXPix = ev->x();
             m_zoomRectLastYPix = ev->y();
             eraseCrosshair(true);
             m_mouseMode = GraphView::MouseMode::ZOOM;
-          } else if (m_graphCtrlMode == GraphControlModes::INTEGRATE) {
+            break;
+          case GraphControlModes::INTEGRATE_BASELINE:
+            m_integrateStartBLYPix = relToYPix(m_controller->valueToRel(m_controller->getXYValues(xPixToRel(ev->x())).second));
+            m_integrateStopBLYPix = m_integrateStartBLYPix;
+          case GraphControlModes::INTEGRATE_INTERSECT:
             m_integrateStartXPix = ev->x();
             m_integrateStartYPix = ev->y();
             m_integrateStopXPix = ev->x();
@@ -143,7 +149,7 @@ void GraphView::mousePressEvent(QMouseEvent* ev)
           break;
         case GraphView::MouseMode::INTEGRATE:
           PeakDrawData pdData = m_controller->integratePeak(xPixToRel(m_integrateStartXPix), yPixToRel(m_integrateStartYPix),
-                                      xPixToRel(m_integrateStopXPix), yPixToRel(m_integrateStopYPix));
+                                      xPixToRel(m_integrateStopXPix), yPixToRel(m_integrateStopYPix), m_integrationType);
           eraseIntegrationBaseline(true);
           QRegion reg = renderPeak(pdData, m_background);
           copyPixmapRegion(reg, m_background, m_pixmap);
@@ -233,6 +239,18 @@ void GraphView::drawIntegrationBaseline(const int x, const int y)
 
   reg = eraseIntegrationBaseline();
 
+  if (m_integrationType == IntegrationType::BASELINE) {
+      m_integrateStopBLYPix = relToYPix(m_controller->valueToRel(m_controller->getXYValues(xPixToRel(x)).second));
+
+      p.begin(m_pixmap);
+      p.setPen(Qt::black);
+      p.drawLine(m_integrateStartXPix, m_integrateStartYPix, m_integrateStartXPix, m_integrateStartBLYPix);
+      p.drawLine(x, y, x, m_integrateStopBLYPix);
+      p.end();
+      reg += QRect(m_integrateStartXPix, m_integrateStopXPix, m_integrateStartXPix, m_integrateStopBLYPix);
+      reg += QRect(x, y, x, m_integrateStopBLYPix);
+  }
+
   if (m_integrateStartXPix > m_integrateStopXPix) {
     lstartX = (m_integrateStopXPix > 1) ? m_integrateStopXPix - 1 : 0;
     lstopX = (m_integrateStartXPix < dwidth()-1) ? m_integrateStartXPix + 1 : dwidth()-1;
@@ -254,6 +272,8 @@ void GraphView::drawIntegrationBaseline(const int x, const int y)
   p.drawLine(m_integrateStartXPix, m_integrateStartYPix, x, y);
   p.end();
 
+
+
   reg += QRect(lstartX, lstartY, lstopX, lstopY);
 
   m_integrateStopXPix = x;
@@ -347,6 +367,25 @@ QRegion GraphView::eraseIntegrationBaseline(bool apply)
   if (m_integrateStartXPix < 0)
     return QRegion();
 
+  if (m_integrationType == IntegrationType::BASELINE) {
+    int top, bottom, left, right;
+    top = Helpers::minof(m_integrateStartYPix, m_integrateStopYPix, m_integrateStartBLYPix, m_integrateStopBLYPix);
+    bottom = Helpers::maxof(m_integrateStartYPix, m_integrateStopYPix, m_integrateStartBLYPix, m_integrateStopBLYPix);
+    left = std::min(m_integrateStartXPix, m_integrateStopXPix);
+    right = std::max(m_integrateStartXPix, m_integrateStopXPix);
+
+    p.begin(m_pixmap);
+    p.drawPixmap(left, top, *m_background, left, top, right - left+1, bottom - top+1);
+    //p.drawPixmap(lstartX, lstartY, *m_background, lstartX, lstartY, lstopX - lstartX+1, lstopY - lstartY+1); //FIXME: +1 should not be needed!
+      /*p.begin(m_pixmap);
+      p.setPen(Qt::yellow);
+      p.drawLine(m_integrateStartXPix, m_integrateStartYPix, m_integrateStartXPix, m_integrateStartBLYPix);
+      p.drawLine(x, y, x, m_integrateStopBLYPix);
+      p.end();*/
+    reg += QRect(left, top, right - left+1, bottom - top+1);
+    p.end();
+  }
+
   p.begin(m_pixmap);
   if (m_integrateStartXPix > m_integrateStopXPix) {
     lstartX = (m_integrateStopXPix > 1) ? m_integrateStopXPix - 1 : 0;
@@ -366,7 +405,7 @@ QRegion GraphView::eraseIntegrationBaseline(bool apply)
   p.drawPixmap(lstartX, lstartY, *m_background, lstartX, lstartY, lstopX - lstartX+1, lstopY - lstartY+1); //FIXME: +1 should not be needed!
   p.end();
 
-  reg = QRect(lstartX, lstartY, lstopX - lstartX +1, lstopY - lstartY + 1);
+  reg += QRect(lstartX, lstartY, lstopX - lstartX +1, lstopY - lstartY + 1);
 
   if (apply)
     update(reg);
index 2718ef70414020a13adc5980544bce7cb851b83e..eaa7009ab94f72141990d2560ed4ac9cb50a936b 100644 (file)
@@ -82,6 +82,9 @@ private:
   int m_graphCrosshairXPix;
   int m_graphCrosshairYPix;
   /* Integration baseline */
+  IntegrationType m_integrationType;
+  int m_integrateStartBLYPix;
+  int m_integrateStopBLYPix;
   int m_integrateStartXPix;
   int m_integrateStartYPix;
   int m_integrateStopXPix;
@@ -100,7 +103,11 @@ private slots:
   void onCtxMenuZoomOut();
 
 public slots:
-  void onControlModeChanged(GraphControlModes mode) { m_graphCtrlMode = mode; }
+  void onControlModeChanged(GraphControlModes mode)
+  { m_graphCtrlMode = mode;
+    if (mode == GraphControlModes::INTEGRATE_BASELINE) m_integrationType = IntegrationType::BASELINE;
+    else if (mode == GraphControlModes::INTEGRATE_INTERSECT) m_integrationType = IntegrationType::INTERSECTION;
+  }
 
 signals:
   void crosshairValuesUpdated(const double time, const double value);
index 68d6d7fb69e924d469c74f332f9905c50f98809a..f220bed75fb291825cd31c32dd88ab6605020713 100644 (file)
@@ -64,7 +64,8 @@ void MainWindow::connectActions()
 #endif
 {
   /* Controls panel */
-  connect(ui->qpb_integrate, SIGNAL(pressed()), this, SLOT(onIntegrateSelected()));
+  connect(ui->qpb_integrateBaseline, SIGNAL(pressed()), this, SLOT(onIntegrateBaselineSelected()));
+  connect(ui->qpb_integrateIntersect, SIGNAL(pressed()), this, SLOT(onIntegrateIntersectSelected()));
   connect(ui->qpb_zoom, SIGNAL(pressed()), this, SLOT(onZoomSelected()));
 
   /* DATA menu */
@@ -85,8 +86,10 @@ void MainWindow::connectActions()
 /* Public slots */
 void MainWindow::onAddToDashboard(SignalView* sw)
 {
-  if (ui->qpb_integrate->isChecked())
-    sw->m_graphView->onControlModeChanged(GraphControlModes::INTEGRATE);
+  if (ui->qpb_integrateBaseline->isChecked())
+    sw->m_graphView->onControlModeChanged(GraphControlModes::INTEGRATE_BASELINE);
+  else if(ui->qpb_integrateIntersect->isChecked())
+    sw->m_graphView->onControlModeChanged(GraphControlModes::INTEGRATE_INTERSECT);
   else if(ui->qpb_zoom->isChecked())
     sw->m_graphView->onControlModeChanged(GraphControlModes::ZOOM);
 
@@ -144,10 +147,16 @@ void MainWindow::onAboutAnyanka()
   aa.exec();
 }
 
-void MainWindow::onIntegrateSelected()
+void MainWindow::onIntegrateBaselineSelected()
 {
-  emit controlModeChanged(GraphControlModes::INTEGRATE);
+  emit controlModeChanged(GraphControlModes::INTEGRATE_BASELINE);
 }
+
+void MainWindow::onIntegrateIntersectSelected()
+{
+  emit controlModeChanged(GraphControlModes::INTEGRATE_INTERSECT);
+}
+
 void MainWindow::onLoadSequence()
 {
   m_loadDataFileDialog->setWindowTitle("Load sequence");
index f181d2dc844aad7ee7df0a69e98e63890e626eda..88cc39860c8c82b2b783fe40528804045af0c5f5 100644 (file)
@@ -73,7 +73,8 @@ private slots:
   void onExportGraphToImage() { emit exportGraphToImage(); }
   void onExportPeaks() { emit exportPeaks(); }
   void onExportRawData() { emit exportRawData(); }
-  void onIntegrateSelected();
+  void onIntegrateBaselineSelected();
+  void onIntegrateIntersectSelected();
   void onLoadSequence();
   void onLoadSingleRun();
   void onSaveChanges() { emit saveChanges(); }
index 2748af23888021152ea1cccdbf06a79ea3f6ddcb..4a0d98439348adcaae75c799dc54b3a7677c970b 100644 (file)
         </widget>
        </item>
        <item row="0" column="1">
-        <widget class="QPushButton" name="qpb_integrate">
+        <widget class="QPushButton" name="qpb_integrateIntersect">
          <property name="text">
-          <string>Integrate</string>
+          <string>Integrate by intersection</string>
+         </property>
+         <property name="checkable">
+          <bool>true</bool>
+         </property>
+         <property name="autoExclusive">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="2">
+        <widget class="QPushButton" name="qpb_integrateBaseline">
+         <property name="text">
+          <string>Integrate by baseline</string>
          </property>
          <property name="checkable">
           <bool>true</bool>
index f492ed28025261e80af5048b679c77d3971c6068..fcf3cb7b45ae2eeae96071261d9b90db8347813c 100644 (file)
--- a/helpers.h
+++ b/helpers.h
@@ -54,5 +54,35 @@ public:
     return name.mid(dotIdx+1).toLower();
   }
 
+  template <typename T> static T maxof(T n, ...)
+  {
+    T idx;
+    T val, largest;
+    va_list vl;
+    va_start(vl, n);
+    largest = va_arg(vl, T);
+    for (idx = 1; idx < n; idx++) {
+      val = va_arg(vl, T);
+      largest = (largest > val) ? largest : val;
+    }
+    va_end(vl);
+    return largest;
+  }
+
+  template <typename T> static T minof(T n, ...)
+  {
+    T idx;
+    T val, largest;
+    va_list vl;
+    va_start(vl, n);
+    largest = va_arg(vl, T);
+    for (idx = 1; idx < n; idx++) {
+      val = va_arg(vl, T);
+      largest = (largest < val) ? largest : val;
+    }
+    va_end(vl);
+    return largest;
+  }
+
 };
 #endif // MATHHELPERS_H
index b0c42161d30f89627bf23010ef44fd78e1831681..d4b17562fc05278ad67ea4464007eb4a8d1a8eee 100644 (file)
@@ -27,6 +27,7 @@ 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_ITYPE("itype");
 const QString IntegratedPeak::KEY_PEAKIDX("peakIdx");
 const QString IntegratedPeak::KEY_PEAKTIME("peakTime");
 const QString IntegratedPeak::KEY_PEAKY("peakY");
@@ -39,13 +40,14 @@ const QString IntegratedPeak::KEY_RELBLQ("relBlQ");
 
 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,
-                               double relBlSlope, double relBlQ, QObject* parent) :
+                               double relBlSlope, double relBlQ, IntegrationType itype, QObject* parent) :
   QObject(parent),
   JSONSerializable(),
   m_auc(auc),
   m_fromIdx(fromIdx),
   m_fromTime(fromTime),
   m_fromY(fromY),
+  m_itype(itype),
   m_peakIdx(peakIdx),
   m_peakTime(peakTime),
   m_peakY(peakY),
@@ -85,6 +87,9 @@ bool IntegratedPeak::deserialize(const QJsonValue& value)
   if (!jso.contains(KEY_FROMY))
     return false;
   m_fromY = jso.value(KEY_FROMY).toDouble();
+  if (!jso.contains(KEY_ITYPE))
+    m_itype = IntegrationType::INTERSECTION;
+  m_itype = jso.value(KEY_ITYPE).toBool() ? IntegrationType::BASELINE : IntegrationType::INTERSECTION;
 
   if (!jso.contains(KEY_PEAKIDX))
     return false;
@@ -138,6 +143,7 @@ QJsonValue IntegratedPeak::serialize() const
   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_ITYPE, QJsonValue( (m_itype == IntegrationType::BASELINE) ? true : false) );
   jso.insert(KEY_PEAKIDX, QJsonValue(static_cast<qint64>(m_peakIdx)));
   jso.insert(KEY_PEAKTIME, QJsonValue(m_peakTime));
   jso.insert(KEY_PEAKY, QJsonValue(m_peakY));
index af38729ff937ea03a8dee6c5cf1a780fc35ae0e2..1e1e2db05826896a5665d4d0d75a6c0ec3e89257 100644 (file)
 #include "jsonserializable.h"
 #include <QtCore/QObject>
 
+enum class IntegrationType {
+  NONE,
+  INTERSECTION,
+  BASELINE
+};
+
 class IntegratedPeak : public QObject, public JSONSerializable
 {
   Q_OBJECT
@@ -39,13 +45,14 @@ public:
 
   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, double relBlSlope, double relBlQ, QObject* parent = nullptr);
+                          double fromY, double toY, double relBlSlope, double relBlQ, IntegrationType itype, QObject* parent = nullptr);
   double auc() const { return m_auc; }
   double baselineSlope() const;
   size_t fromIdx() const { return m_fromIdx; }
   double fromY() const { return m_fromY; }
   double fromTime() const { return m_fromTime;}
   double height() const;
+  IntegrationType itype() const { return m_itype; }
   size_t peakIdx() const { return m_peakIdx; }
   double peakTime() const { return m_peakTime; }
   double peakY() const { return m_peakY; }
@@ -65,6 +72,7 @@ private:
   size_t m_fromIdx;
   double m_fromTime;
   double m_fromY;
+  IntegrationType m_itype;
   size_t m_peakIdx;
   double m_peakTime;
   double m_peakY;
@@ -79,6 +87,7 @@ private:
   static const QString KEY_FROMIDX;
   static const QString KEY_FROMTIME;
   static const QString KEY_FROMY;
+  static const QString KEY_ITYPE;
   static const QString KEY_PEAKIDX;
   static const QString KEY_PEAKTIME;
   static const QString KEY_PEAKY;
index 98b775ffc00fb55ac411193f704743e877a535f3..5633cc8b69f00a5b646853a67ad1d66027c168f7 100644 (file)
@@ -84,16 +84,10 @@ Integrator::PeakList Integrator::allPeaks()
 }
 
 Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, IntegratedPeakSPtr& peak,
-                                             double relBlSlope, double relBlQ)
+                                             double relBlSlope, double relBlQ, IntegrationType itype)
 {
-  size_t peakValueIdx;
-  size_t startIntersIdx, stopIntersIdx;
-  size_t i;
-  double auc = 0.0;
   double slope;
-  double startYVal, stopYVal;
-  bool expectDownward;
-  IntegratedPeak::Type peakType;
+  bool down;
 
   if (startIdx > m_signal->valuesCount()-1) {
     Logger::log(Logger::Level::ERROR, ME_SENDER_STR, "Invalid startIdx value " + QString::number(startIdx));
@@ -110,25 +104,45 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
   }
 
   slope = (stopY - startY) / static_cast<double>(stopIdx - startIdx);
-  /* Try to find first intersection */
-  if (startY < m_signal->valueAt(startIdx)) {
-    expectDownward = true;
-    //qDebug() << "Expecting downward peak";
-  } else {
-    expectDownward = false;
-    //qDebug() << "Expecting upward peak";
+
+  switch (itype) {
+  case IntegrationType::INTERSECTION: {
+    if (startY < m_signal->valueAt(startIdx))
+      down = true;
+    else
+      down = false;
+    ReturnCode ret = findIntersections(startIdx, startY, stopIdx, stopY, down, slope);
+    if (ret != ReturnCode::SUCCESS)
+      return ret;
+    break;
   }
+  default:
+    if (startY > m_signal->valueAt(startIdx))
+      down = true;
+    else down = false;
+    break;
+  }
+
+  return integrateInternal(startIdx, startY, stopIdx, stopY, down, slope, peak, relBlSlope, relBlQ, itype);
+}
+
+Integrator::ReturnCode Integrator::findIntersections(size_t& startIdx, double& startY, size_t& stopIdx, double& stopY, bool& down, const double slope)
+{
+  size_t origStartIdx = startIdx;
+  size_t i;
+
+  /* Try to find first intersection */
   for (i = startIdx; i <= stopIdx; i++) {
     double value = m_signal->valueAt(i);
-    double blY = slope * static_cast<double>(i - startIdx) + startY;
+    double blY = slope * static_cast<double>(i - origStartIdx) + startY;
 
-    if (expectDownward && blY > value) { /* Found first intersection */
-      startIntersIdx = i;
-      startYVal = blY;
+    if (down && blY > value) { /* Found first intersection */
+      startIdx = i;
+      startY = blY;
       break;
-    } else if (!expectDownward && blY < value) { /* Found first intersection */
-      startIntersIdx = i;
-      startYVal = blY;
+    } else if (!down && blY < value) { /* Found first intersection */
+      startIdx = i;
+      startY = blY;
       break;
     }
   }
@@ -140,15 +154,15 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
   /* Try to find second intersection */
   for (; i <= stopIdx; i++) {
     double value = m_signal->valueAt(i);
-    double blY = slope * static_cast<double>(i - startIdx) + startY;
+    double blY = slope * static_cast<double>(i - origStartIdx) + startY;
 
-    if (expectDownward && blY < value) {
-      stopIntersIdx = i;
-      stopYVal = blY;
+    if (down && blY < value) {
+      stopIdx = i;
+      stopY = blY;
       break;
-    } else if (!expectDownward && blY > value) {
-      stopIntersIdx = i;
-      stopYVal = blY;
+    } else if (!down && blY > value) {
+      stopIdx = i;
+      stopY = blY;
       break;
     }
   }
@@ -157,11 +171,21 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
     return ReturnCode::E_NO_SECOND_INTERSECT;
   }
 
+  return ReturnCode::SUCCESS;
+}
+
+Integrator::ReturnCode Integrator::integrateInternal(const size_t startIdx, const double startY, const size_t stopIdx, const double stopY,
+                                                     const bool down, const double slope, IntegratedPeakSPtr& peak,
+                                                     double relBlSlope, double relBlQ, IntegrationType itype)
+{
+  double auc = 0.0;
+  size_t peakValueIdx = startIdx;
+  IntegratedPeak::Type peakType;
+
   /* Integrate */
-  peakValueIdx = startIntersIdx;
-  for (i = startIntersIdx+1; i < stopIntersIdx; i++) {
-    double blXA = slope * (i - startIntersIdx) + startY;
-    double blXB = slope * (i - startIntersIdx) + startY;
+  for (size_t i = startIdx+1; i < stopIdx; i++) {
+    double blXA = slope * (i - startIdx) + startY;
+    double blXB = slope * (i - startIdx) + startY;
     double valA = m_signal->valueAt(i-1);
     double valB = m_signal->valueAt(i);
     double tA = m_signal->timeAt(i-1);
@@ -169,26 +193,26 @@ Integrator::ReturnCode Integrator::integrate(size_t startIdx, size_t stopIdx, do
     double avgH = (valB + valA)/2 - (blXB + blXA)/2;
     double area = avgH * (tB - tA);
     auc += area;
-    if (expectDownward && valB < m_signal->valueAt(peakValueIdx)) peakValueIdx = i;
-    else if (!expectDownward && valB > m_signal->valueAt(peakValueIdx)) peakValueIdx = i;
+    if (down && valB < m_signal->valueAt(peakValueIdx)) peakValueIdx = i;
+    else if (!down && valB > m_signal->valueAt(peakValueIdx)) peakValueIdx = i;
     //qDebug() << area << auc;
   }
   /* Convert AUC to positive and seconds */
   auc = fabs(auc) * 60;
 
   /* Add peak to list */
-  if (expectDownward) peakType = IntegratedPeak::Type::VALLEY;
+  if (down) peakType = IntegratedPeak::Type::VALLEY;
   else peakType = IntegratedPeak::Type::PEAK;
 
-  /*qDebug("Peak integrated");
-  qDebug() << "SXC" << fromX << "SYC" << fromY << "EXC" << toX << "EYC" << toY << "Slope" << slope;
-  qDebug() << "1st(X, Y, vY)" << startIntersIdx << m_signal->valueAt(startIntersIdx) << startYVal;
-  qDebug() << "2nd(X, Y, vY)" << stopIntersIdx << m_signal->valueAt(stopIntersIdx) << stopYVal;
-  qDebug("---");*/
+  qDebug("Peak integrated");
+  //qDebug() << "SXC" << fromX << "SYC" << fromY << "EXC" << toX << "EYC" << toY << "Slope" << slope;
+  qDebug() << "1st(X, Y, vY)" << startIdx << m_signal->valueAt(startIdx) << startY;
+  qDebug() << "2nd(X, Y, vY)" << stopIdx << m_signal->valueAt(stopIdx) << stopY;
+  qDebug("---");
 
   peak = std::shared_ptr<IntegratedPeak>(new IntegratedPeak(peakType, auc, peakValueIdx, m_signal->timeAt(peakValueIdx), m_signal->valueAt(peakValueIdx),
-                                                            startIntersIdx, stopIntersIdx, m_signal->timeAt(startIntersIdx), m_signal->timeAt(stopIntersIdx),
-                                                            startYVal, stopYVal, relBlSlope, relBlQ));
+                                                            startIdx, stopIdx, m_signal->timeAt(startIdx), m_signal->timeAt(stopIdx),
+                                                            startY, stopY, relBlSlope, relBlQ, itype));
   emit addingPeak(m_peakCount);
   addPeakToMap(peak);
   emit peakAdded();
index b5248d58dff1bb08978d3c1d11f21f615e444b7c..71e89a6a6340a378577a4540cef0e55922da9e81 100644 (file)
@@ -52,14 +52,15 @@ public:
   PeakList allPeaks();
   IntegratedPeakCSPtr deletePeak(size_t idx);
   ReturnCode integrate(size_t startIdx, size_t stopIdx, double startY, double stopY, std::shared_ptr<IntegratedPeak>& peak,
-                       double relBlSlope, double relBlQ);
+                       double relBlSlope, double relBlQ, IntegrationType itype);
   IntegratedPeakCSPtr peakByLinearIdx(const size_t idx);
-  //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCBegin() const { return m_peaks.cbegin(); }
-  //std::multimap<size_t, std::shared_ptr<IntegratedPeak>>::const_iterator peaksCEnd() const { return m_peaks.cend(); }
   size_t peakCount() const { return m_peakCount; }
 
 private:
   void addPeakToMap(IntegratedPeakCSPtr peak);
+  ReturnCode findIntersections(size_t& startIdx, double& startY, size_t& stopIdx, double& stopY, bool& down, const double slope);
+  ReturnCode integrateInternal(const size_t startIdx, const double startY, const size_t stopIdx, const double stopY, const bool down,
+                               const double slope, IntegratedPeakSPtr& peak, double relBlSlope, double relBlQ, const IntegrationType itype);
 
   size_t m_peakCount;
   PeakMap m_peakMap;
index 2c13c89c6d6fe0d8447fd86ed20376140c288293..62eccee0ae93dc088f3ffc5b566d44c3c6b71972 100644 (file)
@@ -32,7 +32,8 @@ Q_DECLARE_METATYPE(SignalViewPtr);
 
 enum class GraphControlModes {
   ZOOM,
-  INTEGRATE
+  INTEGRATE_INTERSECT,
+  INTEGRATE_BASELINE
 };
 Q_DECLARE_METATYPE(GraphControlModes);
 
index 25ed6b5b3d3852d6291766e7b9d7cef083132361..1792715d3e8ff90b4aa4ba134b3725779e36e677 100644 (file)
@@ -34,15 +34,18 @@ const QString Signal::MILLIAU_SI("mAU");
 const QString Signal::MILLIVOLTS_SI("mV");
 const QString Signal::WATTS_SI("W");
 
-Signal::Signal(const Equipment equipment, const Resource resource, const double samplingRate, const YUnit yunit, uint16_t wavelengthAbs, uint16_t wavelengthRef,
+Signal::Signal(const Equipment equipment, const Resource resource, const double samplingRate, const YUnit yunit,
+               const uint16_t wlMsr, const uint16_t wlMsrInt, const uint16_t wlRef, const uint16_t wlRefInt,
                const std::vector<TimeValuePair>& values, QObject* parent) :
   QObject(parent),
   m_equipment(equipment),
   m_resource(resource),
   m_samplingRate(samplingRate),
   m_values(values),
-  m_wavelengthAbs(wavelengthAbs),
-  m_wavelengthRef(wavelengthRef),
+  m_wavelengthMeasured(wlMsr),
+  m_wavelengthMeasuredInterval(wlMsrInt),
+  m_wavelengthReference(wlRef),
+  m_wavelengthReferenceInterval(wlRefInt),
   m_xunit(XUnit::MINUTE),
   m_yunit(yunit)
 {
@@ -58,7 +61,8 @@ QString Signal::descriptiveName() const
 {
   QString name = resourceAsString();
   if (m_resource == Resource::CE_DAD)
-    name += "_SIG" + QString::number(m_wavelengthAbs) + "_REF" + QString::number(m_wavelengthRef);
+    name += "_SIG" + QString::number(m_wavelengthMeasured) + "/" + QString::number(m_wavelengthMeasuredInterval) +  "_REF" +
+            QString::number(m_wavelengthReference) + "/" + QString::number(m_wavelengthReferenceInterval);
   return name;
 }
 
index c18abc7af9bcf9a60d4728f2cf85e777467e55bd..367a946d22eb9067a5bc0d4494ba429979d408e7 100644 (file)
--- a/signal.h
+++ b/signal.h
@@ -53,9 +53,15 @@ public:
     MILLIVOLTS,
     WATTS
   };
+  struct Wavelength {
+    Wavelength (uint16_t w, uint16_t i) : wavelength(w), interval(i) {}
+    uint16_t wavelength;
+    uint16_t interval;
+  };
 
-  explicit Signal(const Equipment equipment, const Resource resource, const double samplingRate, const YUnit yunit, const uint16_t wavelengthAbs,
-                  const uint16_t wavelengthRef, const std::vector<TimeValuePair>& values, QObject* parent = nullptr);
+  explicit Signal(const Equipment equipment, const Resource resource, const double samplingRate, const YUnit yunit, const uint16_t wlMsr,
+                  const uint16_t wlMsrInt, const uint16_t wlRef, const uint16_t wlRefInt,
+                  const std::vector<TimeValuePair>& values, QObject* parent = nullptr);
   uint count() const { return m_values.size(); }
   QString descriptiveName() const;
   Equipment equipment() const { return m_equipment; }
@@ -72,8 +78,8 @@ public:
   std::vector<TimeValuePair>::const_iterator pairsBegin() const { return m_values.cbegin(); }
   size_t valuesCount() const { return m_values.size(); }
   std::vector<TimeValuePair>::const_iterator pairsEnd() const { return m_values.cend(); }
-  uint16_t wavelengthAbsorbed() const { return m_wavelengthAbs; }
-  uint16_t wavelengthReference() const { return m_wavelengthRef; }
+  Wavelength wavelengthMeasured() const { return Wavelength(m_wavelengthMeasured, m_wavelengthMeasuredInterval); }
+  Wavelength wavelengthReference() const { return Wavelength(m_wavelengthReference, m_wavelengthReferenceInterval); }
   XUnit xunit() const { return m_xunit; }
   QString xunitAsString() const;
   YUnit yunit() const { return m_yunit; }
@@ -86,8 +92,10 @@ private:
   const Resource m_resource;
   const double m_samplingRate;
   const std::vector<TimeValuePair> m_values;
-  const uint16_t m_wavelengthAbs;
-  const uint16_t m_wavelengthRef;
+  const uint16_t m_wavelengthMeasured;
+  const uint16_t m_wavelengthMeasuredInterval;
+  const uint16_t m_wavelengthReference;
+  const uint16_t m_wavelengthReferenceInterval;
   const XUnit m_xunit;
   const YUnit m_yunit;
 
index 5cad2bc877ef5812311442d953690b691f0403bc..ed1ebbcf853da74aedf440bb504d0bb33b2c576d 100644 (file)
@@ -212,7 +212,8 @@ Signal::TimeValuePair SignalController::getXYValues(const double x)
   return std::pair<double, double>(m_signal->timeAt(idx), m_signal->valueAt(idx+1));
 }
 
-PeakDrawData SignalController::integratePeak(const double fromX, const double fromY, const double toX, const double toY)
+PeakDrawData SignalController::integratePeak(const double fromX, const double fromY, const double toX, const double toY,
+                                             const IntegrationType itype)
 {
   size_t fromIdx, toIdx;
   double fromVal, toVal;
@@ -236,7 +237,7 @@ PeakDrawData SignalController::integratePeak(const double fromX, const double fr
   fromVal = relToValue(fromY);
   toVal = relToValue(toY);
 
-  ret = m_integrator->integrate(fromIdx, toIdx, fromVal, toVal, peak, relBlSlope, relBlQ);
+  ret = m_integrator->integrate(fromIdx, toIdx, fromVal, toVal, peak, relBlSlope, relBlQ, itype);
 
   switch (ret) {
     case Integrator::ReturnCode::SUCCESS:
@@ -280,6 +281,17 @@ PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<const Integ
   double fromY = m_signal->valueAt(peak->fromIdx());
   double toY = m_signal->valueAt(peak->toIdx());
 
+  switch (peak->itype()) {
+  case IntegrationType::INTERSECTION:
+    fromY = m_signal->valueAt(peak->fromIdx());
+    toY = m_signal->valueAt(peak->toIdx());
+    break;
+  case IntegrationType::BASELINE:
+    fromY = peak->fromY();
+    toY = peak->toY();
+    break;
+  }
+
   //qDebug() << __QFUNC__ << beforeFromY << fromY
   //         << beforeToY << toY;
   //qDebug() << m_signal->timeAt(peak->fromIdx() - 0) << m_signal->timeAt(peak->fromIdx() + 1) << peak->fromTime();
@@ -288,7 +300,8 @@ PeakDrawData SignalController::genPeakDrawData(const std::shared_ptr<const Integ
                       idxToRel(peak->toIdx()), valueToRel(toY), idxToRel(peak->toIdx()-1), valueToRel(beforeToY),
                       peak->relBlSlope(), peak->relBlQ(),
                       idxToRel(peak->peakIdx()), valueToRel(m_signal->valueAt(peak->peakIdx())),
-                      peak->peakTime(), peak->auc());
+                      peak->peakTime(), peak->auc(), peak->itype(),
+                      valueToRel(m_signal->valueAt(peak->fromIdx())), valueToRel(m_signal->valueAt(peak->toIdx())));
 }
 
 double SignalController::idxToRel(const size_t idx)
index 4f5f8f52bd61fdf530200388fc1f89e2bf17774f..ea8bf6dff9bb4f54fbcbdaa4beec018447847c77 100644 (file)
@@ -63,21 +63,25 @@ struct GraphDrawData {
 
 struct PeakDrawData {
   PeakDrawData() : fromX(0), fromY(0), toX(0), toY(0), beforeFromX(0), beforeFromY(0), beforeToX(0),
-    beforeToY(0), blSlope(0), blQ(0), peakX(0), peakY(0), auc(0), time(0) {}
+    beforeToY(0), blSlope(0), blQ(0), peakX(0), peakY(0), auc(0), time(0), itype(IntegrationType::NONE),
+    blFromY(0), blToY(0) {}
   PeakDrawData(const double fromX, const double fromY, const double beforeFromX, const double beforeFromY,
                const double toX, const double toY, const double beforeToX, const double beforeToY,
                const double blSlope, const double blQ,
-               const double peakX, const double peakY, const double auc, const double time) :
+               const double peakX, const double peakY, const double auc, const double time,
+               const IntegrationType itype, const double blFromY, const double blToY) :
     fromX(fromX), fromY(fromY), toX(toX), toY(toY),
     beforeFromX(beforeFromX), beforeFromY(beforeFromY), beforeToX(beforeToX), beforeToY(beforeToY),
     blSlope(blSlope), blQ(blQ),
-    peakX(peakX), peakY(peakY), auc(auc), time(time) {}
+    peakX(peakX), peakY(peakY), auc(auc), time(time), itype(itype), blFromY(blFromY), blToY(blToY) {}
 
   const double fromX, fromY, toX, toY;
   const double beforeFromX, beforeFromY, beforeToX, beforeToY;
   const double blSlope, blQ;
   const double peakX, peakY;
   const double auc, time;
+  const IntegrationType itype;
+  const double blFromY, blToY;
 };
 
 struct RulerDrawData {
@@ -111,7 +115,7 @@ public:
   double toXAbs() const { return m_signal->timeAt(m_signal->count()-1); }
   double fromYAbs() const { return m_signal->valueAt(0); }
   double toYAbs() const { return m_signal->valueAt(m_signal->count()-1); }
-  PeakDrawData integratePeak(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, const IntegrationType itype);
   IntegrationTableModel* integrationTableModel() { return m_integTblModel;}
   void setGUIViewport(const double fromX, const double fromY, const double toX, const double toY);
   virtual QJsonValue serialize() const;
index a709ba425681025d404e86a83e78f19948dcabb8..24863092dce8624676c2116c31cbf9071bd5da49 100644 (file)
@@ -27,7 +27,7 @@
 
 const QString SignalDrawer::ME_SENDER_STR("SignalDrawer");
 const int SignalDrawer::AXIS_LABEL_BORDER_OFFSET(2);
-const int SignalDrawer::AXIS_LABEL_SCALE_OFFSET(2);
+const int SignalDrawer::AXIS_LABEL_SCALE_OFFSET(3);
 const int SignalDrawer::SCALE_MARGIN_TIME(16);
 const int SignalDrawer::SCALE_MARGIN_VALUE(48);
 
@@ -308,14 +308,13 @@ void SignalDrawer::renderValueScaleTick(QPainter* const p, const double rel, con
 
 QRegion SignalDrawer::erasePeak(const PeakDrawData& pd)
 {
-  //QPainter p;
   QFont font("arial", 10);
   QFontMetrics fm(font);
   QString aucText, timeText;
   QRegion peakReg;
   int tTextHeight, tTextWidth, aTextWidth;
-  int fromXPix, fromYPix;
-  int toXPix, toYPix;
+  int fromXPix;
+  int toXPix;
   int peakX, peakY;
   int beginXPix, endXPix;
 
@@ -327,8 +326,8 @@ QRegion SignalDrawer::erasePeak(const PeakDrawData& pd)
   if (pd.auc == 0)
     return QRect();
 
-  fromXPix = relToXPix(pd.fromX); fromYPix = relToYPix(pd.fromY);
-  toXPix = relToXPix(pd.toX); toYPix = relToYPix(pd.toY);
+  fromXPix = relToXPix(pd.fromX);
+  toXPix = relToXPix(pd.toX);
   peakX = relToXPix(pd.peakX); peakY = relToYPix(pd.peakY);
   aucText = m_locale.toString(pd.auc, 'f', 4);
   timeText = m_locale.toString(pd.time, 'f', 4);
@@ -347,7 +346,7 @@ QRegion SignalDrawer::erasePeak(const PeakDrawData& pd)
   else
     endXPix = toXPix;
 
-  peakReg = QRect(beginXPix, 0, endXPix - beginXPix, m_height);
+  peakReg = QRect(beginXPix, 0, endXPix - beginXPix + 1, m_height);
   if (peakReg.intersects(m_xAxisLabelRect)) {
     peakReg += m_xAxisLabelRect;
   }
@@ -422,25 +421,29 @@ QRegion SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   if (pd.auc == 0)
     return QRect();
 
-  /* Psycho: Calculate precise position of the beginning and end of the baseline */
-  double fromSlope = (pd.fromY - pd.beforeFromY) / (pd.fromX - pd.beforeFromX);
-  double toSlope = (pd.toY - pd.beforeToY) / (pd.toX - pd.beforeToX);
-  double qf = pd.beforeFromY - fromSlope * pd.beforeFromX;
-  double qt = pd.beforeToY - toSlope * pd.beforeToX;
-  double precFromX = linesIntersection(fromSlope, qf, pd.blSlope, pd.blQ);
-  double precToX = linesIntersection(toSlope, qt, pd.blSlope, pd.blQ);
-  double precFromY = precFromX * pd.blSlope + pd.blQ;
-  double precToY = precToX * pd.blSlope + pd.blQ;
-
-  /*qDebug() << __QFUNC__ << "idxStep" << pd.idxStep;
-  qDebug() << __QFUNC__ << "blSlope" << pd.blSlope << "blQ" << pd.blQ;
-  qDebug() << __QFUNC__ << "fromSlope" << fromSlope;
-  qDebug() << __QFUNC__ << "qf" << qf << "qt" << qt;
-  qDebug() << __QFUNC__ << precFromX << pd.beforeFromX;
-  qDebug() << __QFUNC__ << precFromY << pd.beforeFromY;*/
-
-  fromXPix = relToXPix(precFromX); fromYPix = relToYPix(precFromY);
-  toXPix = relToXPix(precToX); toYPix = relToYPix(precToY);
+  switch (pd.itype) {
+  case IntegrationType::INTERSECTION:
+    {
+    /* Psycho: Calculate precise position of the beginning and end of the baseline */
+    double fromSlope = (pd.fromY - pd.beforeFromY) / (pd.fromX - pd.beforeFromX);
+    double toSlope = (pd.toY - pd.beforeToY) / (pd.toX - pd.beforeToX);
+    double qf = pd.beforeFromY - fromSlope * pd.beforeFromX;
+    double qt = pd.beforeToY - toSlope * pd.beforeToX;
+    double precFromX = linesIntersection(fromSlope, qf, pd.blSlope, pd.blQ);
+    double precToX = linesIntersection(toSlope, qt, pd.blSlope, pd.blQ);
+    double precFromY = precFromX * pd.blSlope + pd.blQ;
+    double precToY = precToX * pd.blSlope + pd.blQ;
+
+    fromXPix = relToXPix(precFromX); fromYPix = relToYPix(precFromY);
+    toXPix = relToXPix(precToX); toYPix = relToYPix(precToY);
+    }
+    break;
+  default:
+    fromXPix = relToXPix(pd.fromX); fromYPix = relToYPix(pd.fromY);
+    toXPix = relToXPix(pd.toX); toYPix = relToYPix(pd.toY);
+    break;
+  }
+
   peakX = relToXPix(pd.peakX); peakY = relToYPix(pd.peakY);
   aucText = m_locale.toString(pd.auc, 'f', 4);
   timeText = QString("A:") + m_locale.toString(pd.time, 'f', 4);
@@ -448,6 +451,10 @@ QRegion SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   p.begin(target);
   p.setPen(Qt::red);
   p.drawLine(fromXPix, fromYPix, toXPix, toYPix);
+  if (pd.itype == IntegrationType::BASELINE) {
+    p.drawLine(fromXPix, fromYPix, fromXPix, relToYPix(pd.blFromY));
+    p.drawLine(toXPix, toYPix, toXPix, relToYPix(pd.blToY));
+  }
 
   /* Draw AREA and TIME caption */
   p.setFont(font);
@@ -474,7 +481,7 @@ QRegion SignalDrawer::renderPeak(const PeakDrawData& pd, QPixmap* const target)
   else
     endXPix = toXPix;
 
-  peakReg = QRect(beginXPix, 0, endXPix - beginXPix, m_height);
+  peakReg = QRect(beginXPix, 0, endXPix - beginXPix + 1, m_height);
   p.end();
 
   if (peakReg.intersects(m_xAxisLabelRect)) {