@@ -56,25 +56,45 @@ def atomBareSymbol(smbl):
5656
5757def _linkAtomAttribute (attrname , doc , toarray = numpy .array ):
5858 '''Create property wrapper that maps the specified atom attribute.
59+
5960 The returned property object provides convenient access to atom
6061 attributes from the owner Structure class.
6162
62- attrname -- string name of the Atom class attribute to be mapped
63- doc -- docstring of the property wrapper
64- toarray -- factory function that converts list of attributes to
65- numpy.array. Use numpy.char.array for string attributes.
63+ Parameters
64+ ----------
65+ attrname : str
66+ The string name of the Atom class attribute to be mapped.
67+ doc : str
68+ The docstring for the property wrapper.
69+ toarray : callable, optional
70+ Factory function that converts list of attributes to `numpy.ndarray`.
71+ Use `numpy.char.array` for string attributes.
6672
6773 Return a property object.
6874 '''
75+ from itertools import repeat
76+ from operator import setitem
77+ _all = slice (None )
6978 def fget (self ):
7079 va = toarray ([getattr (a , attrname ) for a in self ])
7180 return va
7281 def fset (self , value ):
73- if len (self ) == 0 : return
74- # dummy array va helps to broadcast the value to proper iterable
75- va = numpy .asarray (len (self ) * [getattr (self [0 ], attrname )])
76- for a , v in zip (self , numpy .broadcast_arrays (va , value )[1 ]):
77- setattr (a , attrname , v )
82+ n = len (self )
83+ if n == 0 :
84+ return
85+ v0 = getattr (self [0 ], attrname )
86+ # replace scalar values, but change array attributes in place
87+ if numpy .isscalar (v0 ):
88+ setvalue = lambda a , v : setattr (a , attrname , v )
89+ else :
90+ setvalue = lambda a , v : setitem (getattr (a , attrname ), _all , v )
91+ # avoid broadcasting if the new value is a scalar
92+ if numpy .isscalar (value ):
93+ genvalues = repeat (value )
94+ else :
95+ genvalues = numpy .broadcast_to (value , (n ,) + numpy .shape (v0 ))
96+ for a , v in zip (self , genvalues ):
97+ setvalue (a , v )
7898 return
7999 rv = property (fget , fset , doc = doc )
80100 return rv
0 commit comments