code: def associated_legendre_polynomials(
      L, zero_m_only=True, pos_m_only=True
  ):
      """Computes string formulas of the associated legendre polynomials up to degree L (excluded).
      Parameters
      ----------
          L: int
              Degree up to which to calculate the associated legendre polynomials (degree L is excluded).
          zero_m_only: bool
              If True only calculate the polynomials for the polynomials where m=0.
          pos_m_only: bool
              If True only calculate the polynomials for the polynomials where m>=0. Overwritten by zero_m_only.
      Returns
      -------
          polynomials: list
              Contains the sympy functions of the polynomials (in total L many if zero_m_only is True else L^2 many).
      """
      # calculations from http://web.cmb.usc.edu/people/alber/Software/tomominer/docs/cpp/group__legendre__polynomials.html
      z = sym.symbols("z")
      P_l_m = [
          [0] * (2 * l + 1) for l in range(L)
      ]  # for order l: -l <= m <= l
  
      P_l_m[0][0] = 1
      if L > 0:
          if zero_m_only:
              # m = 0
              P_l_m[1][0] = z
              for l in range(2, L):
                  P_l_m[l][0] = sym.simplify(
                      (
                          (2 * l - 1) * z * P_l_m[l - 1][0]
                          - (l - 1) * P_l_m[l - 2][0]
                      )
                      / l
                  )
              return P_l_m
          else:
              # for m >= 0
              for l in range(1, L):
                  P_l_m[l][l] = sym.simplify(
                      (1 - 2 * l)
                      * (1 - z**2) ** 0.5
                      * P_l_m[l - 1][l - 1]
                  )  # P_00, P_11, P_22, P_33
  
              for m in range(0, L - 1):
                  P_l_m[m + 1][m] = sym.simplify(
                      (2 * m + 1) * z * P_l_m[m][m]
                  )  # P_10, P_21, P_32, P_43
  
              for l in range(2, L):
                  for m in range(l - 1):  # P_20, P_30, P_31
                      P_l_m[l][m] = sym.simplify(
                          (
                              (2 * l - 1) * z * P_l_m[l - 1][m]
                              - (l + m - 1) * P_l_m[l - 2][m]
                          )
                          / (l - m)
                      )
  
              if not pos_m_only:
                  # for m < 0: P_l(-m) = (-1)^m * (l-m)!/(l+m)! * P_lm
                  for l in range(1, L):
                      for m in range(
                          1, l + 1
                      ):  # P_1(-1), P_2(-1) P_2(-2)
                          P_l_m[l][-m] = sym.simplify(
                              (-1) ** m
                              * np.math.factorial(l - m)
                              / np.math.factorial(l + m)
                              * P_l_m[l][m]
                          )
  
              return P_l_m
  
file_path: DIG/dig/threedgraph/method/comenet/ocp/utils.py
imports: import torch
  import sympy
  import numpy
  from scipy.optimize import brentq
  from scipy import special
label_desc: Use image node_id 6 for calling a global function with example usage: associated_legendre_polynomials(L, zero_m_only, pos_m_only) and returns: P_l_m, P_l_m