@@ -111,6 +111,9 @@ def __init__(self, data, dtype=None, symmetry_group=None):
111111 # Set symmetry_group. If None, default to 'C1'.
112112 self ._set_symmetry_group (symmetry_group )
113113
114+ # Flag to ensure T and transpose have the same symmetry_group warning stacklevel.
115+ self ._called_from_T = False
116+
114117 # Numpy interop
115118 # https://numpy.org/devdocs/user/basics.interoperability.html#the-array-interface-protocol
116119 self .__array_interface__ = self ._data .__array_interface__
@@ -179,22 +182,27 @@ def _set_symmetry_group(self, value):
179182 )
180183 self ._symmetry_group = value
181184
182- def _symmetry_group_warning (self ):
185+ def _symmetry_group_warning (self , stacklevel ):
183186 """
184187 Warn when an operation has the potential to change the symmetry
185188 of a volume or the alignment of symmetry axes.
189+
190+ :param stacklevel: Warning stacklevel.
186191 """
187192 msg = (
188193 f"`symmetry_group` attribute is being set to `C1`. This operation may"
189194 f" effect the symmetry (or symmetric alignment) of the volume. To reset the"
190195 f" symmetry group run `self._set_symmetry_group('{ self .symmetry_group } ')`."
191196 )
192- warnings .warn (msg , UserWarning , stacklevel = 4 )
197+ warnings .warn (msg , UserWarning , stacklevel = stacklevel )
193198
194- def _result_symmetry (self , other = None ):
199+ def _result_symmetry (self , other = None , stacklevel = 4 ):
195200 """
196201 Check if `other` will alter symmetry of `self` and return resulting symmetry_group.
197202
203+ :param other: Other operand to self. Default is None for self transformations.
204+ :param stacklevel: Warning stacklevel. Default of 4 indicates line of code where
205+ operation was performed.
198206 :return: SymmetryGroup instance.
199207 """
200208 # No need to check for C1.
@@ -214,7 +222,7 @@ def _result_symmetry(self, other=None):
214222 )
215223
216224 if any ([self_transformation , incompat_syms , arbitrary_array ]):
217- self ._symmetry_group_warning ()
225+ self ._symmetry_group_warning (stacklevel = stacklevel )
218226 result_symmetry = IdentitySymmetryGroup (dtype = self .dtype )
219227
220228 return result_symmetry
@@ -400,15 +408,18 @@ def from_vec(cls, vec):
400408
401409 return cls (data )
402410
403- def transpose (self , symmetry = None ):
411+ def transpose (self ):
404412 """
405413 Returns a new Volume instance with volume data axes transposed.
406414
407415 :return: Volume instance.
408416 """
409417 # Ensures warning stacklevel is the same for `vol.T` and `vol.transpose()`.
410- if symmetry is None :
411- symmetry = self ._result_symmetry ()
418+ stacklevel = 4
419+ if self ._called_from_T :
420+ stacklevel = 5
421+ self ._called_from_T = False
422+ symmetry = self ._result_symmetry (stacklevel = stacklevel )
412423
413424 original_stack_shape = self .stack_shape
414425 v = self ._data .reshape (- 1 , * self ._data .shape [- 3 :])
@@ -423,8 +434,8 @@ def T(self):
423434
424435 :return: Volume instance.
425436 """
426- symmetry = self . _result_symmetry ()
427- return self .transpose (symmetry = symmetry )
437+ self . _called_from_T = True
438+ return self .transpose ()
428439
429440 def flatten (self ):
430441 """
0 commit comments