From b060cf4e2d058a958185595c70c3fa85946df23b Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Mon, 14 Dec 2020 18:42:27 +0100 Subject: [PATCH] new Py fcts run_and_plot, save_and_plot to make examples and checks a bit simpler --- Core/Export/ExportToPython.cpp | 13 +++- Core/Export/ExportToPython.h | 5 +- Core/Export/SampleToPython.cpp | 2 +- Core/Export/SampleToPython.h | 2 +- Core/Export/SimulationToPython.cpp | 26 +++++-- Core/Export/SimulationToPython.h | 6 +- .../Views/InfoWidgets/PySampleWidget.cpp | 2 +- .../SimulationWidgets/PythonScriptWidget.cpp | 2 +- Tests/Functional/Python/PyEmbedded/Tests.cpp | 4 +- Tests/Functional/Python/Std/Check.cpp | 13 ++-- Wrap/Python/plot_utils.py | 4 + auto/Wrap/doxygenCore.i | 18 +++-- auto/Wrap/libBornAgainCore.py | 24 ++++-- auto/Wrap/libBornAgainCore_wrap.cpp | 73 +++++++++++++++---- 14 files changed, 138 insertions(+), 56 deletions(-) diff --git a/Core/Export/ExportToPython.cpp b/Core/Export/ExportToPython.cpp index 6a408a8cc13..d83fc6daa4f 100644 --- a/Core/Export/ExportToPython.cpp +++ b/Core/Export/ExportToPython.cpp @@ -17,10 +17,15 @@ #include "Core/Export/SimulationToPython.h" #include "Core/Simulation/ISimulation.h" -std::string ExportToPython::generateSampleCode(const MultiLayer& multilayer) { - return SampleToPython().generateSampleCode(multilayer); +std::string ExportToPython::sampleCode(const MultiLayer& multilayer) { + return SampleToPython().sampleCode(multilayer); } -std::string ExportToPython::generateSimulationCode(const ISimulation& simulation) { - return SimulationToPython().generateSimulationCode(simulation); +std::string ExportToPython::simulationPlotCode(const ISimulation& simulation) { + return SimulationToPython().simulationPlotCode(simulation); +} + +std::string ExportToPython::simulationSaveCode(const ISimulation& simulation, + const std::string& fname) { + return SimulationToPython().simulationSaveCode(simulation, fname); } diff --git a/Core/Export/ExportToPython.h b/Core/Export/ExportToPython.h index 85613516249..ae93fb101ab 100644 --- a/Core/Export/ExportToPython.h +++ b/Core/Export/ExportToPython.h @@ -24,8 +24,9 @@ class ISimulation; namespace ExportToPython { -std::string generateSampleCode(const MultiLayer& multilayer); -std::string generateSimulationCode(const ISimulation& simulation); +std::string sampleCode(const MultiLayer& multilayer); +std::string simulationPlotCode(const ISimulation& simulation); +std::string simulationSaveCode(const ISimulation& simulation, const std::string& fname); } // namespace ExportToPython diff --git a/Core/Export/SampleToPython.cpp b/Core/Export/SampleToPython.cpp index 0c1b6060675..87cae21c9d0 100644 --- a/Core/Export/SampleToPython.cpp +++ b/Core/Export/SampleToPython.cpp @@ -93,7 +93,7 @@ void setPositionInformation(const IParticle* particle, std::string name, // class SampleToPython // ************************************************************************************************ -std::string SampleToPython::generateSampleCode(const MultiLayer& multilayer) { +std::string SampleToPython::sampleCode(const MultiLayer& multilayer) { initLabels(multilayer); return defineGetSample(); } diff --git a/Core/Export/SampleToPython.h b/Core/Export/SampleToPython.h index b195d0bb025..01d0adcb758 100644 --- a/Core/Export/SampleToPython.h +++ b/Core/Export/SampleToPython.h @@ -35,7 +35,7 @@ public: SampleToPython(); ~SampleToPython(); - std::string generateSampleCode(const MultiLayer& multilayer); + std::string sampleCode(const MultiLayer& multilayer); private: void initLabels(const MultiLayer& multilayer); diff --git a/Core/Export/SimulationToPython.cpp b/Core/Export/SimulationToPython.cpp index 11ca322921a..2f20a2d9876 100644 --- a/Core/Export/SimulationToPython.cpp +++ b/Core/Export/SimulationToPython.cpp @@ -438,9 +438,13 @@ std::string defineSimulate(const ISimulation* simulation) { return result.str(); } -const std::string defineMain = - "if __name__ == '__main__':\n" - " ba.run_and_plot(get_simulation(get_sample()))\n"; + +std::string simulationCode(const ISimulation& simulation) { + if (simulation.sample() == nullptr) + throw std::runtime_error("Cannot export: Simulation has no sample"); + return pyfmt::scriptPreamble() + SampleToPython().sampleCode(*simulation.sample()) + + defineSimulate(&simulation); +} } // namespace @@ -448,9 +452,15 @@ const std::string defineMain = // class SimulationToPython // ************************************************************************************************ -std::string SimulationToPython::generateSimulationCode(const ISimulation& simulation) { - if (simulation.sample() == nullptr) - throw std::runtime_error("Cannot export: Simulation has no sample"); - return pyfmt::scriptPreamble() + SampleToPython().generateSampleCode(*simulation.sample()) - + defineSimulate(&simulation) + defineMain; +std::string SimulationToPython::simulationPlotCode(const ISimulation& simulation) { + return simulationCode(simulation) + + "if __name__ == '__main__':\n" + " ba.run_and_plot(get_simulation(get_sample()))\n"; +} + +std::string SimulationToPython::simulationSaveCode( + const ISimulation& simulation, const std::string& fname) { + return simulationCode(simulation) + + "if __name__ == '__main__':\n" + " ba.run_and_save(get_simulation(get_sample()), \"" + fname + "\")\n"; } diff --git a/Core/Export/SimulationToPython.h b/Core/Export/SimulationToPython.h index 2110dc202a2..73f77402951 100644 --- a/Core/Export/SimulationToPython.h +++ b/Core/Export/SimulationToPython.h @@ -28,8 +28,10 @@ class ISimulation; class SimulationToPython { public: - //! Returns a Python script that sets up a simulation and runs it if invoked as main program. - std::string generateSimulationCode(const ISimulation& simulation); + //! Returns a Python script that runs a simulation and plots the result + std::string simulationPlotCode(const ISimulation& simulation); + //! Returns a Python script that runs a simulation and saves the result to a file + std::string simulationSaveCode(const ISimulation& simulation, const std::string& fname); }; #endif // BORNAGAIN_CORE_EXPORT_SIMULATIONTOPYTHON_H diff --git a/GUI/coregui/Views/InfoWidgets/PySampleWidget.cpp b/GUI/coregui/Views/InfoWidgets/PySampleWidget.cpp index 0d489d39b2a..da430e81926 100644 --- a/GUI/coregui/Views/InfoWidgets/PySampleWidget.cpp +++ b/GUI/coregui/Views/InfoWidgets/PySampleWidget.cpp @@ -142,7 +142,7 @@ QString PySampleWidget::generateCodeSnippet() { auto multilayer = DomainObjectBuilder::buildMultiLayer(*sampleItem); if (!result.isEmpty()) result.append("\n"); - result.append(QString::fromStdString(ExportToPython::generateSampleCode(*multilayer))); + result.append(QString::fromStdString(ExportToPython::sampleCode(*multilayer))); } catch (const std::exception& ex) { QString message = QString("Generation of Python Script failed. Code is not complete.\n\n" diff --git a/GUI/coregui/Views/SimulationWidgets/PythonScriptWidget.cpp b/GUI/coregui/Views/SimulationWidgets/PythonScriptWidget.cpp index a03ac81497c..c156a52921c 100644 --- a/GUI/coregui/Views/SimulationWidgets/PythonScriptWidget.cpp +++ b/GUI/coregui/Views/SimulationWidgets/PythonScriptWidget.cpp @@ -88,7 +88,7 @@ void PythonScriptWidget::generatePythonScript(const MultiLayerItem* sampleItem, const auto simulation = DomainSimulationBuilder::createSimulation(sampleItem, instrumentItem, optionItem); - QString code = QString::fromStdString(ExportToPython::generateSimulationCode(*simulation)); + QString code = QString::fromStdString(ExportToPython::simulationPlotCode(*simulation)); m_textEdit->clear(); m_textEdit->setText(code); diff --git a/Tests/Functional/Python/PyEmbedded/Tests.cpp b/Tests/Functional/Python/PyEmbedded/Tests.cpp index 3347bea4e77..09b944e020f 100644 --- a/Tests/Functional/Python/PyEmbedded/Tests.cpp +++ b/Tests/Functional/Python/PyEmbedded/Tests.cpp @@ -362,14 +362,14 @@ TEST_F(PyEmbedded, ExportToPythonAndBack) { SampleBuilderFactory factory; std::unique_ptr<MultiLayer> sample(factory.createSampleByName("CylindersAndPrismsBuilder")); - auto code = ExportToPython::generateSampleCode(*sample); + auto code = ExportToPython::sampleCode(*sample); std::stringstream snippet; snippet << pyfmt::scriptPreamble() << code; auto multilayer = PyImport::createFromPython(snippet.str(), "get_sample", BABuild::buildLibDir()); - auto new_code = ExportToPython::generateSampleCode(*multilayer); + auto new_code = ExportToPython::sampleCode(*multilayer); EXPECT_TRUE(code == new_code); } diff --git a/Tests/Functional/Python/Std/Check.cpp b/Tests/Functional/Python/Std/Check.cpp index f593da72305..f7bbe28304c 100644 --- a/Tests/Functional/Python/Std/Check.cpp +++ b/Tests/Functional/Python/Std/Check.cpp @@ -33,23 +33,22 @@ std::unique_ptr<OutputData<double>> domainData(const std::string& test_name, std::cout << "- removed old output " << output_path << std::endl; // Generate Python script - const std::string pyscript_filename = + const std::string pyscript = FileSystemUtils::jointPath(BATesting::TestOutDir_PyStd(), test_name + ".py"); - std::ofstream f(pyscript_filename); - f << ExportToPython::generateSimulationCode(direct_simulation); + std::ofstream f(pyscript); + f << ExportToPython::simulationSaveCode(direct_simulation, output_path); f.close(); - std::cout << "- wrote Python script " << pyscript_filename << std::endl; + std::cout << "- wrote Python script " << pyscript << std::endl; // Run Python script - const std::string py_command = pyscript_filename + " " + output_path; #ifndef _WIN32 const std::string sys_command = std::string("PYTHONPATH=") + BABuild::buildLibDir() + " " + std::string("NOSHOW=TRUE") + " " + BABuild::pythonExecutable() - + " -B " + py_command; + + " -B " + pyscript; #else const std::string sys_command = std::string("set PYTHONPATH=") + BABuild::buildLibDir() + " & " + std::string("set NOSHOW=TRUE") + " & \"" - + BABuild::pythonExecutable() + "\" -B " + py_command; + + BABuild::pythonExecutable() + "\" -B " + pyscript; #endif std::cout << "- system call: " << sys_command << std::endl; int err = std::system(sys_command.c_str()); diff --git a/Wrap/Python/plot_utils.py b/Wrap/Python/plot_utils.py index dab5dcabc32..2cf3c73e9f0 100644 --- a/Wrap/Python/plot_utils.py +++ b/Wrap/Python/plot_utils.py @@ -219,3 +219,7 @@ def plot_simulation_result(result, **kwargs): def run_and_plot(simulation, **kwargs): simulation.runSimulation() plot_simulation_result(simulation.result(), **kwargs) + +def run_and_save(simulation, fname): + simulation.runSimulation() + ba.IntensityDataIOFactory.writeSimulationResult(simulation.result(), fname) diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i index f36d5b93012..afa3f4f9c1f 100644 --- a/auto/Wrap/doxygenCore.i +++ b/auto/Wrap/doxygenCore.i @@ -1851,7 +1851,7 @@ C++ includes: SampleToPython.h %feature("docstring") SampleToPython::~SampleToPython "SampleToPython::~SampleToPython() "; -%feature("docstring") SampleToPython::generateSampleCode "std::string SampleToPython::generateSampleCode(const MultiLayer &multilayer) +%feature("docstring") SampleToPython::sampleCode "std::string SampleToPython::sampleCode(const MultiLayer &multilayer) "; @@ -1959,9 +1959,14 @@ Write a Python script that allows to run the current simulation. C++ includes: SimulationToPython.h "; -%feature("docstring") SimulationToPython::generateSimulationCode "std::string SimulationToPython::generateSimulationCode(const ISimulation &simulation) +%feature("docstring") SimulationToPython::simulationPlotCode "std::string SimulationToPython::simulationPlotCode(const ISimulation &simulation) -Returns a Python script that sets up a simulation and runs it if invoked as main program. +Returns a Python script that runs a simulation and plots the result. +"; + +%feature("docstring") SimulationToPython::simulationSaveCode "std::string SimulationToPython::simulationSaveCode(const ISimulation &simulation, const std::string &fname) + +Returns a Python script that runs a simulation and saves the result to a file. "; @@ -2323,10 +2328,13 @@ C++ includes: VarianceFunctions.h // File: namespaceExportToPython.xml -%feature("docstring") ExportToPython::generateSampleCode "std::string ExportToPython::generateSampleCode(const MultiLayer &multilayer) +%feature("docstring") ExportToPython::sampleCode "std::string ExportToPython::sampleCode(const MultiLayer &multilayer) +"; + +%feature("docstring") ExportToPython::simulationPlotCode "std::string ExportToPython::simulationPlotCode(const ISimulation &simulation) "; -%feature("docstring") ExportToPython::generateSimulationCode "std::string ExportToPython::generateSimulationCode(const ISimulation &simulation) +%feature("docstring") ExportToPython::simulationSaveCode "std::string ExportToPython::simulationSaveCode(const ISimulation &simulation, const std::string &fname) "; diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py index cacedc49857..cfecc37f6fe 100644 --- a/auto/Wrap/libBornAgainCore.py +++ b/auto/Wrap/libBornAgainCore.py @@ -4337,21 +4337,29 @@ class PoissonNoiseBackground(IBackground): _libBornAgainCore.PoissonNoiseBackground_swigregister(PoissonNoiseBackground) -def generateSampleCode(multilayer): +def sampleCode(multilayer): r""" - generateSampleCode(MultiLayer const & multilayer) -> std::string - std::string ExportToPython::generateSampleCode(const MultiLayer &multilayer) + sampleCode(MultiLayer const & multilayer) -> std::string + std::string ExportToPython::sampleCode(const MultiLayer &multilayer) """ - return _libBornAgainCore.generateSampleCode(multilayer) + return _libBornAgainCore.sampleCode(multilayer) -def generateSimulationCode(simulation): +def simulationPlotCode(simulation): r""" - generateSimulationCode(ISimulation simulation) -> std::string - std::string ExportToPython::generateSimulationCode(const ISimulation &simulation) + simulationPlotCode(ISimulation simulation) -> std::string + std::string ExportToPython::simulationPlotCode(const ISimulation &simulation) """ - return _libBornAgainCore.generateSimulationCode(simulation) + return _libBornAgainCore.simulationPlotCode(simulation) + +def simulationSaveCode(simulation, fname): + r""" + simulationSaveCode(ISimulation simulation, std::string const & fname) -> std::string + std::string ExportToPython::simulationSaveCode(const ISimulation &simulation, const std::string &fname) + + """ + return _libBornAgainCore.simulationSaveCode(simulation, fname) class IIntensityFunction(object): r""" diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp index fca69001c51..7adfb9bbec2 100644 --- a/auto/Wrap/libBornAgainCore_wrap.cpp +++ b/auto/Wrap/libBornAgainCore_wrap.cpp @@ -42125,7 +42125,7 @@ SWIGINTERN PyObject *PoissonNoiseBackground_swiginit(PyObject *SWIGUNUSEDPARM(se return SWIG_Python_InitShadowInstance(args); } -SWIGINTERN PyObject *_wrap_generateSampleCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_sampleCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; MultiLayer *arg1 = 0 ; void *argp1 = 0 ; @@ -42137,13 +42137,13 @@ SWIGINTERN PyObject *_wrap_generateSampleCode(PyObject *SWIGUNUSEDPARM(self), Py swig_obj[0] = args; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_MultiLayer, 0 | 0); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "generateSampleCode" "', argument " "1"" of type '" "MultiLayer const &""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "sampleCode" "', argument " "1"" of type '" "MultiLayer const &""'"); } if (!argp1) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "generateSampleCode" "', argument " "1"" of type '" "MultiLayer const &""'"); + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "sampleCode" "', argument " "1"" of type '" "MultiLayer const &""'"); } arg1 = reinterpret_cast< MultiLayer * >(argp1); - result = ExportToPython::generateSampleCode((MultiLayer const &)*arg1); + result = ExportToPython::sampleCode((MultiLayer const &)*arg1); resultobj = SWIG_From_std_string(static_cast< std::string >(result)); return resultobj; fail: @@ -42151,7 +42151,7 @@ fail: } -SWIGINTERN PyObject *_wrap_generateSimulationCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_simulationPlotCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; ISimulation *arg1 = 0 ; void *argp1 = 0 ; @@ -42163,13 +42163,13 @@ SWIGINTERN PyObject *_wrap_generateSimulationCode(PyObject *SWIGUNUSEDPARM(self) swig_obj[0] = args; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_ISimulation, 0 | 0); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "generateSimulationCode" "', argument " "1"" of type '" "ISimulation const &""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "simulationPlotCode" "', argument " "1"" of type '" "ISimulation const &""'"); } if (!argp1) { - SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "generateSimulationCode" "', argument " "1"" of type '" "ISimulation const &""'"); + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "simulationPlotCode" "', argument " "1"" of type '" "ISimulation const &""'"); } arg1 = reinterpret_cast< ISimulation * >(argp1); - result = ExportToPython::generateSimulationCode((ISimulation const &)*arg1); + result = ExportToPython::simulationPlotCode((ISimulation const &)*arg1); resultobj = SWIG_From_std_string(static_cast< std::string >(result)); return resultobj; fail: @@ -42177,6 +42177,46 @@ fail: } +SWIGINTERN PyObject *_wrap_simulationSaveCode(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + ISimulation *arg1 = 0 ; + std::string *arg2 = 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 = SWIG_OLDOBJ ; + PyObject *swig_obj[2] ; + std::string result; + + if (!SWIG_Python_UnpackTuple(args, "simulationSaveCode", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_ISimulation, 0 | 0); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "simulationSaveCode" "', argument " "1"" of type '" "ISimulation const &""'"); + } + if (!argp1) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "simulationSaveCode" "', argument " "1"" of type '" "ISimulation const &""'"); + } + arg1 = reinterpret_cast< ISimulation * >(argp1); + { + std::string *ptr = (std::string *)0; + res2 = SWIG_AsPtr_std_string(swig_obj[1], &ptr); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "simulationSaveCode" "', argument " "2"" of type '" "std::string const &""'"); + } + if (!ptr) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "simulationSaveCode" "', argument " "2"" of type '" "std::string const &""'"); + } + arg2 = ptr; + } + result = ExportToPython::simulationSaveCode((ISimulation const &)*arg1,(std::string const &)*arg2); + resultobj = SWIG_From_std_string(static_cast< std::string >(result)); + if (SWIG_IsNewObj(res2)) delete arg2; + return resultobj; +fail: + if (SWIG_IsNewObj(res2)) delete arg2; + return NULL; +} + + SWIGINTERN PyObject *_wrap_delete_IIntensityFunction(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; IIntensityFunction *arg1 = (IIntensityFunction *) 0 ; @@ -45056,14 +45096,19 @@ static PyMethodDef SwigMethods[] = { { "delete_PoissonNoiseBackground", _wrap_delete_PoissonNoiseBackground, METH_O, "delete_PoissonNoiseBackground(PoissonNoiseBackground self)"}, { "PoissonNoiseBackground_swigregister", PoissonNoiseBackground_swigregister, METH_O, NULL}, { "PoissonNoiseBackground_swiginit", PoissonNoiseBackground_swiginit, METH_VARARGS, NULL}, - { "generateSampleCode", _wrap_generateSampleCode, METH_O, "\n" - "generateSampleCode(MultiLayer const & multilayer) -> std::string\n" - "std::string ExportToPython::generateSampleCode(const MultiLayer &multilayer)\n" + { "sampleCode", _wrap_sampleCode, METH_O, "\n" + "sampleCode(MultiLayer const & multilayer) -> std::string\n" + "std::string ExportToPython::sampleCode(const MultiLayer &multilayer)\n" + "\n" + ""}, + { "simulationPlotCode", _wrap_simulationPlotCode, METH_O, "\n" + "simulationPlotCode(ISimulation simulation) -> std::string\n" + "std::string ExportToPython::simulationPlotCode(const ISimulation &simulation)\n" "\n" ""}, - { "generateSimulationCode", _wrap_generateSimulationCode, METH_O, "\n" - "generateSimulationCode(ISimulation simulation) -> std::string\n" - "std::string ExportToPython::generateSimulationCode(const ISimulation &simulation)\n" + { "simulationSaveCode", _wrap_simulationSaveCode, METH_VARARGS, "\n" + "simulationSaveCode(ISimulation simulation, std::string const & fname) -> std::string\n" + "std::string ExportToPython::simulationSaveCode(const ISimulation &simulation, const std::string &fname)\n" "\n" ""}, { "delete_IIntensityFunction", _wrap_delete_IIntensityFunction, METH_O, "\n" -- GitLab