Commit 1e59b6f2 authored by Tobias WEBER's avatar Tobias WEBER
Browse files

continued with data plotting

parent 863fdc57
......@@ -74,6 +74,7 @@ add_executable(in20
tools/in20/filebrowser.cpp tools/in20/filebrowser.h
tools/in20/workspace.cpp tools/in20/workspace.h
tools/in20/data.cpp tools/in20/data.h
tools/in20/plot.cpp tools/in20/plot.h
tools/in20/command.cpp tools/in20/command.h
${BISON_cliparser_OUTPUT_SOURCE} ${BISON_cliparser_OUTPUT_HEADER}
......
......@@ -8,6 +8,8 @@
#ifndef __CLI_PARSER_TYPES_H__
#define __CLI_PARSER_TYPES_H__
#include <memory>
class CliParserContext;
class CliAST;
......
......@@ -6,5 +6,127 @@
*/
#include "data.h"
#include "tlibs/file/loadinstr.h"
#include "libs/algos.h"
using t_real = t_real_dat;
/**
* convert an instrument data file to the internal data format
*/
std::tuple<bool, Dataset> Dataset::convert_instr_file(const char* pcFile)
{
Dataset dataset;
// load instrument data file
std::unique_ptr<tl::FileInstrBase<t_real>> pInstr(tl::FileInstrBase<t_real>::LoadInstr(pcFile));
if(!pInstr)
return std::make_tuple(false, dataset);
const auto &colnames = pInstr->GetColNames();
const auto &filedata = pInstr->GetData();
if(!pInstr || !colnames.size()) // only valid files with a non-zero column count
return std::make_tuple(false, dataset);
// process polarisation data
pInstr->SetPolNames("p1", "p2", "i11", "i10");
pInstr->ParsePolData();
// get scan axis indices
std::vector<std::size_t> scan_idx;
for(const auto& scanvar : pInstr->GetScannedVars())
{
std::size_t idx = 0;
pInstr->GetCol(scanvar, &idx);
if(idx < colnames.size())
scan_idx.push_back(idx);
}
// try first axis if none found
if(scan_idx.size() == 0) scan_idx.push_back(0);
// get counter column index
std::vector<std::size_t> ctr_idx;
{
std::size_t idx = 0;
pInstr->GetCol(pInstr->GetCountVar(), &idx);
if(idx < colnames.size())
ctr_idx.push_back(idx);
}
// try second axis if none found
if(ctr_idx.size() == 0) ctr_idx.push_back(1);
// get monitor column index
std::vector<std::size_t> mon_idx;
{
std::size_t idx = 0;
pInstr->GetCol(pInstr->GetMonVar(), &idx);
if(idx < colnames.size())
mon_idx.push_back(idx);
}
std::size_t numpolstates = pInstr->NumPolChannels();
if(numpolstates == 0) numpolstates = 1;
// iterate through all (polarisation) subplots
for(std::size_t polstate=0; polstate<numpolstates; ++polstate)
{
Data data;
// get scan axes
for(std::size_t idx : scan_idx)
{
std::vector<t_real> thedat;
copy_interleave(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(thedat), numpolstates, polstate);
data.AddAxis(thedat, colnames[idx]);
}
// get counters
for(std::size_t idx : ctr_idx)
{
std::vector<t_real> thedat, theerr;
copy_interleave(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(thedat), numpolstates, polstate);
std::transform(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(theerr),
[](t_real y) -> t_real
{
if(tl::float_equal<t_real>(y, 0))
return 1;
return std::sqrt(y);
});
data.AddCounter(thedat, theerr);
}
// get monitors
for(std::size_t idx : mon_idx)
{
std::vector<t_real> thedat, theerr;
copy_interleave(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(thedat), numpolstates, polstate);
std::transform(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(theerr),
[](t_real y) -> t_real
{
if(tl::float_equal<t_real>(y, 0))
return 1;
return std::sqrt(y);
});
data.AddMonitor(thedat, theerr);
}
dataset.AddChannel(std::move(data));
}
return std::make_tuple(true, dataset);
}
......@@ -10,6 +10,7 @@
#include <vector>
#include <string>
#include <tuple>
using t_real_dat = double;
......@@ -35,8 +36,8 @@ private:
std::vector<std::string> m_x_names;
public:
std::size_t GetNumDets() const { return m_counts.size(); }
std::size_t GetNumMons() const { return m_monitors.size(); }
std::size_t GetNumCounters() const { return m_counts.size(); }
std::size_t GetNumMonitors() const { return m_monitors.size(); }
std::size_t GetNumAxes() const { return m_x.size(); }
......@@ -108,6 +109,9 @@ public:
const Data& GetChannel(std::size_t channel) const { return m_data[channel]; }
void AddChannel(const Data &data) { m_data.push_back(data); }
void AddChannel(Data &&data) { m_data.emplace_back(std::move(data)); }
static std::tuple<bool, Dataset> convert_instr_file(const char* pcFile);
};
......
......@@ -13,11 +13,9 @@
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QFileDialog>
#include "libs/algos.h"
#include "tlibs/file/loadinstr.h"
using t_real = double;
#include "data.h"
using t_real = t_real_dat;
// ----------------------------------------------------------------------------
......@@ -116,7 +114,7 @@ void FileBrowserWidget::SetFolder(const QString& dir)
// add files to list widget
for(const auto& strFile : vecFiles)
{
QString fileFull = dir + "/" + strFile;
QString fileFull = dir + QDir::separator() + strFile;
// load file to get a description
std::unique_ptr<tl::FileInstrBase<t_real>> pInstr(tl::FileInstrBase<t_real>::LoadInstr(fileFull.toStdString().c_str()));
......@@ -152,109 +150,13 @@ void FileBrowserWidget::SetFolder(const QString& dir)
*/
void FileBrowserWidget::SetFile(QListWidgetItem* pCur)
{
static const std::vector<unsigned> colors = {
0xffff0000, 0xff0000ff, 0xff009900, 0xff000000,
};
m_pPlotter->clearGraphs();
if(!pCur) return;
// load scan file for preview
QString file = pCur->data(Qt::UserRole).toString();
std::unique_ptr<tl::FileInstrBase<t_real>> pInstr(tl::FileInstrBase<t_real>::LoadInstr(file.toStdString().c_str()));
const auto &colnames = pInstr->GetColNames();
const auto &data = pInstr->GetData();
if(pInstr && colnames.size()) // only valid files with a non-zero column count
if(auto [ok, dataset] = Dataset::convert_instr_file(file.toStdString().c_str()); ok)
{
// process polarisation data
pInstr->SetPolNames("p1", "p2", "i11", "i10");
pInstr->ParsePolData();
std::size_t x_idx = 0, y_idx = 1;
// get x column index
if(auto vecScanVars = pInstr->GetScannedVars(); vecScanVars.size() >= 1)
{
// try to find scan var, if not found, use first column
pInstr->GetCol(vecScanVars[0], &x_idx);
if(x_idx >= colnames.size())
x_idx = 0;
}
// get y column index
{
// try to find count var, if not found, use second column
pInstr->GetCol(pInstr->GetCountVar(), &y_idx);
if(y_idx >= colnames.size())
y_idx = 1;
}
// labels
m_pPlotter->xAxis->setLabel(x_idx<colnames.size() ? colnames[x_idx].c_str() : "x");
m_pPlotter->yAxis->setLabel(y_idx<colnames.size() ? colnames[y_idx].c_str() : "y");
t_real xmin = std::numeric_limits<t_real>::max();
t_real xmax = -xmin;
t_real ymin = std::numeric_limits<t_real>::max();
t_real ymax = -xmin;
// plot the data
if(x_idx < data.size() && y_idx < data.size())
{
std::size_t numpolstates = pInstr->NumPolChannels();
if(numpolstates == 0) numpolstates = 1;
// iterate all (polarisation) subplots
for(std::size_t graphidx=0; graphidx<numpolstates; ++graphidx)
{
// get x, y, yerr data
QVector<t_real> x_data, y_data, y_err;
copy_interleave(data[x_idx].begin(), data[x_idx].end(), std::back_inserter(x_data), numpolstates, graphidx);
copy_interleave(data[y_idx].begin(), data[y_idx].end(), std::back_inserter(y_data), numpolstates, graphidx);
std::transform(data[y_idx].begin(), data[y_idx].end(), std::back_inserter(y_err),
[](t_real y) -> t_real
{
if(tl::float_equal<t_real>(y, 0))
return 1;
return std::sqrt(y);
});
// graph
auto *graph = m_pPlotter->addGraph();
auto *graph_err = new QCPErrorBars(m_pPlotter->xAxis, m_pPlotter->yAxis);
graph_err->setDataPlottable(graph);
QPen pen = QPen(QColor(colors[graphidx % colors.size()]));
QBrush brush(pen.color());
t_real ptsize = 8;
graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, pen, brush, ptsize));
graph->setPen(pen);
graph_err->setSymbolGap(ptsize);
graph->setData(x_data, y_data);
graph_err->setData(y_err);
// ranges
auto xminmax = std::minmax_element(x_data.begin(), x_data.end());
auto yminmax = std::minmax_element(y_data.begin(), y_data.end());
auto yerrminmax = std::minmax_element(y_err.begin(), y_err.end());
xmin = std::min(*xminmax.first, xmin);
xmax = std::max(*xminmax.second, xmax);
ymin = std::min(*yminmax.first - *yerrminmax.first, ymin);
ymax = std::max(*yminmax.second + *yerrminmax.second, ymax);
}
m_pPlotter->xAxis->setRange(xmin, xmax);
m_pPlotter->yAxis->setRange(ymin, ymax);
}
m_pPlotter->replot();
m_pPlotter->Plot(dataset);
}
}
......
......@@ -18,7 +18,7 @@
#include <vector>
#include <string>
#include "qcp/qcustomplot.h"
#include "plot.h"
/**
......@@ -31,7 +31,7 @@ private:
QLineEdit *m_pEditFolder = new QLineEdit(this);
QListWidget *m_pListFiles = new QListWidget(this);
QCustomPlot *m_pPlotter = new QCustomPlot(this);
Plotter *m_pPlotter = new Plotter(this);
public:
FileBrowserWidget(QWidget *pParent = nullptr, QSettings *pSettings = nullptr);
......
/**
* plotter
* @author Tobias Weber <tweber@ill.fr>
* @date 15-Jun-2018
* @license see 'LICENSE' file
*/
#include "plot.h"
#include <QtWidgets/QGridLayout>
using t_real = t_real_dat;
Plotter::Plotter(QWidget *parent) : QWidget(parent)
{
auto *pGrid = new QGridLayout(this);
pGrid->setHorizontalSpacing(4);
pGrid->setVerticalSpacing(4);
pGrid->setContentsMargins(0,0,0,0);
pGrid->addWidget(m_pPlotter, 0, 0, 1, 1);
}
Plotter::~Plotter()
{
}
/**
* show a dataset
*/
void Plotter::Plot(const Dataset &dataset)
{
static const std::vector<unsigned> colors = {
0xffff0000, 0xff0000ff, 0xff009900, 0xff000000,
};
m_pPlotter->clearGraphs();
t_real xmin = std::numeric_limits<t_real>::max();
t_real xmax = -xmin;
t_real ymin = std::numeric_limits<t_real>::max();
t_real ymax = -xmin;
bool labels_already_set = false;
// iterate over (polarisation) channels
for(std::size_t channel=0; channel<dataset.GetNumChannels(); ++channel)
{
const auto &data = dataset.GetChannel(channel);
if(data.GetNumAxes()==0 || data.GetNumCounters()==0)
continue;
const auto &datx = data.GetAxis(0);
const auto &daty = data.GetCounter(0);
const auto &datyerr = data.GetCounterErrors(0);
// graph
auto *graph = m_pPlotter->addGraph();
auto *graph_err = new QCPErrorBars(m_pPlotter->xAxis, m_pPlotter->yAxis);
graph_err->setDataPlottable(graph);
QPen pen = QPen(QColor(colors[channel % colors.size()]));
QBrush brush(pen.color());
t_real ptsize = 8;
graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, pen, brush, ptsize));
graph->setPen(pen);
graph_err->setSymbolGap(ptsize);
// convert to qvector
QVector<t_real> _datx, _daty, _datyerr;
std::copy(datx.begin(), datx.end(), std::back_inserter(_datx));
std::copy(daty.begin(), daty.end(), std::back_inserter(_daty));
std::copy(datyerr.begin(), datyerr.end(), std::back_inserter(_datyerr));
graph->setData(_datx, _daty);
graph_err->setData(_datyerr);
// ranges
auto xminmax = std::minmax_element(datx.begin(), datx.end());
auto yminmax = std::minmax_element(daty.begin(), daty.end());
auto yerrminmax = std::minmax_element(datyerr.begin(), datyerr.end());
xmin = std::min(*xminmax.first, xmin);
xmax = std::max(*xminmax.second, xmax);
ymin = std::min(*yminmax.first - *yerrminmax.first, ymin);
ymax = std::max(*yminmax.second + *yerrminmax.second, ymax);
// labels
if(!labels_already_set)
{
m_pPlotter->xAxis->setLabel(data.GetAxisName(channel).size() ? data.GetAxisName(channel).c_str() : "x");
m_pPlotter->yAxis->setLabel("Counts");
labels_already_set = true;
}
}
m_pPlotter->xAxis->setRange(xmin, xmax);
m_pPlotter->yAxis->setRange(ymin, ymax);
m_pPlotter->replot();
}
/**
* plotter
* @author Tobias Weber <tweber@ill.fr>
* @date 15-Jun-2018
* @license see 'LICENSE' file
*/
#ifndef __PLOT_H__
#define __PLOT_H__
#include <QtWidgets/QWidget>
#include "qcp/qcustomplot.h"
#include "data.h"
class Plotter : public QWidget
{
private:
QCustomPlot *m_pPlotter = new QCustomPlot(this);
public:
Plotter(QWidget *parent);
virtual ~Plotter();
QCustomPlot* GetPlotter() { return m_pPlotter; }
const QCustomPlot* GetPlotter() const { return m_pPlotter; }
void Plot(const Dataset &dataset);
};
#endif
......@@ -12,10 +12,7 @@
#include <QtWidgets/QPushButton>
#include <QtWidgets/QFileDialog>
#include <boost/filesystem.hpp>
#include "libs/algos.h"
#include "tlibs/file/loadinstr.h"
#include <iostream>
using t_real = t_real_dat;
......@@ -61,6 +58,18 @@ WorkSpaceWidget::~WorkSpaceWidget()
*/
void WorkSpaceWidget::ItemSelected(QListWidgetItem* pCur)
{
if(!pCur) return;
std::string ident = pCur->text().toStdString();
auto iter = m_workspace.find(ident);
if(iter == m_workspace.end())
{
std::cerr << "Identifier \"" << ident << "\" is not in workspace." << std::endl;
return;
}
const Dataset& dataset = iter->second;
m_pPlotter->Plot(dataset);
}
......@@ -72,6 +81,7 @@ void WorkSpaceWidget::ItemDoubleClicked(QListWidgetItem* pCur)
}
/**
* transfer a file from the file browser and convert it into the internal format
*/
......@@ -79,118 +89,22 @@ void WorkSpaceWidget::ReceiveFiles(const std::vector<std::string> &files)
{
for(const auto& file : files)
{
boost::filesystem::path filepath(file);
if(!boost::filesystem::exists(filepath))
continue;
// load instrument data file
std::unique_ptr<tl::FileInstrBase<t_real>> pInstr(tl::FileInstrBase<t_real>::LoadInstr(filepath.string().c_str()));
const auto &colnames = pInstr->GetColNames();
const auto &filedata = pInstr->GetData();
if(!pInstr || !colnames.size()) // only valid files with a non-zero column count
continue;
// process polarisation data
pInstr->SetPolNames("p1", "p2", "i11", "i10");
pInstr->ParsePolData();
// get scan axis indices
std::vector<std::size_t> scan_idx;
for(const auto& scanvar : pInstr->GetScannedVars())
QFileInfo filepath(file.c_str());
if(!filepath.exists())
{
std::size_t idx = 0;
pInstr->GetCol(scanvar, &idx);
if(idx < colnames.size())
scan_idx.push_back(idx);
std::cerr << "File \"" << file << "\" does not exist." << std::endl;
//continue;
}
// try first axis if none found
if(scan_idx.size() == 0) scan_idx.push_back(0);
// get counter column index
std::vector<std::size_t> ctr_idx;
{
std::size_t idx = 0;
pInstr->GetCol(pInstr->GetCountVar(), &idx);
if(idx < colnames.size())
ctr_idx.push_back(idx);
}
// try second axis if none found
if(ctr_idx.size() == 0) ctr_idx.push_back(1);
// get monitor column index
std::vector<std::size_t> mon_idx;
{
std::size_t idx = 0;
pInstr->GetCol(pInstr->GetMonVar(), &idx);
if(idx < colnames.size())
mon_idx.push_back(idx);
}
std::size_t numpolstates = pInstr->NumPolChannels();
if(numpolstates == 0) numpolstates = 1;
Dataset dataset;
// iterate through all (polarisation) subplots
for(std::size_t polstate=0; polstate<numpolstates; ++polstate)
auto [ok, dataset] = Dataset::convert_instr_file(file.c_str());
if(!ok)
{
Data data;
// get scan axes
for(std::size_t idx : scan_idx)
{
std::vector<t_real> thedat;
copy_interleave(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(thedat), numpolstates, polstate);
data.AddAxis(thedat, colnames[idx]);
}
// get counters
for(std::size_t idx : ctr_idx)
{
std::vector<t_real> thedat, theerr;
copy_interleave(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(thedat), numpolstates, polstate);
std::transform(filedata[idx].begin(), filedata[idx].end(), std::back_inserter(theerr),
[](t_real y) -> t_real
{
if(tl::float_equal<t_real>(y, 0))
return 1;
return std::sqrt(y);
});
data.AddCounter(thedat, theerr);
}
// get monitors
for(std::size_t idx : mon_idx)
{