Merge pull request #4546 from akohlmey/lammps-gui-enhancements

LAMMPS-GUI enhancements
This commit is contained in:
Axel Kohlmeyer
2025-04-14 10:49:54 -04:00
committed by GitHub
16 changed files with 388 additions and 82 deletions

View File

@ -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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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">

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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: