26#include <QCoreApplication>
29#include <QProcessEnvironment>
31#include <QRegularExpression>
59 return m_runner.isPythonAvailable();
66 return m_runner.isPackageAvailable(packageName);
74 return m_runner.runCode(code);
89 double value = result.
stdOut.trimmed().toDouble(&parseOk);
92 return parseOk ? value : 0.0;
107 QString output = result.
stdOut.trimmed();
108 if (output.isEmpty()) {
114 QStringList lines = output.split(
'\n', Qt::SkipEmptyParts);
117 QList<double> values;
118 for (
const QString& line : lines) {
119 QStringList tokens = line.trimmed().split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
120 for (
const QString& token : tokens) {
121 bool parseOk =
false;
122 double val = token.toDouble(&parseOk);
132 VectorXd vec(values.size());
133 for (
int i = 0; i < values.size(); ++i) {
153 QString output = result.
stdOut.trimmed();
154 if (output.isEmpty()) {
160 QStringList lines = output.split(
'\n', Qt::SkipEmptyParts);
161 int nRows = lines.size();
164 QList<QList<double>> rowData;
165 for (
const QString& line : lines) {
166 QStringList tokens = line.trimmed().split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
168 nCols = tokens.size();
169 }
else if (tokens.size() != nCols) {
176 for (
const QString& token : tokens) {
177 bool parseOk =
false;
178 double val = token.toDouble(&parseOk);
195 MatrixXd mat(nRows, nCols);
196 for (
int r = 0; r < nRows; ++r) {
197 for (
int c = 0; c < nCols; ++c) {
198 mat(r, c) = rowData[r][c];
210 const QStringList& args,
214 return m_runner.run(scriptPath, args);
221 return QCoreApplication::applicationDirPath() +
"/../resources/data/mne-cpp-test-data/";
228 const QString val = QProcessEnvironment::systemEnvironment().value(
"MNE_REQUIRE_PYTHON").toLower();
229 return val ==
"true" || val ==
"1";
236 QFile file(filePath);
237 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
241 QTextStream out(&file);
242 out.setRealNumberNotation(QTextStream::ScientificNotation);
243 out.setRealNumberPrecision(17);
245 for (
int r = 0; r < mat.rows(); ++r) {
246 for (
int c = 0; c < mat.cols(); ++c) {
262 QFile file(filePath);
263 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
269 QTextStream in(&file);
270 QList<QList<double>> rowData;
273 while (!in.atEnd()) {
274 QString line = in.readLine().trimmed();
278 QStringList tokens = line.split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
280 nCols = tokens.size();
281 }
else if (tokens.size() != nCols) {
288 for (
const QString& token : tokens) {
289 bool parseOk =
false;
290 double val = token.toDouble(&parseOk);
303 if (rowData.isEmpty() || nCols <= 0) {
309 MatrixXd mat(rowData.size(), nCols);
310 for (
int r = 0; r < rowData.size(); ++r) {
311 for (
int c = 0; c < nCols; ++c) {
312 mat(r, c) = rowData[r][c];
324 const QString& outputFilePath,
QtTest convenience layer on top of UTILSLIB::PythonRunner for cross-validating MNE-CPP results agains...
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
Script execution result container.
Eigen::VectorXd evalVector(const QString &code, bool *ok=nullptr, int timeoutMs=60000) const
static bool writeMatrix(const QString &filePath, const Eigen::MatrixXd &mat)
double evalDouble(const QString &code, bool *ok=nullptr, int timeoutMs=30000) const
PythonRunnerResult runScript(const QString &scriptPath, const QStringList &args={}, int timeoutMs=120000) const
static QString testDataPath()
Eigen::MatrixXd evalMatrixViaFile(const QString &code, const QString &outputFilePath, bool *ok=nullptr, int timeoutMs=120000) const
bool isPythonAvailable() const
bool hasPackage(const QString &packageName) const
PythonRunnerResult eval(const QString &code, int timeoutMs=30000) const
static bool isPythonRequired()
static Eigen::MatrixXd readMatrix(const QString &filePath, bool *ok=nullptr)
Eigen::MatrixXd evalMatrix(const QString &code, bool *ok=nullptr, int timeoutMs=60000) const