diff --git a/CMakeLists.txt b/CMakeLists.txt index c86468c..2d666a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) project(QtPMbrowser VERSION 2.4.3 LANGUAGES CXX) -set(MY_COPYRIGHT "2020 - 2024 Christian R. Halaszovich") +set(MY_COPYRIGHT "2020 - 2025 Christian R. Halaszovich") set(LINUX_RELEASE_DESCRIPTION "

This is a bugfix release.

") set(CMAKE_CXX_STANDARD 20) diff --git a/QtPMbrowser/DlgGraphSettings.cpp b/QtPMbrowser/DlgGraphSettings.cpp index b5fa4a2..1587eec 100644 --- a/QtPMbrowser/DlgGraphSettings.cpp +++ b/QtPMbrowser/DlgGraphSettings.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2022, 2025 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/QtPMbrowser/DlgGraphSettings.h b/QtPMbrowser/DlgGraphSettings.h index 0283f58..18c4cef 100644 --- a/QtPMbrowser/DlgGraphSettings.h +++ b/QtPMbrowser/DlgGraphSettings.h @@ -1,5 +1,5 @@ /* - Copyright 2020 -2022 Christian R. Halaszovich + Copyright 2020 -2022, 2025 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/QtPMbrowser/DlgPreferences.cpp b/QtPMbrowser/DlgPreferences.cpp index abd0ddb..37b0bc0 100644 --- a/QtPMbrowser/DlgPreferences.cpp +++ b/QtPMbrowser/DlgPreferences.cpp @@ -36,6 +36,7 @@ DlgPreferences::DlgPreferences(QWidget *parent) else ui->radioButtonCustomExt->setChecked(true); ui->lineEditVmon->setText(settings.value("Vmon", "Vmon").toString()); ui->lineEditImon->setText(settings.value("Imon", "Imon").toString()); + ui->checkBoxSysLocale->setChecked(!settings.value("use_C_locale", false).toBool()); settings.endGroup(); } @@ -56,6 +57,7 @@ void DlgPreferences::accept() settings.setValue("selectionButton", selection); settings.setValue("Vmon", ui->lineEditVmon->text()); settings.setValue("Imon", ui->lineEditImon->text()); + settings.setValue("use_C_locale", !ui->checkBoxSysLocale->isChecked()); settings.endGroup(); switch (selection) { case 0: diff --git a/QtPMbrowser/DlgPreferences.ui b/QtPMbrowser/DlgPreferences.ui index 8e10c25..5978fa7 100644 --- a/QtPMbrowser/DlgPreferences.ui +++ b/QtPMbrowser/DlgPreferences.ui @@ -7,7 +7,7 @@ 0 0 453 - 321 + 360 @@ -17,29 +17,6 @@ - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - Qt::Orientation::Vertical - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - @@ -128,6 +105,36 @@ + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + Qt::Orientation::Vertical + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + + + + + Use System Locale (takes effect only after re-start!) + + + diff --git a/QtPMbrowser/main.cpp b/QtPMbrowser/main.cpp index e9f5d5b..cf65243 100644 --- a/QtPMbrowser/main.cpp +++ b/QtPMbrowser/main.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2025 Christian R. Halaszovich This file is part of PMbrowser. @@ -17,9 +17,11 @@ along with PMbrowser. If not, see . */ +#include #include "pmbrowserwindow.h" #include #include +#include int main(int argc, char *argv[]) { @@ -30,6 +32,17 @@ int main(int argc, char *argv[]) QCoreApplication::setApplicationName("PM browser"); QSettings::setDefaultFormat(QSettings::IniFormat); QApplication::setWindowIcon(QIcon(QString(":/myappico.ico"))); // sets icon in OS X dock + + { + QSettings settings; + const bool use_C_locale = settings.value("Preferences/use_C_locale", false).toBool(); + if (use_C_locale) { + QLocale::setDefault(QLocale::c()); + } + QLocale loc; + std::locale::global(std::locale(loc.name().toUtf8())); + qDebug() << std::locale().name(); + } PMbrowserWindow w; w.show(); if (argc > 1) { diff --git a/QtPMbrowser/pmbrowserwindow.cpp b/QtPMbrowser/pmbrowserwindow.cpp index f21cf55..2e5abbb 100644 --- a/QtPMbrowser/pmbrowserwindow.cpp +++ b/QtPMbrowser/pmbrowserwindow.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2024 Christian R. Halaszovich + Copyright 2020 - 2025 Christian R. Halaszovich This file is part of PMbrowser. @@ -111,7 +111,7 @@ void PMbrowserWindow::populateTreeView() tree->expandAll(); } -void PMbrowserWindow::traceSelected(QTreeWidgetItem* item, hkTreeNode* trace) +void PMbrowserWindow::traceSelected(const QTreeWidgetItem* item, const hkTreeNode* trace) { (void)item; int indextrace = trace->extractInt32(TrTraceID); @@ -129,7 +129,7 @@ void PMbrowserWindow::traceSelected(QTreeWidgetItem* item, hkTreeNode* trace) // keep the following, since here we format it more nicely, with correct name and units // this is beyond what PMparmaters can do right now. - QString info = QString("%1=%2 %3").arg(prefix).arg(holding).arg(QLatin1StringView(yunit)); + QString info = QString("%1=%L2 %3").arg(prefix).arg(holding).arg(QLatin1StringView(yunit)); std::string str; formatParamListPrint(*trace, parametersTrace, str); info.append("\n"); @@ -138,7 +138,7 @@ void PMbrowserWindow::traceSelected(QTreeWidgetItem* item, hkTreeNode* trace) ui->renderArea->renderTrace(trace, this->infile); } -void PMbrowserWindow::collectChildTraces(QTreeWidgetItem* item, int level, std::vector& trace_list) +void PMbrowserWindow::collectChildTraces(const QTreeWidgetItem* item, int level, std::vector& trace_list) { if (!item->isHidden()) { if (level < hkTreeNode::LevelTrace) { @@ -180,7 +180,7 @@ void PMbrowserWindow::animateTraceList(const QString& info_text, const std::vect progress.setValue(num_traces); } -static hkLib::hkTreeNode* item2node(QTreeWidgetItem* item) +static const hkLib::hkTreeNode* item2node(const QTreeWidgetItem* item) { return item->data(0, Qt::UserRole).value(); } @@ -228,7 +228,7 @@ hkLib::hkTreeView PMbrowserWindow::getVisibleNodes() return tree; } -void PMbrowserWindow::sweepSelected(QTreeWidgetItem* item, hkTreeNode* sweep) { +void PMbrowserWindow::sweepSelected(const QTreeWidgetItem* item, const hkTreeNode* sweep) { (void)item; QString txt = MakeSweepLabel(*sweep) + '\n'; std::string str; @@ -239,7 +239,7 @@ void PMbrowserWindow::sweepSelected(QTreeWidgetItem* item, hkTreeNode* sweep) { ui->textEdit->append(txt); } -void PMbrowserWindow::seriesSelected(QTreeWidgetItem* item, hkTreeNode* series) +void PMbrowserWindow::seriesSelected(const QTreeWidgetItem* item, const hkTreeNode* series) { (void)item; QString label = qs_from_sv(series->getString(SeLabel)); @@ -252,7 +252,7 @@ void PMbrowserWindow::seriesSelected(QTreeWidgetItem* item, hkTreeNode* series) ui->textEdit->append(txt); } -void PMbrowserWindow::groupSelected(QTreeWidgetItem* item, hkTreeNode* group) +void PMbrowserWindow::groupSelected(const QTreeWidgetItem* item, const hkTreeNode* group) { (void)item; QString label = qs_from_sv(group->getString(GrLabel)); @@ -803,7 +803,8 @@ void PMbrowserWindow::on_actionExport_Metadata_as_Table_triggered() try { hkLib::locale_manager lm; if (dlg.useSystemLocale()) { - lm.setLocale(""); // set default locale + // for macOS, we need to jump to some hoops + lm.setLocale(QLocale::system().name().toUtf8()); } else { lm.setLocale("C"); @@ -1009,12 +1010,12 @@ void PMbrowserWindow::on_actionSelect_Parameters_triggered() } } -void ::PMbrowserWindow::printAllParameters(QTreeWidgetItem* item) +void ::PMbrowserWindow::printAllParameters(const QTreeWidgetItem* item) { printAllParameters(item->data(0, Qt::UserRole).value()); } -void ::PMbrowserWindow::printAllParameters(hkTreeNode* n) +void ::PMbrowserWindow::printAllParameters(const hkTreeNode* n) { std::string s; QString lb; diff --git a/QtPMbrowser/pmbrowserwindow.h b/QtPMbrowser/pmbrowserwindow.h index 6994891..6ac6b92 100644 --- a/QtPMbrowser/pmbrowserwindow.h +++ b/QtPMbrowser/pmbrowserwindow.h @@ -78,15 +78,15 @@ public slots: void loadFile() {loadFile(currentFile);}; void closeFile(); void populateTreeView(); - void groupSelected(QTreeWidgetItem* item, hkLib::hkTreeNode* node); - void seriesSelected(QTreeWidgetItem* item, hkLib::hkTreeNode* node); - void sweepSelected(QTreeWidgetItem* item, hkLib::hkTreeNode* node); - void traceSelected(QTreeWidgetItem* item, hkLib::hkTreeNode* trace); - void collectChildTraces(QTreeWidgetItem* item, int level, std::vector& trace_list); + void groupSelected(const QTreeWidgetItem* item, const hkLib::hkTreeNode* node); + void seriesSelected(const QTreeWidgetItem* item, const hkLib::hkTreeNode* node); + void sweepSelected(const QTreeWidgetItem* item, const hkLib::hkTreeNode* node); + void traceSelected(const QTreeWidgetItem* item, const hkLib::hkTreeNode* trace); + void collectChildTraces(const QTreeWidgetItem* item, int level, std::vector& trace_list); void animateTraceList(const QString& info_text, const std::vector& trace_list); hkLib::hkTreeView getVisibleNodes(); - void printAllParameters(QTreeWidgetItem* item); - void printAllParameters(hkLib::hkTreeNode* node); + void printAllParameters(const QTreeWidgetItem* item); + void printAllParameters(const hkLib::hkTreeNode* node); void printAmplifierState(const hkLib::hkTreeNode* series); void drawStimulus(const hkLib::hkTreeNode* sweep); void useStimAsX(const hkLib::hkTreeNode* sweep); diff --git a/QtPMbrowser/renderarea.cpp b/QtPMbrowser/renderarea.cpp index b789391..e628eef 100644 --- a/QtPMbrowser/renderarea.cpp +++ b/QtPMbrowser/renderarea.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2022, 2025 Christian R. Halaszovich This file is part of PMbrowser. @@ -683,7 +683,7 @@ void RenderArea::zoomIn(double x_center, double y_center, double factor) update(); } -void RenderArea::renderTrace(hkLib::hkTreeNode* TrRecord, std::istream& infile) +void RenderArea::renderTrace(const hkLib::hkTreeNode* TrRecord, std::istream& infile) { using namespace hkLib; DisplayTrace newYtrace{}; diff --git a/QtPMbrowser/renderarea.h b/QtPMbrowser/renderarea.h index b5642fb..e2091b8 100644 --- a/QtPMbrowser/renderarea.h +++ b/QtPMbrowser/renderarea.h @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2022, 2025 Christian R. Halaszovich This file is part of PMbrowser. @@ -48,7 +48,7 @@ class RenderArea : public QWidget explicit RenderArea(QWidget *parent = nullptr); ~RenderArea(); bool noData() { return !yTrace.isValid(); }; - void renderTrace(hkLib::hkTreeNode* trace, std::istream& infile); + void renderTrace(const hkLib::hkTreeNode* trace, std::istream& infile); void addTrace(DisplayTrace&& dt); /// diff --git a/README.md b/README.md index 636d4dd..94fbb04 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # PMbrowser -Copyright 2020 - 2024 Christian R. Halaszovich +Copyright 2020 - 2025 Christian R. Halaszovich Created using Qt under GPLv3. diff --git a/demo/calc_mean.py b/demo/calc_mean.py index 5f3176f..8639682 100644 --- a/demo/calc_mean.py +++ b/demo/calc_mean.py @@ -5,7 +5,7 @@ def getMeta(npy_filename): json_filename=os.path.splitext(npy_filename)[0]+".json" - with open(json_filename, "r", encoding='latin1') as f: + with open(json_filename, "r", encoding='utf8') as f: meta=json.load(f) return meta diff --git a/demo/calc_means.py b/demo/calc_means.py new file mode 100644 index 0000000..7e52d3c --- /dev/null +++ b/demo/calc_means.py @@ -0,0 +1,68 @@ +# This Python file uses the following encoding: utf-8 +import os.path +import sys +import json +import glob +import numpy as np + +def getMeta(npy_filename): + json_filename=os.path.splitext(npy_filename)[0]+".json" + with open(json_filename, "r", encoding='utf8') as f: + meta=json.load(f) + return meta + +def getNpyBasename(npy_filename): + return os.path.basename(os.path.splitext(npy_filename)[0]) + +class TraceKey: + """Key useable for sorting tracenames.""" + def __init__(self,npy_filename): + c=getNpyBasename(npy_filename).split('_') + self.prefix=c[0] + self.group=int(c[1]) + self.series=int(c[2]) + self.sweep=int(c[3]) + self.trace=c[4] + + def __lt__(self, other): + if(self.prefixother.prefix): + return False + if(self.groupother.group): + return False + if(self.seriesother.series): + return False + if(self.sweepother.sweep): + return False + if(self.trace .npy [additional files ...] +example: calc_mean 0 100 PM_1_1_1_Imon.npy + """,file=sys.stderr) + sys.exit(-1) + p1=int(sys.argv[1]) + p2=int(sys.argv[2]) + filelist=[] + for index in range(3,len(sys.argv)): + filelist+=glob.glob(sys.argv[index]) + if(len(filelist)==0): + print("no matching files found",file=sys.stderr) + sys.exit(-1) + filelist.sort(key=TraceKey) + for npy_filename in filelist: + basename=os.path.basename(os.path.splitext(npy_filename)[0]) + meta=getMeta(npy_filename) + y_w=np.load(npy_filename) + print(basename, meta['params']['sweep']['Rel. Sweep Time'], np.mean(y_w[p1:p2]), sep='\t') diff --git a/demo/multiplot_traces.py b/demo/multiplot_traces.py index 98a1830..55f8afe 100644 --- a/demo/multiplot_traces.py +++ b/demo/multiplot_traces.py @@ -6,7 +6,7 @@ def getMeta(npy_filename): json_filename=os.path.splitext(npy_filename)[0]+".json" - with open(json_filename, "r", encoding='latin1') as f: + with open(json_filename, "r", encoding='utf8') as f: meta=json.load(f) return meta diff --git a/demo/plot_trace.py b/demo/plot_trace.py index 5623598..7dc9ce8 100644 --- a/demo/plot_trace.py +++ b/demo/plot_trace.py @@ -6,7 +6,7 @@ def getMeta(npy_filename): json_filename=os.path.splitext(npy_filename)[0]+".json" - with open(json_filename, "r", encoding='latin1') as f: + with open(json_filename, "r", encoding='utf8') as f: meta=json.load(f) return meta diff --git a/demo/plot_traces.py b/demo/plot_traces.py index 79f517f..686a8cb 100644 --- a/demo/plot_traces.py +++ b/demo/plot_traces.py @@ -7,7 +7,7 @@ def getMeta(npy_filename): json_filename=os.path.splitext(npy_filename)[0]+".json" - with open(json_filename, "r", encoding='latin1') as f: + with open(json_filename, "r", encoding='utf8') as f: meta=json.load(f) return meta diff --git a/doc/usage/displayarea.rst b/doc/usage/displayarea.rst index 63ec48f..4c770de 100644 --- a/doc/usage/displayarea.rst +++ b/doc/usage/displayarea.rst @@ -16,6 +16,8 @@ autoscale Select autoscale from the context menue of the **graph area** or use the keyboard shortcut `Ctrl+A`. +.. _graph-panning-lable: + panning ------- diff --git a/doc/usage/installation.rst b/doc/usage/installation.rst index d0c9f4b..526346b 100644 --- a/doc/usage/installation.rst +++ b/doc/usage/installation.rst @@ -52,7 +52,7 @@ page: https://github.com/ChrisHal/PMbrowser/releases . Use the command `sudo dpk to install. Your distribution needs to provide packages for the Qt libraries, version 6. If it does not, you can -use the selfcontained *AppImage* (see :ref:`appimage`) or the flatpak (see :ref:`flatpak`). +use the flatpak (see :ref:`flatpak`). Documentation will be installed in :file:`/usr/share/doc/QtPMbrowser` by default. The executable :file:`QtPMbrowser` in :file:`/usr/bin` . @@ -62,27 +62,16 @@ Now, you can start :program:`PMbrowser` with ``QtPMbrowser &`` from a terminal. Starting with Version 2.2.1, you should find :program:`PM browser` under *Applications*, too. -.. _appimage: - -using the *AppImage* (currently not supported) -********************************************** - -Dowload the AppImage file from https://github.com/ChrisHal/PMbrowser/releases. Make -the file executable (usually a right-click in you file manager is involved in this). -Double-clicking the file should start the application. - -The *AppImage contains* all necessary Qt libraries, even when your distro does not provide -them. - Installing on macOS =================== -Download the DragN'Dropinstaller :file:`PMbrowser--Darwin.dmg` from +Download the ZIP-archive :file:`PMbrowser--Darwin.zip` from the GitHub repository release -page: https://github.com/ChrisHal/PMbrowser/releases . -After opening the :file:`dmg` image by double-clicking, -drag the application icon *QtPMbrowser* to your Applications directory. +page: https://github.com/ChrisHal/PMbrowser/releases and unzip it. Since the +app is not (yet) notarized (which does cost money) by Apple, you must convince macOS +to open it. Information on how to do this can be found here: +https://support.apple.com/en-us/guide/mac-help/mh40616/mac Building from Source ==================== diff --git a/doc/usage/menues.rst b/doc/usage/menues.rst index 9dfa430..a310ce5 100644 --- a/doc/usage/menues.rst +++ b/doc/usage/menues.rst @@ -56,7 +56,8 @@ metadata as table +++++++++++++++++ Export :index:`metadata ` as tab-delimited table. The table can be either copied to the clipboard -or saved to file. +or saved to a file. + Parameters marked for export (see :ref:`select-params-dlg-label` ) will be included in the export. In addition to these parameters, the first four columns of the table will contain the group, series, sweep, and trace counts. @@ -289,6 +290,8 @@ can be set using the context menu of the **tree-view**. By default, the referenc 'Setting and Ranges' Dialog *************************** -Here you can configure the display area: axis ranges, *autoscale on load*, if grid lines should be displayed, colors -used for drawing traces and grid +Here you can configure the display area: axis ranges, *autoscale on load*, if grid lines should be displayed, +if panning / dragging (see :ref:`graph-panning-lable`) +should affect all Y scales or only the scale pertaining to the data unit of the currently selected trace, +colors used for drawing traces and grid and the number of overlay traces to be kept in the internal display buffer. diff --git a/hekatoolslib/PMparameters.cpp b/hekatoolslib/PMparameters.cpp index 4936dff..d5fec6d 100644 --- a/hekatoolslib/PMparameters.cpp +++ b/hekatoolslib/PMparameters.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "hkTree.h" #include "PMparameters.h" @@ -47,11 +48,12 @@ namespace hkLib { }; - std::array parametersTrace{ { + std::array parametersTrace{ { {false,false,"TrMark","",PMparameter::Int32,0}, {false,false,"TrLabel","",PMparameter::String32,4}, {false,false,"TraceID","",PMparameter::Int32,36}, - {false,false,"Holding","V|A",PMparameter::LongReal,408}, + {false,false,"DataPoints","",PMparameter::Int32,44}, + {false,false,"Holding","V|A",PMparameter::LongReal,408}, {false,false,"Internal Solution","",PMparameter::Int32,48}, {false,false,"Leak traces","",PMparameter::Int32,60}, {false,false,"TrDataKind","",PMparameter::Set16,64}, @@ -196,6 +198,7 @@ namespace hkLib { { true,true,"seScanRate","", PMparameter::LongReal, 72} } }; + constexpr char list_seperator{ ';' }; void PMparameter::formatValueOnly(const hkTreeNode& node, std::ostream& ss) const { @@ -331,7 +334,7 @@ namespace hkLib { auto a = node.extractValueOpt(offset); auto b = node.extractValueOpt(offset + 8); if (a && b) { - ss << '(' << *a << ',' + ss << '(' << *a << list_seperator << *b << ')'; } else { @@ -344,7 +347,7 @@ namespace hkLib { for (std::size_t i = 0; i < 4; ++i) { auto v = node.extractValueOpt(offset + 8 * i); if (v) { - ss << *v << ","; + ss << *v << list_seperator; } else { ss << "n/a"; @@ -359,7 +362,7 @@ namespace hkLib { for (std::size_t i = 0; i < 8; ++i) { auto v = node.extractValueOpt(offset + 8 * i); if (v) { - ss << *v << ","; + ss << *v << list_seperator; } else { ss << "n/a"; @@ -373,7 +376,7 @@ namespace hkLib { for (std::size_t i = 0; i < 16; ++i) { auto v = node.extractValueOpt(offset + 8 * i); if (v) { - ss << *v << ","; + ss << *v << list_seperator; } else { ss << "n/a"; @@ -454,27 +457,55 @@ namespace hkLib { return tmp; } - void PMparameter::formatJSON(const hkTreeNode& node, std::ostream& ss) const + constexpr auto format_json_needs_quotes = std::to_array({ + PMparameter::Set16, // for bitfields + PMparameter::DateTime, // weird PowerMod date + PMparameter::StringType, + PMparameter::String8, // String of length 8 + PMparameter::String16, + PMparameter::String32, + PMparameter::String80, + PMparameter::String400, + PMparameter::Boolean, + PMparameter::LongReal2, // array of 2 doubles + PMparameter::LongReal4, // array of 4 doubles + PMparameter::LongReal8, // array of 8 double + PMparameter::LongReal16, // 16 double + PMparameter::RecordingMode, + PMparameter::AmpModeName, + PMparameter::UserParamDesc4, // 4x UserParamDesc + PMparameter::UserParamDesc2, + PMparameter::UserParamDesc8 + }); + + + void PMparameter::formatJSON(const hkTreeNode& node, std::ostream& ss, bool include_unit) const { - ss << '"' << name << "\": \""; + const bool do_quotes = include_unit || (std::find(format_json_needs_quotes.begin(), + format_json_needs_quotes.end(), data_type)!= + format_json_needs_quotes.end()); + ss << '"' << name << "\": "; + if(do_quotes) ss << '"'; std::stringstream tmp; formatValueOnly(node, tmp); ss << JSONescapeQuotes(tmp.str()); - // hack to choose correctly for holding voltage or current - if (node.getLevel() == hkTreeNode::LevelTrace && std::strcmp("V|A", unit) == 0) - { - int recording_mode = node.getChar(TrRecordingMode); - if (recording_mode == CClamp) { - ss << " A"; - } - else { - ss << " V"; - } - } - else { - if (unit[0]) { ss << ' ' << JSONescapeQuotes(unit); } - } - ss << '"'; + if(include_unit) { + // hack to choose correctly for holding voltage or current + if (node.getLevel() == hkTreeNode::LevelTrace && std::strcmp("V|A", unit) == 0) + { + int recording_mode = node.getChar(TrRecordingMode); + if (recording_mode == CClamp) { + ss << " A"; + } + else { + ss << " V"; + } + } + else { + if (unit[0]) { ss << ' ' << JSONescapeQuotes(unit); } + } + } + if(do_quotes) ss << '"'; } void PMparameter::format(const hkTreeNode& node, std::string& s) const diff --git a/hekatoolslib/PMparameters.h b/hekatoolslib/PMparameters.h index d7c1c7e..d70dd08 100644 --- a/hekatoolslib/PMparameters.h +++ b/hekatoolslib/PMparameters.h @@ -51,7 +51,7 @@ namespace hkLib { LongReal2, // array of 2 doubles LongReal4, // array of 4 doubles LongReal8, // array of 8 double - LongReal16, // 8 double + LongReal16, // 16 double RecordingMode, RelativeTime, AmpModeName, @@ -67,7 +67,7 @@ namespace hkLib { void format(const hkTreeNode& node, std::string& s) const; void format(const hkTreeNode& node, std::ostream& ss) const; - void formatJSON(const hkTreeNode& node, std::ostream& ss) const; + void formatJSON(const hkTreeNode& node, std::ostream& ss, bool include_unit = false) const; void formatValueOnly(const hkTreeNode& node, std::ostream& ss) const; /// @@ -99,7 +99,7 @@ namespace hkLib { } }; - extern std::arrayparametersTrace; + extern std::arrayparametersTrace; extern std::arrayparametersSweep; extern std::arrayparametersSeries; extern std::arrayparametersGroup; diff --git a/hekatoolslib/exportNPY.cpp b/hekatoolslib/exportNPY.cpp index d115038..651a30d 100644 --- a/hekatoolslib/exportNPY.cpp +++ b/hekatoolslib/exportNPY.cpp @@ -140,6 +140,8 @@ namespace hkLib { } if (createJSON) { + locale_manager lm; + lm.setLocale("C"); filename.replace_extension("json"); std::ofstream jsonfile(filename); if (!jsonfile) { @@ -221,6 +223,8 @@ namespace hkLib { } writeNpyArray(outfile, data); if (createJSON) { + locale_manager lm; + lm.setLocale("C"); std::filesystem::path filepath(filename); filepath.replace_extension("json"); std::ofstream jsonfile(filepath);