Skip to content

Commit 1022c70

Browse files
authored
Merge pull request #10 from psavery/ptycho-workflow
Add Ptycho Workflow
2 parents c0853a5 + da54b42 commit 1022c70

15 files changed

Lines changed: 2193 additions & 4 deletions

tests/cxx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ add_cxx_test(Variant)
5252

5353
add_cxx_qtest(DockerUtilities)
5454
add_cxx_qtest(AcquisitionClient PYTHONPATH "${CMAKE_SOURCE_DIR}/acquisition")
55+
add_cxx_qtest(PtychoWorkflow)
5556
add_cxx_qtest(PyXRFWorkflow)
5657

5758
# Generate the executable

tests/cxx/PtychoWorkflowTest.cxx

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/* This source file is part of the Tomviz project, https://tomviz.org/.
2+
It is released under the 3-Clause BSD License, see "LICENSE". */
3+
4+
#include <QApplication>
5+
#include <QDebug>
6+
#include <QDir>
7+
#include <QFileInfo>
8+
#include <QLineEdit>
9+
#include <QProcess>
10+
#include <QProcessEnvironment>
11+
#include <QTest>
12+
#include <QThread>
13+
14+
#include <pqPVApplicationCore.h>
15+
16+
#include "PythonUtilities.h"
17+
#include "PtychoDialog.h"
18+
#include "PtychoRunner.h"
19+
20+
#include "TomvizTest.h"
21+
22+
using namespace tomviz;
23+
24+
const QDir ROOT_DATA_DIR = QString(SOURCE_DIR) + "/data";
25+
const QDir DATA_DIR = ROOT_DATA_DIR.absolutePath() + "/Pt_Zn_Phase";
26+
27+
template <typename T>
28+
T* findWidget()
29+
{
30+
for (auto* widget : QApplication::topLevelWidgets()) {
31+
if (qobject_cast<T*>(widget)) {
32+
return qobject_cast<T*>(widget);
33+
}
34+
}
35+
36+
return nullptr;
37+
}
38+
39+
class PtychoWorkflowTest : public QObject
40+
{
41+
Q_OBJECT
42+
43+
private:
44+
void downloadDataIfMissing()
45+
{
46+
if (DATA_DIR.exists()) {
47+
// Nothing to do
48+
return;
49+
}
50+
// Download the data if it is not present
51+
QString python = "python";
52+
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
53+
if (env.contains("TOMVIZ_TEST_PYTHON_EXECUTABLE")) {
54+
python = env.value("TOMVIZ_TEST_PYTHON_EXECUTABLE");
55+
}
56+
57+
auto scriptFile = QFileInfo(QString(SOURCE_DIR) + "/fixtures/download_and_unzip.py");
58+
QString scriptPath = scriptFile.absoluteFilePath();
59+
60+
QString url = "https://data.kitware.com/api/v1/file/6914aad883abdcd84d150c91/download";
61+
62+
// We unzip into the parent directory, which will then have `Pt_Zn_Phase`
63+
// after unzipping.
64+
QStringList arguments;
65+
arguments << scriptPath << url << ROOT_DATA_DIR.absolutePath();
66+
67+
QProcess process;
68+
process.setProcessChannelMode(QProcess::ForwardedChannels);
69+
process.start(python, arguments);
70+
71+
// Timeout in seconds
72+
int timeout = 60 * 10;
73+
QVERIFY(process.waitForFinished(timeout * 1000));
74+
QVERIFY(process.exitCode() == 0);
75+
}
76+
77+
private slots:
78+
void initTestCase()
79+
{
80+
downloadDataIfMissing();
81+
}
82+
83+
void cleanupTestCase() {}
84+
85+
void runTest()
86+
{
87+
QString ptychoDir = DATA_DIR.absolutePath() + "/Ptycho/recon_result/";
88+
QString outputDir = DATA_DIR.absolutePath() + "/output/";
89+
90+
auto* runner = new PtychoRunner(this);
91+
runner->setAutoLoadFinalData(false);
92+
runner->start();
93+
94+
auto* dialog = findWidget<PtychoDialog>();
95+
QVERIFY(dialog);
96+
97+
auto* ptychoDirEdit = dialog->findChild<QLineEdit*>("ptychoDirectory");
98+
QVERIFY(ptychoDirEdit);
99+
ptychoDirEdit->setText(ptychoDir);
100+
101+
// Trigger the necessary changes
102+
emit ptychoDirEdit->editingFinished();
103+
104+
auto* outputDirEdit = dialog->findChild<QLineEdit*>("outputDirectory");
105+
QVERIFY(outputDirEdit);
106+
outputDirEdit->setText(outputDir);
107+
108+
dialog->accept();
109+
110+
QStringList outputFileNames = {"ptycho_object.emd", "ptycho_probe.emd"};
111+
112+
auto checkAllExist = [&outputDir, &outputFileNames]() {
113+
for (const auto& filename : outputFileNames) {
114+
if (!QFile::exists(outputDir + filename)) {
115+
return false;
116+
}
117+
118+
}
119+
return true;
120+
};
121+
122+
// Wait for it to finish, and verify the output files were written
123+
int timeout = 30;
124+
int waitTime = 0;
125+
bool found = false;
126+
127+
while (waitTime < timeout) {
128+
if (checkAllExist()) {
129+
found = true;
130+
break;
131+
}
132+
QThread::sleep(1);
133+
++waitTime;
134+
}
135+
// Verify everything was found
136+
QVERIFY(found);
137+
}
138+
139+
};
140+
141+
int main(int argc, char** argv)
142+
{
143+
QApplication app(argc, argv);
144+
145+
pqPVApplicationCore appCore(argc, argv);
146+
147+
Python::initialize();
148+
149+
PtychoWorkflowTest tc;
150+
return QTest::qExec(&tc, argc, argv);
151+
}
152+
153+
#include "PtychoWorkflowTest.moc"

tomviz/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ set(SOURCES
172172
ProgressDialog.h
173173
ProgressDialogManager.cxx
174174
ProgressDialogManager.h
175+
PtychoDialog.cxx
176+
PtychoDialog.h
177+
PtychoRunner.cxx
178+
PtychoRunner.h
175179
PythonGeneratedDatasetReaction.cxx
176180
PythonGeneratedDatasetReaction.h
177181
PythonReader.cxx
@@ -688,6 +692,18 @@ foreach(file ${tomviz_python_pyxrf_modules})
688692
"${tomviz_python_binary_dir}/tomviz/pyxrf/${file}")
689693
endforeach()
690694

695+
set(tomviz_python_ptycho_modules
696+
__init__.py
697+
ptycho.py
698+
)
699+
700+
file(MAKE_DIRECTORY "${tomviz_python_binary_dir}/tomviz/ptycho")
701+
foreach(file ${tomviz_python_ptycho_modules})
702+
execute_process(COMMAND ${CMAKE_COMMAND} -E ${script_cmd}
703+
"${tomviz_SOURCE_DIR}/tomviz/python/tomviz/ptycho/${file}"
704+
"${tomviz_python_binary_dir}/tomviz/ptycho/${file}")
705+
endforeach()
706+
691707
file(GLOB tomviz_python_state_modules "${tomviz_SOURCE_DIR}/tomviz/python/tomviz/state/*.py")
692708
file(MAKE_DIRECTORY "${tomviz_python_binary_dir}/tomviz/state")
693709
foreach(file_ ${tomviz_python_state_modules})

tomviz/MainWindow.cxx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "PipelineProxy.h"
4949
#include "PipelineSettingsDialog.h"
5050
#include "ProgressDialogManager.h"
51+
#include "PtychoRunner.h"
5152
#include "PyXRFRunner.h"
5253
#include "PythonGeneratedDatasetReaction.h"
5354
#include "PythonUtilities.h"
@@ -257,6 +258,9 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
257258
auto pyXRFRunner = new PyXRFRunner(this);
258259
connect(m_ui->actionPyXRFWorkflow, &QAction::triggered, pyXRFRunner,
259260
&PyXRFRunner::start);
261+
auto ptychoRunner = new PtychoRunner(this);
262+
connect(m_ui->actionPtychoWorkflow, &QAction::triggered, ptychoRunner,
263+
&PtychoRunner::start);
260264

261265
// Build Data Transforms menu
262266
new DataTransformMenu(this, m_ui->menuData, m_ui->menuSegmentation);
@@ -574,7 +578,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
574578
statusBar()->showMessage("Initializing python...");
575579
auto pythonWatcher = new QFutureWatcher<std::vector<OperatorDescription>>;
576580
connect(pythonWatcher, &QFutureWatcherBase::finished, this,
577-
[this, pyXRFRunner, pythonWatcher, dataBrokerSaveReaction]() {
581+
[this, pyXRFRunner, ptychoRunner, pythonWatcher, dataBrokerSaveReaction]() {
578582
m_ui->actionAcquisition->setEnabled(true);
579583
m_ui->actionPassiveAcquisition->setEnabled(true);
580584
registerCustomOperators(pythonWatcher->result());
@@ -599,6 +603,16 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
599603
m_ui->actionPyXRFWorkflow->setToolTip(tooltip);
600604
}
601605

606+
installed = ptychoRunner->isInstalled();
607+
m_ui->actionPtychoWorkflow->setEnabled(installed);
608+
if (!installed) {
609+
// Grab the import error and show it in the tooltip
610+
QString tooltip = "Failed to import required modules. "
611+
"Error message was:\n\n" +
612+
ptychoRunner->importError();
613+
m_ui->actionPtychoWorkflow->setToolTip(tooltip);
614+
}
615+
602616
delete pythonWatcher;
603617
statusBar()->showMessage("Initialization complete", 1500);
604618
});

tomviz/MainWindow.ui

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
<string>Workflows</string>
116116
</property>
117117
<addaction name="actionPyXRFWorkflow"/>
118+
<addaction name="actionPtychoWorkflow"/>
118119
</widget>
119120
<addaction name="menu_File"/>
120121
<addaction name="menuWorkflows"/>
@@ -539,6 +540,11 @@
539540
<string>PyXRF Workflow</string>
540541
</property>
541542
</action>
543+
<action name="actionPtychoWorkflow">
544+
<property name="text">
545+
<string>Ptycho</string>
546+
</property>
547+
</action>
542548
</widget>
543549
<customwidgets>
544550
<customwidget>

0 commit comments

Comments
 (0)