Skip to content
Snippets Groups Projects
Commit 9e45c60b authored by Van Herck, Walter's avatar Van Herck, Walter
Browse files

Merge branch 'GUI_pythonscriptsamples' into develop

parents a505ed0c 689fbff4
No related branches found
No related tags found
No related merge requests found
#include "PythonScriptSampleBuilder.h"
#include <Python.h>
#include <boost/python.hpp>
#include <cstring>
#include <QByteArray>
namespace bp = boost::python;
const char *PythonScriptSampleBuilder::m_class_name = "PythonSampleBuilder";
const char *PythonScriptSampleBuilder::m_const_function_name = "buildSample";
PythonScriptSampleBuilder::PythonScriptSampleBuilder(QString script_path)
: m_script_path(script_path)
{
}
PythonScriptSampleBuilder::~PythonScriptSampleBuilder()
{
// release python objects
}
ISample *PythonScriptSampleBuilder::buildSample() const
{
PyObject *pName, *pModule, *pDict, *pClass, *pInstance, *pValue;
Py_Initialize();
// add path to script:
QString addPathPython("sys.path.append('");
addPathPython.append(m_script_path.path());
addPathPython.append("')");
QByteArray path_command = addPathPython.toLocal8Bit();
PyRun_SimpleString("import sys");
PyRun_SimpleString(path_command.data());
PyRun_SimpleString("sys.path.append('/Users/herck/Development/git/BornAgain/lib')");
// use predefined function in python module to create a pyobject
// which is then 'extracted' to ISample* by boost::python
// build the name object
QByteArray script_name = m_script_path.completeBaseName().toLocal8Bit();
pName = PyString_FromString(script_name.data());
// load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// get class and instance
pClass = PyDict_GetItemString(pDict, m_class_name);
pInstance = PyObject_CallObject(pClass, 0);
// get the ISample PyObject
char function_name[12];
std::strcpy(function_name, m_const_function_name);
pValue = PyObject_CallMethod(pInstance, function_name, 0);
ISample *pResult = bp::extract<ISample *>(pValue);
return pResult;
}
#ifndef PYTHONSCRIPTSAMPLEBUILDER_H
#define PYTHONSCRIPTSAMPLEBUILDER_H
#include "ISampleBuilder.h"
#include <QFileInfo>
class PythonScriptSampleBuilder : public ISampleBuilder
{
public:
PythonScriptSampleBuilder(QString script_path);
virtual ~PythonScriptSampleBuilder();
virtual ISample *buildSample() const;
private:
QFileInfo m_script_path;
static const char *m_class_name;
static const char *m_const_function_name;
};
#endif // PYTHONSCRIPTSAMPLEBUILDER_H
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "Simulation.h" #include "Simulation.h"
#include "JobModel.h" #include "JobModel.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "PythonScriptSampleBuilder.h"
#include <QGroupBox> #include <QGroupBox>
#include <QPushButton> #include <QPushButton>
...@@ -12,6 +13,8 @@ ...@@ -12,6 +13,8 @@
#include <QLabel> #include <QLabel>
#include <QGridLayout> #include <QGridLayout>
#include <QMessageBox> #include <QMessageBox>
#include <QFileDialog>
#include <QDir>
SimulationView::SimulationView(SimulationDataModel *p_simulation_data_model, QWidget *parent) SimulationView::SimulationView(SimulationDataModel *p_simulation_data_model, QWidget *parent)
: QWidget(parent) : QWidget(parent)
...@@ -67,16 +70,21 @@ SimulationView::SimulationView(SimulationDataModel *p_simulation_data_model, QWi ...@@ -67,16 +70,21 @@ SimulationView::SimulationView(SimulationDataModel *p_simulation_data_model, QWi
// run simulation button // run simulation button
runSimulationButton = new QPushButton(tr("Run Simulation")); runSimulationButton = new QPushButton(tr("Run Simulation"));
// run simulation with python script sample builder
runPyScriptSimulation = new QPushButton(tr("And now for something completely different..."));
// main layout // main layout
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(inputDataGroup); mainLayout->addWidget(inputDataGroup);
mainLayout->addWidget(simulationParametersGroup); mainLayout->addWidget(simulationParametersGroup);
mainLayout->addWidget(runSimulationButton); mainLayout->addWidget(runSimulationButton);
mainLayout->addWidget(runPyScriptSimulation);
mainLayout->addStretch(); mainLayout->addStretch();
setLayout(mainLayout); setLayout(mainLayout);
// signal and slots // signal and slots
connect(runSimulationButton, SIGNAL(clicked()), this, SLOT(onRunSimulation())); connect(runSimulationButton, SIGNAL(clicked()), this, SLOT(onRunSimulation()));
connect(runPyScriptSimulation, SIGNAL(clicked()), this, SLOT(onPythonJobLaunched()));
} }
void SimulationView::updateViewElements() void SimulationView::updateViewElements()
...@@ -114,6 +122,31 @@ void SimulationView::onRunSimulation() ...@@ -114,6 +122,31 @@ void SimulationView::onRunSimulation()
tr("The simulation is now calculating.")); tr("The simulation is now calculating."));
} }
void SimulationView::onPythonJobLaunched()
{
Instrument *p_instrument = mp_simulation_data_model->getInstrumentList().value(
instrumentSelectionBox->currentText(), 0);
if (!p_instrument) {
QMessageBox::warning(this, tr("No Instrument Selected"),
tr("You must select an instrument first."));
return;
}
// QString file_name = QFileDialog::getOpenFileName(this, tr("Select Python Script"),
// QDir::homePath(), tr("Python scripts (*.py)"));
QString file_name("/Users/herck/Development/git/BornAgain/GUI/test_sample_builder");
PythonScriptSampleBuilder builder(file_name);
ISample *p_sample = builder.buildSample();
Simulation *p_sim = new Simulation;
p_sim->setSample(*p_sample);
p_sim->setInstrument(*p_instrument);
JobModel *p_new_job = new JobModel(p_sim);
connect(p_new_job, SIGNAL(finished()), this, SLOT(onJobFinished()));
p_new_job->start();
// initialize a Simulation object and run it
QMessageBox::information(this, tr("Simulation Started"),
tr("The simulation is now calculating."));
}
void SimulationView::onJobFinished() void SimulationView::onJobFinished()
{ {
QMessageBox::information(this, tr("Simulation Job Finished"), QMessageBox::information(this, tr("Simulation Job Finished"),
......
...@@ -17,6 +17,7 @@ public: ...@@ -17,6 +17,7 @@ public:
public slots: public slots:
void onRunSimulation(); void onRunSimulation();
void onPythonJobLaunched();
void onJobFinished(); void onJobFinished();
private: private:
...@@ -24,6 +25,7 @@ private: ...@@ -24,6 +25,7 @@ private:
QComboBox *instrumentSelectionBox; QComboBox *instrumentSelectionBox;
QComboBox *sampleSelectionBox; QComboBox *sampleSelectionBox;
QPushButton *runSimulationButton; QPushButton *runSimulationButton;
QPushButton *runPyScriptSimulation;
}; };
#endif // SIMULATIONVIEW_H #endif // SIMULATIONVIEW_H
...@@ -39,7 +39,8 @@ SOURCES += \ ...@@ -39,7 +39,8 @@ SOURCES += \
Views/WelcomeView.cpp \ Views/WelcomeView.cpp \
Views/sampleeditor.cpp \ Views/sampleeditor.cpp \
Views/sampleeditorstack.cpp \ Views/sampleeditorstack.cpp \
Models/JobModel.cpp Models/JobModel.cpp \
Models/PythonScriptSampleBuilder.cpp
HEADERS += \ HEADERS += \
mainwindow/imode.h \ mainwindow/imode.h \
...@@ -59,7 +60,8 @@ HEADERS += \ ...@@ -59,7 +60,8 @@ HEADERS += \
Views/WelcomeView.h \ Views/WelcomeView.h \
Views/sampleeditor.h \ Views/sampleeditor.h \
Views/sampleeditorstack.h \ Views/sampleeditorstack.h \
Models/JobModel.h Models/JobModel.h \
Models/PythonScriptSampleBuilder.h
INCLUDEPATH += $$PWD/mainwindow $$PWD/utils $$PWD/welcomemanager $$PWD/samplemanager $$PWD/experimentmanager $$PWD/simulationmanager $$PWD/fitmanager INCLUDEPATH += $$PWD/mainwindow $$PWD/utils $$PWD/welcomemanager $$PWD/samplemanager $$PWD/experimentmanager $$PWD/simulationmanager $$PWD/fitmanager
INCLUDEPATH += $$PWD/mainwindow $$PWD/utils $$PWD/Views $$PWD/Models INCLUDEPATH += $$PWD/mainwindow $$PWD/utils $$PWD/Views $$PWD/Models
...@@ -112,13 +114,17 @@ isEmpty(MYROOT) { ...@@ -112,13 +114,17 @@ isEmpty(MYROOT) {
MYROOTCINT = $${MYROOT}/bin/rootcint MYROOTCINT = $${MYROOT}/bin/rootcint
} }
#FORMS += \ #FORMS += \
# testform.ui # testform.ui
RESOURCES += coregui.qrc RESOURCES += coregui.qrc
# python include and library flags:
pythonvers=$$system("python -c 'import sys; sys.stdout.write(sys.version[:3])'")
INCLUDEPATH += $$system("python -c 'import sys; sys.stdout.write(sys.prefix + \"/include/python\" + sys.version[:3])'")
LIBS += -L$$system("python -c 'import sys; sys.stdout.write(sys.prefix + \"/lib\" )'") -lboost_python -lpython$$pythonvers
lessThan(QT_MAJOR_VERSION, 5): LIBS += -lQtDesigner -lQtDesignerComponents -lQtXml lessThan(QT_MAJOR_VERSION, 5): LIBS += -lQtDesigner -lQtDesignerComponents -lQtXml
#lessThan(QT_MAJOR_VERSION, 5): LIBS += -lQtDesigner -lQtDesignerComponents -lQtScript -lQtXml #lessThan(QT_MAJOR_VERSION, 5): LIBS += -lQtDesigner -lQtDesignerComponents -lQtScript -lQtXml
#
# extending C++ ISampleBuilder class in python
#
# The idea is following. We derive python's MySampleBuilder class from C++ ISampleBuilder.
# MySampleBuilder has set of registered parameters and redefined method 'buildSample' which
# build and return some complicated sample
#
# MySampleBuilder is passed to the GISASFWExperiment instance (i.e. inside C++) and then experiment (C++) can
# call MySampleBuilder (python) for new sample.
import sys, os
sys.path.append(os.path.abspath(
os.path.join(os.path.split(__file__)[0],
'..', '..', '..', 'lib')))
from libBornAgainCore import *
#-----------------------------------------------------------
# Cylinders with interference
# Function constructs sample depending on three parameters
#-----------------------------------------------------------
def BuildSample(m_layer_thickness, m_cylinder_height, m_cylinder_radius):
n_particle = complex(1.0-5e-5, 2e-8)
p_air_material = MaterialManager.instance().addHomogeneousMaterial("Air", 1.0, 0.0)
p_layer_material = MaterialManager.instance().addHomogeneousMaterial("Layer", 1.0-2e-6, 2e-8)
p_substrate_material = MaterialManager.instance().addHomogeneousMaterial("Substrate", 1.0-2e-6, 2e-8)
air_layer = Layer(p_air_material)
middle_layer = Layer(p_layer_material, m_layer_thickness)
substrate_layer = Layer(p_substrate_material)
interference_funtion = InterferenceFunction1DParaCrystal(20.0*nanometer, 7*nanometer, 1e7*nanometer)
ff_cylinder = FormFactorCylinder(m_cylinder_height, m_cylinder_radius)
nano_particle = Particle(n_particle, ff_cylinder )
particle_collection = ParticleDecoration()
particle_collection.addParticle(nano_particle)
particle_collection.addInterferenceFunction(interference_funtion)
layer_with_particles = LayerDecorator(air_layer, particle_collection)
p_multi_layer = MultiLayer()
p_multi_layer.addLayer(layer_with_particles)
p_multi_layer.addLayer(middle_layer)
p_multi_layer.addLayer(substrate_layer)
return p_multi_layer
# ---------------------------------------------------------------
# defining SampleBuilder class which will build samples for us
#
# ---------------------------------------------------------------
class PythonSampleBuilder(ISampleBuilder):
def __init__(self):
ISampleBuilder.__init__(self)
print "MySampleBuilder ctor"
self.sample = ISample() # this should be the class variable to increment reference counter and hold object created in buildSample while C++ processes it
def buildSample(self):
self.sample = BuildSample(10, 5, 5)
return self.sample
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment