class_docstr: Represents a coordinate system in 3-D space.
class_docstr_tok: ["Represents","a","coordinate","system","in","3-D","space","."]
docstr: The orientation/location parameters are necessary if this system
  is being defined at a certain orientation or location wrt another.
  
  Parameters
  ==========
  
  name : str
      The name of the new CoordSys3D instance.
  
  transformation : Lambda, Tuple, str
      Transformation defined by transformation equations or chosen
      from predefined ones.
  
  location : Vector
      The position vector of the new system's origin wrt the parent
      instance.
  
  rotation_matrix : SymPy ImmutableMatrix
      The rotation matrix of the new coordinate system with respect
      to the parent. In other words, the output of
      new_system.rotation_matrix(parent).
  
  parent : CoordSys3D
      The coordinate system wrt which the orientation/location
      (or both) is being defined.
  
  vector_names, variable_names : iterable(optional)
      Iterables of 3 strings each, with custom names for base
      vectors and base scalars of the new system respectively.
      Used for simple str printing.
code: def __new__(
      cls,
      name,
      transformation=None,
      parent=None,
      location=None,
      rotation_matrix=None,
      vector_names=None,
      variable_names=None,
  ):
      """
      The orientation/location parameters are necessary if this system
      is being defined at a certain orientation or location wrt another.
  
      Parameters
      ==========
  
      name : str
          The name of the new CoordSys3D instance.
  
      transformation : Lambda, Tuple, str
          Transformation defined by transformation equations or chosen
          from predefined ones.
  
      location : Vector
          The position vector of the new system's origin wrt the parent
          instance.
  
      rotation_matrix : SymPy ImmutableMatrix
          The rotation matrix of the new coordinate system with respect
          to the parent. In other words, the output of
          new_system.rotation_matrix(parent).
  
      parent : CoordSys3D
          The coordinate system wrt which the orientation/location
          (or both) is being defined.
  
      vector_names, variable_names : iterable(optional)
          Iterables of 3 strings each, with custom names for base
          vectors and base scalars of the new system respectively.
          Used for simple str printing.
  
      """
  
      name = str(name)
      Vector = sympy.vector.Vector
      Point = sympy.vector.Point
  
      if not isinstance(name, str):
          raise TypeError("name should be a string")
  
      if transformation is not None:
          if (location is not None) or (rotation_matrix is not None):
              raise ValueError(
                  "specify either `transformation` or "
                  "`location`/`rotation_matrix`"
              )
          if isinstance(transformation, (Tuple, tuple, list)):
              if isinstance(transformation[0], MatrixBase):
                  rotation_matrix = transformation[0]
                  location = transformation[1]
              else:
                  transformation = Lambda(
                      transformation[0], transformation[1]
                  )
          elif isinstance(transformation, Callable):
              x1, x2, x3 = symbols("x1 x2 x3", cls=Dummy)
              transformation = Lambda(
                  (x1, x2, x3), transformation(x1, x2, x3)
              )
          elif isinstance(transformation, str):
              transformation = Str(transformation)
          elif isinstance(transformation, (Str, Lambda)):
              pass
          else:
              raise TypeError(
                  "transformation: "
                  "wrong type {}".format(type(transformation))
              )
  
      # If orientation information has been provided, store
      # the rotation matrix accordingly
      if rotation_matrix is None:
          rotation_matrix = ImmutableDenseMatrix(eye(3))
      else:
          if not isinstance(rotation_matrix, MatrixBase):
              raise TypeError(
                  "rotation_matrix should be an Immutable"
                  + "Matrix instance"
              )
          rotation_matrix = rotation_matrix.as_immutable()
  
      # If location information is not given, adjust the default
      # location as Vector.zero
      if parent is not None:
          if not isinstance(parent, CoordSys3D):
              raise TypeError("parent should be a " + "CoordSys3D/None")
          if location is None:
              location = Vector.zero
          else:
              if not isinstance(location, Vector):
                  raise TypeError("location should be a Vector")
              # Check that location does not contain base
              # scalars
              for x in location.free_symbols:
                  if isinstance(x, BaseScalar):
                      raise ValueError(
                          "location should not contain" + " BaseScalars"
                      )
          origin = parent.origin.locate_new(name + ".origin", location)
      else:
          location = Vector.zero
          origin = Point(name + ".origin")
  
      if transformation is None:
          transformation = Tuple(rotation_matrix, location)
  
      if isinstance(transformation, Tuple):
          lambda_transformation = (
              CoordSys3D._compose_rotation_and_translation(
                  transformation[0], transformation[1], parent
              )
          )
          r, l = transformation
          l = l._projections
          lambda_lame = CoordSys3D._get_lame_coeff("cartesian")
          lambda_inverse = lambda x, y, z: r.inv() * Matrix(
              [x - l[0], y - l[1], z - l[2]]
          )
      elif isinstance(transformation, Str):
          trname = transformation.name
          lambda_transformation = (
              CoordSys3D._get_transformation_lambdas(trname)
          )
          if parent is not None:
              if parent.lame_coefficients() != (S.One, S.One, S.One):
                  raise ValueError(
                      "Parent for pre-defined coordinate "
                      "system should be Cartesian."
                  )
          lambda_lame = CoordSys3D._get_lame_coeff(trname)
          lambda_inverse = CoordSys3D._set_inv_trans_equations(trname)
      elif isinstance(transformation, Lambda):
          if not CoordSys3D._check_orthogonality(transformation):
              raise ValueError(
                  "The transformation equation does not "
                  "create orthogonal coordinate system"
              )
          lambda_transformation = transformation
          lambda_lame = CoordSys3D._calculate_lame_coeff(
              lambda_transformation
          )
          lambda_inverse = None
      else:
          lambda_transformation = lambda x, y, z: transformation(
              x, y, z
          )
          lambda_lame = CoordSys3D._get_lame_coeff(transformation)
          lambda_inverse = None
  
      if variable_names is None:
          if isinstance(transformation, Lambda):
              variable_names = ["x1", "x2", "x3"]
          elif isinstance(transformation, Str):
              if transformation.name == "spherical":
                  variable_names = ["r", "theta", "phi"]
              elif transformation.name == "cylindrical":
                  variable_names = ["r", "theta", "z"]
              else:
                  variable_names = ["x", "y", "z"]
          else:
              variable_names = ["x", "y", "z"]
      if vector_names is None:
          vector_names = ["i", "j", "k"]
  
      # All systems that are defined as 'roots' are unequal, unless
      # they have the same name.
      # Systems defined at same orientation/position wrt the same
      # 'parent' are equal, irrespective of the name.
      # This is true even if the same orientation is provided via
      # different methods like Axis/Body/Space/Quaternion.
      # However, coincident systems may be seen as unequal if
      # positioned/oriented wrt different parents, even though
      # they may actually be 'coincident' wrt the root system.
      if parent is not None:
          obj = super().__new__(cls, Str(name), transformation, parent)
      else:
          obj = super().__new__(cls, Str(name), transformation)
      obj._name = name
      # Initialize the base vectors
  
      _check_strings("vector_names", vector_names)
      vector_names = list(vector_names)
      latex_vects = [
          (r"\mathbf{\hat{%s}_{%s}}" % (x, name)) for x in vector_names
      ]
      pretty_vects = ["%s_%s" % (x, name) for x in vector_names]
  
      obj._vector_names = vector_names
  
      v1 = BaseVector(0, obj, pretty_vects[0], latex_vects[0])
      v2 = BaseVector(1, obj, pretty_vects[1], latex_vects[1])
      v3 = BaseVector(2, obj, pretty_vects[2], latex_vects[2])
  
      obj._base_vectors = (v1, v2, v3)
  
      # Initialize the base scalars
  
      _check_strings("variable_names", vector_names)
      variable_names = list(variable_names)
      latex_scalars = [
          (r"\mathbf{{%s}_{%s}}" % (x, name)) for x in variable_names
      ]
      pretty_scalars = ["%s_%s" % (x, name) for x in variable_names]
  
      obj._variable_names = variable_names
      obj._vector_names = vector_names
  
      x1 = BaseScalar(0, obj, pretty_scalars[0], latex_scalars[0])
      x2 = BaseScalar(1, obj, pretty_scalars[1], latex_scalars[1])
      x3 = BaseScalar(2, obj, pretty_scalars[2], latex_scalars[2])
  
      obj._base_scalars = (x1, x2, x3)
  
      obj._transformation = transformation
      obj._transformation_lambda = lambda_transformation
      obj._lame_coefficients = lambda_lame(x1, x2, x3)
      obj._transformation_from_parent_lambda = lambda_inverse
  
      setattr(obj, variable_names[0], x1)
      setattr(obj, variable_names[1], x2)
      setattr(obj, variable_names[2], x3)
  
      setattr(obj, vector_names[0], v1)
      setattr(obj, vector_names[1], v2)
      setattr(obj, vector_names[2], v3)
  
      # Assign params
      obj._parent = parent
      if obj._parent is not None:
          obj._root = obj._parent._root
      else:
          obj._root = obj
  
      obj._parent_rotation_matrix = rotation_matrix
      obj._origin = origin
  
      # Return the instance
      return obj
  
imports: from collections.abc import Callable
  from sympy.core.basic import Basic
  from sympy.core.cache import cacheit
  from sympy.core import S, Dummy, Lambda
  from sympy.core.symbol import Str
  from sympy.core.symbol import symbols
  from sympy.matrices.immutable import ImmutableDenseMatrix
  from sympy.matrices.matrixbase import MatrixBase
  from sympy.solvers import solve
  from sympy.vector.scalar import BaseScalar
  from sympy.core.containers import Tuple
  from sympy.core.function import diff
  from sympy.functions.elementary.miscellaneous import sqrt
  from sympy.functions.elementary.trigonometric import acos, atan2, cos, sin
  from sympy.matrices.dense import eye
  from sympy.matrices.immutable import ImmutableDenseMatrix
  from sympy.simplify.simplify import simplify
  from sympy.simplify.trigsimp import trigsimp
  import sympy.vector
  from sympy.vector.orienters import Orienter, AxisOrienter, BodyOrienter, SpaceOrienter, QuaternionOrienter
  from sympy.vector.vector import BaseVector
label_desc: Use image node_id 1 for calling the CoordSys3D obj's underlying member method code with example usage: obj.__new__(cls, name, transformation, parent, location, rotation_matrix, vector_names, variable_names) and returns: obj