/
Instrument.py
100 lines (77 loc) · 3.18 KB
/
Instrument.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python
#
#
# this is the original, minimal implementation of the Instrument data object
# it just contains a list of components
class Instrument0(object):
'''Instrument is a container of neutron components'''
def __init__(self, components = None ):
self.components = components or []
return
def append(self, component):
self.components.append(component)
return
def insert(self, index, component):
self.components.insert(index, component)
return
pass # Instrument
# This class provides some syntatic sugar to simplify the
# procedure for users to create an instrument.
# It contains the geometer also.
class Instrument(Instrument0):
'''Instrument is a container of neutron components, with a geometer'''
def __init__(self, components = None, geometer = None):
super(Instrument, self).__init__(components)
self.geometer = geometer or self._createGeometer()
return
def __str__(self):
g = self.geometer
def s(c):
if hasattr(c, '_factory_kwds'):
kwds = c._factory_kwds
return ', '.join(f'{k}={v!r}' for k, v in kwds.items())
return str(c)
return "Instrument:\n " + '\n '.join([
f"{c.name}:{c.__class__.__name__}"
f" at {g.position(c)} rotated {g.orientation(c)}"
f"\n * {s(c)}"
for c in self.components
])
def simulate(self, N, **kwds):
"""simulate N neutrons. **kwds are used to update simulation context
simulation context is an instance of SimulationContext
"""
# convenient method to run simulation
from . import simulate, neutron_buffer
neutrons = neutron_buffer(N)
simulate(self, self.geometer, neutrons, **kwds)
return neutrons
def append(self, component, position=None, orientation=None, relativeTo=None):
super(Instrument, self).append(component)
if position is None and orientation is None: return
self._register(component, position, orientation, relativeTo)
return
def insert(self, index, component, position=None, orientation=None, relativeTo=None):
super(Instrument, self).insert(index, component)
if position is None and orientation is None: return
self._register(component, position, orientation, relativeTo)
return
def _register(self, component, position, orientation, relativeTo=None):
from .Geometer2 import AbsoluteCoord as abs, RelativeCoord as rel
if position is None: position = (0,0,0)
if orientation is None: orientation = (0,0,0)
if relativeTo:
position = rel(position, relativeTo)
orientation = rel(orientation, relativeTo)
else:
position = abs(position)
orientation = abs(orientation)
self.geometer.register(component, position, orientation)
component.abs_position = self.geometer.position(component)
component.abs_orientation = self.geometer.orientation(component)
return
def _createGeometer(self):
from .Geometer2 import Geometer
return Geometer()
pass # Instrument
# End of file