Skip to content

Commit a8eec61

Browse files
committed
Move PythonWorker, implement deepssm CLI command
1 parent 8cdf6d8 commit a8eec61

File tree

15 files changed

+93
-38
lines changed

15 files changed

+93
-38
lines changed

Applications/shapeworks/Commands.cpp

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <Analyze/Analyze.h>
44
#include <Application/DeepSSM/DeepSSMJob.h>
5+
#include <Application/Job/PythonWorker.h>
56
#include <Groom/Groom.h>
67
#include <Logging.h>
78
#include <Optimize/Optimize.h>
@@ -11,6 +12,7 @@
1112
#include <ShapeworksUtils.h>
1213
#include <Utils/StringUtils.h>
1314

15+
#include <QApplication>
1416
#include <boost/filesystem.hpp>
1517

1618
namespace shapeworks {
@@ -350,7 +352,7 @@ void DeepSSMCommand::buildParser() {
350352
.action("store")
351353
.type("choice")
352354
.choices(prep_choices.begin(), prep_choices.end())
353-
.set_default("all")
355+
//.set_default("all")
354356
.help("Preparation step to run");
355357

356358
// Boolean flag options
@@ -366,6 +368,11 @@ void DeepSSMCommand::buildParser() {
366368
}
367369

368370
bool DeepSSMCommand::execute(const optparse::Values& options, SharedCommandData& sharedData) {
371+
// Create a non-gui QApplication instance
372+
int argc = 0;
373+
char** argv = nullptr;
374+
QApplication app(argc, argv);
375+
369376
// Handle project file: either from --name or first positional argument
370377
std::string project_file;
371378
if (options.is_set_by_user("name")) {
@@ -379,13 +386,26 @@ bool DeepSSMCommand::execute(const optparse::Values& options, SharedCommandData&
379386
parser.error("Project file must be provided either as --name or as a positional argument");
380387
}
381388

389+
// Handle prep option with manual default
390+
std::string prep_step;
391+
if (options.is_set_by_user("prep")) {
392+
prep_step = options["prep"];
393+
} else {
394+
prep_step = "all"; // Manual default
395+
}
396+
382397
std::cout << "DeepSSM: Using project file: " << project_file << std::endl;
383398

384399
bool do_prep = options.is_set("prep") || options.is_set("all");
385-
std::string prep_step = options["prep"];
386400
bool do_augment = options.is_set("augment") || options.is_set("all");
387401
bool do_train = options.is_set("train") || options.is_set("all");
388402
bool do_test = options.is_set("test") || options.is_set("all");
403+
404+
std::cout << "Prep step: " << (do_prep ? "on" : "off") << "\n";
405+
std::cout << "Augment step: " << (do_augment ? "on" : "off") << "\n";
406+
std::cout << "Train step: " << (do_train ? "on" : "off") << "\n";
407+
std::cout << "Test step: " << (do_test ? "on" : "off") << "\n";
408+
389409
if (!do_prep && !do_augment && !do_train && !do_test) {
390410
do_prep = true;
391411
do_augment = true;
@@ -396,42 +416,73 @@ bool DeepSSMCommand::execute(const optparse::Values& options, SharedCommandData&
396416
ProjectHandle project = std::make_shared<Project>();
397417
project->load(project_file);
398418

399-
DeepSSMJob job(project, DeepSSMJob::JobType::DeepSSM_PrepType);
419+
PythonWorker python_worker;
420+
421+
auto wait_for_job = [&](auto job) {
422+
// This lambda will block until the job is complete
423+
while (!job->is_complete()) {
424+
QCoreApplication::processEvents();
425+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
426+
if (job->is_aborted()) {
427+
return false;
428+
}
429+
}
430+
return true;
431+
};
400432

401433
if (do_prep) {
434+
auto job = QSharedPointer<DeepSSMJob>::create(project, DeepSSMJob::JobType::DeepSSM_PrepType);
402435
if (prep_step == "all") {
403-
job.set_prep_step(DeepSSMJob::PrepStep::NOT_STARTED);
436+
job->set_prep_step(DeepSSMJob::PrepStep::NOT_STARTED);
404437
} else if (prep_step == "groom_training") {
405-
job.set_prep_step(DeepSSMJob::PrepStep::GROOM_TRAINING);
438+
job->set_prep_step(DeepSSMJob::PrepStep::GROOM_TRAINING);
406439
} else if (prep_step == "optimize_training") {
407-
job.set_prep_step(DeepSSMJob::PrepStep::OPTIMIZE_TRAINING);
440+
job->set_prep_step(DeepSSMJob::PrepStep::OPTIMIZE_TRAINING);
408441
} else if (prep_step == "optimize_validation") {
409-
job.set_prep_step(DeepSSMJob::PrepStep::OPTIMIZE_VALIDATION);
442+
job->set_prep_step(DeepSSMJob::PrepStep::OPTIMIZE_VALIDATION);
410443
} else if (prep_step == "groom_images") {
411-
job.set_prep_step(DeepSSMJob::PrepStep::GROOM_IMAGES);
444+
job->set_prep_step(DeepSSMJob::PrepStep::GROOM_IMAGES);
412445
} else {
413446
SW_ERROR("Unknown prep step: {}", prep_step);
414447
return false;
415448
}
416449
std::cout << "Running DeepSSM preparation step...\n";
417-
job.run_prep();
450+
python_worker.run_job(job);
451+
if (!wait_for_job(job)) {
452+
return false;
453+
}
454+
std::cout << "DeepSSM preparation step completed.\n";
418455
}
419456
if (do_augment) {
420457
std::cout << "Running DeepSSM data augmentation...\n";
421-
job.run_augmentation();
458+
auto job = QSharedPointer<DeepSSMJob>::create(project, DeepSSMJob::JobType::DeepSSM_AugmentationType);
459+
python_worker.run_job(job);
460+
if (!wait_for_job(job)) {
461+
return false;
462+
}
463+
std::cout << "DeepSSM data augmentation completed.\n";
422464
}
423465
if (do_train) {
424466
std::cout << "Running DeepSSM training...\n";
425-
job.run_training();
467+
auto job = QSharedPointer<DeepSSMJob>::create(project, DeepSSMJob::JobType::DeepSSM_TrainingType);
468+
python_worker.run_job(job);
469+
if (!wait_for_job(job)) {
470+
return false;
471+
}
472+
std::cout << "DeepSSM training completed.\n";
426473
}
427474
if (do_test) {
428475
std::cout << "Running DeepSSM testing...\n";
429-
job.run_testing();
476+
auto job = QSharedPointer<DeepSSMJob>::create(project, DeepSSMJob::JobType::DeepSSM_TestingType);
477+
python_worker.run_job(job);
478+
if (!wait_for_job(job)) {
479+
return false;
480+
}
481+
std::cout << "DeepSSM testing completed.\n";
430482
}
431483

432484
project->save();
433485

434-
SW_ERROR("DeepSSM command is not implemented yet.");
435486
return false;
436487
}
437488

Libs/Application/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
SET(APPLICATION_MOC_HDRS
22
DeepSSM/DeepSSMJob.h
33
Job/Job.h
4+
Job/PythonWorker.h
5+
ShapeWorksVtkOutputWindow.h
46
)
57

68
qt5_wrap_cpp( APPLICATION_MOC_SRCS ${APPLICATION_MOC_HDRS} )
@@ -11,6 +13,8 @@ SET(Application_headers
1113
add_library(Application STATIC
1214
DeepSSM/DeepSSMJob.cpp
1315
Job/Job.cpp
16+
Job/PythonWorker.cpp
17+
ShapeWorksVtkOutputWindow.cpp
1418
${APPLICATION_MOC_SRCS}
1519
)
1620

Libs/Application/Job/Job.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <QElapsedTimer>
33
#include <QObject>
4+
#include <QSharedPointer>
45

56
namespace shapeworks {
67

@@ -62,3 +63,6 @@ class Job : public QObject {
6263
QElapsedTimer timer_;
6364
};
6465
} // namespace shapeworks
66+
67+
68+
Q_DECLARE_METATYPE(QSharedPointer<shapeworks::Job>);
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,14 @@
77
namespace py = pybind11;
88
using namespace pybind11::literals; // to bring in the `_a` literal
99

10+
#include <Libs/Application/Job/PythonWorker.h>
1011
#include <Logging.h>
11-
#include <Python/PythonWorker.h>
12-
#include <Shape.h>
1312

1413
#include <QFileInfo>
1514
#include <QMessageBox>
1615
#include <QProcess>
16+
#include <QThread>
1717
#include <iostream>
18-
#include <sstream>
1918

2019
namespace shapeworks {
2120

@@ -58,6 +57,8 @@ PYBIND11_EMBEDDED_MODULE(logger, m) {
5857
PythonWorker::PythonWorker() {
5958
python_logger_ = QSharedPointer<PythonLogger>::create();
6059

60+
qRegisterMetaType<QSharedPointer<Job>>("QSharedPointer<Job>");
61+
6162
// create singular Python thread and move this object to the new thread
6263
thread_ = new QThread(this);
6364
moveToThread(thread_);
@@ -67,8 +68,10 @@ PythonWorker::PythonWorker() {
6768
//---------------------------------------------------------------------------
6869
PythonWorker::~PythonWorker() {
6970
end_python();
70-
thread_->wait();
71-
delete thread_;
71+
if (thread_) {
72+
thread_->wait();
73+
delete thread_;
74+
}
7275
}
7376

7477
//---------------------------------------------------------------------------
@@ -109,6 +112,9 @@ void PythonWorker::run_job(QSharedPointer<Job> job) {
109112
QMetaObject::invokeMethod(this, "start_job", Qt::QueuedConnection, Q_ARG(QSharedPointer<Job>, job));
110113
}
111114

115+
//---------------------------------------------------------------------------
116+
void PythonWorker::set_current_job(QSharedPointer<Job> job) { current_job_ = job; }
117+
112118
//---------------------------------------------------------------------------
113119
bool PythonWorker::init() {
114120
std::string script = "install_shapeworks.sh";
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// studio
1111
#include <Job/Job.h>
12-
#include <Visualization/ShapeWorksVtkOutputWindow.h>
12+
#include <Libs/Application/ShapeWorksVtkOutputWindow.h>
1313

1414
namespace shapeworks {
1515
class PythonLogger;
@@ -26,6 +26,7 @@ class PythonWorker : public QObject {
2626
void set_vtk_output_window(vtkSmartPointer<ShapeWorksVtkOutputWindow> output_window);
2727

2828
void run_job(QSharedPointer<Job> job);
29+
void set_current_job(QSharedPointer<Job> job);
2930

3031
void incoming_python_message(std::string message_string);
3132
void incoming_python_progress(double value, std::string message);
@@ -57,6 +58,6 @@ class PythonWorker : public QObject {
5758

5859
QSharedPointer<Job> current_job_;
5960

60-
QThread* thread_;
61+
QThread* thread_{nullptr};
6162
};
6263
} // namespace shapeworks
File renamed without changes.
File renamed without changes.

Studio/Analysis/AnalysisTool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#include <Job/NetworkAnalysisJob.h>
1212
#include <Job/ParticleNormalEvaluationJob.h>
1313
#include <Job/StatsGroupLDAJob.h>
14+
#include <Libs/Application/Job/PythonWorker.h>
1415
#include <Logging.h>
15-
#include <Python/PythonWorker.h>
1616
#include <QMeshWarper.h>
1717
#include <Shape.h>
1818
#include <StudioMesh.h>

Studio/Analysis/ShapeScalarPanel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include <Interface/ShapeWorksStudioApp.h>
1111
#include <Interface/Style.h>
1212
#include <Job/GroupPvalueJob.h>
13+
#include <Libs/Application/Job/PythonWorker.h>
1314
#include <Logging.h>
14-
#include <Python/PythonWorker.h>
1515
#include <QMeshWarper.h>
1616
#include <Shape.h>
1717
#include <StudioMesh.h>

Studio/CMakeLists.txt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,6 @@ SET(STUDIO_GROOM_MOC_HDRS
126126
Groom/GroomTool.h
127127
)
128128

129-
SET(STUDIO_PYTHON_SRCS
130-
Python/PythonWorker.cpp
131-
)
132-
SET(STUDIO_PYTHON_MOC_HDRS
133-
Python/PythonWorker.h
134-
)
135-
136129
SET(STUDIO_OPTIMIZE_SRCS
137130
Optimize/OptimizeTool.cpp
138131
Optimize/QOptimize.cpp
@@ -228,14 +221,12 @@ SET(STUDIO_VISUALIZATION_SRCS
228221
Visualization/MeshSlice.cpp
229222
Visualization/Viewer.cpp
230223
Visualization/Visualizer.cpp
231-
Visualization/ShapeWorksVtkOutputWindow.cpp
232224
Visualization/StudioHandleWidget.cpp
233225
)
234226

235227
SET(STUDIO_VISUALIZATION_MOC_HDRS
236228
Visualization/Lightbox.h
237229
Visualization/ParticleColors.h
238-
Visualization/ShapeWorksVtkOutputWindow.h
239230
Visualization/Visualizer.h
240231
)
241232

@@ -246,7 +237,6 @@ SET(STUDIO_SRCS
246237
${STUDIO_DEEPSSM_SRCS}
247238
${STUDIO_MONAILABEL_SRCS}
248239
${STUDIO_GROOM_SRCS}
249-
${STUDIO_PYTHON_SRCS}
250240
${STUDIO_INTERFACE_SRCS}
251241
${STUDIO_OPTIMIZE_SRCS}
252242
${STUDIO_UTILS_SRCS}
@@ -260,7 +250,6 @@ SET(STUDIO_MOC_HDRS
260250
${STUDIO_DEEPSSM_MOC_HDRS}
261251
${STUDIO_MONAILABEL_MOC_HDRS}
262252
${STUDIO_GROOM_MOC_HDRS}
263-
${STUDIO_PYTHON_MOC_HDRS}
264253
${STUDIO_INTERFACE_MOC_HDRS}
265254
${STUDIO_OPTIMIZE_MOC_HDRS}
266255
${STUDIO_UTILS_MOC_HDRS}

0 commit comments

Comments
 (0)