docs: def read_intensities(file_name, needed_markers_chr, needed_samples_gender,
                       sex_problems):
      """Reads the intensities from a file.
  
      :param file_name: the name of the input file.
      :param needed_markers_chr: the markers that are needed.
      :param needed_samples_gender: the gender of all the samples.
      :param sex_problems: the sample with sex problem.
  
      :type file_name: str
      :type needed_markers_chr: dict
      :type needed_samples_gender: dict
      :type sex_problems: frozenset
  
      :returns: a :py:class`numpy.recarray` containing the following columns (for
                each of the samples): ``sampleID``, ``chr23``, ``chr24``,
                ``gender`` and ``status``.
  
      Reads the normalized intensities from a final report. The file must contain
      the following columns: ``SNP Name``, ``Sample ID``, ``X``, ``Y`` and
      ``Chr``. It then keeps only the required markers (those that are on
      sexual chromosomes (``23`` or ``24``), encoding `NaN` intensities to zero.
  
      The final data set contains the following information for each sample:
  
      * ``sampleID``: the sample ID.
      * ``chr23``: the summarized intensities for chromosome 23.
      * ``chr24``: the summarized intensities for chromosome 24.
      * ``gender``: the gender of the sample (``Male`` or ``Female``).
      * ``status``: the status of the sample (``OK`` or ``Problem``).
  
      The summarized intensities for a chromosome (:math:`S_{chr}`) is computed
      using this formula (where :math:`I_{chr}` is the set of all marker
      intensities on chromosome :math:`chr`):
  
      .. math::
          S_{chr} = \\frac{\\sum{I_{chr}}}{||I_{chr}||}
  
      """
      input_file = None
      if file_name.endswith(".gz"):
          input_file = gzip.open(file_name, 'rb')
      else:
          input_file = open(file_name, 'r')
  
      # The intensities
      intensities = {}
  
      header_index = None
      for line_nb, line in enumerate(input_file):
          row = line.rstrip("\r\n").split("\t")
  
          if line_nb == 0:
              # This is the header
              header_index = dict([
                  (col_name, i) for i, col_name in enumerate(row)
              ])
              # Check the column names
              for col_name in {"SNP Name", "Sample ID", "X", "Y", "Chr"}:
                  if col_name not in header_index:
                      msg = "{}: no column named {}".format(file_name, col_name)
                      raise ProgramError(msg)
          else:
              # This is the data
              # Check if we want this sample and this marker
              sampleID = row[header_index["Sample ID"]]
              markerID = row[header_index["SNP Name"]]
              chromosome = encode_chr(row[header_index["Chr"]])
              if chromosome not in {23, 24}:
                  # Not good chromsoome
                  continue
              if sampleID not in needed_samples_gender:
                  # Sample not needed
                  continue
              if markerID not in needed_markers_chr:
                  # Marker not needed
                  continue
  
              if sampleID not in intensities:
                  # First time we see this sample
                  intensities[sampleID] = [0, 0, 0, 0]
  
              # We get the intensities
              allele_a = row[header_index["X"]]
              allele_b = row[header_index["Y"]]
  
              # Check for NaN
              if allele_a == "NaN" or allele_b == "NaN":
                  continue
              try:
                  allele_a = float(allele_a)
                  allele_b = float(allele_b)
              except ValueError:
                  msg = "{}: {} and {}: wrong intensities".format(file_name,
                                                                  allele_a,
                                                                  allele_b)
                  raise ProgramError(msg)
  
              if chromosome == 23:
                  # Chromosome 23
                  intensities[sampleID][0] += allele_a + allele_b
                  intensities[sampleID][1] += 1
              else:
                  # Chromosome 24
                  intensities[sampleID][2] += allele_a + allele_b
                  intensities[sampleID][3] += 1
  
      # Closing the input file
      input_file.close()
  
      # Creating the data structure
      data = []
      for sampleID in intensities.iterkeys():
          sum_chr_23, nb_chr_23, sum_chr_24, nb_chr_24 = intensities[sampleID]
          status = "OK"
          if sampleID in sex_problems:
              status = "Problem"
          try:
              data.append((sampleID, sum_chr_23 / nb_chr_23, sum_chr_24 /
                           nb_chr_24, needed_samples_gender[sampleID], status))
          except ZeroDivisionError:
              msg = "0 marker on chr23 or chr24"
              raise ProgramError(msg)
  
      data = np.array(
          data,
          dtype=[("sampleID", "a{}".format(max([len(i[0]) for i in data]))),
                 ("chr23", float),
                 ("chr24", float),
                 ("gender", "a{}".format(max([len(i[3]) for i in data]))),
                 ("status", "a{}".format(max([len(i[4]) for i in data])))],
      )
      return data