docs: def merge_related_samples(file_name, out_prefix, no_status):
      """Merge related samples.
  
      :param file_name: the name of the input file.
      :param out_prefix: the prefix of the output files.
      :param no_status: is there a status column in the file?
  
      :type file_name: str
      :type out_prefix: str
      :type no_status: boolean
  
      In the output file, there are a pair of samples per line. Hence, one can
      find related individuals by merging overlapping pairs.
  
      """
      # What we need to save
      status = {}
      samples_sets = []
      open_function = open
      if file_name.endswith(".gz"):
          open_function = gzip.open
      with open_function(file_name, 'rb') as input_file:
          header_index = dict([
              (col_name, i) for i, col_name in
              enumerate(input_file.readline().rstrip("\r\n").split("\t"))
          ])
          for col_name in {"FID1", "IID1", "FID2", "IID2"}:
              if col_name not in header_index:
                  msg = "{}: no column named {}".format(file_name, col_name)
                  raise ProgramError(msg)
          if not no_status:
              if "status" not in header_index:
                  msg = "{}: no column named status".format(file_name)
                  raise ProgramError(msg)
  
          for line in input_file:
              row = line.rstrip("\r\n").split("\t")
              sample_1 = (row[header_index["FID1"]], row[header_index["IID1"]])
              sample_2 = (row[header_index["FID2"]], row[header_index["IID2"]])
              tmp_set = {sample_1, sample_2}
              match = False
              for i in xrange(len(samples_sets)):
                  if len(tmp_set & samples_sets[i]) > 0:
                      # We have a match
                      samples_sets[i] |= tmp_set
                      match = True
              if not match:
                  # We did not find a match, so we add
                  samples_sets.append(tmp_set)
  
              # Check for the status
              the_status = "None"
              if not no_status:
                  the_status = row[header_index["status"]]
              status[(sample_1, sample_2)] = the_status
  
      # Doing a final check
      final_samples_set = []
      removed = set()
      for i in xrange(len(samples_sets)):
          if i in removed:
              # We removed this group
              continue
          group = samples_sets[i]
          j = i + 1
          while j < len(samples_sets):
              if j in removed:
                  j += 1
                  continue
              if len(group & samples_sets[j]) > 0:
                  # We have a match, we start from the beginning
                  group |= samples_sets[j]
                  removed.add(j)
                  j = i + 1
                  continue
              j += 1
  
          final_samples_set.append(group)
  
      # Printing the output file
      output_file = None
      try:
          output_file = open(out_prefix + ".merged_related_individuals", 'w')
          to_print = ["index", "FID1", "IID1", "FID2", "IID2"]
          if not no_status:
              to_print.append("status")
          print >>output_file, "\t".join(to_print)
      except IOError:
          msg = "{}: can't write file".format(out_prefix +
                                              ".merged_related_individuals")
          raise ProgramError(msg)
  
      # Iterating on the groups
      chosen_samples = set()
      remaining_samples = set()
      for i, group in enumerate(final_samples_set):
          index = str(i+1)
          for sample_1, sample_2 in status.iterkeys():
              if (sample_1 in group) and (sample_2 in group):
                  to_print = [index, sample_1[0], sample_1[1], sample_2[0],
                              sample_2[1]]
                  if not no_status:
                      to_print.append(status[(sample_1, sample_2)])
                  print >>output_file, "\t".join(to_print)
  
          # Choose a random sample from the group
          chosen = random.choice(list(group))
          chosen_samples.add(chosen)
          remaining_samples |= group - {chosen}
  
      # Printing the files
      try:
          filename = out_prefix + ".chosen_related_individuals"
          with open(filename, "w") as chosen_file:
              for sample_id in chosen_samples:
                  print >>chosen_file, "\t".join(sample_id)
  
          filename = out_prefix + ".discarded_related_individuals"
          with open(filename, "w") as discarded_file:
              for sample_id in remaining_samples:
                  print >>discarded_file, "\t".join(sample_id)
      except IOError:
          msg = "{}: can't write files".format(out_prefix + ".*")
          raise ProgramError(msg)
  
      # Closing the output file
      output_file.close()