Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSV export for plots #128

Merged
merged 9 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions gui/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@
<file>images/us3-icon-48x48.png</file>
<file>images/arrow_left.png</file>
<file>images/arrow_right.png</file>
<file>images/analysis.png</file>
<file>images/editing.png</file>
<file>images/import_1.png</file>
<file>images/import_2.png</file>
<file>images/analysis_2.png</file>
<file>images/report.png</file>
<file>images/live_update.png</file>
<file>images/setup.png</file>
<file>images/new_item2.png</file>
<file>images/analysis.png</file>
<file>images/editing.png</file>
<file>images/import_1.png</file>
<file>images/import_2.png</file>
<file>images/analysis_2.png</file>
<file>images/report.png</file>
<file>images/live_update.png</file>
<file>images/setup.png</file>
<file>images/new_item2.png</file>
<file>images/table.png</file>
</qresource>
</RCC>
Binary file added gui/images/table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
173 changes: 173 additions & 0 deletions gui/us_gui_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "us_settings.h"
#if QT_VERSION > 0x050000
#include "qwt_plot_renderer.h"
#include "us_spectrodata.h"

#endif

// Save SVG+PNG or PNG file
Expand Down Expand Up @@ -105,3 +107,174 @@ int US_GuiUtil::save_png( const QString& filename, const QwtPlot* plot )
return status;
}

int US_GuiUtil::save_csv( const QString& filename, const QwtPlot* plot )
{
int status = 0;


if ( filename.endsWith( ".csv" ) )
{ // Save the file as a CSV
// iterate over all plot items and construct the output data
QVector<QVector<QString>> export_data;
export_data.clear();
// determine axis title
QString x_axis_title = plot->axisTitle( QwtPlot::xBottom ).text();
if ( x_axis_title.isEmpty() )
{
x_axis_title = plot->axisTitle( QwtPlot::xTop ).text();
}
if ( x_axis_title.isEmpty() )
{
x_axis_title = QString("x");
}
QString y_axis_title = plot->axisTitle( QwtPlot::yLeft ).text();
if ( y_axis_title.isEmpty() )
{
y_axis_title = plot->axisTitle( QwtPlot::yRight ).text();
}
if ( y_axis_title.isEmpty() )
{
y_axis_title = QString("y");
}
int max_length = 0;
for ( QwtPlotItem* it: plot->itemList( QwtPlotItem::Rtti_PlotCurve ) )
{
if ( it->rtti() != QwtPlotItem::Rtti_PlotCurve )
{
continue;
}
QwtPlotCurve* item = static_cast<QwtPlotCurve*>(it);
// create two Vectors for x and y respective
QVector<QString> x_data;
x_data.clear();
QVector<QString> y_data;
y_data.clear();
x_data << QString("\"") + item->title().text() + " " + x_axis_title + QString("\"");
y_data << QString("\"") + item->title().text() + " " + y_axis_title + QString("\"");
const QwtSeriesData<QPointF>* data = item->data();
for (size_t i = 0; i < data->size(); i++)
{
QPointF point = data->sample(i);
x_data << QString::number(point.x());
y_data << QString::number(point.y());
}
if ( max_length < x_data.size() )
{
max_length = x_data.size();
}
if ( max_length < y_data.size() )
{
max_length = y_data.size();
}
if ( data->size() > 0 || (x_data.size() > 1 && y_data.size() > 1) )
{ // Only add data if there is data to add
export_data << x_data << y_data;
}
}
QString z_axis_title;
if ( !plot->itemList( QwtPlotItem::Rtti_PlotSpectrogram ).isEmpty() )
{
z_axis_title = plot->axisTitle( QwtPlot::yRight ).text();
if ( !(!z_axis_title.isEmpty() && z_axis_title != y_axis_title) )
{
z_axis_title = z_axis_title + " z";
}
}
for ( QwtPlotItem* it: plot->itemList( QwtPlotItem::Rtti_PlotSpectrogram ) )
{
if ( it->rtti() != QwtPlotItem::Rtti_PlotSpectrogram )
{
continue;
}
QwtPlotSpectrogram* item = static_cast<QwtPlotSpectrogram*>(it);
qDebug() << item->interval( Qt::XAxis ).minValue() << item->interval( Qt::XAxis ).maxValue();
qDebug() << item->interval( Qt::YAxis ).minValue() << item->interval( Qt::YAxis ).maxValue();
qDebug() << item->boundingRect().bottomLeft() << item->boundingRect().topRight();
US_SpectrogramData* data = dynamic_cast<US_SpectrogramData*>(item->data());
// create two Vectors for x and y respective
QSize raster_size;
QRectF rect;
// Get the raster data from US_SpectrogramData
data->initRaster( rect, raster_size );
QVector<QString> x_data;
x_data.clear();
QVector<QString> y_data;
y_data.clear();
QVector<QString> z_data;
x_data << QString("\"") + item->title().text() + " " + x_axis_title + QString("\"");
y_data << QString("\"") + item->title().text() + " " + y_axis_title + QString("\"");
z_data << QString("\"") + item->title().text() + " " + z_axis_title + QString("\"");
// Get the matrix data
int rows = raster_size.width();
int cols = raster_size.height();

for (int row = 0; row < rows; ++row) {
for (int col = 0; col < cols; ++col) {
double x, y, z;
data->value( row, col, x, y, z );
x_data << QString::number(x);
y_data << QString::number(y);
z_data << QString::number(z);
}
}

if ( max_length < x_data.size() )
{
max_length = x_data.size();
}
if ( max_length < y_data.size() )
{
max_length = y_data.size();
}
if ( max_length < z_data.size() )
{
max_length = z_data.size();
}
if ( x_data.size() > 1 && y_data.size() > 1 && z_data.size() > 1 )
{ // Only add data if there is data to add
export_data << x_data << y_data << z_data;
}
}
// iterate over all entries to ensure a proper csv format
for (auto & i : export_data)
{
if ( i.size() < max_length )
{
QVector<QString> vec = i;
for ( int jj = vec.size(); jj < max_length; jj++ )
{
vec << QString("");
}
i = vec;
}
}
// dump everything into a file
QFile myFile( filename );
if ( !myFile.open( QIODevice::WriteOnly ) )
{
qDebug() << "Could not write to file:" << filename << "Error string:" << myFile.errorString();
}
else
{
QTextStream out(&myFile);
for ( int ii = 0; ii < max_length; ii++ )
{
for ( int jj = 0; jj < export_data.size() - 1; jj++ )
{
out << export_data[ jj ][ ii ] << ", ";
}
out << export_data.last()[ ii ] << Qt::endl;
}
myFile.flush();
}

myFile.close();
}

else
{ // Mark error: filename does not end with ".csv"
status = 1;
}

return status;
}
12 changes: 12 additions & 0 deletions gui/us_gui_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
#define dataPlotClear(a) a->clear()
#endif
#include "qwt_plot.h"
#include "qwt_plot_curve.h"
#include "qwt_series_data.h"
#include <qwt_plot_spectrogram.h>
#include <qwt_raster_data.h>
#include <qwt_matrix_raster_data.h>
#include "us_extern.h"

//! \brief General GUI utilities for UltraScan
Expand Down Expand Up @@ -44,5 +49,12 @@ class US_GUI_EXTERN US_GuiUtil
//! \returns A status flag: 0 if all-ok
static int save_png( const QString&, const QwtPlot* );

//! \brief Save a plot to a CSV file
//!
//! \param filename Full path name of the file to produce
//! \param plot A pointer to the plot to save
//! \returns A status flag: 0 if all-ok
static int save_csv( const QString&, const QwtPlot* );

};
#endif
89 changes: 45 additions & 44 deletions gui/us_images.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,50 +37,51 @@ const QString US_Images::image_name( int itype )

static const struct nameMap nameMaps[] =
{
{ US3_SPLASH, "us3-splash" },
{ CHECK, "check" },
{ ARROW_BLUE, "bluearrow" },
{ ARROW_GREEN, "greenarrow" },
{ ARROW_RED, "redarrow" },
{ AXES_BOX, "box" },
{ AXES_FRAME, "frame" },
{ AXES_NONE, "none" },
{ FILE_CELL, "filecell" },
{ FILE_OPEN, "fileopen" },
{ FLOOR_DATA, "floordata" },
{ FLOOR_EMPTY, "floorempty" },
{ FLOOR_ISO, "flooriso" },
{ FLOOR_MESH, "floormesh" },
{ GRID_NONE, "grid" },
{ GRID_BACK, "gridb" },
{ GRID_CEILING, "gridc" },
{ GRID_FLOOR, "gridf" },
{ GRID_FRONT, "gridfr" },
{ GRID_LEFT, "gridl" },
{ GRID_RIGHT, "gridr" },
{ MESH_FILLED, "filledmesh" },
{ MESH_HIDDEN, "hiddenline" },
{ MESH_NODATA, "nodata" },
{ MESH_NORMALS, "normals" },
{ MESH_POLYGON, "polygon" },
{ MESH_SCATTERED, "scattered" },
{ MESH_WIRE, "wireframe" },
{ MOVIE, "movie" },
{ SAVE_CONTENT, "savecontent" },
{ ICON_PROP, "icon" },
{ QWTPLOT, "qwtplot" },
{ US3_ICON, "us3-icon-48x48" },
{ ARROW_LEFT, "arrow_left" },
{ ARROW_RIGHT, "arrow_right" },
{ SETUP_COM, "setup" },
{ ANALYSIS_COM, "analysis" },
{ EDITING_COM, "editing" },
{ ANALYSIS_COM_2, "analysis_2" },
{ LIVE_UPDATE_COM, "live_update" },
{ IMPORT_COM_1, "import_1" },
{ IMPORT_COM_2, "import_2" },
{ REPORT_COM, "report" },
{ NEW_ITEM_COM, "new_item2" }
{ US3_SPLASH, "us3-splash" },
{ CHECK, "check" },
{ ARROW_BLUE, "bluearrow" },
{ ARROW_GREEN, "greenarrow" },
{ ARROW_RED, "redarrow" },
{ AXES_BOX, "box" },
{ AXES_FRAME, "frame" },
{ AXES_NONE, "none" },
{ FILE_CELL, "filecell" },
{ FILE_OPEN, "fileopen" },
{ FLOOR_DATA, "floordata" },
{ FLOOR_EMPTY, "floorempty" },
{ FLOOR_ISO, "flooriso" },
{ FLOOR_MESH, "floormesh" },
{ GRID_NONE, "grid" },
{ GRID_BACK, "gridb" },
{ GRID_CEILING, "gridc" },
{ GRID_FLOOR, "gridf" },
{ GRID_FRONT, "gridfr" },
{ GRID_LEFT, "gridl" },
{ GRID_RIGHT, "gridr" },
{ MESH_FILLED, "filledmesh" },
{ MESH_HIDDEN, "hiddenline" },
{ MESH_NODATA, "nodata" },
{ MESH_NORMALS, "normals" },
{ MESH_POLYGON, "polygon" },
{ MESH_SCATTERED, "scattered" },
{ MESH_WIRE, "wireframe" },
{ MOVIE, "movie" },
{ SAVE_CONTENT, "savecontent" },
{ ICON_PROP, "icon" },
{ QWTPLOT, "qwtplot" },
{ US3_ICON, "us3-icon-48x48" },
{ ARROW_LEFT, "arrow_left" },
{ ARROW_RIGHT, "arrow_right" },
{ SETUP_COM, "setup" },
{ ANALYSIS_COM, "analysis" },
{ EDITING_COM, "editing" },
{ ANALYSIS_COM_2, "analysis_2" },
{ LIVE_UPDATE_COM, "live_update" },
{ IMPORT_COM_1, "import_1" },
{ IMPORT_COM_2, "import_2" },
{ REPORT_COM, "report" },
{ NEW_ITEM_COM, "new_item2" },
{ TABLE, "table" }
};

static const int nimages = sizeof( nameMaps ) / sizeof( nameMaps[ 0 ] );
Expand Down
2 changes: 1 addition & 1 deletion gui/us_images.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class US_GUI_EXTERN US_Images
MOVIE, SAVE_CONTENT, ICON_PROP,
QWTPLOT, US3_ICON, ARROW_LEFT, ARROW_RIGHT,
SETUP_COM, ANALYSIS_COM, EDITING_COM, ANALYSIS_COM_2,
IMPORT_COM_1, IMPORT_COM_2, LIVE_UPDATE_COM, NEW_ITEM_COM, REPORT_COM
IMPORT_COM_1, IMPORT_COM_2, LIVE_UPDATE_COM, NEW_ITEM_COM, REPORT_COM, TABLE
};

//! \brief Get image (embedded or from file) as a pixmap
Expand Down
Loading