From 02166926982f4a8d9f0a930c104565a825e6811c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 5 Aug 2024 20:04:44 -0400 Subject: [PATCH] add restart file inspector showing system info, data file, and snapshot image --- tools/lammps-gui/TODO.md | 4 --- tools/lammps-gui/codeeditor.cpp | 33 +++++++++++++---- tools/lammps-gui/codeeditor.h | 1 + tools/lammps-gui/fileviewer.cpp | 7 ++-- tools/lammps-gui/fileviewer.h | 2 +- tools/lammps-gui/imageviewer.cpp | 3 +- tools/lammps-gui/imageviewer.h | 2 +- tools/lammps-gui/lammpsgui.cpp | 61 ++++++++++++++++++++++++++++++++ tools/lammps-gui/lammpsgui.h | 7 ++++ tools/lammps-gui/lammpsgui.ui | 12 +++++++ 10 files changed, 117 insertions(+), 15 deletions(-) diff --git a/tools/lammps-gui/TODO.md b/tools/lammps-gui/TODO.md index 07155cbbd6..40788f0e8e 100644 --- a/tools/lammps-gui/TODO.md +++ b/tools/lammps-gui/TODO.md @@ -5,10 +5,6 @@ LAMMPS-GUI TODO list: - 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 - figure out how to avoid corrupted cached thermo data while reading it. -- add an "Inspect restart file" feature that will execute "read_restart" do a "run 0" - and then launch the image viewer. also we can capture the output from the info command - and use "write_data" and view the data file as well. - ideally, this would be done without having to drop the existing buffer in the editor. - implement a timed "Auto-Save" feature that saves after some idle time. set timeout in Editor preferences. - bundle or download? LAMMPS tutorial input files - add a "Colors" menu to the image viewer to adjust color settings for the diff --git a/tools/lammps-gui/codeeditor.cpp b/tools/lammps-gui/codeeditor.cpp index 10d829d34c..c60003db2d 100644 --- a/tools/lammps-gui/codeeditor.cpp +++ b/tools/lammps-gui/codeeditor.cpp @@ -770,10 +770,22 @@ void CodeEditor::contextMenuEvent(QContextMenuEvent *event) QString word = line.mid(begin, end - begin).trimmed(); QFileInfo fi(word); if (fi.exists() && fi.isFile()) { - auto *action = menu->addAction(QString("View file '%1'").arg(word)); - action->setIcon(QIcon(":/icons/document-open.png")); - action->setData(word); - connect(action, &QAction::triggered, this, &CodeEditor::view_file); + // check if file is a LAMMPS restart + char magic[16] = " "; + QFile file(word); + QDataStream in(&file); + in.readRawData(magic, 16); + if (strcmp(magic, LAMMPS_MAGIC) != 0) { + auto *action = menu->addAction(QString("Inspect restart file '%1'").arg(word)); + action->setIcon(QIcon(":/icons/document-open.png")); + action->setData(word); + connect(action, &QAction::triggered, this, &CodeEditor::inspect_file); + } else { + auto *action = menu->addAction(QString("View file '%1'").arg(word)); + action->setIcon(QIcon(":/icons/document-open.png")); + action->setData(word); + connect(action, &QAction::triggered, this, &CodeEditor::view_file); + } } } } @@ -1246,11 +1258,20 @@ void CodeEditor::open_url() QDesktopServices::openUrl(QUrl(act->data().toString())); } +// forward requests to view or inspect files to the corresponding LammpsGui methods + void CodeEditor::view_file() { auto *act = qobject_cast(sender()); - auto *viewer = new FileViewer(act->data().toString()); - viewer->show(); + auto *guimain = qobject_cast(parent()); + guimain->view_file(act->data().toString()); +} + +void CodeEditor::inspect_file() +{ + auto *act = qobject_cast(sender()); + auto *guimain = qobject_cast(parent()); + guimain->inspect_file(act->data().toString()); } // Local Variables: diff --git a/tools/lammps-gui/codeeditor.h b/tools/lammps-gui/codeeditor.h index 17236e3252..79688b46ac 100644 --- a/tools/lammps-gui/codeeditor.h +++ b/tools/lammps-gui/codeeditor.h @@ -89,6 +89,7 @@ private slots: void open_help(); void open_url(); void view_file(); + void inspect_file(); void reformatCurrentLine(); void runCompletion(); void insertCompletedCommand(const QString &completion); diff --git a/tools/lammps-gui/fileviewer.cpp b/tools/lammps-gui/fileviewer.cpp index acd966329a..996c5eb890 100644 --- a/tools/lammps-gui/fileviewer.cpp +++ b/tools/lammps-gui/fileviewer.cpp @@ -29,7 +29,7 @@ #include #include -FileViewer::FileViewer(const QString &_filename, QWidget *parent) : +FileViewer::FileViewer(const QString &_filename, QString title, QWidget *parent) : QPlainTextEdit(parent), fileName(_filename) { auto *action = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this); @@ -99,7 +99,10 @@ FileViewer::FileViewer(const QString &_filename, QWidget *parent) : setLineWrapMode(NoWrap); setMinimumSize(800, 500); setWindowIcon(QIcon(":/icons/lammps-icon-128x128.png")); - setWindowTitle("LAMMPS-GUI - Viewer - " + fileName); + if (title.isEmpty()) + setWindowTitle("LAMMPS-GUI - Viewer - " + fileName); + else + setWindowTitle(title); } void FileViewer::quit() diff --git a/tools/lammps-gui/fileviewer.h b/tools/lammps-gui/fileviewer.h index d52fa15a12..f137e25a66 100644 --- a/tools/lammps-gui/fileviewer.h +++ b/tools/lammps-gui/fileviewer.h @@ -20,7 +20,7 @@ class FileViewer : public QPlainTextEdit { Q_OBJECT public: - FileViewer(const QString &filename, QWidget *parent = nullptr); + FileViewer(const QString &filename, QString title = "", QWidget *parent = nullptr); private slots: void quit(); diff --git a/tools/lammps-gui/imageviewer.cpp b/tools/lammps-gui/imageviewer.cpp index 4841d651d0..3650a552f8 100644 --- a/tools/lammps-gui/imageviewer.cpp +++ b/tools/lammps-gui/imageviewer.cpp @@ -133,7 +133,7 @@ static int get_pte_from_mass(double mass) static const QString blank(" "); -ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QWidget *parent) : +ImageViewer::ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QString title, QWidget *parent) : QDialog(parent), menuBar(new QMenuBar), imageLabel(new QLabel), scrollArea(new QScrollArea), saveAsAct(nullptr), copyAct(nullptr), cmdAct(nullptr), zoomInAct(nullptr), zoomOutAct(nullptr), normalSizeAct(nullptr), lammps(_lammps), group("all"), filename(fileName), useelements(false), @@ -600,6 +600,7 @@ void ImageViewer::createImage() dumpcmd += " axes no 0.0 0.0"; dumpcmd += QString(" center s %1 %2 %3").arg(xcenter).arg(ycenter).arg(zcenter); + dumpcmd += " noinit"; dumpcmd += " modify boxcolor " + settings.value("boxcolor", "yellow").toString(); dumpcmd += " backcolor " + settings.value("background", "black").toString(); if (useelements) dumpcmd += blank + elements + blank + adiams + blank; diff --git a/tools/lammps-gui/imageviewer.h b/tools/lammps-gui/imageviewer.h index 94632bde89..aa2ade2bd9 100644 --- a/tools/lammps-gui/imageviewer.h +++ b/tools/lammps-gui/imageviewer.h @@ -34,7 +34,7 @@ class ImageViewer : public QDialog { Q_OBJECT public: - explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, + explicit ImageViewer(const QString &fileName, LammpsWrapper *_lammps, QString title = "", QWidget *parent = nullptr); private slots: diff --git a/tools/lammps-gui/lammpsgui.cpp b/tools/lammps-gui/lammpsgui.cpp index 1b477f63c4..b5f63b66f6 100644 --- a/tools/lammps-gui/lammpsgui.cpp +++ b/tools/lammps-gui/lammpsgui.cpp @@ -26,8 +26,10 @@ #include "stdcapture.h" #include "ui_lammpsgui.h" +#include #include #include +#include #include #include #include @@ -198,6 +200,7 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) : connect(ui->actionSave, &QAction::triggered, this, &LammpsGui::save); connect(ui->actionSave_As, &QAction::triggered, this, &LammpsGui::save_as); connect(ui->actionView, &QAction::triggered, this, &LammpsGui::view); + connect(ui->actionInspect, &QAction::triggered, this, &LammpsGui::inspect); connect(ui->actionQuit, &QAction::triggered, this, &LammpsGui::quit); connect(ui->actionCopy, &QAction::triggered, this, &LammpsGui::copy); connect(ui->actionCut, &QAction::triggered, this, &LammpsGui::cut); @@ -406,6 +409,12 @@ void LammpsGui::view() view_file(fileName); } +void LammpsGui::inspect() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Open the restart file"); + inspect_file(fileName); +} + void LammpsGui::open_recent() { auto *act = qobject_cast(sender()); @@ -666,6 +675,58 @@ void LammpsGui::view_file(const QString &fileName) } } +// read restart file into LAMMPS instance and launch image viewer +void LammpsGui::inspect_file(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::warning(this, "Warning", + "Cannot open file " + fileName + ": " + file.errorString() + ".\n"); + return; + } + + char magic[16] = " "; + QDataStream in(&file); + in.readRawData(magic, 16); + file.close(); + if (strcmp(magic, LAMMPS_MAGIC) != 0) { + QMessageBox::warning(this, "Warning", + "File " + fileName + " is not a LAMMPS restart file.\n"); + return; + } + + // LAMMPS is not re-entrant, so we can only query LAMMPS when it is not running a simulation + if (!lammps.is_running()) { + start_lammps(); + lammps.command("clear"); + lammps.command(QString("read_restart %1").arg(fileName).toLocal8Bit()); + capturer->BeginCapture(); + lammps.command("info system comm group compute fix"); + capturer->EndCapture(); + auto info = capturer->GetCapture(); + auto infolog = QString("%1.info.log").arg(fileName); + QFile dumpinfo(infolog); + if (dumpinfo.open(QIODevice::WriteOnly)) { + auto shortName = QFileInfo(fileName).fileName(); + auto infodata = QString("%1.tmp.data").arg(fileName); + dumpinfo.write(info.c_str(), info.size()); + dumpinfo.close(); + auto *infoviewer = + new FileViewer(infolog, QString("LAMMPS-GUI: restart info for %1").arg(shortName)); + infoviewer->show(); + dumpinfo.remove(); + lammps.command(QString("write_data %1 noinit").arg(infodata).toLocal8Bit()); + auto *dataviewer = + new FileViewer(infodata, QString("LAMMPS-GUI: data file for %1").arg(shortName)); + dataviewer->show(); + QFile(infodata).remove(); + auto *inspect_image = new ImageViewer( + fileName, &lammps, QString("LAMMPS-GUI: Image for %1").arg(shortName)); + inspect_image->show(); + } + } +} + // write file and update CWD to its folder void LammpsGui::write_file(const QString &fileName) diff --git a/tools/lammps-gui/lammpsgui.h b/tools/lammps-gui/lammpsgui.h index a575b0acc1..296ac89afe 100644 --- a/tools/lammps-gui/lammpsgui.h +++ b/tools/lammps-gui/lammpsgui.h @@ -27,6 +27,11 @@ #include "lammpswrapper.h" +// identifier for LAMMPS restart files +#if !defined(LAMMPS_MAGIC) +#define LAMMPS_MAGIC "LammpS RestartT" +#endif + // forward declarations class GeneralTab; @@ -64,6 +69,7 @@ public: protected: void open_file(const QString &filename); void view_file(const QString &filename); + void inspect_file(const QString &filename); void write_file(const QString &filename); void update_recents(const QString &filename = ""); void update_variables(); @@ -82,6 +88,7 @@ private slots: void new_document(); void open(); void view(); + void inspect(); void open_recent(); void start_exe(); void save(); diff --git a/tools/lammps-gui/lammpsgui.ui b/tools/lammps-gui/lammpsgui.ui index 2607e715b9..e9edb12c69 100644 --- a/tools/lammps-gui/lammpsgui.ui +++ b/tools/lammps-gui/lammpsgui.ui @@ -38,6 +38,7 @@ + @@ -138,6 +139,17 @@ Ctrl+Shift+F + + + + + + Inspect &Restart + + + Ctrl+Shift+R + +