code: def uncontract_spdf(basis, max_am=0, use_copy=True):
      
  
      if use_copy:
          basis = copy.deepcopy(basis)
  
      for k, el in basis['elements'].items():
  
          if not 'electron_shells' in el:
              continue
          newshells = []
  
          for sh in el['electron_shells']:
  
              # am will be a list
              am = sh['angular_momentum']
              coeff = sh['coefficients']
  
              # if this is an sp, spd,...  orbital
              if len(am) > 1:
                  newsh = sh.copy()
                  newsh['angular_momentum'] = []
                  newsh['coefficients'] = []
  
                  ngen = len(sh['coefficients'])
                  for g in range(ngen):
                      if am[g] > max_am:
                          newsh2 = sh.copy()
                          newsh2['angular_momentum'] = [am[g]]
                          newsh2['coefficients'] = [coeff[g]]
                          newshells.append(newsh2)
                      else:
                          newsh['angular_momentum'].append(am[g])
                          newsh['coefficients'].append(coeff[g])
  
                  newshells.insert(0, newsh)
  
              else:
                  newshells.append(sh)
  
          el['electron_shells'] = newshells
  
      return basis
docs: Removes sp, spd, spdf, etc, contractions from a basis set
  
      The general contractions are replaced by uncontracted versions
  
      Contractions up to max_am will be left in place. For example,
      if max_am = 1, spd will be split into sp and d
  
      The input basis set is not modified. The returned basis
      may have functions with coefficients of zero and may have duplicate
      shells.
  
      If use_copy is True, the input basis set is not modified.