From 4c7df46c7c5baf12cba327939d335f5e24aa3f45 Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:03:09 +0100 Subject: [PATCH 01/16] Update index.md --- doc/source/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/index.md b/doc/source/index.md index 887481e..6d2af81 100644 --- a/doc/source/index.md +++ b/doc/source/index.md @@ -10,7 +10,7 @@ MStruct projects provides two main components: - **mstruct** program for powder diffraction data refinement - **python module** for either interactive or automated powder diffraction analysis -Windows, MacOS and Linux are all supported. However the level of intagration is varying. +Windows, macOS and Linux are all supported. However the level of intagration is varying. See the table below for a quick overview. | | Windows | macOS | Linux | @@ -20,7 +20,7 @@ See the table below for a quick overview. | Anaconda | available | available | available | In short: -- **Windows binaries** are small (few MBs), easy to download and run but you will - miss the Python module. Maybe you do not care. +- **Windows binaries** are small (few MBs), easy to download and run. - **Anaconda** is the most universal. You will get all MStruct features without limitations but you need to have Anaconda enviroment. Anaconda occupies around 2-3 GBs. However you may use it also for something else. You will need to compile MStruct yourself, short instructions are provided, we tested it but some issues are hard to exluclude with any effort (just try it). + There is a less demanding *Miniconda* alternative. - **Linux native compilation** will give you all features and will not use much space. Compilation process is similar to Anaconda. Use of Anaconda is still adviced mainly in order to protect your system against dirty MStruct features :-) From 29c2a04da99ba5d03994d5b44d8258e28d623ef0 Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:24:28 +0100 Subject: [PATCH 07/16] Update index.md --- doc/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/index.md b/doc/source/index.md index 6070fea..070208b 100644 --- a/doc/source/index.md +++ b/doc/source/index.md @@ -33,7 +33,7 @@ In short: 2-3 GBs. However you may use it also for something else. You will need to compile MStruct yourself, short instructions are provided, we tested it but some issues are hard to exluclude with any effort (just try it). - There is a less demanding *Miniconda* alternative. + There is a less demanding **Miniconda** alternative. - **Linux native compilation** will give you all features and will not use much space. Compilation process is similar to Anaconda. Use of Anaconda is still adviced mainly in order to protect your system against dirty MStruct features :-) From b1e62d4e97cf5ae62cad84af6f2ed7e30f6ff398 Mon Sep 17 00:00:00 2001 From: Zdenek Matej Date: Fri, 8 Mar 2024 02:23:29 +0100 Subject: [PATCH 08/16] Adding python methods for QPA --- MStruct/libmstruct.cpp | 55 ++++++++++++++++++++++++++++++++++++------ libmstruct/SConstruct | 2 +- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/MStruct/libmstruct.cpp b/MStruct/libmstruct.cpp index db9662e..4a19cb8 100755 --- a/MStruct/libmstruct.cpp +++ b/MStruct/libmstruct.cpp @@ -147,7 +147,7 @@ MStruct::ReflectionProfile * _Create_ReflectionProfile(ObjCryst::Crystal* crysta } */ -MStruct::PowderPattern& _gRefinableObjRegistry_GetPowderpattern(const std::string& name) +MStruct::PowderPattern& _gRefinableObjRegistry_GetPowderPattern(const std::string& name) { // Get PowderPattern object ObjCryst::RefinableObj &obj = ObjCryst::gRefinableObjRegistry.GetObj(name, "MStruct::PowderPattern"); @@ -155,6 +155,14 @@ MStruct::PowderPattern& _gRefinableObjRegistry_GetPowderpattern(const std::strin return data; } +ObjCryst::Crystal& _gRefinableObjRegistry_GetCrystal(const std::string& name) +{ + // Get Crystal object + ObjCryst::RefinableObj &obj = ObjCryst::gRefinableObjRegistry.GetObj(name, "Crystal"); + ObjCryst::Crystal &crystal = dynamic_cast(obj); + return crystal; +} + // credit: @vincefn, https://github.com/diffpy/pyobjcryst/blob/main/src/extensions/lsq_ext.cpp /*bool _LSQ_SafeRefine(MStruct::LSQNumObj & lsq, REAL maxChi2factor, int nbCycle, bool useLevenbergMarquardt, @@ -239,8 +247,10 @@ BOOST_PYTHON_MODULE(libMStruct) def("CreateCrystalFromXML", &_XMLLoadCrystal, return_value_policy()); def("XMLCrystFileLoadAllObject", (void (*)(const std::string&)) &MStruct::XMLCrystFileLoadAllObject, (bp::arg("name"))); def("XMLCrystFileSaveGlobal", (void (*)(const std::string&)) &ObjCryst::XMLCrystFileSaveGlobal, (bp::arg("name"))); - def("GetPowderPattern", _gRefinableObjRegistry_GetPowderpattern, return_value_policy()); + def("GetPowderPattern", _gRefinableObjRegistry_GetPowderPattern, return_value_policy()); + def("GetCrystal", _gRefinableObjRegistry_GetCrystal, return_value_policy()); def("GetPar", _GetParExtString, return_value_policy()); + def("CalcUnitCellMass", (REAL (*)(const ObjCryst::Crystal&)) &MStruct::CalcUnitCellMass, (bp::arg("crystal"))); //def("Create_ReflectionProfile", &_Create_ReflectionProfile); class_("Restraint"); @@ -268,8 +278,30 @@ BOOST_PYTHON_MODULE(libMStruct) return_value_policy()) .def("PrepareForRefinement", &ObjCryst::RefinableObj::PrepareForRefinement) .def("Print", &ObjCryst::RefinableObj::Print) - ; - + // Virtual + .def("GetClassName", &ObjCryst::RefinableObj::GetClassName, + &ObjCryst::RefinableObj::GetClassName, + return_value_policy()) + .def("GetName", &ObjCryst::RefinableObj::GetName, + &ObjCryst::RefinableObj::GetName, + return_value_policy()); + + class_, boost::noncopyable>( + "ScatteringData", no_init) + .def("GetCrystal", (ObjCryst::Crystal& (ObjCryst::ScatteringData::*)()) &ObjCryst::ScatteringData::GetCrystal, + return_internal_reference<>()) + .def("HasCrystal", &ObjCryst::ScatteringData::HasCrystal); + + class_, boost::noncopyable> + ("_ObjCryst::PowderPatternComponent", no_init) + .def("GetParentPowderPattern", + (ObjCryst::PowderPattern& (ObjCryst::PowderPatternComponent::*)()) + &ObjCryst::PowderPatternComponent::GetParentPowderPattern, + return_internal_reference<>()); + + class_ >( + "_Obj_Cryst_PowderPatternDiffraction", no_init); + class_ >("PowderPattern") .def(init<>()) .def("SetPowderPatternObs", &_SetPowderPatternObs) @@ -289,13 +321,20 @@ BOOST_PYTHON_MODULE(libMStruct) .def("Print", &MStruct::PowderPattern::Print) .def("AddComponent", &MStruct::PowderPattern::AddPowderPatternComponent) .def("AddComponent", &_AddPowderPatternComponent) - .def("FitScaleFactorForRw", &MStruct::PowderPattern::FitScaleFactorForRw); + .def("GetNbPowderPatternComponent", &ObjCryst::PowderPattern::GetNbPowderPatternComponent) + .def("GetPowderPatternComponent", (ObjCryst::PowderPatternComponent& (ObjCryst::PowderPattern::*) (const int)) + &ObjCryst::PowderPattern::GetPowderPatternComponent, return_internal_reference<>()) + .def("FitScaleFactorForRw", &MStruct::PowderPattern::FitScaleFactorForRw) + .def("GetScaleFactor", (REAL (MStruct::PowderPattern::*) (const int) const) &ObjCryst::PowderPattern::GetScaleFactor) + .def("GetScaleFactor", (REAL (MStruct::PowderPattern::*) (const ObjCryst::PowderPatternComponent&) const) &ObjCryst::PowderPattern::GetScaleFactor) + .def("SetScaleFactor", (void (MStruct::PowderPattern::*) (const int, REAL)) &ObjCryst::PowderPattern::SetScaleFactor); class_("PseudoVoigtBroadeningEffect") .def(init<>()) .def("SetParentProfile", &_SetParentProfile); - class_("Crystal"); + class_ >("Crystal") + .def("GetVolume", (REAL (ObjCryst::Crystal::*) () const) &ObjCryst::Crystal::GetVolume); //class_("ReflectionProfile", no_init); class_("ReflectionProfile", init()) @@ -315,8 +354,8 @@ BOOST_PYTHON_MODULE(libMStruct) class_("Radiation", init()) //.def("GetWavelength", &ObjCryst::Radiation::GetWavelength) .def("Print", &ObjCryst::Radiation::Print); - - class_("PowderPatternDiffraction") + + class_ >("PowderPatternDiffraction") .def(init<>()) .def("SetProfile", &_SetProfile) .def("SetIsIgnoringImagScattFact", &MStruct::PowderPatternDiffraction::SetIsIgnoringImagScattFact) diff --git a/libmstruct/SConstruct b/libmstruct/SConstruct index 4d392b7..4c75d18 100644 --- a/libmstruct/SConstruct +++ b/libmstruct/SConstruct @@ -42,7 +42,7 @@ env = DefaultEnvironment().Clone() # Variables definitions below work only with 0.98.1 or later. env.EnsureSConsVersion(0, 98, 1) -env['version_str'] = "0.15.8" +env['version_str'] = "0.15.9" #Adds option for selecting desired python version AddOption('--python-version', dest='python_version', type='string', help="Python version to build libmstruct against."\ From 1d2f45c7fab7a0ac6e4dc0f80912f89f36cd231f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Mat=C4=9Bj?= Date: Mon, 11 Mar 2024 23:21:26 +0100 Subject: [PATCH 09/16] fixing @rpath in *.dylib(s) and binaries --- SConscript | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/SConscript b/SConscript index 73da1f3..10248a3 100644 --- a/SConscript +++ b/SConscript @@ -47,6 +47,7 @@ if env['PLATFORM'] == 'darwin': env.Append(SHLINKFLAGS=['-install_name', '$TARGET.abspath']) env.AppendUnique(SHLINKFLAGS='-headerpad_max_install_names') env.AppendUnique(SHLINKFLAGS=['-undefined', 'dynamic_lookup']) + env.AppendUnique(LINKFLAGS=['-Wl,-rpath,@loader_path/../lib']) fast_linkflags[:] = [] # Compiler specific options @@ -180,6 +181,14 @@ libms = Alias('libmstruct', [libmstruct,] + env['libmstruct_includes']) #if env['PLATFORM'] != 'win32': # Depends(libmstruct, lib) +# Make sure we have @rpath/libObjCryst.dylib instead of an absolute path on Darwin +if env['PLATFORM'] == 'darwin': + for f in libmstruct: + if f.get_suffix()=='.dylib': + target_name = os.path.normpath( os.path.join('build', env['build']+'-'+env['HOST_ARCH'], f.rstr()) ) + env.AddPostAction(libmstruct, + 'install_name_tool -change `otool -L ' + target_name + ' | grep libObjCryst.dylib | tail -n1 | tr -d "\\t" | cut -f1 -d " "` @rpath/libObjCryst.dylib ' + target_name) + # This builds mstruct binary executable binmstruct = env.Program("mstruct_am", binmstructobjs, LIBS=binMStructlibs, LIBPATH=MStructlibpaths) binms = Alias('mstruct', [binmstruct,] + env['binmstruct_includes']) @@ -188,17 +197,20 @@ binms = Alias('mstruct', [binmstruct,] + env['binmstruct_includes']) binxmlmstruct = env.Program("mstruct_xml", binxmlmstructobjs, LIBS=binMStructlibs, LIBPATH=MStructlibpaths) binms_xml = Alias('mstruct_xml', [binxmlmstruct,] + env['binmstruct_includes']) +# Make sure we have @rpath/libObjCryst.dylib and @rpath/libMStruct.dylib in binaries +if env['PLATFORM'] == 'darwin': + for build_obj, name in zip([binmstruct, binxmlmstruct],['mstruct_am','mstruct_xml']): + target_name = os.path.normpath( os.path.join('build', env['build']+'-'+env['HOST_ARCH'], name) ) + for libname in ['libObjCryst.dylib']: + env.AddPostAction(build_obj, + 'install_name_tool -change `otool -L ' + target_name + ' | grep ' + libname + ' | tail -n1 | tr -d "\\t" | cut -f1 -d " "` @rpath/' + libname + ' ' + target_name) + # Installation targets. prefix = env['prefix'] # install-lib libinstall = env.Install(env['libdir'], libobjcryst) -if env['PLATFORM'] == 'darwin': - # DARWIN_INSTALL_NAME can be pre-set in sconscript.local - env.SetDefault(DARWIN_INSTALL_NAME='$TARGET.abspath') - env.AddPostAction(libinstall, - 'install_name_tool -id $DARWIN_INSTALL_NAME $TARGET') if env['PLATFORM'] == 'posix' and WhereIs('ldconfig'): opts = '' if os.getuid() != 0: opts = '-n' @@ -208,11 +220,6 @@ if env['PLATFORM'] != 'win32': libinstall = env.Install(env['libdir'], libmstruct+libobjcryst) else: libinstall = env.Install(env['libdir'], [f for f in libmstruct if f.get_suffix()=='.lib']) -if env['PLATFORM'] == 'darwin': - # DARWIN_INSTALL_NAME can be pre-set in sconscript.local - env.SetDefault(DARWIN_INSTALL_NAME='$TARGET.abspath') - env.AddPostAction(libinstall, - 'install_name_tool -id $DARWIN_INSTALL_NAME $TARGET') if env['PLATFORM'] == 'posix' and WhereIs('ldconfig'): opts = '' if os.getuid() != 0: opts = '-n' @@ -248,9 +255,14 @@ Alias('install-lib', libinstall + dllinstall) # install-bin if env['PLATFORM'] == 'win32': - bininstall = env.InstallAs(prefix+'/bin/mstruct.exe', binmstruct) + env.InstallAs(prefix+'/bin/mstruct_xml.exe', binxmlmstruct) + bininstall = env.InstallAs(prefix+'/bin/mstruct.exe', binmstruct) + env.InstallAs(prefix+'/bin/mstruct_xml.exe', binxmlmstruct) else: - bininstall = env.InstallAs(prefix+'/bin/mstruct', binmstruct) + env.InstallAs(prefix+'/bin/mstruct_xml', binxmlmstruct) + bininstall = env.InstallAs(prefix+'/bin/mstruct', binmstruct) + env.InstallAs(prefix+'/bin/mstruct_xml', binxmlmstruct) +if env['PLATFORM'] == 'darwin': + # DARWIN_INSTALL_NAME can be pre-set in sconscript.local + env.SetDefault(DARWIN_INSTALL_NAME='$TARGET.abspath') + env.AddPostAction(bininstall, + 'install_name_tool -id $DARWIN_INSTALL_NAME $TARGET') Alias('install-bin', bininstall) # install-python From c2123808a0d1c77f6eeda42b3be9a89966e14d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Mat=C4=9Bj?= Date: Sun, 17 Nov 2024 20:10:36 +0100 Subject: [PATCH 10/16] (pymstruct) exposing Powderpattern::SetSigmaToSqrtIobs and SetWeightToInvSigmaSq methods. --- MStruct/libmstruct.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MStruct/libmstruct.cpp b/MStruct/libmstruct.cpp index 4a19cb8..51f1a0a 100755 --- a/MStruct/libmstruct.cpp +++ b/MStruct/libmstruct.cpp @@ -306,6 +306,8 @@ BOOST_PYTHON_MODULE(libMStruct) .def(init<>()) .def("SetPowderPatternObs", &_SetPowderPatternObs) .def("SetWeightToUnit", &MStruct::PowderPattern::SetWeightToUnit) + .def("SetSigmaToSqrtIobs", &MStruct::PowderPattern::SetSigmaToSqrtIobs) + .def("SetWeightToInvSigmaSq", &MStruct::PowderPattern::SetWeightToInvSigmaSq) .def("Prepare", &MStruct::PowderPattern::Prepare) .def("SetObsToZero", &_PowderPattern_SetObsToZero) .def("SavePowderPattern", &_SavePowderPattern) From 89898175803631caa4a869609ce28f0fd71744f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Mat=C4=9Bj?= Date: Sun, 17 Nov 2024 20:25:01 +0100 Subject: [PATCH 11/16] update version --- libmstruct/SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmstruct/SConstruct b/libmstruct/SConstruct index 4c75d18..d87a11a 100644 --- a/libmstruct/SConstruct +++ b/libmstruct/SConstruct @@ -42,7 +42,7 @@ env = DefaultEnvironment().Clone() # Variables definitions below work only with 0.98.1 or later. env.EnsureSConsVersion(0, 98, 1) -env['version_str'] = "0.15.9" +env['version_str'] = "0.15.10" #Adds option for selecting desired python version AddOption('--python-version', dest='python_version', type='string', help="Python version to build libmstruct against."\ From 087d52f0163a6f924a394727b94ba8330eeca7ea Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Sun, 31 Aug 2025 23:02:44 +0200 Subject: [PATCH 12/16] Update build.yml: libgsl-*.dll --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7142b24..fe98a18 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,7 +68,7 @@ jobs: copy %P%\Library\bin\mstruct.exe dist\mstruct copy %P%\Library\bin\mstruct_xml.exe dist\mstruct copy %P%\Library\bin\fftw3.dll dist\mstruct - copy %P%\Library\bin\gsl-25.dll dist\mstruct + copy %P%\Library\bin\gsl-*.dll dist\mstruct copy %P%\Library\bin\libcblas.dll dist\mstruct copy %P%\Library\bin\zlib.dll dist\mstruct copy %P%\Library\bin\boost_python311.dll dist\mstruct From ade9de9b1859163643604c03e669ed5fe53af83e Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Sun, 31 Aug 2025 23:24:33 +0200 Subject: [PATCH 13/16] Update build.yml: mkl_rt*.dll --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe98a18..ca10347 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -73,6 +73,7 @@ jobs: copy %P%\Library\bin\zlib.dll dist\mstruct copy %P%\Library\bin\boost_python311.dll dist\mstruct copy %P%\Library\bin\boost_numpy311.dll dist\mstruct + copy %P%\Library\bin\mkl_rt*.dll dist\mstruct copy %P%\Library\bin\boost_program_options.dll dist\mstruct copy %P%\Library\bin\boost_date_time.dll dist\mstruct copy %P%\Library\bin\libMStruct.dll dist\mstruct\libMStruct.pyd From a82d0665bf49d5578bb29f150e22543c5633a5a2 Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Wed, 3 Sep 2025 16:58:32 +0200 Subject: [PATCH 14/16] Update build.yml: linux distribution --- .github/workflows/build.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca10347..2da03ac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,7 +85,7 @@ jobs: build-and-test-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout repository @@ -126,6 +126,13 @@ jobs: cp $P/bin/mstruct_xml dist/mstruct cp $P/lib/libMStruct.so dist/mstruct cp $P/lib/libObjCryst.so dist/mstruct + cp $P/lib/libfftw3.so.3 dist/mstruct + cp $P/lib/libgsl.so.28 dist/mstruct + cp $P/lib/libcblas.so.3 dist/mstruct + cp $P/lib/libmkl_rt.so.2 dist/mstruct + cp $P/lib/libboost_python311.so.1.78.0 dist/mstruct + cp $P/lib/libboost_numpy311.so.1.78.0 dist/mstruct + cp $P/lib/libboost_program_options.so.1.78.0 dist/mstruct - name: Archive distribution uses: actions/upload-artifact@v4 with: From eae6ae2a716641c7940a71078bd37961c1709741 Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Sat, 6 Sep 2025 11:41:51 +0200 Subject: [PATCH 15/16] Update build.yml: adding mkl_intel_thread.dll --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2da03ac..4df5ee3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,6 +77,7 @@ jobs: copy %P%\Library\bin\boost_program_options.dll dist\mstruct copy %P%\Library\bin\boost_date_time.dll dist\mstruct copy %P%\Library\bin\libMStruct.dll dist\mstruct\libMStruct.pyd + copy %P%\Library\bin\mkl_intel_thread.2.dll dist\mstruct - name: Archive distribution uses: actions/upload-artifact@v4 with: From 5b799f56b33d0293b6a737752ee57bfa2dfd0f9f Mon Sep 17 00:00:00 2001 From: Zdenek <32390711+zdemat@users.noreply.github.com> Date: Sun, 7 Sep 2025 19:03:30 +0200 Subject: [PATCH 16/16] Update index.md: minor update (win) --- doc/source/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/index.md b/doc/source/index.md index 070208b..6a60246 100644 --- a/doc/source/index.md +++ b/doc/source/index.md @@ -117,7 +117,7 @@ For Windows **Python3 (x64) is strongly adviced!** # add 'conda-forge' channel conda config --add channels conda-forge # install required packages -conda install python=3.11 boost=1.78 lapack fftw gsl scons bzip2 git blas=*=*mkl +conda install python=3.11 boost=1.78 lapack fftw gsl scons bzip2 git blas=*=*mkl gcc gxx # git clone or download ZIP # git clone https://github.com/xray-group/mstruct.git