Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,16 @@ 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
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
copy %P%\Library\bin\mkl_intel_thread.2.dll dist\mstruct
- name: Archive distribution
uses: actions/upload-artifact@v4
with:
Expand All @@ -84,7 +86,7 @@ jobs:

build-and-test-linux:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- name: Checkout repository
Expand Down Expand Up @@ -125,6 +127,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:
Expand Down
57 changes: 49 additions & 8 deletions MStruct/libmstruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,22 @@ 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");
MStruct::PowderPattern &data = dynamic_cast<MStruct::PowderPattern&>(obj);
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<ObjCryst::Crystal&>(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,
Expand Down Expand Up @@ -239,8 +247,10 @@ BOOST_PYTHON_MODULE(libMStruct)
def("CreateCrystalFromXML", &_XMLLoadCrystal, return_value_policy<manage_new_object>());
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<reference_existing_object>());
def("GetPowderPattern", _gRefinableObjRegistry_GetPowderPattern, return_value_policy<reference_existing_object>());
def("GetCrystal", _gRefinableObjRegistry_GetCrystal, return_value_policy<reference_existing_object>());
def("GetPar", _GetParExtString, return_value_policy<reference_existing_object>());
def("CalcUnitCellMass", (REAL (*)(const ObjCryst::Crystal&)) &MStruct::CalcUnitCellMass, (bp::arg("crystal")));
//def("Create_ReflectionProfile", &_Create_ReflectionProfile);

class_<ObjCryst::Restraint, boost::noncopyable>("Restraint");
Expand Down Expand Up @@ -268,12 +278,36 @@ BOOST_PYTHON_MODULE(libMStruct)
return_value_policy<copy_const_reference>())
.def("PrepareForRefinement", &ObjCryst::RefinableObj::PrepareForRefinement)
.def("Print", &ObjCryst::RefinableObj::Print)
;

// Virtual
.def("GetClassName", &ObjCryst::RefinableObj::GetClassName,
&ObjCryst::RefinableObj::GetClassName,
return_value_policy<copy_const_reference>())
.def("GetName", &ObjCryst::RefinableObj::GetName,
&ObjCryst::RefinableObj::GetName,
return_value_policy<copy_const_reference>());

class_<ObjCryst::ScatteringData, bases<ObjCryst::RefinableObj>, boost::noncopyable>(
"ScatteringData", no_init)
.def("GetCrystal", (ObjCryst::Crystal& (ObjCryst::ScatteringData::*)()) &ObjCryst::ScatteringData::GetCrystal,
return_internal_reference<>())
.def("HasCrystal", &ObjCryst::ScatteringData::HasCrystal);

class_<ObjCryst::PowderPatternComponent, bases<ObjCryst::RefinableObj>, boost::noncopyable>
("_ObjCryst::PowderPatternComponent", no_init)
.def("GetParentPowderPattern",
(ObjCryst::PowderPattern& (ObjCryst::PowderPatternComponent::*)())
&ObjCryst::PowderPatternComponent::GetParentPowderPattern,
return_internal_reference<>());

class_<ObjCryst::PowderPatternDiffraction, bases<ObjCryst::PowderPatternComponent, ObjCryst::ScatteringData> >(
"_Obj_Cryst_PowderPatternDiffraction", no_init);

class_<MStruct::PowderPattern, bases<ObjCryst::RefinableObj> >("PowderPattern")
.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)
Expand All @@ -289,13 +323,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_<MStruct::PseudoVoigtBroadeningEffect>("PseudoVoigtBroadeningEffect")
.def(init<>())
.def("SetParentProfile", &_SetParentProfile<MStruct::PseudoVoigtBroadeningEffect, MStruct::ReflectionProfile>);

class_<ObjCryst::Crystal>("Crystal");
class_<ObjCryst::Crystal, bases<ObjCryst::RefinableObj> >("Crystal")
.def("GetVolume", (REAL (ObjCryst::Crystal::*) () const) &ObjCryst::Crystal::GetVolume);

//class_<ReflectionProfile, boost::noncopyable>("ReflectionProfile", no_init);
class_<MStruct::ReflectionProfile>("ReflectionProfile", init<ObjCryst::Crystal&, ObjCryst::Radiation&>())
Expand All @@ -315,8 +356,8 @@ BOOST_PYTHON_MODULE(libMStruct)
class_<ObjCryst::Radiation>("Radiation", init<const std::string, REAL>())
//.def("GetWavelength", &ObjCryst::Radiation::GetWavelength)
.def("Print", &ObjCryst::Radiation::Print);

class_<MStruct::PowderPatternDiffraction>("PowderPatternDiffraction")
class_<MStruct::PowderPatternDiffraction, bases<ObjCryst::PowderPatternDiffraction> >("PowderPatternDiffraction")
.def(init<>())
.def("SetProfile", &_SetProfile)
.def("SetIsIgnoringImagScattFact", &MStruct::PowderPatternDiffraction::SetIsIgnoringImagScattFact)
Expand Down
36 changes: 24 additions & 12 deletions SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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'])
Expand All @@ -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'
Expand All @@ -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'
Expand Down Expand Up @@ -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
Expand Down
28 changes: 14 additions & 14 deletions doc/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ 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 |
|:--------------- |:-------------:|:---------:|:---------:|
| native binaries | available | - | - |
| native source | ask authors | - | available |
| native binaries | available | - | available |
| native source | depricated | - | available |
| Anaconda | available | available | available |

<!--
| | Windows | MacOS | Linux |
| | Windows | macOS | Linux |
| native binaries | available | - | - |
| native source | ask authors | - | available |
| 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 :-)
Expand Down Expand Up @@ -83,7 +83,7 @@ git clone https://github.com/xray-group/mstruct.git
##### Installing Anaconda

[Anaconda](https://www.anaconda.com) is a popular Python data science platform and
scientific software for personal computers with Windows, MacOS or Linux.
scientific software for personal computers with Windows, macOS or Linux.

The most straighforward way is to get a graphical [installer](https://www.anaconda.com/download/)
- no need to sign (web download)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -262,18 +262,18 @@ tricks from Honza

```bash
# (optional) gls, fftw3, lapack, python and scons are required
sudo apt-get install libgsl-dev fftw3-dev liblapack-dev python-dev scons
sudo apt-get install libgsl-dev libfftw3-dev liblapack-dev libpython3.11-dev scons

# (optional) boost>=1.63 is required, we may want to use a specific one
export B=~/sw/boost_1_67_0
export CPPPATH=$B/include:$CPPPATH/
export B=~/sw/boost_1_78_0
export CPPPATH=$B/include:$CPPPATH
export LIBRARY_PATH=$B/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=$B/lib:$LD_LIBRARY_PATH

# (optional) prepare user env for installation (define prefix)
export P=~/.local
# (optional) make sure we have place for python modules
mkdir -p $P/lib/python2.7/site-packages
mkdir -p $P/lib/python3.11/site-packages

# build library
scons -j4 libmstruct
Expand All @@ -286,7 +286,7 @@ scons -j4 install prefix=$P

# (optional) we may want to activate the installation
export PATH=$P/bin:$PATH
export PYTHONPATH=$P/lib/python2.7/site-packages:$PYTHONATH
export PYTHONPATH=$P/lib/python3.11/site-packages:$PYTHONATH
export LD_LIBRARY_PATH=$P/lib:$LD_LIBRARY_PATH
```

Expand All @@ -313,7 +313,7 @@ links to plotting tools
### Instructions

You should have `mstruct` binary running on your laptop. It should be pretty straighforward
for Windows, unfortunately for MacOS or Linux you need to compile the source. *No stress in
for Windows, unfortunately for macOS or Linux you need to compile the source. *No stress in
case you fail, we will make it working at the beginning of the course.*

### Time plan
Expand Down
2 changes: 1 addition & 1 deletion libmstruct/SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -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.10"

#Adds option for selecting desired python version
AddOption('--python-version', dest='python_version', type='string', help="Python version to build libmstruct against."\
Expand Down