code: def _compute_term_weights(
      candidates: list[Candidate],
      candidate_counts: dict[str, int],
      unique_candidates: set[str],
      n_toks: int,
      idf: Optional[dict[str, float]],
  ) -> dict[str, float]:
      """
      Compute term weights from statistical attributes: position of first occurrence,
      not subsumed frequency, and number of constituent words.
      """
      clen: float
      term_weights = {}
      seen_terms = set()
      n_toks_p1 = n_toks + 1
      for cand in candidates:
          # we only want the *first* occurrence of a unique term (by its text)
          if cand.text in seen_terms:
              continue
          else:
              seen_terms.add(cand.text)
          pos_first_occ = math.log(n_toks_p1 / (cand.idx + 1))
          # TODO: do we want to sub-linear scale term len or not?
          clen = math.sqrt(cand.length)
          # subtract from subsum_count for the case when ctext == ctext2
          subsum_count = (
              sum(
                  candidate_counts[ctext2]
                  for ctext2 in unique_candidates
                  if cand.text in ctext2
              )
              - cand.count
          )
          term_freq_factor = cand.count - subsum_count
          if idf and clen == 1:
              term_freq_factor *= idf.get(cand.text, 1)
          term_weights[cand.text] = (
              term_freq_factor * pos_first_occ * clen
          )
      return term_weights
  
file_path: textacy/src/textacy/extract/keyterms/sgrank.py
imports: from __future__ import annotations
  import collections
  import itertools
  import math
  from operator import itemgetter
  from typing import Callable, Collection, Counter, Optional
  import networkx
  from spacy.tokens import Doc, Span
  from ...None import utils
  from ..None import utils
label_desc: Use image node_id 4 for calling a global function with example usage: _compute_term_weights(candidates, candidate_counts, unique_candidates, n_toks, idf) and returns: term_weights