From 49b891757377ef9cebe857862f51950ccab142f7 Mon Sep 17 00:00:00 2001 From: Stockentenbrot Date: Sat, 22 Dec 2018 23:09:20 +0100 Subject: [PATCH 1/3] New --ld command line argument for linepoints Added command line option --ld for plots with lines and points --- commandlineparser.cpp | 937 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 937 insertions(+) create mode 100644 commandlineparser.cpp diff --git a/commandlineparser.cpp b/commandlineparser.cpp new file mode 100644 index 000000000..763d6de2a --- /dev/null +++ b/commandlineparser.cpp @@ -0,0 +1,937 @@ +/*************************************************************************** + * * + * copyright : (C) 2008 Barth Netterfield * + * netterfield@astro.utoronto.ca * + * * + * 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. * + * * + ***************************************************************************/ + +#include +#include + +#include "commandlineparser.h" +//#include "datasource.h" +#include "datasourcepluginmanager.h" +#include "objectstore.h" +#include "colorsequence.h" +#ifdef KST_HAVE_REVISION_H +#include "kstrevision.h" +#endif + +#include +#include +#include +#include + +#include "curve.h" +#include "psd.h" +#include "histogram.h" +#include "datamatrix.h" +#include "image.h" +#include "palette.h" + +#include "updatemanager.h" +#include "dialogdefaults.h" + +namespace Kst { + + static const char *usageMessage = +"KST Command Line Usage\n" +"************************\n" +"*** Load a kst session: ***\n" +"kst [OPTIONS] \n" +"\n" +"[OPTIONS] will override the datasource parameters for all data sources in the kst file:\n" +" -F \n" +" -f \n" +" -n \n" +" -s \n" +" -a (apply averaging filter: requires -s)\n\n" +"************************\n"; + + static const char *usageDetailsMessage = +"*** Read a data file ***\n" +"kst [ [OPTIONS]]\n" +"\n" +"OPTIONS are read and interpreted in order. Except for data object options, all are applied to all future data objects, unless later overridden.\n" +"Output Options:\n" +" --print Print to file and exit.\n" +" --landscape Print in landscape mode.\n" +" --portrait Print in portrait mode.\n" +" --Letter Print to Letter sized paper.\n" +" --A4 Print to A4 sized paper.\n" +" --png Render to a png image, and exit.\n" +" --pngHeight Height of png image (pixels)\n" +" --pngWidth Width of png image (pixels)\n" +"File Options:\n" +" -f default: 'end' counts from end.\n" +" -n default: 'end' reads to end of file\n" +" -s default: 0 (read every sample)\n" +" -a apply averaging filter: requires -s\n\n" +"Ascii File Options - for ascii files only: these are all stick\n" +" --asciiDataStart Data starts here. Files start at line 1.\n" +" --asciiFieldNames Field names are in this row.\n" +" --asciiNoFieldNames Fields are named for their data column\n" +" --asciiReadUnits Read units from line \n" +" --asciiNoUnits Do not read units\n" +" --asciiSpaceDelim Columns are Space/tab delimited\n" +" --asciiDelim Columns are dlimited with \n" +" --asciiFixedWidth Columns have width \n" +" --asciiNoFixedWidth Columns are delimited, not fixed width\n" +" --asciiDecimalDot Use a . as a decimal separator (ie, 10.1)\n" +" --asciiDecimalComma Use a , as a decimal separator (ie, 10,1)\n" +"Position:\n" +" -P : Place curves in one plot.\n" +" -A Place future curves in individual plots.\n" +" -m Layout plots in columns\n" +" -T Place future curves a new tab.\n" +"Appearance\n" +" -d: use points for the next curve\n" +" -l: use lines for the next curve\n" +" --ld: use lines and points for the next curve\n" +" -b: use bargraph for the next curve\n" +" --xlabel Set X label of all future plots.\n" +" --ylabel Set Y label of all future plots.\n" +" --xlabelauto AutoSet X label of all future plots.\n" +" --ylabelauto AutoSet Y label of all future plots.\n" +"Data Object Modifiers\n" +" -x : Create vector and use as X vector for curves.\n" +" -e : Create vector and use as Y-error vector for next -y.\n" +" -r : sample rate (spectra & spectograms).\n" +"Data Objects:\n" +" -y plot an XY curve of field.\n" +" -p plot the spectrum of field.\n" +" -h plot a histogram of field.\n" +" -z plot an image of matrix field.\n" +"Misc:\n" +" --serverName= Set the server name for pyKst scrips connecting with this session.\n" +"\n" +"****************\n" +"*** Examples ***\n" +"\n" +"Data sources and fields:\n" +"Plot all data in column 2 from data.dat.\n" +" kst data.dat -y 2\n" +"\n" +"Same as above, except only read 20 lines, starting at line 10.\n" +" kst data.dat -f 10 -n 20 -y 2\n" +"\n" +"... also read col 1. One plot per curve.\n" +" kst data.dat -f 10 -n 20 -y 1 -y 2\n" +"\n" +"Read col 1 from data2.dat and col 1 from data.dat\n" +" kst data.dat -f 10 -n 20 -y 2 data2.dat -y 1\n" +"\n" +"Same as above, except read 40 lines starting at 30 in data2.dat\n" +" kst data.dat -f 10 -n 20 -y 2 data2.dat -f 30 -n 40 -y 1\n" +"\n" +"Specify the X vector and error bars:\n" +"Plot x = col 1 and Y = col 2 and error flags = col 3 from data.dat\n" +" kst data.dat -x 1 -e 3 -y 2\n" +"\n" +"Get the X vector from data1.dat, and the Y vector from data2.dat.\n" +" kst data1.dat -x 1 data2.dat -y 1\n" +"\n" +"Placement:\n" +"Plot column 2 and column 3 in plot P1 and column 4 in plot P2\n" +" kst data.dat -P P1 -y 2 -y 3 -P P2 -y 4\n"; + +static void printText(const QString& text, const QString& detailText = QString(), const QString& t = QString()) +{ +#ifdef Q_OS_WIN + // No console on Windows. + QMessageBox box(QMessageBox::Information, "Kst", text + t); + if (!detailText.isEmpty()) { + box.setDetailedText(detailText); + } + box.exec(); +#else + QString displayText = QString(text) + QString(detailText) + t; + + fprintf(stderr,"%s\n", qPrintable(displayText)); + //qWarning("%s", qPrintable(displayText)); +#endif +} + + +void CommandLineParser::printUsage(const QString &t) +{ + printText(tr(usageMessage), tr(usageDetailsMessage), '\n' + t); +} + + +CommandLineParser::CommandLineParser(Document *doc, MainWindow* mw) : + _mainWindow(mw), + _doAve(false), _doSkip(false), _doConsecutivePlots(true), _useBargraph(false), + _useLines(true), _usePoints(false), _overrideStyle(false), _sampleRate(1.0), + _numFrames(-1), _startFrame(-1), + _skip(0), _plotName(), _errorField(), _fileName(), _xField(QString("INDEX")), + _pngFile(QString()), _pngWidth(-1), _pngHeight(-1), _printFile(QString()), _landscape(false), _plotItem(0), + _num_cols(0), _asciiFirstLine(-1), _asciiFieldLine(-1), _asciiNoFieldNames(false), + _asciiUnitsLine(-1), _asciiNoUnits(false), _asciiSpaceDelim(false), + _asciiDelim('\0'), _asciiFixedWidth(-1), _asciiNoFixedWidth(false), + _asciiDecimalDot(false), _asciiDecimalComma(false) +{ + + Q_ASSERT(QCoreApplication::instance()); + _arguments = QCoreApplication::instance()->arguments(); + _arguments.takeFirst(); //appname + + _document = doc; + + _fileNames.clear(); + _vectors.clear(); + _plotItems.clear(); + _xlabel.clear(); + _ylabel.clear(); +} + + +CommandLineParser::~CommandLineParser() { +} + + +bool CommandLineParser::_setIntArg(int *arg, QString Message, bool accept_end) { + QString param; + bool ok = true; + + if (_arguments.count()> 0) { + param = _arguments.takeFirst(); + if ((param==tr("end") || (param=="end")) && (accept_end)) { + *arg = -1; + } else { + *arg = param.toInt(&ok); + } + } else { + ok=false; + } + if (!ok) printUsage(Message); + return ok; +} + + +bool CommandLineParser::_setDoubleArg(double *arg, QString Message) { + QString param; + bool ok = true; + + if (_arguments.count()> 0) { + param = _arguments.takeFirst(); + *arg = param.toDouble(&ok); + } else { + ok=false; + } + if (!ok) printUsage(Message); + return ok; +} + + +bool CommandLineParser::_setStringArg(QString &arg, QString Message) { + bool ok = true; + if (_arguments.count()> 0) { + arg = _arguments.takeFirst(); + } else { + ok=false; + } + if (!ok) printUsage(Message); + return ok; +} + + +DataVectorPtr CommandLineParser::createOrFindDataVector(QString field, DataSourcePtr ds) { + DataVectorPtr xv; + bool found = false; + + if ((_startFrame==-1) && (_numFrames==-1)) { // count from end and read to end + _startFrame = 0; + } + // Flaky magic: if ds is an ascii file, change fields named 0 to 99 to + // Column xx. This allows "-y 2" but prevents ascii files with fields + // actually named "0 to 99" from being read from the command line. + if (ds->fileType() == "ASCII file") { + QRegExp num("^[0-9]{1,2}$"); + if (num.exactMatch(field)) { + field = ds->vector().list()[field.toInt()]; + } + } + // check to see if an identical vector already exists. If so, use it. + for (int i=0; i<_vectors.count(); i++) { + xv = _vectors.at(i); + if (field == xv->field()) { + if ((xv->reqStartFrame() == _startFrame) && + (xv->reqNumFrames() == _numFrames) && + (xv->skip() == _skip) && + (xv->doSkip() == (_skip>0)) && + (xv->doAve() == _doAve) ){ + if (xv->filename()==ds->fileName()) { + found = true; + break; + } + } + } + } + + if (!found) { + Q_ASSERT(_document && _document->objectStore()); + + xv = _document->objectStore()->createObject(); + + xv->writeLock(); + xv->change(ds, field, _startFrame, _numFrames, _skip, _skip>0, _doAve); + + xv->registerChange(); + xv->unlock(); + + _vectors.append(xv); + + } + + return xv; +} + +void CommandLineParser::createCurveInPlot(VectorPtr xv, VectorPtr yv, VectorPtr ev) { + CurvePtr curve = _document->objectStore()->createObject(); + + curve->setXVector(xv); + curve->setYVector(yv); + curve->setXError(0); + curve->setXMinusError(0); + curve->setColor(ColorSequence::self().next()); + curve->setHasPoints(_usePoints); + curve->setHasLines(_useLines); + curve->setHasBars(_useBargraph); + curve->setLineWidth(dialogDefaults().value("curves/lineWidth",0).toInt()); + //curve->setPointType(ptype++ % KSTPOINT_MAXTYPE); + + if (ev) { + curve->setYError(ev); + curve->setYMinusError(ev); + } else { + curve->setYError(0); + curve->setYMinusError(0); + } + + curve->writeLock(); + curve->registerChange(); + curve->unlock(); + + addCurve(curve); +} + +void CommandLineParser::addCurve(CurvePtr curve) +{ + if (_doConsecutivePlots) { + CreatePlotForCurve *cmd = new CreatePlotForCurve(); + cmd->createItem(); + _plotItem = static_cast(cmd->item()); + _plotItem->view()->appendToLayout(CurvePlacement::Auto, _plotItem); + applyLabels(); + } + PlotRenderItem *renderItem = _plotItem->renderItem(PlotRenderItem::Cartesian); + renderItem->addRelation(kst_cast(curve)); + if (renderItem->relationList().size()>1) { + _plotItem->setShowLegend(true,true); + } + _plotItem->update(); +} + +void CommandLineParser::createImageInPlot(MatrixPtr m) { + ImagePtr image = _document->objectStore()->createObject(); + + image->changeToColorOnly(m, 0.0, 1.0, true, Palette::getPaletteList().at(0)); + + image->writeLock(); + image->registerChange(); + image->unlock(); + + if (_doConsecutivePlots) { + CreatePlotForCurve *cmd = new CreatePlotForCurve(); + cmd->createItem(); + _plotItem = static_cast(cmd->item()); + _plotItem->view()->appendToLayout(CurvePlacement::Auto, _plotItem); + applyLabels(); + } + PlotRenderItem *renderItem = _plotItem->renderItem(PlotRenderItem::Cartesian); + renderItem->addRelation(kst_cast(image)); + _plotItem->update(); +} + +void CommandLineParser::createOrFindTab(const QString name) { + bool found = false; + int i; + int n_tabs = _mainWindow->tabWidget()->count(); + + for (i=0; itabWidget()->tabText(i) == name) { + found = true; + _mainWindow->tabWidget()->setCurrentIndex(i); + return; + } + } + + if (!found) { + _mainWindow->tabWidget()->createView(); + _mainWindow->tabWidget()->setCurrentViewName(name); + } +} + +void CommandLineParser::createOrFindPlot( const QString plot_name ) { + bool found = false; + PlotItem *pi; + + // check to see if a plot with this name exists. If so, use it. + for (int i=0; i<_plotItems.count(); i++) { + pi = _plotItems.at(i); + if (plot_name == pi->descriptiveName()) { + found = true; + break; + } + } + + if (!found) { + + CreatePlotForCurve *cmd = new CreatePlotForCurve(); + cmd->createItem(); + pi = static_cast ( cmd->item() ); + + pi->setDescriptiveName( plot_name ); + _plotItems.append(pi); + pi->view()->appendToLayout(CurvePlacement::Auto, pi); + _plotItem = pi; + applyLabels(); + } + _plotItem = pi; + +} + +void CommandLineParser::applyLabels() { + if (!_plotItem) { + return; + } + + if (!_xlabel.isEmpty()) { + _plotItem->bottomLabelDetails()->setText(_xlabel); + _plotItem->bottomLabelDetails()->setIsAuto(false); + } + if (!_ylabel.isEmpty()) { + _plotItem->leftLabelDetails()->setText(_ylabel); + _plotItem->leftLabelDetails()->setIsAuto(false); + } + +} + +QString CommandLineParser::kstFileName() { + if (_fileNames.size()>0) { + return (_fileNames.at(0)); + } else { + return QString(); + } +} + +bool CommandLineParser::processCommandLine(bool *ok) { + QString arg, param; + *ok=true; + bool new_fileList=true; + bool dataPlotted = false; + DataVectorPtr xv = 0L; + bool use_old_xv = false; + +#ifndef KST_NO_PRINTER + // set paper settings to match defaults. + _paperSize = QPrinter::PaperSize(dialogDefaults().value("print/paperSize", QPrinter::Letter).toInt()); + if (dialogDefaults().value("print/landscape",true).toBool()) { + _landscape = true; + } else { + _landscape = false; + } +#endif + + while (*ok) { + if (_arguments.count() < 1) { + break; + } + + arg = _arguments.takeFirst(); + if ((arg == "--help")||(arg == "-help")) { + printUsage(QString()); + *ok = false; + } else if (arg == "--version" || arg == "-version") { + + printText(QString("Kst ") + KSTVERSION +#ifdef KST_REVISION ++ " Revision " + KST_REVISION +#endif +); + + *ok = false; + } else if (arg == "-f") { + *ok = _setIntArg(&_startFrame, tr("Usage: -f \n"), true); + _document->objectStore()->override.f0 = _startFrame; + } else if (arg == "-n") { + *ok = _setIntArg(&_numFrames, tr("Usage: -n \n"), true); + _document->objectStore()->override.N = _numFrames; + } else if (arg == "-s") { + *ok = _setIntArg(&_skip, tr("Usage: -s \n")); + _document->objectStore()->override.skip = _skip; + } else if (arg == "-a") { + _doAve = true; + _document->objectStore()->override.doAve = _doAve; + } else if (arg == "-P") { + QString plot_name; + *ok = _setStringArg(plot_name,tr("Usage: -P \n")); + _doConsecutivePlots=false; + createOrFindPlot(plot_name); + } else if (arg == "-A") { + _doConsecutivePlots = true; + } else if (arg == "-T") { + QString tab_name; + _doConsecutivePlots = true; + *ok = _setStringArg(tab_name,tr("Usage: -T \n")); + if (dataPlotted) { + if (_num_cols > 0) { + _mainWindow->tabWidget()->currentView()->createLayout(false, _num_cols); + } + createOrFindTab(tab_name); + } else { + _mainWindow->tabWidget()->setCurrentViewName(tab_name); + } + } else if (arg == "-m") { + *ok = _setIntArg(&_num_cols, tr("Usage: -m \n"), true); + } else if (arg == "-d") { + _useBargraph=false; + _useLines = false; + _usePoints = true; + _overrideStyle = true; + } else if (arg == "-l") { + _useBargraph=false; + _useLines = true; + _usePoints = false; + _overrideStyle = true; + } else if (arg == "--ld") { + _useBargraph=false; + _useLines = true; + _usePoints = true; + _overrideStyle = true; + }else if (arg == "-b") { + _useBargraph=true; + _useLines = false; + _usePoints = false; + _overrideStyle = true; + } else if (arg == "-x") { + *ok = _setStringArg(_xField,tr("Usage: -x \n")); + for (int i_file=0; i_file<_fileNames.size(); i_file++) { + QString file = _fileNames.at(i_file); + QFileInfo info(file); + if (!info.exists()) { + printUsage(tr("file %1 does not exist\n").arg(file)); + *ok = false; + break; + } + + DataSourcePtr ds = DataSourcePluginManager::findOrLoadSource(_document->objectStore(), file); + xv = createOrFindDataVector(_xField, ds); + use_old_xv = false; + } + new_fileList = true; + } else if (arg == "-e") { + *ok = _setStringArg(_errorField,tr("Usage: -e \n")); + } else if (arg == "-r") { + *ok = _setDoubleArg(&_sampleRate,tr("Usage: -r \n")); + } else if (arg == "-y") { + QString field; + *ok = _setStringArg(field,tr("Usage: -y \n")); + + if (_fileNames.size()<1) { + printUsage(tr("No data files specified\n")); + *ok = false; + break; + } + for (int i_file=0; i_file<_fileNames.size(); i_file++) { + QString file = _fileNames.at(i_file); + QFileInfo info(file); + if (!info.exists()) { + printUsage(tr("file %1 does not exist\n").arg(file)); + *ok = false; + break; + } + + DataSourcePtr ds = DataSourcePluginManager::findOrLoadSource(_document->objectStore(), file); + if (!xv || !use_old_xv) { + xv = createOrFindDataVector(_xField, ds); + } + DataVectorPtr yv = createOrFindDataVector(field, ds); + + /* + DataSourcePluginManager::settingsObject().beginGroup("ASCII file"); + DataSourcePluginManager::settingsObject().beginGroup(file); + qDebug() << "ds settings: " << file << DataSourcePluginManager::settingsObject().allKeys(); + qDebug() << "Use Dot: " << file << DataSourcePluginManager::settingsObject().value("Use Dot"); + DataSourcePluginManager::settingsObject().endGroup(); + DataSourcePluginManager::settingsObject().endGroup(); + */ + + DataVectorPtr ev; + if (!_errorField.isEmpty()) { + ev = createOrFindDataVector(_errorField, ds); + if (!_overrideStyle) { + _useBargraph=false; + _useLines = false; + _usePoints = true; + } + } else { + ev = 0; + if (!_overrideStyle) { + _useBargraph=false; + _useLines = true; + _usePoints = false; + } + + } + + createCurveInPlot(xv, yv, ev); + dataPlotted = true; + } + + _errorField.clear(); + new_fileList = true; + _overrideStyle = false; + } else if (arg == "-p") { + QString field; + *ok = _setStringArg(field,tr("Usage: -p \n")); + + if (*ok) { + for (int i_file=0; i_file<_fileNames.size(); i_file++) { + QString file = _fileNames.at(i_file); + QFileInfo info(file); + if (!info.exists()) { + printUsage(tr("file %1 does not exist\n").arg(file)); + *ok = false; + break; + } + + DataSourcePtr ds = DataSourcePluginManager::findOrLoadSource(_document->objectStore(), file); + + DataVectorPtr pv = createOrFindDataVector(field, ds); + + Q_ASSERT(_document && _document->objectStore()); + PSDPtr powerspectrum = _document->objectStore()->createObject(); + Q_ASSERT(powerspectrum); + + powerspectrum->writeLock(); + powerspectrum->change(pv, _sampleRate, true, 14, true, true, QString(), QString()); + powerspectrum->registerChange(); + powerspectrum->unlock(); + + VectorPtr ev=0; + + if ( !_overrideStyle ) { + _useBargraph=false; + _useLines = true; + _usePoints = false; + } + + createCurveInPlot(powerspectrum->vX(), powerspectrum->vY(), ev); + dataPlotted = true; + } + new_fileList = true; + _overrideStyle = false; + } + } else if (arg == "--xlabel") { + *ok = _setStringArg(_xlabel, "Usage -xlabel