Skip to content

Commit 2527fad

Browse files
authored
Merge pull request #25 from vincefn/master
Update pyobjcryst
2 parents 335af6c + e29c49b commit 2527fad

14 files changed

+3634
-1142
lines changed

examples/cimetidine-structure-solution-powder.ipynb

+512-1,032
Large diffs are not rendered by default.

examples/crystal_3d_widget.ipynb

+191-40
Large diffs are not rendered by default.

examples/structure-solution-multiprocessing.ipynb

+2,560
Large diffs are not rendered by default.

src/extensions/molatom_ext.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,6 @@ void wrap_molatom()
9090
.add_property("Occupancy", &MolAtom::GetOccupancy,
9191
&MolAtom::SetOccupancy)
9292
.def("__str__", &__str__)
93+
.def("int_ptr", &MolAtom::int_ptr)
9394
;
9495
}

src/extensions/molbond_ext.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,6 @@ void wrap_molbond()
103103
&MolBond::SetBondOrder)
104104
.def("__getitem__", &_GetAtom,
105105
return_internal_reference<>())
106+
.def("int_ptr", &MolBond::int_ptr)
106107
;
107108
}

src/extensions/molbondangle_ext.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,6 @@ void wrap_molbondangle()
110110
// Iterate other the atoms involved
111111
.def("__iter__", range<return_value_policy<reference_existing_object> >
112112
(&MolBondAngle::begin, &MolBondAngle::end))
113+
.def("int_ptr", &MolBondAngle::int_ptr)
113114
;
114115
}

src/extensions/moldihedralangle_ext.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,6 @@ void wrap_moldihedralangle()
113113
// Iterate other the atoms involved
114114
.def("__iter__", range<return_value_policy<reference_existing_object> >
115115
(&MolDihedralAngle::begin, &MolDihedralAngle::end))
116+
.def("int_ptr", &MolDihedralAngle::int_ptr)
116117
;
117118
}

src/extensions/refinableobj_ext.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <boost/python/copy_const_reference.hpp>
3838

3939
#include <string>
40+
#include <sstream>
4041
#include <map>
4142

4243
#include <ObjCryst/RefinableObj/RefinableObj.h>
@@ -404,6 +405,15 @@ void _XMLInput(
404405
in.sync();
405406
}
406407

408+
void _XMLInputString(RefinableObj& r, const string& s)
409+
{
410+
stringstream ss(s);
411+
ss.imbue(std::locale::classic());
412+
XMLCrystTag tag;
413+
ss>>tag;
414+
r.XMLInput(ss, tag);
415+
}
416+
407417
} // anonymous namespace
408418

409419

@@ -555,6 +565,7 @@ void wrap_refinableobj()
555565
.def("XMLInput", &_XMLInput, (bp::arg("file"), bp::arg("tag")))
556566
.def("XMLInput", &RefinableObj::XMLInput,
557567
&RefinableObjWrap::default_XMLInput)
568+
.def("XMLInput", &_XMLInputString, (bp::arg("xml")))
558569
.def("GetGeneGroup", &RefinableObj::GetGeneGroup,
559570
&RefinableObjWrap::default_GetGeneGroup)
560571
.def("UpdateDisplay", &RefinableObj::UpdateDisplay,
@@ -563,6 +574,7 @@ void wrap_refinableobj()
563574
&RefinableObjWrap::default_GetRestraintCost)
564575
.def("TagNewBestConfig", &RefinableObj::TagNewBestConfig,
565576
&RefinableObjWrap::default_TagNewBestConfig)
577+
.def("int_ptr", &RefinableObj::int_ptr)
566578
// Additional methods for python only
567579
.def("__str__", &__str__<RefinableObj>)
568580
;

src/extensions/rigidgroup_ext.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ void wrap_rigidgroup()
4444
class_<RigidGroup, bases<MolAtomSet> >("RigidGroup")
4545
.def(init<const RigidGroup&>())
4646
.def("GetName", &RigidGroup::GetName)
47+
.def("int_ptr", &RigidGroup::int_ptr)
4748
;
4849
}

src/pyobjcryst/crystal.py

+266-32
Large diffs are not rendered by default.

src/pyobjcryst/globaloptim.py

+62-25
Original file line numberDiff line numberDiff line change
@@ -20,47 +20,84 @@
2020
"""
2121
__all__ = ["MonteCarlo", "AnnealingSchedule", "GlobalOptimType"]
2222

23+
import warnings
24+
try:
25+
import ipywidgets as widgets
26+
except ImportError:
27+
widgets = None
2328
from pyobjcryst._pyobjcryst import MonteCarlo as MonteCarlo_orig, AnnealingSchedule, GlobalOptimType
2429
from .refinableobj import *
2530

2631

2732
class MonteCarlo(MonteCarlo_orig):
2833

29-
def MultiRunOptimize(self, nb_run: int, nb_step: int, final_cost=0, max_time=-1):
30-
# Fix parameters that should not be optimised in a MonterCarlo run
31-
self.SetParIsFixed(refpartype_unitcell, True);
32-
self.SetParIsFixed(refpartype_scattdata_scale, True);
33-
self.SetParIsFixed(refpartype_scattdata_profile, True);
34-
self.SetParIsFixed(refpartype_scattdata_corr, True);
35-
self.SetParIsFixed(refpartype_scattdata_background, True);
36-
self.SetParIsFixed(refpartype_scattdata_radiation, True);
34+
def Optimize(self, nb_step: int, final_cost=0, max_time=-1):
35+
self._fix_parameters_for_global_optim()
36+
super().Optimize(int(nb_step), True, final_cost, max_time)
3737

38+
def MultiRunOptimize(self, nb_run: int, nb_step: int, final_cost=0, max_time=-1):
39+
self._fix_parameters_for_global_optim()
3840
super().MultiRunOptimize(int(nb_run), int(nb_step), True, final_cost, max_time)
3941

4042
def RunSimulatedAnnealing(self, nb_step: int, final_cost=0, max_time=-1):
41-
# Fix parameters that should not be optimised in a MonterCarlo run
42-
self.SetParIsFixed(refpartype_unitcell, True);
43-
self.SetParIsFixed(refpartype_scattdata_scale, True);
44-
self.SetParIsFixed(refpartype_scattdata_profile, True);
45-
self.SetParIsFixed(refpartype_scattdata_corr, True);
46-
self.SetParIsFixed(refpartype_scattdata_background, True);
47-
self.SetParIsFixed(refpartype_scattdata_radiation, True);
48-
43+
self._fix_parameters_for_global_optim()
4944
super().RunSimulatedAnnealing(int(nb_step), True, final_cost, max_time)
5045

5146
def RunParallelTempering(self, nb_step: int, final_cost=0, max_time=-1):
47+
self._fix_parameters_for_global_optim()
48+
super().RunParallelTempering(int(nb_step), True, final_cost, max_time)
49+
50+
def _fix_parameters_for_global_optim(self):
5251
# Fix parameters that should not be optimised in a MonterCarlo run
53-
self.SetParIsFixed(refpartype_unitcell, True);
54-
self.SetParIsFixed(refpartype_scattdata_scale, True);
55-
self.SetParIsFixed(refpartype_scattdata_profile, True);
56-
self.SetParIsFixed(refpartype_scattdata_corr, True);
57-
self.SetParIsFixed(refpartype_scattdata_background, True);
58-
self.SetParIsFixed(refpartype_scattdata_radiation, True);
52+
self.SetParIsFixed(refpartype_unitcell, True)
53+
self.SetParIsFixed(refpartype_scattdata_scale, True)
54+
self.SetParIsFixed(refpartype_scattdata_profile, True)
55+
self.SetParIsFixed(refpartype_scattdata_corr, True)
56+
self.SetParIsFixed(refpartype_scattdata_background, True)
57+
self.SetParIsFixed(refpartype_scattdata_radiation, True)
5958

60-
super().RunParallelTempering(int(nb_step), True, final_cost, max_time)
59+
def widget(self):
60+
"""
61+
Display a simple widget for this MonteCarloObj, which only updates the current
62+
cost (log-likelihood). Requires ipywidgets
63+
"""
64+
if widgets is None:
65+
warnings.warn("You need to install ipywidgets to use MonteCarlo.widget()")
66+
return
67+
self._widget = widgets.Box()
68+
# See https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Styling.html
69+
self._widget_label = widgets.Label("", layout=widgets.Layout(max_width='25%', width='20em'))
70+
self._widget_llk = widgets.Text("", disabled=True, layout=widgets.Layout(max_width='50%', width='30em'))
71+
self._widget.children = [widgets.HBox([self._widget_label, self._widget_llk])]
72+
self._widget_update()
73+
return self._widget
6174

6275
def UpdateDisplay(self):
76+
try:
77+
if self._display_update_disabled:
78+
return
79+
except:
80+
pass
81+
try:
82+
if self._widget is not None:
83+
self._widget_update()
84+
except AttributeError:
85+
# self._3d_widget does not exist
86+
pass
87+
88+
def disable_display_update(self):
89+
""" Disable display (useful for multiprocessing)"""
90+
self._display_update_disabled = True
91+
92+
def enable_display_update(self):
93+
""" Enable display"""
94+
self._display_update_disabled = False
95+
96+
def _widget_update(self):
97+
self._widget_label.value = "MonteCarlo:%s" % self.GetName()
98+
self._widget_label.layout.width = '%dem' % len(self._widget_label.value)
6399
if self.IsOptimizing():
64-
print("Run %2d Trial %8d LLK=%12.2f" % (self.run, self.trial, self.llk))
100+
self._widget_llk.value = "LLK=%12.2f Run %2d Trial %8d" % (self.llk, self.run, self.trial)
65101
else:
66-
print("MonteCarlo: current LLK=%12.2f" % self.llk)
102+
self._widget_llk.value = "LLK=%12.2f " % self.llk
103+
self._widget_llk.layout.width = '%dem' % len(self._widget_llk.value)

src/pyobjcryst/powderpattern.py

+14
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"""
2020

2121
import urllib
22+
from multiprocessing import current_process
2223
import numpy as np
2324

2425
__all__ = ["PowderPattern", "CreatePowderPatternFromCIF",
@@ -54,12 +55,25 @@ def __init__(self):
5455
self.evts = []
5556

5657
def UpdateDisplay(self):
58+
try:
59+
if self._display_update_disabled:
60+
return
61+
except:
62+
pass
5763
if self._plot_fig is not None:
5864
import matplotlib.pyplot as plt
5965
if 'inline' not in plt.get_backend():
6066
if plt.fignum_exists(self._plot_fig.number):
6167
self.plot()
6268

69+
def disable_display_update(self):
70+
""" Disable display (useful for multiprocessing)"""
71+
self._display_update_disabled = True
72+
73+
def enable_display_update(self):
74+
""" Enable display"""
75+
self._display_update_disabled = False
76+
6377
def plot(self, diff=None, hkl=None, figsize=(9, 4), fontsize_hkl=6, reset=False, **kwargs):
6478
"""
6579
Show the powder pattern in a plot using matplotlib

src/pyobjcryst/tests/testcrystal.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,13 @@ def __init__(self, level1):
154154

155155
return
156156

157-
def test_cif_display(self):
158-
"""Test the creation of a CIF just for display"""
157+
def test_display_list(self):
158+
"""Test the creation of a atoms list for display using 3dmol"""
159159
c = makeCrystal(*makeScatterer())
160-
s = c._display_cif()
161-
s = c._display_cif(full_molecule=True)
162-
s = c._display_cif(enantiomer=True)
163-
s = c._display_cif(only_independent_atoms=True)
164-
160+
s = c._display_list()
161+
s = c._display_list(full_molecule=True)
162+
s = c._display_list(enantiomer=True)
163+
s = c._display_list(only_independent_atoms=True)
165164

166165

167166
if __name__ == "__main__":

src/pyobjcryst/tests/testglobaloptim.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,28 @@ def test_mc_optim(self):
7474
mc.AddRefinableObj(self.c)
7575
mc.AddRefinableObj(self.d)
7676
mc.RandomizeStartingConfig()
77-
mc.Optimize(nbSteps=1000, silent=True)
77+
mc.Optimize(nb_step=1000)
7878

7979
def test_mc_optim_multi(self):
8080
mc = MonteCarlo()
8181
mc.AddRefinableObj(self.c)
8282
mc.AddRefinableObj(self.d)
8383
mc.RandomizeStartingConfig()
84-
mc.MultiRunOptimize(nbCycle=2, nbSteps=1000, silent=True)
84+
mc.MultiRunOptimize(nb_run=2, nb_step=1000)
8585

8686
def test_mc_sa(self):
8787
mc = MonteCarlo()
8888
mc.AddRefinableObj(self.c)
8989
mc.AddRefinableObj(self.d)
9090
mc.RandomizeStartingConfig()
91-
mc.RunSimulatedAnnealing(nbSteps=1000, silent=True)
91+
mc.RunSimulatedAnnealing(nb_step=1000)
9292

9393
def test_mc_pt(self):
9494
mc = MonteCarlo()
9595
mc.AddRefinableObj(self.c)
9696
mc.AddRefinableObj(self.d)
9797
mc.RandomizeStartingConfig()
98-
mc.RunParallelTempering(nbSteps=1000, silent=True)
98+
mc.RunParallelTempering(nb_step=1000)
9999

100100
# TODO: this is experimental and leads to segfault if testcrystal:testDummyAtom() has been run before (?!)
101101
# def test_mc_lsq(self):
@@ -113,9 +113,9 @@ def test_mc_set_algo(self):
113113
mc.AddRefinableObj(self.d)
114114
mc.RandomizeStartingConfig()
115115
mc.SetAlgorithmSimulAnnealing(AnnealingSchedule.SMART, 1000.0, 1.0)
116-
mc.Optimize(nbSteps=1000, silent=True)
116+
mc.Optimize(nb_step=1000)
117117
mc.SetAlgorithmParallTempering(AnnealingSchedule.SMART, 1000.0, 1.0)
118-
mc.Optimize(nbSteps=1000, silent=True)
118+
mc.Optimize(nb_step=1000)
119119

120120

121121
if __name__ == "__main__":

0 commit comments

Comments
 (0)