diff --git a/src/backend/datasources/filters/NgspiceRawAsciiFilter.cpp b/src/backend/datasources/filters/NgspiceRawAsciiFilter.cpp index 88f443b02..0698c4c60 100644 --- a/src/backend/datasources/filters/NgspiceRawAsciiFilter.cpp +++ b/src/backend/datasources/filters/NgspiceRawAsciiFilter.cpp @@ -1,377 +1,367 @@ /*************************************************************************** File : NgspiceRawAsciiFilter.cpp Project : LabPlot Description : Ngspice RAW ASCII filter -------------------------------------------------------------------- Copyright : (C) 2018 Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "backend/datasources/LiveDataSource.h" #include "backend/datasources/filters/NgspiceRawAsciiFilter.h" #include "backend/datasources/filters/NgspiceRawAsciiFilterPrivate.h" #include "backend/lib/trace.h" #include /*! \class NgspiceRawAsciiFilter \brief Import of data stored in Ngspice's raw formant, ASCCI version of it. \ingroup datasources */ NgspiceRawAsciiFilter::NgspiceRawAsciiFilter() : AbstractFileFilter(), d(new NgspiceRawAsciiFilterPrivate(this)) {} NgspiceRawAsciiFilter::~NgspiceRawAsciiFilter() {} bool NgspiceRawAsciiFilter::isNgspiceAsciiFile(const QString& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return false; } QString line = file.readLine(); if (!line.startsWith(QLatin1String("Title:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Date:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Plotname:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Flags:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("No. Variables:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("No. Points:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Variables:"))) return false; return true; } QString NgspiceRawAsciiFilter::fileInfoString(const QString& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return QString(); QString info; while (!file.atEnd()) { QString line = file.readLine(); if (line.simplified() == QLatin1String("Values:")) break; if (!info.isEmpty()) info += QLatin1String("
"); info += line; } return info; } /*! reads the content of the file \c fileName. */ void NgspiceRawAsciiFilter::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) { d->readDataFromFile(fileName, dataSource, importMode); } QVector NgspiceRawAsciiFilter::preview(const QString& fileName, int lines) { return d->preview(fileName, lines); } /*! writes the content of the data source \c dataSource to the file \c fileName. */ void NgspiceRawAsciiFilter::write(const QString& fileName, AbstractDataSource* dataSource) { d->write(fileName, dataSource); } /*! loads the predefined filter settings for \c filterName */ void NgspiceRawAsciiFilter::loadFilterSettings(const QString& filterName) { Q_UNUSED(filterName); } /*! saves the current settings as a new filter with the name \c filterName */ void NgspiceRawAsciiFilter::saveFilterSettings(const QString& filterName) const { Q_UNUSED(filterName); } void NgspiceRawAsciiFilter::setStartRow(const int r) { d->startRow = r; } int NgspiceRawAsciiFilter::startRow() const { return d->startRow; } void NgspiceRawAsciiFilter::setEndRow(const int r) { d->endRow = r; } int NgspiceRawAsciiFilter::endRow() const { return d->endRow; } QStringList NgspiceRawAsciiFilter::vectorNames() const { return d->vectorNames; } QVector NgspiceRawAsciiFilter::columnModes() { return d->columnModes; } //##################################################################### //################### Private implementation ########################## //##################################################################### NgspiceRawAsciiFilterPrivate::NgspiceRawAsciiFilterPrivate(NgspiceRawAsciiFilter* owner) : q(owner), startRow(1), endRow(-1) { } /*! reads the content of the file \c fileName to the data source \c dataSource. Uses the settings defined in the data source. */ void NgspiceRawAsciiFilterPrivate::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) { DEBUG("NgspiceRawAsciiFilterPrivate::readDataFromFile(): fileName = \'" << fileName.toStdString() << "\', dataSource = " << dataSource << ", mode = " << ENUM_TO_STRING(AbstractFileFilter, ImportMode, importMode)); QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return; } - //skip the first four lines in the header - file.readLine(); - file.readLine(); - file.readLine(); - file.readLine(); + //skip the first three lines in the header + file.readLine(); //"Title" + file.readLine(); //"Date" + file.readLine(); //"Plotname" - //number of variables + //evaluate the "Flags" line to check whether we have complex numbers QString line = file.readLine(); + bool hasComplexValues = line.endsWith(QLatin1String("complex\n")); + + //number of variables + line = file.readLine(); const int vars = line.right(line.length() - 15).toInt(); //remove the "No. Variables: " sub-string //number of points line = file.readLine(); const int points = line.right(line.length() - 12).toInt(); //remove the "No. Points: " sub-string //add names of the variables vectorNames.clear(); columnModes.clear(); file.readLine(); for (int i = 0; i points) ? points : endRow; const int actualRows = actualEndRow - startRow + 1; const int actualCols = hasComplexValues ? vars*2 : vars; const int columnOffset = dataSource->prepareImport(m_dataContainer, importMode, actualRows, actualCols, vectorNames, columnModes); //skip data lines, if required DEBUG(" Skipping " << startRow - 1 << " lines"); for (int i = 0; i < startRow - 1; ++i) { for (int j = 0; j < vars; ++j) file.readLine(); file.readLine(); //skip the empty line after each value block } //read the data points QStringList lineString; int currentRow = 0; // indexes the position in the vector(column) QLocale locale(QLocale::C); bool isNumber(false); for (int i = 0; i < actualRows; ++i) { lineString.clear(); for (int j = 0; j < vars; ++j) { line = file.readLine(); QStringList tokens = line.split(QLatin1Char('\t')); QString valueString = tokens.at(1).simplified(); //string containing the value(s) if (hasComplexValues) { QStringList realImgTokens = valueString.split(QLatin1Char(',')); if (realImgTokens.size() == 2) { //sanity check to make sure we really have both parts //real part double value = locale.toDouble(realImgTokens.at(0), &isNumber); static_cast*>(m_dataContainer[2*j])->operator[](currentRow) = (isNumber ? value : NAN); //imaginary part value = locale.toDouble(realImgTokens.at(1), &isNumber); static_cast*>(m_dataContainer[2*j+1])->operator[](currentRow) = (isNumber ? value : NAN); } } else { const double value = locale.toDouble(valueString, &isNumber); static_cast*>(m_dataContainer[j])->operator[](currentRow) = (isNumber ? value : NAN); } } file.readLine(); //skip the empty line after each value block currentRow++; emit q->completed(100 * currentRow/actualRows); } dataSource->finalizeImport(columnOffset, -1, -1, currentRow, "", importMode); } /*! * generates the preview for the file \c fileName reading the provided number of \c lines. */ QVector NgspiceRawAsciiFilterPrivate::preview(const QString& fileName, int lines) { QVector dataStrings; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return dataStrings; } - //skip the first four lines in the header - file.readLine(); - file.readLine(); - file.readLine(); - file.readLine(); + //skip the first three lines in the header + file.readLine(); //"Title" + file.readLine(); //"Date" + file.readLine(); //"Plotname" - //number of variables + //evaluate the "Flags" line to check whether we have complex numbers QString line = file.readLine(); + bool hasComplexValues = line.endsWith(QLatin1String("complex\n")); + + //number of variables + line = file.readLine(); const int vars = line.right(line.length() - 15).toInt(); //remove the "No. Variables: " sub-string //number of points line = file.readLine(); const int points = line.right(line.length() - 12).toInt(); //remove the "No. Points: " sub-string //add names of the variables vectorNames.clear(); columnModes.clear(); file.readLine(); for (int i = 0; i /*! \class NgspiceRawBinaryFilter \brief Import of data stored in Ngspice's raw formant, ASCCI version of it. \ingroup datasources */ NgspiceRawBinaryFilter::NgspiceRawBinaryFilter() : AbstractFileFilter(), d(new NgspiceRawBinaryFilterPrivate(this)) {} NgspiceRawBinaryFilter::~NgspiceRawBinaryFilter() {} bool NgspiceRawBinaryFilter::isNgspiceBinaryFile(const QString& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return false; } QString line = file.readLine(); if (!line.startsWith(QLatin1String("Title:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Date:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Plotname:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Flags:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("No. Variables:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("No. Points:"))) return false; line = file.readLine(); if (!line.startsWith(QLatin1String("Variables:"))) return false; return true; } QString NgspiceRawBinaryFilter::fileInfoString(const QString& fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return QString(); QString info; while (!file.atEnd()) { QString line = file.readLine(); if (line.simplified() == QLatin1String("Binary:")) break; if (!info.isEmpty()) info += QLatin1String("
"); info += line; } return info; } /*! reads the content of the file \c fileName. */ void NgspiceRawBinaryFilter::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) { d->readDataFromFile(fileName, dataSource, importMode); } QVector NgspiceRawBinaryFilter::preview(const QString& fileName, int lines) { return d->preview(fileName, lines); } /*! writes the content of the data source \c dataSource to the file \c fileName. */ void NgspiceRawBinaryFilter::write(const QString& fileName, AbstractDataSource* dataSource) { d->write(fileName, dataSource); } /*! loads the predefined filter settings for \c filterName */ void NgspiceRawBinaryFilter::loadFilterSettings(const QString& filterName) { Q_UNUSED(filterName); } /*! saves the current settings as a new filter with the name \c filterName */ void NgspiceRawBinaryFilter::saveFilterSettings(const QString& filterName) const { Q_UNUSED(filterName); } void NgspiceRawBinaryFilter::setStartRow(const int r) { d->startRow = r; } int NgspiceRawBinaryFilter::startRow() const { return d->startRow; } void NgspiceRawBinaryFilter::setEndRow(const int r) { d->endRow = r; } int NgspiceRawBinaryFilter::endRow() const { return d->endRow; } QStringList NgspiceRawBinaryFilter::vectorNames() const { return d->vectorNames; } QVector NgspiceRawBinaryFilter::columnModes() { return d->columnModes; } //##################################################################### //################### Private implementation ########################## //##################################################################### NgspiceRawBinaryFilterPrivate::NgspiceRawBinaryFilterPrivate(NgspiceRawBinaryFilter* owner) : q(owner), startRow(1), endRow(-1) { } /*! reads the content of the file \c fileName to the data source \c dataSource. Uses the settings defined in the data source. */ void NgspiceRawBinaryFilterPrivate::readDataFromFile(const QString& fileName, AbstractDataSource* dataSource, AbstractFileFilter::ImportMode importMode) { DEBUG("NgspiceRawBinaryFilterPrivate::readDataFromFile(): fileName = \'" << fileName.toStdString() << "\', dataSource = " << dataSource << ", mode = " << ENUM_TO_STRING(AbstractFileFilter, ImportMode, importMode)); QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return; } - //skip the first four lines in the header - file.readLine(); - file.readLine(); - file.readLine(); - file.readLine(); + //skip the first three lines in the header + file.readLine(); //"Title" + file.readLine(); //"Date" + file.readLine(); //"Plotname" - //number of variables + //evaluate the "Flags" line to check whether we have complex numbers QString line = file.readLine(); + bool hasComplexValues = line.endsWith(QLatin1String("complex\n")); + + //number of variables + line = file.readLine(); const int vars = line.right(line.length() - 15).toInt(); //remove the "No. Variables: " sub-string //number of points line = file.readLine(); const int points = line.right(line.length() - 12).toInt(); //remove the "No. Points: " sub-string //add names of the variables vectorNames.clear(); columnModes.clear(); file.readLine(); for (int i = 0; i NgspiceRawBinaryFilterPrivate::preview(const QString& fileName, int lines) { QVector dataStrings; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { DEBUG("Failed to open the file " << fileName.toStdString()); return dataStrings; } - //skip the first four lines in the header - file.readLine(); - file.readLine(); - file.readLine(); - file.readLine(); + //skip the first three lines in the header + file.readLine(); //"Title" + file.readLine(); //"Date" + file.readLine(); //"Plotname" - //number of variables + //evaluate the "Flags" line to check whether we have complex numbers QString line = file.readLine(); + bool hasComplexValues = line.endsWith(QLatin1String("complex\n")); + + //number of variables + line = file.readLine(); const int vars = line.right(line.length() - 15).toInt(); //remove the "No. Variables: " sub-string //number of points line = file.readLine(); const int points = line.right(line.length() - 12).toInt(); //remove the "No. Points: " sub-string //add names of the variables vectorNames.clear(); columnModes.clear(); file.readLine(); for (int i = 0; i