class_docstr: Wrapper for Siemens format DICOMs
  
  Adds attributes:
  
  * csa_header : mapping
  * b_matrix : (3,3) array
  * q_vector : (3,) array
code: def slice_normal(self):
      # The std_slice_normal comes from the cross product of the directions
      # in the ImageOrientationPatient
      std_slice_normal = super().slice_normal
      csa_slice_normal = csar.get_slice_normal(self.csa_header)
      if std_slice_normal is None and csa_slice_normal is None:
          return None
      elif std_slice_normal is None:
          return np.array(csa_slice_normal)
      elif csa_slice_normal is None:
          return std_slice_normal
      else:
          # Make sure the two normals are very close to parallel unit vectors
          dot_prod = np.dot(csa_slice_normal, std_slice_normal)
          assert np.allclose(np.fabs(dot_prod), 1.0, atol=1e-5)
          # Use the slice normal computed with the cross product as it will
          # always be the most orthogonal, but take the sign from the CSA
          # slice normal
          if dot_prod < 0:
              return -std_slice_normal
          else:
              return std_slice_normal
  
imports: import operator
  import warnings
  import numpy
  from nibabel.optpkg import optional_package
  from ..onetime import auto_attr
  from ..openers import ImageOpener
  from .None import csareader
  from .dwiparams import B2q, nearest_pos_semi_def, q2bg
label_desc: Use image node_id 2 for calling the SiemensWrapper obj's underlying member method code with example usage: obj.slice_normal() and returns: None, np, std_slice_normal, unknown, std_slice_normal