changeset 1815:c546429d4c2f

Add optional ability to write a header on delimited data output, & to write times in frames
author Chris Cannam
date Fri, 10 Jan 2020 14:29:54 +0000
parents 1318e069906b
children fd5a87f3c5b4 23d5cb3f9f38
files base/DataExportOptions.h base/Event.h base/EventSeries.cpp base/EventSeries.h data/fileio/CSVFileWriter.cpp data/model/AlignmentModel.h data/model/BasicCompressedDenseThreeDimensionalModel.cpp data/model/BasicCompressedDenseThreeDimensionalModel.h data/model/BoxModel.h data/model/Dense3DModelPeakCache.h data/model/DenseTimeValueModel.cpp data/model/DenseTimeValueModel.h data/model/EditableDenseThreeDimensionalModel.cpp data/model/EditableDenseThreeDimensionalModel.h data/model/FFTModel.h data/model/ImageModel.h data/model/Model.h data/model/NoteModel.h data/model/RegionModel.h data/model/SparseOneDimensionalModel.h data/model/SparseTimeValueModel.h data/model/TextModel.h
diffstat 22 files changed, 227 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/base/DataExportOptions.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/base/DataExportOptions.h	Fri Jan 10 14:29:54 2020 +0000
@@ -20,6 +20,7 @@
     DataExportDefaults = 0x0,
     DataExportFillGaps = 0x1,
     DataExportOmitLevels = 0x2,
+    DataExportWriteTimeInFrames = 0x4 // otherwise in seconds
 };
 
 typedef int DataExportOptions;
--- a/base/Event.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/base/Event.h	Fri Jan 10 14:29:54 2020 +0000
@@ -366,21 +366,67 @@
         return n;
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions opts,
+                                       ExportNameOptions nameOpts) const {
+
+        QStringList list;
+
+        // These are considered API rather than human-readable text -
+        // they shouldn't be translated
+
+        if (opts & DataExportWriteTimeInFrames) {
+            list << "frame";
+        } else {
+            list << "time";
+        }
+
+        if (m_haveValue) {
+            list << nameOpts.valueAttributeName;
+        }
+        
+        if (m_haveDuration) {
+            list << "duration";
+        }
+        
+        if (m_haveLevel) {
+            if (!(opts & DataExportOmitLevels)) {
+                list << nameOpts.levelAttributeName;
+            }
+        }
+        
+        if (m_uri != "") {
+            list << nameOpts.uriAttributeName;
+        }
+        
+        list << "label";
+        
+        return list.join(delimiter).toUpper();
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions opts,
                                   sv_samplerate_t sampleRate) const {
         QStringList list;
 
-        list << RealTime::frame2RealTime(m_frame, sampleRate)
-            .toString().c_str();
+        if (opts & DataExportWriteTimeInFrames) {
+            list << QString("%1").arg(m_frame);
+        } else {
+            list << RealTime::frame2RealTime(m_frame, sampleRate)
+                .toString().c_str();
+        }
         
         if (m_haveValue) {
             list << QString("%1").arg(m_value);
         }
         
         if (m_haveDuration) {
-            list << RealTime::frame2RealTime(m_duration, sampleRate)
-                .toString().c_str();
+            if (opts & DataExportWriteTimeInFrames) {
+                list << QString("%1").arg(m_duration);
+            } else {
+                list << RealTime::frame2RealTime(m_duration, sampleRate)
+                    .toString().c_str();
+            }
         }
         
         if (m_haveLevel) {
--- a/base/EventSeries.cpp	Wed Jan 08 15:26:49 2020 +0000
+++ b/base/EventSeries.cpp	Fri Jan 10 14:29:54 2020 +0000
@@ -598,6 +598,20 @@
 }
 
 QString
+EventSeries::getDelimitedDataHeaderLine(QString delimiter,
+                                        DataExportOptions opts,
+                                        Event::ExportNameOptions nopts) const
+{
+    if (m_events.empty()) {
+        return QString();
+    } else {
+        return m_events.begin()->getDelimitedDataHeaderLine(delimiter,
+                                                            opts,
+                                                            nopts);
+    }
+}
+
+QString
 EventSeries::toDelimitedDataString(QString delimiter,
                                    DataExportOptions options,
                                    sv_frame_t startFrame,
--- a/base/EventSeries.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/base/EventSeries.h	Fri Jan 10 14:29:54 2020 +0000
@@ -221,6 +221,14 @@
                Event::ExportNameOptions) const;
 
     /**
+     * Emit a label for each column that would be written by
+     * toDelimitedDataString, separated by the given delimiter.
+     */
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options,
+                                       Event::ExportNameOptions) const;
+    
+    /**
      * Emit events starting within the given range to a delimited
      * (e.g. comma-separated) data format.
      */
--- a/data/fileio/CSVFileWriter.cpp	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/fileio/CSVFileWriter.cpp	Fri Jan 10 14:29:54 2020 +0000
@@ -85,6 +85,9 @@
     
         QTextStream out(&file);
 
+//        out << m_model->getDelimitedDataHeaderLine(m_delimiter, m_options)
+//            << endl;
+        
         sv_frame_t blockSize = 65536;
 
         if (m_model->isSparse()) {
--- a/data/model/AlignmentModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/AlignmentModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -77,6 +77,10 @@
                QString indent = "",
                QString extraAttributes = "") const override;
 
+    QString getDelimitedDataHeaderLine(QString, DataExportOptions) const override {
+        return "";
+    }
+    
     QString toDelimitedDataString(QString, DataExportOptions,
                                   sv_frame_t, sv_frame_t) const override {
         return "";
--- a/data/model/BasicCompressedDenseThreeDimensionalModel.cpp	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/BasicCompressedDenseThreeDimensionalModel.cpp	Fri Jan 10 14:29:54 2020 +0000
@@ -499,6 +499,17 @@
 }
 
 QString
+BasicCompressedDenseThreeDimensionalModel::getDelimitedDataHeaderLine(QString delimiter,
+                                                                      DataExportOptions) const
+{
+    QStringList list;
+    for (int i = 0; i < m_yBinCount; ++i) {
+        list << QString("Bin%1").arg(i+1);
+    }
+    return list.join(delimiter);
+}    
+
+QString
 BasicCompressedDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter,
                                                           DataExportOptions,
                                                           sv_frame_t startFrame,
--- a/data/model/BasicCompressedDenseThreeDimensionalModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/BasicCompressedDenseThreeDimensionalModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -181,6 +181,9 @@
 
     QString getTypeName() const override { return tr("Editable Dense 3-D"); }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions opts) const override;
+
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/BoxModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/BoxModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -348,8 +348,26 @@
         m_events.toXml(out, indent, QString("dimensions=\"2\""), options);
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions opts) const override {
+        QStringList list;
+
+        // These are considered API rather than human-readable text -
+        // they shouldn't be translated
+
+        if (opts & DataExportWriteTimeInFrames) {
+            list << "startframe" << "endframe";
+        } else {
+            list << "start" << "end";
+        }
+
+        list << "extent start" << "extent end" << "label";
+
+        return list.join(delimiter).toUpper();
+    }
+    
     QString toDelimitedDataString(QString delimiter,
-                                  DataExportOptions,
+                                  DataExportOptions opts,
                                   sv_frame_t startFrame,
                                   sv_frame_t duration) const override {
 
@@ -363,14 +381,25 @@
 
             QStringList list;
 
-            list << RealTime::frame2RealTime
-                (e.getFrame(), getSampleRate())
-                .toString().c_str()
-                 << RealTime::frame2RealTime
-                (e.getFrame() + e.getDuration(), getSampleRate())
-                .toString().c_str()
-                 << QString("%1").arg(e.getValue())
-                 << QString("%1").arg(e.getValue() + fabsf(e.getLevel()));
+            if (opts & DataExportWriteTimeInFrames) {
+                
+                list << QString("%1").arg(e.getFrame());
+                list << QString("%1").arg(e.getFrame() + e.getDuration());
+
+            } else {
+            
+                list << RealTime::frame2RealTime
+                    (e.getFrame(), getSampleRate())
+                    .toString().c_str();
+
+                list << RealTime::frame2RealTime
+                    (e.getFrame() + e.getDuration(), getSampleRate())
+                    .toString().c_str();
+            }
+
+            list << QString("%1").arg(e.getValue());
+
+            list << QString("%1").arg(e.getValue() + fabsf(e.getLevel()));
             
             if (e.getLabel() != "") {
                 list << e.getLabel();
--- a/data/model/Dense3DModelPeakCache.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/Dense3DModelPeakCache.h	Fri Jan 10 14:29:54 2020 +0000
@@ -119,6 +119,10 @@
         return source ? source->getCompletion() : 100;
     }
 
+    QString getDelimitedDataHeaderLine(QString, DataExportOptions) const override {
+        return "";
+    }
+    
     QString toDelimitedDataString(QString, DataExportOptions,
                                   sv_frame_t, sv_frame_t) const override {
         return "";
--- a/data/model/DenseTimeValueModel.cpp	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/DenseTimeValueModel.cpp	Fri Jan 10 14:29:54 2020 +0000
@@ -16,7 +16,19 @@
 #include "DenseTimeValueModel.h"
 
 #include <QStringList>
-        
+
+QString
+DenseTimeValueModel::getDelimitedDataHeaderLine(QString delimiter,
+                                                DataExportOptions) const
+{
+    int ch = getChannelCount();
+    QStringList list;
+    for (int i = 0; i < ch; ++i) {
+        list << QString("Channel%1").arg(i+1);
+    }
+    return list.join(delimiter);
+}
+
 QString
 DenseTimeValueModel::toDelimitedDataString(QString delimiter,
                                            DataExportOptions,
--- a/data/model/DenseTimeValueModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/DenseTimeValueModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -82,6 +82,9 @@
     bool canPlay() const override { return true; }
     QString getDefaultPlayClipId() const override { return ""; }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override;
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/EditableDenseThreeDimensionalModel.cpp	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.cpp	Fri Jan 10 14:29:54 2020 +0000
@@ -352,6 +352,17 @@
 }
 
 QString
+EditableDenseThreeDimensionalModel::getDelimitedDataHeaderLine(QString delimiter,
+                                                               DataExportOptions) const
+{
+    QStringList list;
+    for (int i = 0; i < m_yBinCount; ++i) {
+        list << QString("Bin%1").arg(i+1);
+    }
+    return list.join(delimiter);
+}    
+    
+QString
 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter,
                                                           DataExportOptions,
                                                           sv_frame_t startFrame,
--- a/data/model/EditableDenseThreeDimensionalModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/EditableDenseThreeDimensionalModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -172,6 +172,9 @@
 
     QString getTypeName() const override { return tr("Editable Dense 3-D"); }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions opts) const override;
+
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/FFTModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/FFTModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -99,6 +99,9 @@
     float getBinValue(int n) const override;
     QString getBinName(int n) const override;
 
+    QString getDelimitedDataHeaderLine(QString, DataExportOptions) const override {
+        return "";
+    }
     QString toDelimitedDataString(QString, DataExportOptions,
                                   sv_frame_t, sv_frame_t) const override {
         return "";
--- a/data/model/ImageModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/ImageModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -275,6 +275,16 @@
         m_events.toXml(out, indent, QString("dimensions=\"1\""), options);
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        Event::ExportNameOptions nameOpts;
+        nameOpts.uriAttributeName = "image";
+
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   nameOpts);
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/Model.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/Model.h	Fri Jan 10 14:29:54 2020 +0000
@@ -274,6 +274,17 @@
                QString indent = "",
                QString extraAttributes = "") const override;
 
+    /**
+     * Emit a label for each column that would be written by
+     * toDelimitedDataString, separated by the given delimiter.
+     */
+    virtual QString getDelimitedDataHeaderLine(QString delimiter,
+                                               DataExportOptions options) const = 0;
+    
+    /**
+     * Emit the contents of the model within the given range to a
+     * delimited (e.g. comma-separated) data format.
+     */
     virtual QString toDelimitedDataString(QString delimiter,
                                           DataExportOptions options,
                                           sv_frame_t startFrame,
--- a/data/model/NoteModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/NoteModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -408,6 +408,13 @@
         m_events.toXml(out, indent, QString("dimensions=\"3\""));
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   Event::ExportNameOptions());
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/RegionModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/RegionModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -340,6 +340,13 @@
         m_events.toXml(out, indent, QString("dimensions=\"3\""));
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   Event::ExportNameOptions());
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/SparseOneDimensionalModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/SparseOneDimensionalModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -308,6 +308,13 @@
         m_events.toXml(out, indent, QString("dimensions=\"1\""));
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   Event::ExportNameOptions());
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/SparseTimeValueModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/SparseTimeValueModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -347,6 +347,13 @@
         m_events.toXml(out, indent, QString("dimensions=\"2\""));
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   Event::ExportNameOptions());
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,
--- a/data/model/TextModel.h	Wed Jan 08 15:26:49 2020 +0000
+++ b/data/model/TextModel.h	Fri Jan 10 14:29:54 2020 +0000
@@ -278,6 +278,15 @@
         m_events.toXml(out, indent, QString("dimensions=\"2\""), options);
     }
 
+    QString getDelimitedDataHeaderLine(QString delimiter,
+                                       DataExportOptions options) const override {
+        Event::ExportNameOptions nameOpts;
+        nameOpts.valueAttributeName = "height";
+        return m_events.getDelimitedDataHeaderLine(delimiter,
+                                                   options,
+                                                   nameOpts);
+    }
+    
     QString toDelimitedDataString(QString delimiter,
                                   DataExportOptions options,
                                   sv_frame_t startFrame,