code: def coupling(corpus_or_featureset, featureset_name=None,
               min_weight=1, filter=lambda f, v, c, dc: True,
               node_attrs=[]):
      
  
      featureset = _get_featureset(corpus_or_featureset, featureset_name)
  
      c = lambda f: featureset.count(f)           # Overall count.
      dc = lambda f: featureset.documentCount(f)  # Document count.
      f = lambda elem: featureset.index[elem]
      v = lambda p, f: featureset.features[p].value(f)
  
      select = lambda p, elem: filter(f(elem), v(p, f(elem)), c(f(elem)), dc(f(elem)))
  
      pairs = defaultdict(list)
      for elem, papers in featureset.with_feature.iteritems():
          selected = [p for p in papers if select(p, elem)]
          for combo in combinations(selected, 2):
              combo = tuple(sorted(combo))
              pairs[combo].append(featureset.index[elem])
  
      graph = nx.Graph()
      for combo, features in pairs.iteritems():
          count = len(features)
          if count >= min_weight:
              graph.add_edge(combo[0], combo[1], features=features, weight=count)
  
      # Add node attributes.
      for attr in node_attrs:
          for node in graph.nodes():
              value = ''
              if node in corpus_or_featureset:
                  paper = corpus_or_featureset[node]
                  if hasattr(paper, attr):
                      value = getattr(paper, attr)
                      if value is None:
                          value = ''
                      elif callable(value):
                          value = value()
              graph.node[node][attr] = value
  
      return graph
docs: A network of papers linked by their joint posession of features.