docs: def calculate_all_nfs(sample_frame, ranked_targets, ref_sample):
      """For a set of n ranked_genes, calculates normalization factors NF_1,
      NF_2, ..., NF_n. NF_i represents the normalization factor generated by
      considering the first i targets in ranked_targets.
      
      calculate_nf (which returns only NF_n) is probably more
      useful for routine analysis.
  
      :param DataFrame sample_frame: A sample data frame.
      :param iterable ranked_targets: A list or Series of target names, in order
          of descending stability (ascending M).
      :param string ref_sample: The name of the sample to normalize against.
      :return: a DataFrame with columns 1, 2, ..., n containing normalization
          factors NF_1, ..., NF_n for each sample, indexed by sample name.
      :rtype: DataFrame
      """
  
      # Returns a DataFrame, where rows represent samples and columns represent a number of reference genes.
      grouped = sample_frame.groupby(['Target', 'Sample'])['Cq'].aggregate(average_cq)
      samples = sample_frame['Sample'].unique()
      nfs = {}
      for i in xrange(1, len(ranked_targets)+1):
          nfs[i] = gmean([pow(2, -grouped.ix[zip(repeat(ref_gene), samples)] + grouped.ix[ref_gene, ref_sample]) for ref_gene in ranked_targets[:i]])
      return pd.DataFrame(nfs, index=samples)