diff --git a/CMakeLists.txt b/CMakeLists.txt index 206b7bb..c7a7f85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ - cmake_minimum_required(VERSION 3.2.0) +cmake_minimum_required(VERSION 3.2.0) project(catima) ############ options ############# option(BUILD_SHARED_LIBS "build as shared library" ON) -option(PYTHON_MODULE "compile the Catima python module(requires numpy and cython installed)" OFF) +option(PYTHON_MODULE "compile the Catima python module(requires numpy and cython installed)" ON) option(TESTS "build tests" OFF) option(EXAMPLES "build examples" ON) option(APPS "build catima applications" ON) @@ -104,14 +104,14 @@ if(PYTHON_MODULE) if(NOT PYTHONINTERP_FOUND) MESSAGE(SEND_ERROR "Python is required to build nurex python modules") endif(NOT PYTHONINTERP_FOUND) - #find_package(pybind11 REQUIRED) - #set(PYBIND11_CPP_STANDARD -std=c++14) - #pybind11_add_module(pycatima pymodule/pycatima) - #target_include_directories(pycatima PUBLIC - # $ - # $ - # $) - #target_link_libraries(pycatima PRIVATE catima) + find_package(pybind11 REQUIRED) + set(PYBIND11_CPP_STANDARD -std=c++14) + pybind11_add_module(pycatima pymodule/pycatima) + target_include_directories(pycatima PUBLIC + $ + $ + $) + target_link_libraries(pycatima PRIVATE catima) find_program(CYTHON_EXECUTABLE NAMES cython cython2 cython3 cython.bat diff --git a/pymodule/pycatima.cpp b/pymodule/pycatima.cpp new file mode 100644 index 0000000..69536b2 --- /dev/null +++ b/pymodule/pycatima.cpp @@ -0,0 +1,252 @@ +#include +#include +#include +#include +#include +#include "catima/catima.h" +#include "catima/srim.h" +#include "catima/nucdata.h" +#include +namespace py = pybind11; +using namespace catima; + +void catima_info(){ + printf("CATIMA version = 1.5\n"); + printf("number of energy points = %d\n",max_datapoints); + printf("min energy point = 10^%lf MeV/u\n",logEmin); + printf("max energy point = 10^%lf MeV/u\n",logEmax); +} + +py::list storage_info(){ + py::list res; + for(int i=0; i0 && data.p.Z && data.m.ncomponents()>0){ + py::list mat; + for(int j=0; j0.0)m.density(density); + if(ipot>0.0)m.I(ipot); + if(mass>0.0)m.M(mass); + for(int i=0;i(); + int z = e[1].cast(); + double stn = e[2].cast(); + m.add_element(a,z,stn); + } + + return m; +} + +PYBIND11_MODULE(pycatima,m){ + py::class_(m,"Projectile") + .def(py::init<>(),"constructor") + .def(py::init(), "constructor", py::arg("A"),py::arg("Z"),py::arg("Q")=0, py::arg("T")=0) + .def("__call__",&Projectile::operator()) + .def("A",[](const Projectile& p){return p.A;}) + .def("Z",[](const Projectile& p){return p.Z;}) + .def("Q",[](const Projectile& p){return p.Q;}) + .def("T",[](const Projectile& p){return p.T;}) + .def("T",[](Projectile& p, double v){p.T = v;}); + //.def_readwrite("A", &Projectile::A) + //.def_readwrite("Z", &Projectile::Z) + //.def_readwrite("T", &Projectile::T) + //.def_readwrite("Q", &Projectile::Q); + + py::class_(m,"Material") + .def(py::init<>(),"constructor") + .def(py::init(&py_make_material),"constructor", py::arg("elements"),py::arg("density")=0.0,py::arg("i_potential")=0.0, py::arg("mass")=0.0) + .def("add_element",&Material::add_element) + .def("ncomponents",&Material::ncomponents) + .def("density",py::overload_cast<>(&Material::density, py::const_), "get density") + .def("density",py::overload_cast(&Material::density), "set density") + .def("molar_mass",py::overload_cast<>(&Material::M, py::const_), "get mass") + .def("thickness",py::overload_cast<>(&Material::thickness, py::const_), "get thickness") + .def("thickness",py::overload_cast(&Material::thickness), "set thickness") + .def("thickness_cm",&Material::thickness_cm,"set thickness in cm unit") + .def("I",py::overload_cast<>(&Material::I, py::const_), "get I") + .def("I",py::overload_cast(&Material::I), "set I"); + + py::class_(m,"Layers") + .def(py::init<>(),"constructor") + .def("add",&Layers::add) + .def("num",&Layers::num) + .def("__getitem__",&Layers::operator[], py::is_operator()) + .def("get",&Layers::operator[]) + .def(py::self + py::self); + + py::class_(m,"Result") + .def(py::init<>(),"constructor") + .def_readwrite("Ein", &Result::Ein) + .def_readwrite("Eout", &Result::Eout) + .def_readwrite("Eloss", &Result::Eloss) + .def_readwrite("range", &Result::range) + .def_readwrite("dEdxi", &Result::dEdxi) + .def_readwrite("dEdxo", &Result::dEdxo) + .def_readwrite("sigma_E", &Result::sigma_E) + .def_readwrite("sigma_a", &Result::sigma_a) + .def_readwrite("sigma_r", &Result::sigma_r) + .def_readwrite("tof", &Result::tof) + .def_readwrite("sp", &Result::sp) + .def("get_dict",[](const Result& r){ + py::dict d; + d["Ein"] = r.Ein; + d["Eout"] = r.Eout; + d["Eloss"] = r.Eloss; + d["range"] = r.range; + d["dEdxi"] = r.dEdxi; + d["dEdxo"] = r.dEdxo; + d["sigma_E"] = r.sigma_E; + d["sigma_r"] = r.sigma_r; + d["sigma_a"] = r.sigma_a; + d["tof"] = r.tof; + d["sp"] = r.sp; + return d; + }); + + py::class_(m,"MultiResult") + .def(py::init<>(),"constructor") + .def_readwrite("total_result", &MultiResult::total_result) + .def_readwrite("results", &MultiResult::results) + .def("getJSON",[](const MultiResult &r){ + py::dict d; + py::list p; + d["result"] = r.total_result; + for(auto& entry:r.results){ + p.append(py::cast(entry)); + } + d["partial"] = p; + return d; + }); + + py::enum_(m,"z_eff_type") + .value("none", z_eff_type::none) + .value("pierce_blann", z_eff_type::pierce_blann) + .value("anthony_landorf", z_eff_type::anthony_landorf) + .value("hubert", z_eff_type::hubert) + .value("winger", z_eff_type::winger) + .value("schiwietz", z_eff_type::schiwietz) + .value("global", z_eff_type::global) + .value("atima14", z_eff_type::atima14); + + py::enum_(m,"skip_calculation") + .value("skip_none", skip_calculation::skip_none) + .value("skip_tof", skip_calculation::skip_tof) + .value("skip_sigma_a", skip_calculation::skip_sigma_a) + .value("skip_sigma_r", skip_calculation::skip_sigma_r) + .value("skip_reactions", skip_calculation::skip_reactions); + + py::enum_(m,"corrections") + .value("no_barkas", corrections::no_barkas) + .value("no_lindhard", corrections::no_lindhard) + .value("no_shell_correction", corrections::no_shell_correction) + .value("no_highenergy", corrections::no_highenergy); + + py::enum_(m,"omega_types") + .value("atima", omega_types::atima) + .value("bohr", omega_types::bohr); + + py::enum_(m,"low_energy_types") + .value("srim_85", low_energy_types::srim_85) + .value("srim_95", low_energy_types::srim_95); + + py::enum_(m,"material") + .value("Plastics", material::Plastics) + .value("Air", material::Air) + .value("CH2", material::CH2) + .value("lH2", material::lH2) + .value("lD2", material::lD2) + .value("Water", material::Water) + .value("Diamond", material::Diamond) + .value("Glass", material::Glass) + .value("ALMG3", material::ALMG3) + .value("ArCO2_30", material::ArCO2_30) + .value("CF4", material::CF4) + .value("Isobutane", material::Isobutane) + .value("Kapton", material::Kapton) + .value("Mylar", material::Mylar) + .value("NaF", material::NaF) + .value("P10", material::P10) + .value("Polyolefin", material::Polyolefin) + .value("CmO2", material::CmO2) + .value("Suprasil", material::Suprasil) + .value("HAVAR", material::HAVAR) + .value("Steel", material::Steel) + .value("CO2", material::CO2); + + + py::class_(m,"Config") + .def(py::init<>(),"constructor") + .def_readwrite("z_effective", &Config::z_effective) + .def_readwrite("corrections", &Config::corrections) + .def_readwrite("calculation", &Config::calculation) + .def_readwrite("skip", &Config::skip) + .def("get",[](const Config &r){ + py::dict d; + d["z_effective"] = r.z_effective; + d["corrections"] = r.corrections; + d["calculation"] = r.calculation; + d["skip"] = r.skip; + return d; + }); + + m.def("srim_dedx_e",&srim_dedx_e); + m.def("sezi_dedx_e",&sezi_dedx_e, "sezi_dedx_e", py::arg("Projectile"), py::arg("Material"), py::arg("Config")=default_config); + m.def("calculate",py::overload_cast(&calculate),"calculate",py::arg("Projectile"), py::arg("Material"), py::arg("Config")=default_config); + m.def("dedx_from_range",py::overload_cast(&dedx_from_range),"calculate",py::arg("Projectile"), py::arg("energy") ,py::arg("Material"), py::arg("config")=default_config); + m.def("dedx_from_range",py::overload_cast&, const Material&, const Config&>(&dedx_from_range),"calculate",py::arg("Projectile"), py::arg("energy") ,py::arg("Material"), py::arg("config")=default_config); + //m.def("calculate",py::overload_cast(&calculate), "calculate",py::arg("Projectile"), py::arg("Material"), py::arg("energy"), py::arg("config")=default_config); + m.def("get_material",py::overload_cast(&get_material)); + m.def("get_data",py::overload_cast(get_data),"list of data",py::arg("projectile"),py::arg("material"),py::arg("Config")=default_config); + m.def("catima_info",&catima_info); + m.def("storage_info",&storage_info); + m.def("get_energy_table",&get_energy_table); + m.attr("max_datapoints") = max_datapoints; + m.attr("max_storage_data") = max_storage_data; + m.attr("logEmin")=logEmin; + m.attr("logEmax")=logEmax; +}