@@ -183,7 +183,7 @@ def __init__(self, apart, dpart, src_radius, det_radius,
183
183
detector = Flat1dDetector (dpart , det_axis_init )
184
184
translation = kwargs .pop ('translation' , None )
185
185
super ().__init__ (ndim = 2 , motion_part = apart , detector = detector ,
186
- translation = translation )
186
+ translation = translation , ** kwargs )
187
187
188
188
self .__src_radius = float (src_radius )
189
189
if self .src_radius < 0 :
@@ -202,11 +202,6 @@ def __init__(self, apart, dpart, src_radius, det_radius,
202
202
raise ValueError ('`apart` has dimension {}, expected 1'
203
203
'' .format (self .motion_partition .ndim ))
204
204
205
- # Make sure there are no leftover kwargs
206
- if kwargs :
207
- raise TypeError ('got unexpected keyword arguments {}'
208
- '' .format (kwargs ))
209
-
210
205
@classmethod
211
206
def frommatrix (cls , apart , dpart , src_radius , det_radius , init_matrix ):
212
207
"""Create an instance of `FanFlatGeometry` using a matrix.
@@ -357,16 +352,19 @@ def src_position(self, angle):
357
352
>>> np.allclose(geom.src_position(np.pi / 2), [2, 0])
358
353
True
359
354
"""
360
- if angle not in self .motion_params :
361
- raise ValueError ('`angle` {} is not in the valid range {}'
355
+ if self . check_bounds and not self .motion_params . contains_all ( angle ) :
356
+ raise ValueError ('`angle` {} not in the valid range {}'
362
357
'' .format (angle , self .motion_params ))
363
358
359
+ angle = np .array (angle , dtype = float , copy = False , ndmin = 1 )
360
+
364
361
# Initial vector from the rotation center to the source. It can be
365
362
# computed this way since source and detector are at maximum distance,
366
363
# i.e. the connecting line passes the origin.
367
364
center_to_src_init = - self .src_radius * self .src_to_det_init
368
- return (self .translation +
369
- self .rotation_matrix (angle ).dot (center_to_src_init ))
365
+ pos_vec = (self .translation [None , :] +
366
+ self .rotation_matrix (angle ).dot (center_to_src_init ))
367
+ return pos_vec .squeeze ()
370
368
371
369
def det_refpoint (self , angle ):
372
370
"""Return the detector reference point position at ``angle``.
@@ -407,16 +405,18 @@ def det_refpoint(self, angle):
407
405
>>> np.allclose(geom.det_refpoint(np.pi / 2), [-5, 0])
408
406
True
409
407
"""
410
- if angle not in self .motion_params :
411
- raise ValueError ('`angle` {} is not in the valid range {}'
408
+ if self . check_bounds and not self .motion_params . contains_all ( angle ) :
409
+ raise ValueError ('`angle` {} not in the valid range {}'
412
410
'' .format (angle , self .motion_params ))
413
411
412
+ angle = np .array (angle , dtype = float , copy = False , ndmin = 1 )
414
413
# Initial vector from the rotation center to the detector. It can be
415
414
# computed this way since source and detector are at maximum distance,
416
415
# i.e. the connecting line passes the origin.
417
416
center_to_det_init = self .det_radius * self .src_to_det_init
418
- return (self .translation +
419
- self .rotation_matrix (angle ).dot (center_to_det_init ))
417
+ refpt = (self .translation [None , :] +
418
+ self .rotation_matrix (angle ).dot (center_to_det_init ))
419
+ return refpt .squeeze ()
420
420
421
421
def rotation_matrix (self , angle ):
422
422
"""Return the rotation matrix for ``angle``.
@@ -440,10 +440,10 @@ def rotation_matrix(self, angle):
440
440
the local coordinate system of the detector reference point,
441
441
expressed in the fixed system.
442
442
"""
443
- angle = float (angle )
444
- if angle not in self .motion_params :
443
+ if self .check_bounds and not self .motion_params .contains_all (angle ):
445
444
raise ValueError ('`angle` {} not in the valid range {}'
446
445
'' .format (angle , self .motion_params ))
446
+
447
447
return euler_matrix (angle )
448
448
449
449
def __repr__ (self ):
@@ -834,9 +834,9 @@ def angles(self):
834
834
"""Discrete angles given in this geometry."""
835
835
return self .motion_grid .coord_vectors [0 ]
836
836
837
- def det_axes (self , angles ):
837
+ def det_axes (self , angle ):
838
838
"""Return the detector axes tuple at ``angle``."""
839
- return tuple (self .rotation_matrix (angles ).dot (axis )
839
+ return tuple (self .rotation_matrix (angle ).dot (axis )
840
840
for axis in self .det_axes_init )
841
841
842
842
def det_refpoint (self , angle ):
@@ -881,22 +881,25 @@ def det_refpoint(self, angle):
881
881
>>> np.allclose(geom.det_refpoint(np.pi / 2), [-10, 0, 0.5])
882
882
True
883
883
"""
884
- angle = float (angle )
885
- if angle not in self .motion_params :
886
- raise ValueError ('`angle` {} is not in the valid range {}'
884
+ if self .check_bounds and not self .motion_params .contains_all (angle ):
885
+ raise ValueError ('`angle` {} not in the valid range {}'
887
886
'' .format (angle , self .motion_params ))
888
887
888
+ angle = np .array (angle , dtype = float , copy = False , ndmin = 1 )
889
+
889
890
# Initial vector from center of rotation to detector.
890
891
# It can be computed this way since source and detector are at
891
892
# maximum distance, i.e. the connecting line passes the origin.
892
893
center_to_det_init = self .det_radius * self .src_to_det_init
893
894
circle_component = self .rotation_matrix (angle ).dot (center_to_det_init )
894
895
895
896
# Increment along the rotation axis according to pitch and pitch_offset
896
- pitch_component = self .axis * (self .pitch_offset +
897
- self .pitch * angle / (2 * np .pi ))
897
+ shift_along_axis = (self .pitch_offset +
898
+ self .pitch * angle / (2 * np .pi ))
899
+ pitch_component = self .axis [None , :] * shift_along_axis [:, None ]
898
900
899
- return self .translation + circle_component + pitch_component
901
+ refpt = self .translation [None , :] + circle_component + pitch_component
902
+ return refpt .squeeze ()
900
903
901
904
def src_position (self , angle ):
902
905
"""Return the source position at ``angle``.
@@ -940,22 +943,25 @@ def src_position(self, angle):
940
943
>>> np.allclose(geom.src_position(np.pi / 2), [5, 0, 0.5])
941
944
True
942
945
"""
943
- angle = float (angle )
944
- if angle not in self .motion_params :
945
- raise ValueError ('`angle` {} is not in the valid range {}'
946
+ if self .check_bounds and not self .motion_params .contains_all (angle ):
947
+ raise ValueError ('`angle` {} not in the valid range {}'
946
948
'' .format (angle , self .motion_params ))
947
949
950
+ angle = np .array (angle , dtype = float , copy = False , ndmin = 1 )
951
+
948
952
# Initial vector from 0 to the source (non-translated).
949
953
# It can be computed this way since source and detector are at
950
954
# maximum distance, i.e. the connecting line passes the origin.
951
955
origin_to_src_init = - self .src_radius * self .src_to_det_init
952
956
circle_component = self .rotation_matrix (angle ).dot (origin_to_src_init )
953
957
954
- # Increment by pitch
955
- pitch_component = self .axis * (self .pitch_offset +
956
- self .pitch * angle / (np .pi * 2 ))
958
+ # Increment along the rotation axis according to pitch and pitch_offset
959
+ shift_along_axis = (self .pitch_offset +
960
+ self .pitch * angle / (2 * np .pi ))
961
+ pitch_component = self .axis [None , :] * shift_along_axis [:, None ]
957
962
958
- return self .translation + circle_component + pitch_component
963
+ refpt = self .translation [None , :] + circle_component + pitch_component
964
+ return refpt .squeeze ()
959
965
960
966
def __repr__ (self ):
961
967
"""Return ``repr(self)``."""
0 commit comments