private Pair<WholeNetworkAlter, NameMapping> findAlter(Interview interview, Integer alterNumber) {

    for (WholeNetworkAlter alter : wholeNetworkAlters.values()) {
      for (NameMapping mapping : alter.getOccurences()) {
        if (mapping.getInterview().equals(interview)
            && mapping.getAlterNumber().equals(alterNumber))
          return new Pair<WholeNetworkAlter, NameMapping>(alter, mapping);
      }
    }
    return null;
    // throw new IllegalArgumentException("Alter did not exist -- it must have been derived from
    // somewhere, so we *must* find it");
  }
  public void build(Function2<Map<String, String>, Interview, Integer> getAlterAttributes) {
    wholeNetworkAlters = new HashMap<Integer, WholeNetworkAlter>();
    wholeNetworkTies = new HashMap<Pair<WholeNetworkAlter, WholeNetworkAlter>, WholeNetworkTie>();

    // add all alters
    for (NameMapping mapping : nameMap) {
      int group = mapping.getGroup();
      if (!wholeNetworkAlters.containsKey(group)) {
        wholeNetworkAlters.put(group, new WholeNetworkAlter(group));
      }

      WholeNetworkAlter alter = wholeNetworkAlters.get(group);
      alter.addOccurence(mapping);
    }

    // remove WholeNetworkAlters that are not mentioned in enough interviews
    Map<Integer, WholeNetworkAlter> remainingAlters = new HashMap<Integer, WholeNetworkAlter>();
    for (Entry<Integer, WholeNetworkAlter> entry : wholeNetworkAlters.entrySet()) {
      if (entry.getValue().getOccurences().size() < settings.inclusionThreshold) {
        if (settings.alwaysIncludeEgo) {
          boolean isEgo = false;
          for (NameMapping occurrence : entry.getValue().getOccurences()) {
            if (occurrence.getAlterNumber().equals(-1)) {
              isEgo = true;
            }
          }
          if (isEgo) {
            remainingAlters.put(entry.getKey(), entry.getValue());
          }
        }
      } else {
        // Include alter only if mentioned in enough interviews.
        remainingAlters.put(entry.getKey(), entry.getValue());
      }
    }
    wholeNetworkAlters = remainingAlters;

    // Set attributes for remaining alters
    for (WholeNetworkAlter wholeNetworkAlter : wholeNetworkAlters.values()) {
      for (NameMapping mapping : wholeNetworkAlter.getOccurences()) {
        wholeNetworkAlter.addAttributes(
            getAlterAttributes.call(mapping.getInterview(), mapping.getAlterNumber()));
      }
    }

    for (Interview interview : interviews) {

      String[] thisInterviewAlterlist = interview.getAlterList();

      // tie the ego to all alters
      Pair<WholeNetworkAlter, NameMapping> ego = findAlter(interview, -1);
      if (ego != null) {
        for (int i = 0; i < interview.getAlterList().length; i++) {
          Pair<WholeNetworkAlter, NameMapping> alter = findAlter(interview, i);
          if (alter != null) {
            tie(ego, alter, ego.getFirst().getId(), true, true);
          }
        }
      }

      // tie adjacent alters together
      Iterator<Long> questions = study.getQuestionOrder(AlterPairQuestion.class).iterator();
      while (questions.hasNext()) {
        Question q = study.getQuestion((Long) questions.next());
        if (q.determinesAdjacency()) {
          try {
            int[][] adj = interview.generateAdjacencyMatrix(q, false);
            // int [][] adjWeight = interview.generateAdjacencyMatrix(q, true);

            // loop through adj
            // if adj[i][j] == 1, thisInterviewAlters[i] && thisInterviewAlters[j] are adjacent in
            // final matrix

            int alters = Math.min(adj.length, thisInterviewAlterlist.length);
            for (int i = 0; i < alters; i++) {
              for (int j = i + 1; j < alters; j++) {
                boolean adjacent = adj[i][j] == 1;
                String alter1 = thisInterviewAlterlist[i];
                String alter2 = thisInterviewAlterlist[j];
                logger.debug(
                    alter1
                        + "("
                        + i
                        + ") and "
                        + alter2
                        + "("
                        + j
                        + ") are"
                        + (adjacent ? " " : " not ")
                        + "adjacent");

                // find whole network alters
                Pair<WholeNetworkAlter, NameMapping> wholeAlter1 = findAlter(interview, i);
                Pair<WholeNetworkAlter, NameMapping> wholeAlter2 = findAlter(interview, j);

                if (wholeAlter1 != null && wholeAlter2 != null) {
                  if (wholeAlter1.getFirst().compareTo(wholeAlter2.getFirst()) > 0) {
                    Pair<WholeNetworkAlter, NameMapping> swap = wholeAlter1;
                    wholeAlter1 = wholeAlter2;
                    wholeAlter2 = swap;
                  }

                  // TODO: strength of tie, even if not adjacent
                  tie(
                      wholeAlter1,
                      wholeAlter2,
                      ego == null ? null : ego.getFirst().getId(),
                      adjacent,
                      false);
                }
              }
            }
          } catch (MissingPairException ex) {
            logger.error("Couldn't create adjacency matrix for question " + q, ex);
          }
        }
      }
    }

    logger.info("# Alters: " + wholeNetworkAlters.size() + ", # Ties: " + wholeNetworkTies.size());
  }