nodes: 0, module; 1, function_definition; 2, function_name:rot_consts; 3, parameters; 4, block; 5, identifier:geom; 6, identifier:masses; 7, default_parameter; 8, default_parameter; 9, expression_statement; 10, comment:# Imports; 11, import_statement; 12, import_from_statement; 13, comment:# Ensure units are valid; 14, if_statement; 15, comment:## end if; 16, comment:# Retrieve the moments, axes and top type. Geom and masses are proofed; 17, comment:#  internally in this call.; 18, expression_statement; 19, comment:# Check for special cases; 20, if_statement; 21, comment:## end if; 22, comment:# Calculate the values in the indicated units; 23, if_statement; 24, comment:## end if; 25, comment:# Return the result; 26, return_statement; 27, identifier:units; 28, attribute; 29, identifier:on_tol; 30, attribute; 31, comment:"""Rotational constants for a given molecular system.
  
      Calculates the rotational constants for the provided system with numerical
      value given in the units provided in `units`.  The orthnormality tolerance
      `on_tol` is required in order to be passed through to the
      :func:`principals` function.
  
      If the system is linear or a single atom, the effectively-zero principal
      moments of inertia will be assigned values of
      :data:`opan.const.PRM.ZERO_MOMENT_TOL`
      before transformation into the appropriate rotational constant units.
  
      The moments of inertia are always sorted in increasing order as
      :math:`0 \\leq I_A \\leq I_B \\leq I_C`; the rotational constants
      calculated from these will thus always be in **decreasing** order
      as :math:`B_A \\geq B_B \\geq B_C`, retaining the
      ordering and association with the three principal ``axes[:,i]`` generated
      by :func:`principals`.
  
      Parameters
      ----------
      geom
          length-3N |npfloat_| --
          Coordinates of the atoms
  
      masses
          length-N OR length-3N |npfloat_| --
          Atomic masses of the atoms. Length-3N option is to allow calculation of
          a per-coordinate perturbed value.
  
      units
          :class:`~opan.const.EnumUnitsRotConst`, optional --
          Enum value indicating the desired units of the output rotational
          constants. Default is :data:`~opan.const.EnumUnitsRotConst.INV_INERTIA`
          :math:`\\left(1\\over \\mathrm{uB^2}\\right)`
  
      on_tol
          |npfloat_|,  optional --
          Tolerance for deviation from unity/zero for principal axis dot
          products, within which axes are considered orthonormal. Default is
          :data:`opan.const.DEF.ORTHONORM_TOL`
  
      Returns
      -------
      rc
          length-3 |npfloat_| --
          Vector of rotational constants in the indicated units
  
      """; 32, aliased_import; 33, relative_import; 34, aliased_import; 35, aliased_import; 36, dotted_name; 37, dotted_name; 38, not_operator; 39, block; 40, assignment; 41, comparison_operator:top == ETT.ATOM; 42, comment:# All moments are zero; set to zero-moment threshold; 43, block; 44, elif_clause; 45, comparison_operator:units == EURC.INV_INERTIA; 46, comment:# 1/(amu*B^2); 47, block; 48, elif_clause; 49, elif_clause; 50, elif_clause; 51, elif_clause; 52, elif_clause; 53, elif_clause; 54, elif_clause; 55, else_clause; 56, identifier:rc; 57, identifier:_EURC; 58, identifier:INV_INERTIA; 59, identifier:_DEF; 60, identifier:ORTHONORM_TOL; 61, dotted_name; 62, identifier:np; 63, import_prefix; 64, dotted_name; 65, dotted_name; 66, identifier:ETT; 67, dotted_name; 68, identifier:EURC; 69, identifier:PRM; 70, identifier:PHYS; 71, comparison_operator:units in EURC; 72, raise_statement; 73, pattern_list; 74, call; 75, identifier:top; 76, attribute; 77, expression_statement; 78, comparison_operator:top == ETT.LINEAR; 79, comment:# First moment is zero; set to zero-moment threshold; 80, block; 81, identifier:units; 82, attribute; 83, expression_statement; 84, comparison_operator:units == EURC.ANGFREQ_ATOMIC; 85, comment:# 1/Ta; 86, block; 87, comparison_operator:units == EURC.ANGFREQ_SECS; 88, comment:# 1/s; 89, block; 90, comparison_operator:units == EURC.CYCFREQ_ATOMIC; 91, comment:# cyc/Ta; 92, block; 93, comparison_operator:units == EURC.CYCFREQ_HZ; 94, comment:# cyc/s; 95, block; 96, comparison_operator:units == EURC.CYCFREQ_MHZ; 97, comment:# Mcyc/s; 98, block; 99, comparison_operator:units == EURC.WAVENUM_ATOMIC; 100, comment:# cyc/B; 101, block; 102, comparison_operator:units == EURC.WAVENUM_CM; 103, comment:# cyc/cm; 104, block; 105, comment:# pragma: no cover -- Valid units; not implemented; 106, block; 107, identifier:numpy; 108, identifier:const; 109, identifier:EnumTopType; 110, identifier:EnumUnitsRotConst; 111, identifier:units; 112, identifier:EURC; 113, call; 114, identifier:mom; 115, identifier:ax; 116, identifier:top; 117, identifier:principals; 118, argument_list; 119, identifier:ETT; 120, identifier:ATOM; 121, assignment; 122, identifier:top; 123, attribute; 124, expression_statement; 125, identifier:EURC; 126, identifier:INV_INERTIA; 127, assignment; 128, identifier:units; 129, attribute; 130, expression_statement; 131, identifier:units; 132, attribute; 133, expression_statement; 134, identifier:units; 135, attribute; 136, expression_statement; 137, identifier:units; 138, attribute; 139, expression_statement; 140, identifier:units; 141, attribute; 142, expression_statement; 143, identifier:units; 144, attribute; 145, expression_statement; 146, identifier:units; 147, attribute; 148, expression_statement; 149, raise_statement; 150, identifier:ValueError; 151, argument_list; 152, identifier:geom; 153, identifier:masses; 154, identifier:on_tol; 155, identifier:mom; 156, call; 157, identifier:ETT; 158, identifier:LINEAR; 159, assignment; 160, identifier:rc; 161, binary_operator:1.0 / (2.0 * mom); 162, identifier:EURC; 163, identifier:ANGFREQ_ATOMIC; 164, assignment; 165, identifier:EURC; 166, identifier:ANGFREQ_SECS; 167, assignment; 168, identifier:EURC; 169, identifier:CYCFREQ_ATOMIC; 170, assignment; 171, identifier:EURC; 172, identifier:CYCFREQ_HZ; 173, assignment; 174, identifier:EURC; 175, identifier:CYCFREQ_MHZ; 176, assignment; 177, identifier:EURC; 178, identifier:WAVENUM_ATOMIC; 179, assignment; 180, identifier:EURC; 181, identifier:WAVENUM_CM; 182, assignment; 183, call; 184, call; 185, attribute; 186, argument_list; 187, subscript; 188, attribute; 189, float:1.0; 190, parenthesized_expression; 191, identifier:rc; 192, binary_operator:PHYS.PLANCK_BAR / (2.0 * mom * PHYS.ME_PER_AMU); 193, identifier:rc; 194, binary_operator:PHYS.PLANCK_BAR / (2.0 * mom * PHYS.ME_PER_AMU) / PHYS.SEC_PER_TA; 195, identifier:rc; 196, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU); 197, identifier:rc; 198, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU) / \
                                                              PHYS.SEC_PER_TA; 199, identifier:rc; 200, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU) / \
                                                      PHYS.SEC_PER_TA / 1.0e6; 201, identifier:rc; 202, binary_operator:PHYS.PLANCK / (mom * PHYS.ME_PER_AMU) / \
              (8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED); 203, identifier:rc; 204, binary_operator:PHYS.PLANCK / (mom * PHYS.ME_PER_AMU) / \
              (8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED * PHYS.ANG_PER_BOHR) * 1.0e8; 205, identifier:NotImplementedError; 206, argument_list; 207, attribute; 208, argument_list; 209, identifier:np; 210, identifier:repeat; 211, attribute; 212, integer:3; 213, identifier:mom; 214, integer:0; 215, identifier:PRM; 216, identifier:ZERO_MOMENT_TOL; 217, binary_operator:2.0 * mom; 218, attribute; 219, parenthesized_expression; 220, binary_operator:PHYS.PLANCK_BAR / (2.0 * mom * PHYS.ME_PER_AMU); 221, attribute; 222, attribute; 223, parenthesized_expression; 224, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU); 225, line_continuation:\; 226, attribute; 227, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU) / \
                                                      PHYS.SEC_PER_TA; 228, float:1.0e6; 229, binary_operator:PHYS.PLANCK / (mom * PHYS.ME_PER_AMU); 230, line_continuation:\; 231, parenthesized_expression; 232, binary_operator:PHYS.PLANCK / (mom * PHYS.ME_PER_AMU) / \
              (8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED * PHYS.ANG_PER_BOHR); 233, float:1.0e8; 234, string:"Units conversion not yet implemented."; 235, string:"'{0}' is not a valid units value"; 236, identifier:format; 237, identifier:units; 238, identifier:PRM; 239, identifier:ZERO_MOMENT_TOL; 240, float:2.0; 241, identifier:mom; 242, identifier:PHYS; 243, identifier:PLANCK_BAR; 244, binary_operator:2.0 * mom * PHYS.ME_PER_AMU; 245, attribute; 246, parenthesized_expression; 247, identifier:PHYS; 248, identifier:SEC_PER_TA; 249, identifier:PHYS; 250, identifier:PLANCK_BAR; 251, binary_operator:4.0 * np.pi * mom * PHYS.ME_PER_AMU; 252, attribute; 253, parenthesized_expression; 254, identifier:PHYS; 255, identifier:SEC_PER_TA; 256, binary_operator:PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU); 257, line_continuation:\; 258, attribute; 259, attribute; 260, parenthesized_expression; 261, binary_operator:8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED; 262, binary_operator:PHYS.PLANCK / (mom * PHYS.ME_PER_AMU); 263, line_continuation:\; 264, parenthesized_expression; 265, binary_operator:2.0 * mom; 266, attribute; 267, identifier:PHYS; 268, identifier:PLANCK_BAR; 269, binary_operator:2.0 * mom * PHYS.ME_PER_AMU; 270, binary_operator:4.0 * np.pi * mom; 271, attribute; 272, identifier:PHYS; 273, identifier:PLANCK_BAR; 274, binary_operator:4.0 * np.pi * mom * PHYS.ME_PER_AMU; 275, attribute; 276, parenthesized_expression; 277, identifier:PHYS; 278, identifier:SEC_PER_TA; 279, identifier:PHYS; 280, identifier:PLANCK; 281, binary_operator:mom * PHYS.ME_PER_AMU; 282, binary_operator:8.0 * np.pi**2.0; 283, attribute; 284, attribute; 285, parenthesized_expression; 286, binary_operator:8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED * PHYS.ANG_PER_BOHR; 287, float:2.0; 288, identifier:mom; 289, identifier:PHYS; 290, identifier:ME_PER_AMU; 291, binary_operator:2.0 * mom; 292, attribute; 293, binary_operator:4.0 * np.pi; 294, identifier:mom; 295, identifier:PHYS; 296, identifier:ME_PER_AMU; 297, binary_operator:4.0 * np.pi * mom; 298, attribute; 299, identifier:PHYS; 300, identifier:PLANCK_BAR; 301, binary_operator:4.0 * np.pi * mom * PHYS.ME_PER_AMU; 302, identifier:mom; 303, attribute; 304, float:8.0; 305, binary_operator:np.pi**2.0; 306, identifier:PHYS; 307, identifier:LIGHT_SPEED; 308, identifier:PHYS; 309, identifier:PLANCK; 310, binary_operator:mom * PHYS.ME_PER_AMU; 311, binary_operator:8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED; 312, attribute; 313, float:2.0; 314, identifier:mom; 315, identifier:PHYS; 316, identifier:ME_PER_AMU; 317, float:4.0; 318, attribute; 319, binary_operator:4.0 * np.pi; 320, identifier:mom; 321, identifier:PHYS; 322, identifier:ME_PER_AMU; 323, binary_operator:4.0 * np.pi * mom; 324, attribute; 325, identifier:PHYS; 326, identifier:ME_PER_AMU; 327, attribute; 328, float:2.0; 329, identifier:mom; 330, attribute; 331, binary_operator:8.0 * np.pi**2.0; 332, attribute; 333, identifier:PHYS; 334, identifier:ANG_PER_BOHR; 335, identifier:np; 336, identifier:pi; 337, float:4.0; 338, attribute; 339, binary_operator:4.0 * np.pi; 340, identifier:mom; 341, identifier:PHYS; 342, identifier:ME_PER_AMU; 343, identifier:np; 344, identifier:pi; 345, identifier:PHYS; 346, identifier:ME_PER_AMU; 347, float:8.0; 348, binary_operator:np.pi**2.0; 349, identifier:PHYS; 350, identifier:LIGHT_SPEED; 351, identifier:np; 352, identifier:pi; 353, float:4.0; 354, attribute; 355, attribute; 356, float:2.0; 357, identifier:np; 358, identifier:pi; 359, identifier:np; 360, identifier:pi
code: def rot_consts(geom, masses, units=_EURC.INV_INERTIA, on_tol=_DEF.ORTHONORM_TOL):
      """Rotational constants for a given molecular system.
  
      Calculates the rotational constants for the provided system with numerical
      value given in the units provided in `units`.  The orthnormality tolerance
      `on_tol` is required in order to be passed through to the
      :func:`principals` function.
  
      If the system is linear or a single atom, the effectively-zero principal
      moments of inertia will be assigned values of
      :data:`opan.const.PRM.ZERO_MOMENT_TOL`
      before transformation into the appropriate rotational constant units.
  
      The moments of inertia are always sorted in increasing order as
      :math:`0 \\leq I_A \\leq I_B \\leq I_C`; the rotational constants
      calculated from these will thus always be in **decreasing** order
      as :math:`B_A \\geq B_B \\geq B_C`, retaining the
      ordering and association with the three principal ``axes[:,i]`` generated
      by :func:`principals`.
  
      Parameters
      ----------
      geom
          length-3N |npfloat_| --
          Coordinates of the atoms
  
      masses
          length-N OR length-3N |npfloat_| --
          Atomic masses of the atoms. Length-3N option is to allow calculation of
          a per-coordinate perturbed value.
  
      units
          :class:`~opan.const.EnumUnitsRotConst`, optional --
          Enum value indicating the desired units of the output rotational
          constants. Default is :data:`~opan.const.EnumUnitsRotConst.INV_INERTIA`
          :math:`\\left(1\\over \\mathrm{uB^2}\\right)`
  
      on_tol
          |npfloat_|,  optional --
          Tolerance for deviation from unity/zero for principal axis dot
          products, within which axes are considered orthonormal. Default is
          :data:`opan.const.DEF.ORTHONORM_TOL`
  
      Returns
      -------
      rc
          length-3 |npfloat_| --
          Vector of rotational constants in the indicated units
  
      """
  
      # Imports
      import numpy as np
      from ..const import EnumTopType as ETT, EnumUnitsRotConst as EURC, PRM, PHYS
  
      # Ensure units are valid
      if not units in EURC:
          raise ValueError("'{0}' is not a valid units value".format(units))
      ## end if
  
      # Retrieve the moments, axes and top type. Geom and masses are proofed
      #  internally in this call.
      mom, ax, top = principals(geom, masses, on_tol)
  
      # Check for special cases
      if top == ETT.ATOM:
          # All moments are zero; set to zero-moment threshold
          mom = np.repeat(PRM.ZERO_MOMENT_TOL, 3)
      elif top == ETT.LINEAR:
          # First moment is zero; set to zero-moment threshold
          mom[0] = PRM.ZERO_MOMENT_TOL
      ## end if
  
      # Calculate the values in the indicated units
      if units == EURC.INV_INERTIA:            # 1/(amu*B^2)
          rc = 1.0 / (2.0 * mom)
      elif units == EURC.ANGFREQ_ATOMIC:       # 1/Ta
          rc = PHYS.PLANCK_BAR / (2.0 * mom * PHYS.ME_PER_AMU)
      elif units == EURC.ANGFREQ_SECS:      # 1/s
          rc = PHYS.PLANCK_BAR / (2.0 * mom * PHYS.ME_PER_AMU) / PHYS.SEC_PER_TA
      elif units == EURC.CYCFREQ_ATOMIC:    # cyc/Ta
          rc = PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU)
      elif units == EURC.CYCFREQ_HZ:        # cyc/s
          rc = PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU) / \
                                                              PHYS.SEC_PER_TA
      elif units == EURC.CYCFREQ_MHZ:       # Mcyc/s
          rc = PHYS.PLANCK_BAR / (4.0 * np.pi * mom * PHYS.ME_PER_AMU) / \
                                                      PHYS.SEC_PER_TA / 1.0e6
      elif units == EURC.WAVENUM_ATOMIC:       # cyc/B
          rc = PHYS.PLANCK / (mom * PHYS.ME_PER_AMU) / \
              (8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED)
      elif units == EURC.WAVENUM_CM:           # cyc/cm
          rc = PHYS.PLANCK / (mom * PHYS.ME_PER_AMU) / \
              (8.0 * np.pi**2.0 * PHYS.LIGHT_SPEED * PHYS.ANG_PER_BOHR) * 1.0e8
      else:               # pragma: no cover -- Valid units; not implemented
          raise NotImplementedError("Units conversion not yet implemented.")
      ## end if
  
      # Return the result
      return rc