Merge pull request #4546 from akohlmey/lammps-gui-enhancements
LAMMPS-GUI enhancements
@ -498,3 +498,7 @@ systems. Some unit and regression testing is applied as well.
|
||||
A detailed discussion of the LAMMPS developer GitHub workflow can be
|
||||
found in the file `doc/github-development-workflow.md
|
||||
<https://github.com/lammps/lammps/blob/develop/doc/github-development-workflow.md>`_
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\clearpage
|
||||
|
||||
@ -1,36 +1,25 @@
|
||||
Using LAMMPS-GUI
|
||||
================
|
||||
|
||||
LAMMPS-GUI is a graphical text editor programmed using the `Qt Framework
|
||||
<https://www.qt.io/>`_ and customized for editing LAMMPS input files. It
|
||||
is linked to the :ref:`LAMMPS library <lammps_c_api>` and thus can run
|
||||
LAMMPS directly using the contents of the editor's text buffer as input.
|
||||
|
||||
It *differs* from other known interfaces to LAMMPS in that it can
|
||||
retrieve and display information from LAMMPS *while it is running*,
|
||||
display visualizations created with the :doc:`dump image command
|
||||
<dump_image>`, can launch the online LAMMPS documentation for known
|
||||
LAMMPS commands and styles, and directly integrates with a collection
|
||||
of LAMMPS tutorials (:ref:`Gravelle1 <Gravelle1>`).
|
||||
|
||||
This document describes **LAMMPS-GUI version 1.6**.
|
||||
|
||||
-----
|
||||
|
||||
LAMMPS-GUI is a graphical text editor customized for editing LAMMPS
|
||||
input files that is linked to the :ref:`LAMMPS library <lammps_c_api>`
|
||||
and thus can run LAMMPS directly using the contents of the editor's text
|
||||
buffer as input. It can retrieve and display information from LAMMPS
|
||||
while it is running, display visualizations created with the :doc:`dump
|
||||
image command <dump_image>`, and is adapted specifically for editing
|
||||
LAMMPS input files through text completion and reformatting, and linking
|
||||
to the online LAMMPS documentation for known LAMMPS commands and styles.
|
||||
.. contents::
|
||||
|
||||
.. note::
|
||||
|
||||
Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64
|
||||
(Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big
|
||||
Sur or later), and Windows (version 10 or later) :ref:`are available
|
||||
<lammps_gui_install>` for download. Non-MPI LAMMPS executables (as
|
||||
``lmp``) for running LAMMPS from the command-line and :doc:`some
|
||||
LAMMPS tools <Tools>` compiled executables are also included. Also,
|
||||
the pre-compiled LAMMPS-GUI packages include the WHAM executables
|
||||
from http://membrane.urmc.rochester.edu/content/wham/ for use with
|
||||
LAMMPS tutorials documented in this paper (:ref:`Gravelle1
|
||||
<Gravelle1>`).
|
||||
|
||||
The source code for LAMMPS-GUI is included in the LAMMPS source code
|
||||
distribution and can be found in the ``tools/lammps-gui`` folder. It
|
||||
can be compiled alongside LAMMPS when :doc:`compiling with CMake
|
||||
<Build_cmake>`.
|
||||
----
|
||||
|
||||
LAMMPS-GUI tries to provide an experience similar to what people
|
||||
traditionally would have running LAMMPS using a command-line window and
|
||||
@ -65,8 +54,8 @@ simple LAMMPS simulations. It is very suitable for tutorials on LAMMPS
|
||||
since you only need to learn how to use a single program for most tasks
|
||||
and thus time can be saved and people can focus on learning LAMMPS.
|
||||
The tutorials at https://lammpstutorials.github.io/ are specifically
|
||||
updated for use with LAMMPS-GUI and can their tutorial materials can
|
||||
be downloaded and loaded directly from the GUI.
|
||||
updated for use with LAMMPS-GUI and their tutorial materials can
|
||||
be downloaded and edited directly from the GUI.
|
||||
|
||||
Another design goal is to keep the barrier low when replacing part of
|
||||
the functionality of LAMMPS-GUI with external tools. That said, LAMMPS-GUI
|
||||
@ -79,10 +68,31 @@ has some unique functionality that is not found elsewhere:
|
||||
- monitoring of simulation progress
|
||||
- interactive visualization using the :doc:`dump image <dump_image>`
|
||||
command with the option to copy-paste the resulting settings
|
||||
- automatic slide show generation from dump image out at runtime
|
||||
- automatic plotting of thermodynamics data at runtime
|
||||
- automatic slide show generation from dump image output at runtime
|
||||
- automatic plotting of thermodynamic data at runtime
|
||||
- inspection of binary restart files
|
||||
|
||||
.. admonition:: Download LAMMPS-GUI for your platform
|
||||
:class: Hint
|
||||
|
||||
Pre-compiled, ready-to-use LAMMPS-GUI executables for Linux x86\_64
|
||||
(Ubuntu 20.04LTS or later and compatible), macOS (version 11 aka Big
|
||||
Sur or later), and Windows (version 10 or later) :ref:`are available
|
||||
<lammps_gui_install>` for download. Non-MPI LAMMPS executables (as
|
||||
``lmp``) for running LAMMPS from the command-line and :doc:`some
|
||||
LAMMPS tools <Tools>` compiled executables are also included. Also,
|
||||
the pre-compiled LAMMPS-GUI packages include the WHAM executables
|
||||
from http://membrane.urmc.rochester.edu/content/wham/ for use with
|
||||
LAMMPS tutorials documented in this paper (:ref:`Gravelle1
|
||||
<Gravelle1>`).
|
||||
|
||||
The source code for LAMMPS-GUI is included in the LAMMPS source code
|
||||
distribution and can be found in the ``tools/lammps-gui`` folder. It
|
||||
can be compiled alongside LAMMPS when :doc:`compiling with CMake
|
||||
<Build_cmake>`.
|
||||
|
||||
-----
|
||||
|
||||
The following text provides a detailed tour of the features and
|
||||
functionality of LAMMPS-GUI. Suggestions for new features and
|
||||
reports of bugs are always welcome. You can use the :doc:`the same
|
||||
@ -93,9 +103,12 @@ channels as for LAMMPS itself <Errors_bugs>` for that purpose.
|
||||
Installing Pre-compiled LAMMPS-GUI Packages
|
||||
-------------------------------------------
|
||||
|
||||
LAMMPS-GUI is available as pre-compiled binary packages for Linux
|
||||
x86\_64, macOS 11 and later, and Windows 10 and later. Alternately, it
|
||||
can be compiled from source.
|
||||
LAMMPS-GUI is available for download as pre-compiled binary packages for
|
||||
Linux x86\_64 (Ubuntu 20.04LTS or later and compatible), macOS (version
|
||||
11 aka Big Sur or later), and Windows (version 10 or later) from the
|
||||
`LAMMPS release pages on GitHub <https://github.com/lammps/lammps/releases/>`_.
|
||||
A backup download location is at https://download.lammps.org/static/
|
||||
Alternately, LAMMPS-GUI can be compiled from source when building LAMMPS.
|
||||
|
||||
Windows 10 and later
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
@ -350,8 +363,13 @@ data or both. The smoothing uses a `Savitzky-Golay convolution filter
|
||||
window width (left) and order (right) parameters can be set in the boxes
|
||||
next to the drop down menu. Default settings are 10 and 4 which means
|
||||
that the smoothing window includes 10 points each to the left and the
|
||||
right of the current data point and a fourth order polynomial is fit to
|
||||
the data in the window.
|
||||
right of the current data point for a total of 21 points and a fourth
|
||||
order polynomial is fitted to the data in the window.
|
||||
|
||||
The "Title:" and "Y:" input boxes allow to edit the text shown as the
|
||||
plot title and the y-axis label, respectively. The text entered in the
|
||||
"Title:" box is applied to *all* charts, while the "Y:" text changes
|
||||
only the y-axis label of the currently *selected* plot.
|
||||
|
||||
You can use the mouse to zoom into the graph (hold the left button and
|
||||
drag to mark an area) or zoom out (right click) and you can reset the
|
||||
@ -383,6 +401,11 @@ here you get the compounded data set starting with the last change of
|
||||
output fields or timestep setting, while the export from the log will
|
||||
contain *all* YAML output but *segmented* into individual runs.
|
||||
|
||||
The *Preferences* dialog has a *Charts* tab, where you can configure
|
||||
multiple chart-related settings, like the default title, colors for the
|
||||
graphs, default choice of the raw / smooth graph selection, and the
|
||||
default chart graph size.
|
||||
|
||||
Image Slide Show
|
||||
----------------
|
||||
|
||||
@ -462,11 +485,11 @@ correspond to (via their mass) and then colorize them in the image and
|
||||
set their atom diameters accordingly. If this is not possible, for
|
||||
instance when using reduced (= 'lj') :doc:`units <units>`, then
|
||||
LAMMPS-GUI will check the current pair style and if it is a
|
||||
Lennard-Jones type potential, it will extract the *sigma* parameter
|
||||
for each atom type and assign atom diameters from those numbers.
|
||||
For cases where atom diameters are not auto-detected, the *Atom size* field
|
||||
can be edited and a suitable value set manually. The default value
|
||||
is inferred from the x-direction lattice spacing.
|
||||
Lennard-Jones type potential, it will extract the *sigma* parameter for
|
||||
each atom type and assign atom diameters from those numbers. For cases
|
||||
where atom diameters are not auto-detected, the *Atom size* field can be
|
||||
edited and a suitable value set manually. The default value is inferred
|
||||
from the x-direction lattice spacing.
|
||||
|
||||
If elements cannot be detected the default sequence of colors of the
|
||||
:doc:`dump image <dump_image>` command is assigned to the different atom
|
||||
@ -735,13 +758,16 @@ Tutorials
|
||||
|
||||
The *Tutorials* menu is to support the set of LAMMPS tutorials for
|
||||
beginners and intermediate LAMMPS users documented in (:ref:`Gravelle1
|
||||
<Gravelle1>`). From the drop down menu you can select which of the eight
|
||||
currently available tutorial sessions you want to start and then will be
|
||||
taken to a 'wizard' dialog where you can choose in which folder you want
|
||||
to work, whether you want that folder to be cleared, and also whether
|
||||
you want to download the solutions files (can be large). The dialog
|
||||
will then start downloading the files requested and load the first input
|
||||
file for the selected session into LAMMPS-GUI.
|
||||
<Gravelle1>`). From the drop down menu you can select which of the
|
||||
eight currently available tutorial sessions you want to begin. This
|
||||
opens a 'wizard' dialog where you can choose in which folder you want to
|
||||
work, whether you want that folder to be wiped from *any* files, whether
|
||||
you want to download the solutions files (which can be large) to a
|
||||
``solution`` sub-folder, and whether you want the corresponding
|
||||
tutorial's online version opened in your web browser. The dialog will
|
||||
then start downloading the files requested (download progress is
|
||||
reported in the status line) and load the first input file for the
|
||||
selected session into LAMMPS-GUI.
|
||||
|
||||
About
|
||||
^^^^^
|
||||
@ -806,18 +832,21 @@ look of LAMMPS-GUI. The settings are grouped and each group is
|
||||
displayed within a tab.
|
||||
|
||||
.. |guiprefs1| image:: JPG/lammps-gui-prefs-general.png
|
||||
:width: 24%
|
||||
:width: 19%
|
||||
|
||||
.. |guiprefs2| image:: JPG/lammps-gui-prefs-accel.png
|
||||
:width: 24%
|
||||
:width: 19%
|
||||
|
||||
.. |guiprefs3| image:: JPG/lammps-gui-prefs-image.png
|
||||
:width: 24%
|
||||
:width: 19%
|
||||
|
||||
.. |guiprefs4| image:: JPG/lammps-gui-prefs-editor.png
|
||||
:width: 24%
|
||||
:width: 19%
|
||||
|
||||
|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4|
|
||||
.. |guiprefs5| image:: JPG/lammps-gui-prefs-charts.png
|
||||
:width: 19%
|
||||
|
||||
|guiprefs1| |guiprefs2| |guiprefs3| |guiprefs4| |guiprefs5|
|
||||
|
||||
General Settings:
|
||||
^^^^^^^^^^^^^^^^^
|
||||
@ -912,7 +941,7 @@ lists to select the background and box colors.
|
||||
Editor Settings:
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This tab allows tweaking settings of the editor window. Specifically
|
||||
This tab allows tweaking settings of the editor window. Specifically,
|
||||
the amount of padding to be added to LAMMPS commands, types or type
|
||||
ranges, IDs (e.g. for fixes), and names (e.g. for groups). The value
|
||||
set is the minimum width for the text element and it can be chosen in
|
||||
@ -924,6 +953,16 @@ the completion pop-up window, and whether auto-save mode is enabled.
|
||||
In auto-save mode the editor buffer is saved before a run or before
|
||||
exiting LAMMPS-GUI.
|
||||
|
||||
Charts Settings:
|
||||
----------------
|
||||
|
||||
This tab allows tweaking settings of the *Charts* window. Specifically,
|
||||
one can set the default chart title (if the title contains '%f' it will
|
||||
be replaced with the name of the current input file), one can select
|
||||
whether by default the raw data, the smoothed data or both will be
|
||||
plotted, one can set the colors for the two lines, the default smoothing
|
||||
parameters, and the default size of the chart graph in pixels.
|
||||
|
||||
-----------
|
||||
|
||||
Keyboard Shortcuts
|
||||
@ -1022,3 +1061,7 @@ Window), and `Ctrl-Q` (Quit Application) are supported.
|
||||
.. _Gravelle2:
|
||||
|
||||
**(Gravelle2)** Gravelle https://lammpstutorials.github.io/
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\clearpage
|
||||
|
||||
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 31 KiB |
BIN
doc/src/JPG/lammps-gui-prefs-charts.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
@ -2,23 +2,12 @@ LAMMPS-GUI TODO list:
|
||||
|
||||
# Short term goals (v1.x)
|
||||
|
||||
- implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences.
|
||||
- add a "Filter data" checkbox to the "Charts" window to select whether data should be dropped.
|
||||
- add a "Charts tab" to the preferences with the following (default) settings:
|
||||
- default filter data yes/no
|
||||
- default smooth parameters
|
||||
- default plot colors
|
||||
- enable "raw" or "smooth" or "both"
|
||||
- add QLineEdit fields to enter plot title, axis labels and units
|
||||
- add a "Colors" menu to the image viewer to adjust color settings for the
|
||||
current image (unlike the defaults in the perferences) including assigning
|
||||
colors to individual atom types.
|
||||
- Support color by property (e.g. scan computes or fixes with per-atom data), define colormaps etc.
|
||||
- Add a "Diameters" dialog where diamaters can by specified by atom type
|
||||
- figure out how widgets can be resized to fraction of available screen size.
|
||||
- figure out stacking order of frames and whether it can be more flexible
|
||||
|
||||
- implement indenting regions for (nested) loops?
|
||||
- implement data file manager GUI with the following features:
|
||||
- import coordinates and topology via VMD molfile plugins
|
||||
- import coordinates and topology from intermol
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QLineSeries>
|
||||
#include <QList>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <QPushButton>
|
||||
@ -43,11 +44,23 @@
|
||||
|
||||
using namespace QtCharts;
|
||||
|
||||
// brush color index must be kept in sync with preferences
|
||||
|
||||
static const QList<QBrush> mybrushes = {
|
||||
QBrush(QColor(0, 0, 0)), // black
|
||||
QBrush(QColor(100, 150, 255)), // blue
|
||||
QBrush(QColor(255, 125, 125)), // red
|
||||
QBrush(QColor(100, 200, 100)), // green
|
||||
QBrush(QColor(120, 120, 120)), // grey
|
||||
};
|
||||
|
||||
ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
QWidget(parent), menu(new QMenuBar), file(new QMenu("&File")), saveAsAct(nullptr),
|
||||
exportCsvAct(nullptr), exportDatAct(nullptr), exportYamlAct(nullptr), closeAct(nullptr),
|
||||
stopAct(nullptr), quitAct(nullptr), filename(_filename)
|
||||
stopAct(nullptr), quitAct(nullptr), smooth(nullptr), window(nullptr), order(nullptr),
|
||||
chartTitle(nullptr), chartYlabel(nullptr), filename(_filename)
|
||||
{
|
||||
QSettings settings;
|
||||
auto *top = new QHBoxLayout;
|
||||
menu->addMenu(file);
|
||||
menu->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
||||
@ -56,24 +69,47 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
auto *dummy = new QPushButton(QIcon(), "");
|
||||
dummy->hide();
|
||||
|
||||
do_raw = true;
|
||||
do_smooth = true;
|
||||
smooth = new QComboBox;
|
||||
// plot title and axis labels
|
||||
settings.beginGroup("charts");
|
||||
chartTitle =
|
||||
new QLineEdit(settings.value("title", "Thermo: %f").toString().replace("%f", filename));
|
||||
chartYlabel = new QLineEdit("");
|
||||
|
||||
// plot smoothing
|
||||
int smoothchoice = settings.value("smoothchoice", 2).toInt();
|
||||
switch (smoothchoice) {
|
||||
case 0:
|
||||
do_raw = true;
|
||||
do_smooth = false;
|
||||
break;
|
||||
case 1:
|
||||
do_raw = false;
|
||||
do_smooth = true;
|
||||
break;
|
||||
case 2: // fallthrough
|
||||
default:
|
||||
do_raw = true;
|
||||
do_smooth = true;
|
||||
break;
|
||||
}
|
||||
// list of choices must be kepy in sync with list in preferences
|
||||
smooth = new QComboBox;
|
||||
smooth->addItem("Raw");
|
||||
smooth->addItem("Smooth");
|
||||
smooth->addItem("Both");
|
||||
smooth->setCurrentIndex(2);
|
||||
smooth->setCurrentIndex(smoothchoice);
|
||||
smooth->show();
|
||||
window = new QSpinBox;
|
||||
window->setRange(5, 999);
|
||||
window->setValue(10);
|
||||
window->setValue(settings.value("smoothwindow", 10).toInt());
|
||||
window->setEnabled(true);
|
||||
window->setToolTip("Smoothing Window Size");
|
||||
order = new QSpinBox;
|
||||
order->setRange(1, 20);
|
||||
order->setValue(4);
|
||||
order->setValue(settings.value("smoothorder", 4).toInt());
|
||||
order->setEnabled(true);
|
||||
order->setToolTip("Smoothing Order");
|
||||
settings.endGroup();
|
||||
|
||||
auto *normal = new QPushButton(QIcon(":/icons/gtk-zoom-fit.png"), "");
|
||||
normal->setToolTip("Reset zoom to normal");
|
||||
@ -82,6 +118,10 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
top->addWidget(menu);
|
||||
top->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
top->addWidget(dummy);
|
||||
top->addWidget(new QLabel("Title:"));
|
||||
top->addWidget(chartTitle);
|
||||
top->addWidget(new QLabel("Y:"));
|
||||
top->addWidget(chartYlabel);
|
||||
top->addWidget(new QLabel("Plot:"));
|
||||
top->addWidget(smooth);
|
||||
top->addWidget(new QLabel(" Smooth:"));
|
||||
@ -113,6 +153,8 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
layout->addLayout(top);
|
||||
setLayout(layout);
|
||||
|
||||
connect(chartTitle, &QLineEdit::editingFinished, this, &ChartWindow::update_tlabel);
|
||||
connect(chartYlabel, &QLineEdit::editingFinished, this, &ChartWindow::update_ylabel);
|
||||
connect(smooth, SIGNAL(currentIndexChanged(int)), this, SLOT(select_smooth(int)));
|
||||
connect(window, &QAbstractSpinBox::editingFinished, this, &ChartWindow::update_smooth);
|
||||
connect(order, &QAbstractSpinBox::editingFinished, this, &ChartWindow::update_smooth);
|
||||
@ -122,7 +164,6 @@ ChartWindow::ChartWindow(const QString &_filename, QWidget *parent) :
|
||||
connect(columns, SIGNAL(currentIndexChanged(int)), this, SLOT(change_chart(int)));
|
||||
installEventFilter(this);
|
||||
|
||||
QSettings settings;
|
||||
resize(settings.value("chartx", 500).toInt(), settings.value("charty", 320).toInt());
|
||||
}
|
||||
|
||||
@ -160,8 +201,16 @@ void ChartWindow::add_chart(const QString &title, int index)
|
||||
columns->addItem(title, index);
|
||||
columns->show();
|
||||
// hide all but the first chart added
|
||||
if (charts.size() > 0) chart->hide();
|
||||
if (charts.size() > 0) {
|
||||
chart->hide();
|
||||
} else {
|
||||
// must initialize QLineEdit with first title
|
||||
// will be automatically updated when changing charts.
|
||||
chartYlabel->setText(title);
|
||||
}
|
||||
charts.append(chart);
|
||||
update_tlabel();
|
||||
select_smooth(0);
|
||||
}
|
||||
|
||||
void ChartWindow::add_data(int step, double data, int index)
|
||||
@ -226,6 +275,19 @@ void ChartWindow::update_smooth()
|
||||
c->smooth_param(do_raw, do_smooth, wval, oval);
|
||||
}
|
||||
|
||||
void ChartWindow::update_tlabel()
|
||||
{
|
||||
for (auto &c : charts)
|
||||
c->set_tlabel(chartTitle->text());
|
||||
}
|
||||
|
||||
void ChartWindow::update_ylabel()
|
||||
{
|
||||
for (auto &c : charts) {
|
||||
if (c->isVisible()) c->set_ylabel(chartYlabel->text());
|
||||
}
|
||||
}
|
||||
|
||||
void ChartWindow::saveAs()
|
||||
{
|
||||
if (charts.empty()) return;
|
||||
@ -343,10 +405,13 @@ void ChartWindow::change_chart(int)
|
||||
{
|
||||
int choice = columns->currentData().toInt();
|
||||
for (auto &c : charts) {
|
||||
if (choice == c->get_index())
|
||||
if (choice == c->get_index()) {
|
||||
c->show();
|
||||
else
|
||||
chartTitle->setText(c->get_tlabel());
|
||||
chartYlabel->setText(c->get_ylabel());
|
||||
} else {
|
||||
c->hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,6 +455,7 @@ ChartViewer::ChartViewer(const QString &title, int _index, QWidget *parent) :
|
||||
chart->legend()->hide();
|
||||
chart->addAxis(xaxis, Qt::AlignBottom);
|
||||
chart->addAxis(yaxis, Qt::AlignLeft);
|
||||
chart->setTitle("");
|
||||
xaxis->setTitleText("Time step");
|
||||
xaxis->setTickCount(5);
|
||||
xaxis->setLabelFormat("%d");
|
||||
@ -516,17 +582,39 @@ void ChartViewer::smooth_param(bool _do_raw, bool _do_smooth, int _window, int _
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void ChartViewer::set_tlabel(const QString &tlabel)
|
||||
{
|
||||
chart->setTitle(tlabel);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
void ChartViewer::set_ylabel(const QString &ylabel)
|
||||
{
|
||||
yaxis->setTitleText(ylabel);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
// update smooth plot data
|
||||
|
||||
static QList<QPointF> calc_sgsmooth(const QList<QPointF> &input, const int window, const int order);
|
||||
|
||||
void ChartViewer::update_smooth()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("charts");
|
||||
int rawidx = settings.value("rawbrush", 1).toInt();
|
||||
int smoothidx = settings.value("smoothbrush", 2).toInt();
|
||||
if ((rawidx < 0) || (rawidx >= mybrushes.size())) rawidx = 0;
|
||||
if ((smoothidx < 0) || (smoothidx >= mybrushes.size())) smoothidx = 0;
|
||||
settings.endGroup();
|
||||
|
||||
auto allseries = chart->series();
|
||||
if (do_raw) {
|
||||
// add raw data if not in chart
|
||||
if (!allseries.contains(series)) {
|
||||
series->setPen(QPen(QBrush(QColor(100, 150, 255)), 3, Qt::SolidLine, Qt::RoundCap));
|
||||
series->setPen(QPen(mybrushes[rawidx], 3, Qt::SolidLine, Qt::RoundCap));
|
||||
chart->addSeries(series);
|
||||
series->attachAxis(xaxis);
|
||||
series->attachAxis(yaxis);
|
||||
@ -537,7 +625,7 @@ void ChartViewer::update_smooth()
|
||||
if (series->count() > (2 * window)) {
|
||||
if (!smooth) {
|
||||
smooth = new QLineSeries;
|
||||
smooth->setPen(QPen(QBrush(QColor(255, 125, 125)), 3, Qt::SolidLine, Qt::RoundCap));
|
||||
smooth->setPen(QPen(mybrushes[smoothidx], 3, Qt::SolidLine, Qt::RoundCap));
|
||||
chart->addSeries(smooth);
|
||||
smooth->attachAxis(xaxis);
|
||||
smooth->attachAxis(yaxis);
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#define CHARTVIEWER_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QTime>
|
||||
@ -52,6 +53,8 @@ private slots:
|
||||
void stop_run();
|
||||
void select_smooth(int selection);
|
||||
void update_smooth();
|
||||
void update_tlabel();
|
||||
void update_ylabel();
|
||||
|
||||
void saveAs();
|
||||
void exportDat();
|
||||
@ -73,6 +76,7 @@ private:
|
||||
QAction *closeAct, *stopAct, *quitAct;
|
||||
QComboBox *smooth;
|
||||
QSpinBox *window, *order;
|
||||
QLineEdit *chartTitle, *chartYlabel;
|
||||
|
||||
QString filename;
|
||||
QList<QtCharts::ChartViewer *> charts;
|
||||
@ -103,6 +107,11 @@ public:
|
||||
QString get_title() const { return series->name(); }
|
||||
double get_step(int index) const { return (index < 0) ? 0.0 : series->at(index).x(); }
|
||||
double get_data(int index) const { return (index < 0) ? 0.0 : series->at(index).y(); }
|
||||
void set_tlabel(const QString &tlabel);
|
||||
void set_ylabel(const QString &ylabel);
|
||||
QString get_tlabel() const { return chart->title(); }
|
||||
QString get_xlabel() const { return xaxis->titleText(); }
|
||||
QString get_ylabel() const { return yaxis->titleText(); }
|
||||
|
||||
private:
|
||||
int last_step, index;
|
||||
|
||||
@ -60,6 +60,9 @@
|
||||
Change working directory to user's home dir if initial directory is "/" or the Application folder
|
||||
Add preferences option to set https proxy, if not already set via environment variable
|
||||
Add option to visualize molecules defined through the molecule command
|
||||
Add text fields for editing plot title and axis labels for charts
|
||||
Add option to automatically open tutorial websites (enabled by default)
|
||||
Add preferences tab for charts to set default for title, plot colors, smooth/raw plot, smooth params
|
||||
</description>
|
||||
</release>
|
||||
<release version="1.6.12" timestamp="1734890080">
|
||||
|
||||
@ -1617,7 +1617,7 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial)
|
||||
"created if necessary and LAMMPS-GUI will download the files required for the "
|
||||
"tutorial. If selected, an existing directory may be cleared from old "
|
||||
"files.</p>\n<p>Available files of the tutorial solution may be downloaded to a "
|
||||
"sub-folder \"solution\", if requested.</p>\n")
|
||||
"sub-folder called \"solution\", if requested.</p>\n")
|
||||
.arg(ntutorial));
|
||||
label->setWordWrap(true);
|
||||
|
||||
@ -1657,6 +1657,7 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial)
|
||||
auto *solval = new QCheckBox;
|
||||
auto *purgelabel = new QLabel("Remove existing files from directory");
|
||||
auto *sollabel = new QLabel("Download solutions");
|
||||
|
||||
purgeval->setCheckState(Qt::Unchecked);
|
||||
purgeval->setObjectName("t_dirpurge");
|
||||
solval->setCheckState(Qt::Unchecked);
|
||||
@ -1668,6 +1669,18 @@ QWizardPage *LammpsGui::tutorial_directory(const int ntutorial)
|
||||
grid->setColumnStretch(0, 0);
|
||||
grid->setColumnStretch(1, 100);
|
||||
|
||||
// we have tutorials 1 to 7 currently available online
|
||||
|
||||
QCheckBox *webval = nullptr;
|
||||
if ((ntutorial > 0) && (ntutorial < 8)) {
|
||||
grid->addWidget(new QLabel, 2, 0, 1, 2, Qt::AlignVCenter);
|
||||
webval = new QCheckBox;
|
||||
webval->setCheckState(Qt::Checked);
|
||||
webval->setObjectName("t_webopen");
|
||||
grid->addWidget(webval, 3, 0, Qt::AlignVCenter);
|
||||
grid->addWidget(new QLabel("Open tutorial webpage in web browser"), 3, 1, Qt::AlignVCenter);
|
||||
}
|
||||
|
||||
auto *label2 = new QLabel(
|
||||
QString("<hr width=\"33%\">\n<p align=\"center\">Click on "
|
||||
"the \"Finish\" button to complete the setup and start the download.</p>"));
|
||||
@ -2008,7 +2021,8 @@ static const QString geturl =
|
||||
"geturl https://raw.githubusercontent.com/lammpstutorials/"
|
||||
"lammpstutorials-article/refs/heads/main/files/tutorial%1/%2 output %2 verify no";
|
||||
|
||||
void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution)
|
||||
void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, bool getsolution,
|
||||
bool openwebpage)
|
||||
{
|
||||
constexpr int BUFLEN = 1024;
|
||||
char errorbuf[BUFLEN];
|
||||
@ -2023,6 +2037,36 @@ void LammpsGui::setup_tutorial(int tutno, const QString &dir, bool purgedir, boo
|
||||
QDir directory(dir);
|
||||
directory.cd(dir);
|
||||
|
||||
if (openwebpage) {
|
||||
QString weburl = "https://lammpstutorials.github.io/sphinx/build/html/tutorial%1/%2.html";
|
||||
switch (tutno) {
|
||||
case 1:
|
||||
weburl = weburl.arg(tutno).arg("lennard-jones-fluid");
|
||||
break;
|
||||
case 2:
|
||||
weburl = weburl.arg(tutno).arg("breaking-a-carbon-nanotube");
|
||||
break;
|
||||
case 3:
|
||||
weburl = weburl.arg(tutno).arg("polymer-in-water");
|
||||
break;
|
||||
case 4:
|
||||
weburl = weburl.arg(tutno).arg("nanosheard-electrolyte");
|
||||
break;
|
||||
case 5:
|
||||
weburl = weburl.arg(tutno).arg("reactive-silicon-dioxide");
|
||||
break;
|
||||
case 6:
|
||||
weburl = weburl.arg(tutno).arg("water-adsorption-in-silica");
|
||||
break;
|
||||
case 7:
|
||||
weburl = weburl.arg(tutno).arg("free-energy-calculation");
|
||||
break;
|
||||
default:
|
||||
weburl = "https://lammpstutorials.github.io/";
|
||||
}
|
||||
QDesktopServices::openUrl(QUrl(weburl));
|
||||
}
|
||||
|
||||
if (purgedir) purge_directory(dir);
|
||||
if (getsolution) directory.mkpath("solution");
|
||||
|
||||
@ -2138,10 +2182,14 @@ void TutorialWizard::accept()
|
||||
auto *dirname = findChild<QLineEdit *>("t_directory");
|
||||
auto *dirpurge = findChild<QCheckBox *>("t_dirpurge");
|
||||
auto *getsol = findChild<QCheckBox *>("t_getsolution");
|
||||
auto *webopen = findChild<QCheckBox *>("t_webopen");
|
||||
bool purgedir = false;
|
||||
bool getsolution = false;
|
||||
bool openwebpage = false;
|
||||
QString curdir;
|
||||
|
||||
if (webopen) openwebpage = (webopen->checkState() == Qt::Checked);
|
||||
|
||||
// create and populate directory.
|
||||
if (dirname) {
|
||||
QDir directory;
|
||||
@ -2165,7 +2213,7 @@ void TutorialWizard::accept()
|
||||
LammpsGui *main = nullptr;
|
||||
for (QWidget *widget : QApplication::topLevelWidgets())
|
||||
if (widget->objectName() == "LammpsGui") main = dynamic_cast<LammpsGui *>(widget);
|
||||
if (main) main->setup_tutorial(_ntutorial, curdir, purgedir, getsolution);
|
||||
if (main) main->setup_tutorial(_ntutorial, curdir, purgedir, getsolution, openwebpage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +85,8 @@ protected:
|
||||
void setFont(const QFont &newfont);
|
||||
QWizardPage *tutorial_intro(const int ntutorial, const QString &infotext);
|
||||
QWizardPage *tutorial_directory(const int ntutorial);
|
||||
void setup_tutorial(int ntutorial, const QString &dir, bool purgedir, bool getsolution);
|
||||
void setup_tutorial(int ntutorial, const QString &dir, bool purgedir, bool getsolution,
|
||||
bool openwebpage);
|
||||
void purge_inspect_list();
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
|
||||
@ -67,6 +67,7 @@ Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) :
|
||||
tabWidget->addTab(new AcceleratorTab(settings, lammps), "&Accelerators");
|
||||
tabWidget->addTab(new SnapshotTab(settings), "&Snapshot Image");
|
||||
tabWidget->addTab(new EditorTab(settings), "&Editor Settings");
|
||||
tabWidget->addTab(new ChartsTab(settings), "Cha&rts Settings");
|
||||
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &Preferences::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
@ -77,7 +78,7 @@ Preferences::Preferences(LammpsWrapper *_lammps, QWidget *parent) :
|
||||
setLayout(layout);
|
||||
setWindowIcon(QIcon(":/icons/lammps-icon-128x128.png"));
|
||||
setWindowTitle("LAMMPS-GUI - Preferences");
|
||||
resize(600, 450);
|
||||
resize(700, 500);
|
||||
}
|
||||
|
||||
Preferences::~Preferences()
|
||||
@ -207,6 +208,27 @@ void Preferences::accept()
|
||||
if (box) settings->setValue("autosave", box->isChecked());
|
||||
settings->endGroup();
|
||||
|
||||
// chart window settings
|
||||
|
||||
settings->beginGroup("charts");
|
||||
field = tabWidget->findChild<QLineEdit *>("title");
|
||||
if (field) settings->setValue("title", field->text());
|
||||
combo = tabWidget->findChild<QComboBox *>("smoothchoice");
|
||||
if (combo) settings->setValue("smoothchoice", combo->currentIndex());
|
||||
combo = tabWidget->findChild<QComboBox *>("rawbrush");
|
||||
if (combo) settings->setValue("rawbrush", combo->currentIndex());
|
||||
combo = tabWidget->findChild<QComboBox *>("smoothbrush");
|
||||
if (combo) settings->setValue("smoothbrush", combo->currentIndex());
|
||||
spin = tabWidget->findChild<QSpinBox *>("smoothwindow");
|
||||
if (spin) settings->setValue("smoothwindow", spin->value());
|
||||
spin = tabWidget->findChild<QSpinBox *>("smoothorder");
|
||||
if (spin) settings->setValue("smoothorder", spin->value());
|
||||
settings->endGroup();
|
||||
spin = tabWidget->findChild<QSpinBox *>("chartx");
|
||||
if (spin) settings->setValue("chartx", spin->value());
|
||||
spin = tabWidget->findChild<QSpinBox *>("charty");
|
||||
if (spin) settings->setValue("charty", spin->value());
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
@ -288,7 +310,7 @@ GeneralTab::GeneralTab(QSettings *_settings, LammpsWrapper *_lammps, QWidget *pa
|
||||
|
||||
auto https_proxy = QString::fromLocal8Bit(qgetenv("https_proxy"));
|
||||
if (https_proxy.isEmpty()) {
|
||||
https_proxy = settings->value("https_proxy", "").toString();
|
||||
https_proxy = settings->value("https_proxy", "").toString();
|
||||
auto *proxyedit = new QLineEdit(https_proxy);
|
||||
proxyedit->setObjectName("proxyval");
|
||||
gridlayout->addWidget(proxyedit, 3, 1);
|
||||
@ -622,6 +644,7 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s
|
||||
grid->addWidget(retval, i++, 1, Qt::AlignVCenter);
|
||||
grid->addWidget(autolbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(autoval, i++, 1, Qt::AlignVCenter);
|
||||
grid->addWidget(new QLabel(" "), i++, 0);
|
||||
grid->addWidget(savlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(savval, i++, 1, Qt::AlignVCenter);
|
||||
|
||||
@ -631,6 +654,94 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s
|
||||
setLayout(grid);
|
||||
}
|
||||
|
||||
ChartsTab::ChartsTab(QSettings *_settings, QWidget *parent) : QWidget(parent), settings(_settings)
|
||||
{
|
||||
auto *grid = new QGridLayout;
|
||||
auto *chartlbl = new QLabel("Charts default settings:");
|
||||
|
||||
settings->beginGroup("charts");
|
||||
auto *titlelbl = new QLabel("Default chart title:");
|
||||
auto *titletxt = new QLineEdit(settings->value("title", "Thermo: %f").toString());
|
||||
auto *titlehlp = new QLabel("(use %f for current input file)");
|
||||
|
||||
// list of choices must be kepy in sync with list in chartviewer
|
||||
auto *smoothlbl = new QLabel("Default plot data choice:");
|
||||
auto *smoothval = new QComboBox;
|
||||
smoothval->addItem("Raw");
|
||||
smoothval->addItem("Smooth");
|
||||
smoothval->addItem("Both");
|
||||
smoothval->setObjectName("smoothchoice");
|
||||
smoothval->setCurrentIndex(settings->value("smoothchoice", 2).toInt());
|
||||
|
||||
auto *rawbrlbl = new QLabel("Raw plot color:");
|
||||
auto *rawbrush = new QComboBox;
|
||||
rawbrush->addItem("Black");
|
||||
rawbrush->addItem("Blue");
|
||||
rawbrush->addItem("Red");
|
||||
rawbrush->addItem("Green");
|
||||
rawbrush->addItem("Gray");
|
||||
rawbrush->setObjectName("rawbrush");
|
||||
rawbrush->setCurrentIndex(settings->value("rawbrush", 1).toInt());
|
||||
|
||||
auto *smoothbrlbl = new QLabel("Smooth plot color:");
|
||||
auto *smoothbrush = new QComboBox;
|
||||
smoothbrush->addItem("Black");
|
||||
smoothbrush->addItem("Blue");
|
||||
smoothbrush->addItem("Red");
|
||||
smoothbrush->addItem("Green");
|
||||
smoothbrush->addItem("Gray");
|
||||
smoothbrush->setObjectName("smoothbrush");
|
||||
smoothbrush->setCurrentIndex(settings->value("smoothbrush", 2).toInt());
|
||||
|
||||
auto *smwindlbl = new QLabel("Default smoothing window:");
|
||||
auto *smwindval = new QSpinBox;
|
||||
smwindval->setRange(5, 999);
|
||||
smwindval->setValue(settings->value("smoothwindow", 10).toInt());
|
||||
smwindval->setObjectName("smoothwindow");
|
||||
|
||||
auto *smordrlbl = new QLabel("Default smoothing order:");
|
||||
auto *smordrval = new QSpinBox;
|
||||
smordrval->setRange(1, 20);
|
||||
smordrval->setValue(settings->value("smoothorder", 4).toInt());
|
||||
smordrval->setObjectName("smoothorder");
|
||||
settings->endGroup();
|
||||
|
||||
auto *chartxlbl = new QLabel("Chart default width:");
|
||||
auto *chartxval = new QSpinBox;
|
||||
chartxval->setRange(400, 40000);
|
||||
chartxval->setValue(settings->value("chartx", 500).toInt());
|
||||
chartxval->setObjectName("chartx");
|
||||
auto *chartylbl = new QLabel("Chart default height:");
|
||||
auto *chartyval = new QSpinBox;
|
||||
chartyval->setRange(300, 30000);
|
||||
chartyval->setValue(settings->value("charty", 320).toInt());
|
||||
chartyval->setObjectName("charty");
|
||||
|
||||
int i = 0;
|
||||
grid->addWidget(chartlbl, i++, 0, 1, 2, Qt::AlignTop | Qt::AlignHCenter);
|
||||
grid->addWidget(titlelbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(titletxt, i, 1, Qt::AlignTop);
|
||||
grid->addWidget(titlehlp, i++, 2, Qt::AlignTop);
|
||||
grid->addWidget(smoothlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(smoothval, i++, 1, Qt::AlignTop);
|
||||
grid->addWidget(rawbrlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(rawbrush, i++, 1, Qt::AlignTop);
|
||||
grid->addWidget(smoothbrlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(smoothbrush, i++, 1, Qt::AlignTop);
|
||||
grid->addWidget(smwindlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(smwindval, i++, 1, Qt::AlignTop);
|
||||
grid->addWidget(smordrlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(smordrval, i++, 1, Qt::AlignVCenter);
|
||||
grid->addWidget(chartxlbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(chartxval, i++, 1, Qt::AlignVCenter);
|
||||
grid->addWidget(chartylbl, i, 0, Qt::AlignTop);
|
||||
grid->addWidget(chartyval, i++, 1, Qt::AlignVCenter);
|
||||
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 0);
|
||||
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 1);
|
||||
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding), i, 2);
|
||||
setLayout(grid);
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// c-basic-offset: 4
|
||||
// End:
|
||||
|
||||
@ -93,6 +93,16 @@ private:
|
||||
QSettings *settings;
|
||||
};
|
||||
|
||||
class ChartsTab : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ChartsTab(QSettings *settings, QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
QSettings *settings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
|
||||