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);
88 double value = result.
stdOut.trimmed().toDouble(&parseOk);
89 if (ok) *ok = parseOk;
90 return parseOk ? value : 0.0;
104 QString output = result.
stdOut.trimmed();
105 if (output.isEmpty()) {
110 QStringList lines = output.split(
'\n', Qt::SkipEmptyParts);
113 QList<double> values;
114 for (
const QString& line : lines) {
115 QStringList tokens = line.trimmed().split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
116 for (
const QString& token : tokens) {
117 bool parseOk =
false;
118 double val = token.toDouble(&parseOk);
127 VectorXd vec(values.size());
128 for (
int i = 0; i < values.size(); ++i) {
146 QString output = result.
stdOut.trimmed();
147 if (output.isEmpty()) {
152 QStringList lines = output.split(
'\n', Qt::SkipEmptyParts);
153 int nRows = lines.size();
156 QList<QList<double>> rowData;
157 for (
const QString& line : lines) {
158 QStringList tokens = line.trimmed().split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
160 nCols = tokens.size();
161 }
else if (tokens.size() != nCols) {
167 for (
const QString& token : tokens) {
168 bool parseOk =
false;
169 double val = token.toDouble(&parseOk);
184 MatrixXd mat(nRows, nCols);
185 for (
int r = 0; r < nRows; ++r) {
186 for (
int c = 0; c < nCols; ++c) {
187 mat(r, c) = rowData[r][c];
198 const QStringList& args,
202 return m_runner.run(scriptPath, args);
209 return QCoreApplication::applicationDirPath() +
"/../resources/data/mne-cpp-test-data/";
216 const QString val = QProcessEnvironment::systemEnvironment().value(
"MNE_REQUIRE_PYTHON").toLower();
217 return val ==
"true" || val ==
"1";
224 QFile file(filePath);
225 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
229 QTextStream out(&file);
230 out.setRealNumberNotation(QTextStream::ScientificNotation);
231 out.setRealNumberPrecision(17);
233 for (
int r = 0; r < mat.rows(); ++r) {
234 for (
int c = 0; c < mat.cols(); ++c) {
235 if (c > 0) out <<
' ';
249 QFile file(filePath);
250 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
255 QTextStream in(&file);
256 QList<QList<double>> rowData;
259 while (!in.atEnd()) {
260 QString line = in.readLine().trimmed();
261 if (line.isEmpty())
continue;
263 QStringList tokens = line.split(QRegularExpression(
"\\s+"), Qt::SkipEmptyParts);
265 nCols = tokens.size();
266 }
else if (tokens.size() != nCols) {
272 for (
const QString& token : tokens) {
273 bool parseOk =
false;
274 double val = token.toDouble(&parseOk);
286 if (rowData.isEmpty() || nCols <= 0) {
291 MatrixXd mat(rowData.size(), nCols);
292 for (
int r = 0; r < rowData.size(); ++r) {
293 for (
int c = 0; c < nCols; ++c) {
294 mat(r, c) = rowData[r][c];
305 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