code: def select_copula(cls, X):
          
          frank = Bivariate(CopulaTypes.FRANK)
          frank.fit(X)
  
          if frank.tau <= 0:
              selected_theta = frank.theta
              selected_copula = CopulaTypes.FRANK
              return selected_copula, selected_theta
  
          copula_candidates = [frank]
          theta_candidates = [frank.theta]
  
          try:
              clayton = Bivariate(CopulaTypes.CLAYTON)
              clayton.fit(X)
              copula_candidates.append(clayton)
              theta_candidates.append(clayton.theta)
          except ValueError:
              # Invalid theta, copula ignored
              pass
  
          try:
              gumbel = Bivariate(CopulaTypes.GUMBEL)
              gumbel.fit(X)
              copula_candidates.append(gumbel)
              theta_candidates.append(gumbel.theta)
          except ValueError:
              # Invalid theta, copula ignored
              pass
  
          z_left, L, z_right, R = cls.compute_empirical(X)
          left_dependence, right_dependence = cls.get_dependencies(
              copula_candidates, z_left, z_right)
  
          # compute L2 distance from empirical distribution
          cost_L = [np.sum((L - l) ** 2) for l in left_dependence]
          cost_R = [np.sum((R - r) ** 2) for r in right_dependence]
          cost_LR = np.add(cost_L, cost_R)
  
          selected_copula = np.argmax(cost_LR)
          selected_theta = theta_candidates[selected_copula]
          return CopulaTypes(selected_copula), selected_theta
docs: Select best copula function based on likelihood.
  
          Args:
              X: 2-dimensional `np.ndarray`
  
          Returns:
              tuple: `tuple(CopulaType, float)` best fit and model param.