Process anat_entity files with columns:
        Ensembl gene ID,gene name, anatomical entity ID,
        anatomical entity name, rank score, XRefs to BTO

        :param fh: filehandle
        :param limit: int, limit per group
        :return: None
175339
def _parse_gene_anatomy(self, fh, limit):
        
        dataframe = pd.read_csv(fh, sep='\t')
        col = self.files['anat_entity']['columns']
        if list(dataframe) != col:
            LOG.warning(
                '\nExpected headers:  %s\nRecived headers:  %s', col, list(dataframe))

        gene_groups = dataframe.sort_values(
            'rank score', ascending=False).groupby('Ensembl gene ID')

        if limit is None:
            limit = 20
        gene_groups = gene_groups.head(limit).groupby('Ensembl gene ID')

        for gene, group in gene_groups:
            for index, row in group.iterrows():
                self._add_gene_anatomy_association(
                    row['Ensembl gene ID'].strip(),
                    row['anatomical entity ID'].strip(),
                    row['rank score']
                )
                # uberon <==> bto equivelance?
        return
158279
def _process_voc_annot_view(self, limit):
        

        # TODO also get Strain/Attributes (annottypekey = 1000)
        # TODO what is Phenotype (Derived) vs
        # non-derived?  (annottypekey = 1015)
        # TODO is evidence in this table?  what is the evidence vocab key?
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        model = Model(graph)
        line_counter = 0
        LOG.info("getting G2P associations")
        raw = '/'.join((self.rawdir, 'voc_annot_view'))
        col = [
            'annot_key', 'annot_type', 'object_key', 'term_key', 'qualifier_key',
            'qualifier', 'term', 'accid']
        with open(raw, 'r') as f:
            header = f.readline()  # read the header row; skip
            if header != col:
                LOG.error("\nExpected header: %s\nReceived header: %s", col, header)

            for line in f:
                row = line.rstrip('\n').split('\t')

                annot_key = row[col.index('annot_key')]
                annot_type = row[col.index('annot_type')]
                object_key = row[col.index('object_key')]
                term_key = row[col.index('term_key')]
                qualifier_key = row[col.index('qualifier_key')]
                # qualifier,
                # term,
                accid = row[col.index('accid')]

                if self.test_mode is True:
                    if int(annot_key) not in self.test_keys.get('annot'):
                        continue

                # iassoc_id = self._makeInternalIdentifier('annot', annot_key)
                # assoc_id = self.make_id(iassoc_id)

                assoc_id = None
                # Mammalian Phenotype/Genotype are curated G2P assoc
                if annot_type == 'Mammalian Phenotype/Genotype':
                    line_counter += 1

                    # We expect the label for the phenotype
                    # to be taken care of elsewhere
                    model.addClassToGraph(accid, None)

                    genotype_id = self.idhash['genotype'].get(object_key)
                    if genotype_id is None:
                        LOG.error(
                            "can't find genotype id for %s", object_key)
                    else:
                        # add the association
                        assoc = G2PAssoc(graph, self.name, genotype_id, accid)
                        assoc.add_association_to_graph()
                        assoc_id = assoc.get_association_id()
                # OMIM/Genotype are disease-models
                elif annot_type == 'DO/Genotype':
                    # skip NOT annotations for now FIXME
                    if qualifier_key == '1614157':
                        continue
                    genotype_id = self.idhash['genotype'].get(object_key)
                    if genotype_id is None:
                        LOG.error("can't find genotype id for %s", object_key)
                    else:
                        # add the association
                        assoc = Assoc(graph, self.name)
                        # TODO PYLINT
                        # Redefinition of assoc type from
                        # dipper.models.assoc.G2PAssoc.G2PAssoc to
                        # dipper.models.assoc.Association.Assoc
                        assoc.set_subject(genotype_id)
                        assoc.set_object(accid)
                        assoc.set_relationship(self.globaltt['is model of'])
                        assoc.add_association_to_graph()
                        assoc_id = assoc.get_association_id()
                elif annot_type == 'MCV/Marker':
                    # marker category == type
                    marker_id = self.idhash['marker'].get(object_key)
                    if str(term_key).strip() in self.localtt:
                        term_id = self.resolve(str(term_key).strip())
                    else:
                        term_id = None
                        logging.warning('No type mapping for: %s', term_key)
                    # note that the accid here is an internal mouse cv term,
                    # and we don't use it.
                    if term_id is not None and marker_id is not None:
                        # do something special for transgenics -
                        # make sure these are transgenic insertions
                        model.addType(marker_id, term_id)
                elif annot_type == 'DO/Allele':  # allele/Disease
                    allele_id = self.idhash['allele'].get(object_key)
                    if allele_id is None:
                        LOG.error("can't find genotype id for %s", object_key)
                    else:
                        # add the association
                        assoc = Assoc(graph, self.name)
                        assoc.set_subject(allele_id)
                        assoc.set_object(accid)
                        assoc.set_relationship(self.globaltt['is model of'])
                        assoc.add_association_to_graph()
                        assoc_id = assoc.get_association_id()

                if assoc_id is not None:
                    # add the assoc to the hashmap (using the monarch id)
                    self.idhash['annot'][annot_key] = assoc_id
                    model.addComment(assoc_id, "annot_key:" + annot_key)

                if not self.test_mode and limit is not None and line_counter > limit:
                    break

        return
789245
def from_file(cls, fname, form=None):
        
        try:
            tg = TableGroup.from_file(fname)
            opfname = None
        except JSONDecodeError:
            tg = TableGroup.fromvalue(cls.MD)
            opfname = fname
        if len(tg.tables) != 1:
            raise ValueError('profile description must contain exactly one table')
        metadata = tg.common_props
        metadata.update(fname=Path(fname), form=form)
        return cls(
            *[{k: None if (k != cls.GRAPHEME_COL and v == cls.NULL) else v for k, v in d.items()}
              for d in tg.tables[0].iterdicts(fname=opfname)],
            **metadata)
800909
def process_mgi_relationship_transgene_genes(self, limit=None):
        
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        LOG.info("getting transgene genes")
        raw = '/'.join((self.rawdir, 'mgi_relationship_transgene_genes'))
        geno = Genotype(graph)
        col = [
            'rel_key', 'allele_key', 'allele_id', 'allele_label', 'category_key',
            'category_name', 'property_key', 'property_name', 'gene_num'
        ]
        with open(raw, 'r', encoding="utf8") as csvfile:
            filereader = csv.reader(csvfile, delimiter='\t', quotechar='\"')
            header = next(filereader)
            if header != col:
                LOG.error('expected columns:  %s\n\tBut got:\n%s', col, header)
            for row in filereader:
                # rel_key,
                allele_key = int(row[col.index('allele_key')])
                allele_id = row[col.index('allele_id')]
                # allele_label,
                # category_key,
                # category_name,
                # property_key,
                # property_name,
                gene_num = int(row[col.index('gene_num')])

                if self.test_mode and allele_key not in self.test_keys.get('allele')\
                        and gene_num not in self.test_ids:
                    continue

                gene_id = 'NCBIGene:' + str(gene_num)

                # geno.addParts(gene_id, allele_id, self.globaltt['has_variant_part'])
                seqalt_id = self.idhash['seqalt'].get(allele_key)
                if seqalt_id is None:
                    seqalt_id = allele_id
                geno.addSequenceDerivesFrom(seqalt_id, gene_id)

                if not self.test_mode and limit is not None and \
                        filereader.line_num > limit:
                    break

        return
873587
def _process_pathway_pubmed(self, limit):
        
        LOG.info("Processing KEGG pathways to pubmed ids")
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        line_counter = 0
        raw = '/'.join((self.rawdir, self.files['pathway_pubmed']['file']))
        with open(raw, 'r', encoding="iso-8859-1") as csvfile:
            filereader = csv.reader(csvfile, delimiter='\t', quotechar='\"')
            for row in filereader:
                line_counter += 1
                (pubmed_id, kegg_pathway_num) = row

                if self.test_mode and kegg_pathway_num not in self.test_ids['pathway']:
                    continue

                pubmed_id = pubmed_id.upper()
                # will look like KEGG-path:map04130
                kegg_id = 'KEGG-' + kegg_pathway_num

                r = Reference(graph, pubmed_id, self.globaltt['journal article'])
                r.addRefToGraph()
                graph.addTriple(pubmed_id, self.globaltt['is_about'], kegg_id)

                if not self.test_mode and limit is not None and line_counter > limit:
                    break

        return
1084522
def _process_pub_dbxref(self, limit):
        

        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        model = Model(graph)
        raw = '/'.join((self.rawdir, 'pub_dbxref'))
        LOG.info("processing pub_dbxref")

        line_counter = 0

        with open(raw, 'r') as f:
            filereader = csv.reader(f, delimiter='\t', quotechar='\"')
            f.readline()  # read the header row; skip
            for line in filereader:
                (pub_dbxref_id, pub_id, dbxref_id, is_current) = line
                # 49648	43222	395730	t

                pub_key = pub_id
                pub_id = self.idhash['publication'][pub_key]

                if self.test_mode and int(pub_key) not in self.test_keys['pub']:
                    continue

                # get any dbxrefs for pubs, including pmids and dois
                dbxref_key = dbxref_id
                if str(dbxref_key) in self.dbxrefs:
                    dbxrefs = self.dbxrefs[str(dbxref_key)]
                    # pub_dbs = [75, 51, 76, 95, 126]
                    pmid_ids = [50, 77, 275, 286, 347]
                    # flybase_ids = [4]  # TODO unused
                    isbn = [75, 51]
                    for d in dbxrefs:
                        dbxref_id = None
                        if int(d) in pmid_ids:
                            if re.match(r'^PMID', dbxrefs[d]):
                                dbxref_id = dbxrefs[d].strip()
                            else:
                                dbxref_id = 'PMID:'+dbxrefs[d].strip()
                            model.makeLeader(dbxref_id)
                        elif int(d) in isbn:
                            dbxref_id = 'ISBN:'+dbxrefs[d].strip()
                        elif int(d) == 161:
                            dbxref_id = 'DOI:'+dbxrefs[d].strip()
                        # elif int(d) == 4:
                        #     dbxref_id = 'FlyBase:'+dbxrefs[d].strip()

                        if dbxref_id is not None:
                            reference = Reference(
                                graph, dbxref_id, self.globaltt['publication'])
                            reference.addRefToGraph()
                            model.addSameIndividual(pub_id, dbxref_id)
                            line_counter += 1

                if not self.test_mode and limit is not None and line_counter > limit:
                    break

        return
549012
def _process_trait_mappings(self, raw, limit=None):
        
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        line_counter = 0
        model = Model(graph)

        with open(raw, 'r') as csvfile:
            filereader = csv.reader(csvfile, delimiter=',', quotechar='\"')
            next(filereader, None)  # skip header line
            for row in filereader:
                line_counter += 1
                # need to skip the last line
                if len(row) < 8:
                    LOG.info("skipping line %d: %s", line_counter, '\t'.join(row))
                    continue
                (vto_id, pto_id, cmo_id, ato_column, species, trait_class,
                 trait_type, qtl_count) = row

                ato_id = re.sub(
                    r'ATO #', 'AQTLTrait:', re.sub(
                        r'\].*', '', re.sub(r'\[', '', ato_column)))
                ato_id = ato_id.strip()

                ato_label = re.sub(r'.*\]\s*', '', ato_column)

                model.addClassToGraph(ato_id, ato_label.strip())

                if re.match(r'VT:.*', vto_id):
                    model.addClassToGraph(vto_id, None)
                    model.addEquivalentClass(ato_id, vto_id)
                if re.match(r'LPT:.*', pto_id):
                    model.addClassToGraph(pto_id, None)
                    model.addXref(ato_id, pto_id)
                if re.match(r'CMO:.*', cmo_id):
                    model.addClassToGraph(cmo_id, None)
                    model.addXref(ato_id, cmo_id)

        LOG.info("Done with trait mappings")
        return
1097049
def process_data(self, fname, tokenizer, max_size):
        
        logging.info(f'Processing data from {fname}')
        data = []
        with open(fname) as dfile:
            for idx, line in enumerate(dfile):
                if max_size and idx == max_size:
                    break
                entry = tokenizer.segment(line)
                entry = torch.tensor(entry)
                data.append(entry)
        return data
913918
def _process_pathway_ko(self, limit):
        
        LOG.info("Processing KEGG pathways to kegg ortholog classes")
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        line_counter = 0

        raw = '/'.join((self.rawdir, self.files['pathway_ko']['file']))
        with open(raw, 'r', encoding="iso-8859-1") as csvfile:
            filereader = csv.reader(csvfile, delimiter='\t', quotechar='\"')
            for row in filereader:
                line_counter += 1
                (ko_id, pathway_id) = row

                if self.test_mode and pathway_id not in self.test_ids['pathway']:
                    continue

                pathway_id = 'KEGG-' + pathway_id
                ko_id = 'KEGG-' + ko_id

                p = Pathway(graph)
                p.addGeneToPathway(ko_id, pathway_id)

                if not self.test_mode and limit is not None and line_counter > limit:
                    break

        return
1063316
def process_mgi_note_allele_view(self, limit=None):
        

        line_counter = 0
        if self.test_mode:
            graph = self.testgraph
        else:
            graph = self.graph
        model = Model(graph)
        LOG.info("Assembling notes on alleles")
        raw = '/'.join((self.rawdir, 'mgi_note_allele_view'))

        notehash = {}
        with open(raw, 'r', encoding="utf8") as csvfile:
            filereader = csv.reader(csvfile, delimiter='\t', quotechar='\"')
            for line in filereader:
                line_counter += 1
                if line_counter == 1:
                    continue

                (object_key, notetype, note, sequencenum) = line

                # read all the notes into a hash to concatenate
                if object_key not in notehash:
                    notehash[object_key] = {}
                if notetype not in notehash[object_key]:
                    notehash[object_key][notetype] = []
                if len(notehash[object_key][notetype]) < int(sequencenum):
                    for i in range(
                            len(notehash[object_key][notetype]),
                            int(sequencenum)
                    ):
                        notehash[object_key][notetype].append('')  # ??? I don't get it

                notehash[object_key][notetype][int(sequencenum)-1] = note.strip()

            # finish iteration over notes

        line_counter = 0
        for allele_key in notehash:
            if self.test_mode is True:
                if int(allele_key) not in self.test_keys.get('allele'):
                    continue
            line_counter += 1
            allele_id = self.idhash['allele'].get(allele_key)
            if allele_id is None:
                continue
            for n in notehash[allele_key]:
                LOG.info(
                    "found %d %s notes for %s",
                    len(notehash[allele_key]), n, allele_id)
                notes = ''.join(notehash[allele_key][n])
                notes += ' ['+n+']'
                model.addDescription(allele_id, notes)

            if not self.test_mode and limit is not None and line_counter > limit:
                break

        return
578517
def parse(self, limit=None, or_limit=1):
        
        dir_path = Path(self.rawdir)
        aeolus_file = dir_path / self.files['aeolus']['file']
        aeolus_fh = aeolus_file.open('r')
        count = 0
        for line in aeolus_fh.readlines():
            if limit is not None and count >= limit:
                break
            line = line.rstrip("\n,")
            if line != '[' and line != ']':
                self._parse_aeolus_data(document=json.loads(line),
                                        or_limit=or_limit)
                count += 1
            if count % 500 == 0:
                LOG.info("Processed %i documents", count)

        aeolus_fh.close()
        return
1177193
def _init_nt(self, flds):
        """"""
        term = flds[1]
        genes_str = flds[5]
        # pylint: disable=bad-whitespace
        return self.ntobj(
            Category   =       flds[0],
            GO         =       term[:10], #  1  GO:0045202~synapse
            name       =       term[10:], #  1  GO:0045202~synapse
            Count      =   int(flds[2]),  #  2  94
            Perc       = float(flds[3]),  #  3  9.456740442655935
            PValue     = float(flds[4]),  #  4  6.102654380458156E-20
            Genes      =      genes_str, # 5 ['ENSMUSG00000052613', ...]
            Genes_set  = self.get_genes(genes_str), # 5 ['ENSMUSG00000052613', ...]
            List_Total =   int(flds[6]),  #  6  920
            Pop_Hits   =   int(flds[7]),  #  7  444
            Pop_Total  =   int(flds[8]),  #  8  12002
            Fold_Enrichment = float(flds[9]), # 9 2.7619173521347435
            Bonferroni = float(flds[10]), # 10  3.3930758355347344E-17
            Benjamini  = float(flds[11]), # 11  3.3930758355347344E-17
            FDR        = float(flds[12]))
1062372
def parse_fasta_annotations(fastas, annot_tables, trans_table):
    
    if annot_tables is not False:
        annots = {}
        for table in annot_tables:
            for cds in open(table):
                ID, start, end, strand = cds.strip().split()
                annots[ID] = [start, end, int(strand)]
    for fasta in fastas:
        for seq in parse_fasta(fasta):
            if ('# ;gc_cont' not in seq[0] and '# ID=' not in seq[0]) and annot_tables is False:
                print('# specify fasta from Prodigal or annotations table (-t)', file=sys.stderr)
                exit()
            if 'ID=' in seq[0]:
                ID = seq[0].rsplit('ID=', 1)[1].split(';', 1)[0]
                contig = seq[0].split()[0].split('>')[1].rsplit('_%s' % (ID), 1)[0]
            else:
                contig = seq[0].split()[0].split('>')[1].rsplit('_', 1)[0]
            locus = seq[0].split()[0].split('>')[1]
            # annotation info from Prodigal
            if ('# ;gc_cont' in seq[0] or '# ID=' in seq[0]):
                info = seq[0].split(' # ')
                start, end, strand = int(info[1]), int(info[2]), info[3]
                if strand == '1':
                    strand = 1
                else:
                    strand = -1
                product = [''.join(info[4].split()[1:])]
            # annotation info from table
            else:
                start, end, strand = annots[locus]
                product = seq[0].split(' ', 1)[1]
            info = {'transl_table':[trans_table], \
                    'translation':[seq[1]], \
                    'product':product}
            yield contig, [locus, [start, end, strand], info]
1114816
def parse_snpeff_log(self, f):
        

        keys = {
            '# Summary table': [
                'Genome', 'Number_of_variants_before_filter',
                'Number_of_known_variants', 'Number_of_effects',
                'Genome_total_length', 'Change_rate'
            ],
            '# Effects by impact': [ 'HIGH', 'LOW', 'MODERATE', 'MODIFIER' ],
            '# Effects by functional class': [ 'MISSENSE', 'NONSENSE', 'SILENT', 'Missense_Silent_ratio' ],
            '# Hom/Het table': ['Het', 'Hom', 'Missing'],
            '# Ts/Tv summary': [ 'Transitions', 'Transversions', 'Ts_Tv_ratio' ],
            '# Count by effects': 'all',
            '# Count by genomic region': 'all'
        }
        parsed_data = {}
        section = None
        for l in f['f']:
            l = l.strip()
            if l[:1] == '#':
                section = l
                self.snpeff_section_totals[section] = dict()
                continue
            s = l.split(',')

            # Quality values / counts
            if section == '# Quality':
                quals = OrderedDict()
                if l.startswith('Values'):
                    values = [int(c) for c in l.split(',')[1:] ]
                    counts = f['f'].readline()
                    counts = [int(c) for c in counts.split(',')[1:] ]
                    c = 0
                    total = sum(counts)
                    for i, v in enumerate(values):
                        if c < (total * 0.995):
                            quals[v] = counts[i]
                            c += counts[i]
                if len(quals) > 0:
                    self.snpeff_qualities[f['s_name']] = quals

            # Everything else
            elif section in keys:
                if keys[section] == 'all' or any([k in s[0].strip() for k in keys[section]]):
                    try:
                        parsed_data[ s[0].strip() ] = float(s[1].strip())
                    except ValueError:
                        parsed_data[ s[0].strip() ] = s[1].strip()
                    except IndexError:
                        pass
                    else:
                        # Parsing the number worked - add to totals
                        try:
                            self.snpeff_section_totals[section][s[0].strip()] += parsed_data[ s[0].strip() ]
                        except KeyError:
                            self.snpeff_section_totals[section][s[0].strip()] = parsed_data[ s[0].strip() ]
                    if len(s) > 2 and s[2][-1:] == '%':
                        parsed_data[ '{}_percent'.format(s[0].strip()) ] = float(s[2][:-1])

        if len(parsed_data) > 0:
            if f['s_name'] in self.snpeff_data:
                log.debug("Duplicate sample name found! Overwriting: {}".format(f['s_name']))
            self.add_data_source(f)
            self.snpeff_data[f['s_name']] = parsed_data
976365
def get_transcript_ids_for_ensembl_gene_ids(self, gene_ids, hgnc_symbols):
        
        
        chroms = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", \
             "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", \
              "X", "Y"}
        
        headers = {"content-type": "application/json"}
        
        transcript_ids = []
        for gene_id in gene_ids:
            self.attempt = 0
            ext = "/overlap/id/{}?feature=transcript".format(gene_id)
            r = self.ensembl_request(ext, headers)
            
            for item in json.loads(r):
                # ignore non-coding transcripts
                if item["biotype"] not in ["protein_coding", "polymorphic_pseudogene"]:
                    continue
                
                # ignore transcripts not on the standard chromosomes
                # (non-default chroms fail to map the known de novo variants
                # to the gene location
                if item["Parent"] != gene_id or item["seq_region_name"] not in \
                        chroms or \
                        all([symbol not in item["external_name"] for symbol in hgnc_symbols]):
                    continue
                transcript_ids.append(item["id"])
        
        return transcript_ids
460551
def GetPeaksExons(bed,parsedGTF):
    

    bedtool_AB=dfTObedtool(bed)

    exonsGTF=parsedGTF[parsedGTF["feature"]=="exon"]
    exonsGTF.reset_index(inplace=True, drop=True)

    exonsBED=GTFtoBED(exonsGTF, "exon_id")
    exonsBED.columns=['chrom', 'chromStart', 'chromEnd', 'exon_id', 'score', 'strand']
    exonsBEDcols=exonsBED.columns.tolist()

    bedcols=bed.columns.tolist()
    exonsBEDcols_=[]
    for c in exonsBEDcols:
        if c in bedcols:
            exonsBEDcols_.append(c+"_exon")
        else:
            exonsBEDcols_.append(c)

    cols=[bedcols,exonsBEDcols_,["overlap"] ]
    cols=[item for sublist in cols for item in sublist]

    bedtool_exons=dfTObedtool(exonsBED)

    bedtool_target_exons=bedtool_AB.intersect(bedtool_exons, wo=True, s=True)
    dfTargetE=pd.read_table(bedtool_target_exons.fn, names=cols)
    ExonsTransGenes=parsedGTF[["exon_id","transcript_id","gene_id"]].drop_duplicates()
    dfTargets=pd.merge(dfTargetE,ExonsTransGenes,on=["exon_id"],how="left")
    dfTargets["count"]=1

    def getCounts(df,field):
        """
        For each field in a bed narrow peak returns the number or times that field is present,\
        the normalized mean of the '-log10(pValue)' and normalized mean of the signal value.

        :param df: a Pandas dataframe of a bed narrow peak
        :param field: field to analyse, ie. exons or transcripts

        :returns: a Pandas dataframe
        """

        tmp=df[[field,'name',"count"]].drop_duplicates()
        tmp=tmp.drop(["name"],axis=1)
        tmp["count"]=tmp["count"].astype(int)
        tmp.columns=[field,"%s_count" %str(field)]
        tmp=tmp.groupby(field, as_index=False).sum()
        df=pd.merge(df,tmp,on=field,how="left")

        tmp=df[[field,'name',"-log10(pValue)"]].drop_duplicates()
        tmp=tmp.drop(["name"],axis=1)
        tmp["-log10(pValue)"]=tmp["-log10(pValue)"].astype(float)
        tmp=tmp.groupby(field).apply(lambda l: reduce(lambda x, y: x*y, l["-log10(pValue)"]) )
        tmp=pd.DataFrame(tmp)
        tmp.reset_index(inplace=True,drop=False)
        tmp.columns=[field,"%s norm. mean -log10(pValue)" %str(field)]
        df=pd.merge(df,tmp,on=field,how="left")

        tmp=df[[field,'name',"signalValue"]].drop_duplicates()
        tmp=tmp.drop(["name"],axis=1)
        tmp["signalValue"]=tmp["signalValue"].astype(float)
        tmp=tmp.groupby(field).apply(lambda l: reduce(lambda x, y: x*y, l["signalValue"]) )
        tmp=pd.DataFrame(tmp)
        tmp.reset_index(inplace=True,drop=False)
        tmp.columns=[field,"%s signalValue" %str(field)]
        df=pd.merge(df,tmp,on=field,how="left")

        return df

    for f in ["exon_id","transcript_id"]:
        dfTargets=getCounts(dfTargets,f)

    def getCounts_GeneIDs(df):
        """
        For each gene id in a bed narrow peak returns the number or times that field is present,\
        the normalized mean of the '-log10(pValue)' and normalized mean of the signal value.

        :param df: a Pandas dataframe of a bed narrow peak

        :returns: a Pandas dataframe
        """

        field="gene_id"

        tmp=df[[field,"transcript_id","transcript_id_count"]].drop_duplicates()
        tmp=tmp.drop(["transcript_id"],axis=1)
        tmp["transcript_id_count"]=tmp["transcript_id_count"].astype(int)
        tmp.columns=[field,"%s_count" %str(field)]
        tmp=tmp.groupby(field, as_index=False).sum()
        df=pd.merge(df,tmp,on=field,how="left")

        tmp=df[[field,'transcript_id',"transcript_id norm. mean -log10(pValue)"]].drop_duplicates()
        tmp=tmp.drop(["transcript_id"],axis=1)
        tmp["transcript_id norm. mean -log10(pValue)"]=tmp["transcript_id norm. mean -log10(pValue)"].astype(float)
        tmp.columns=[field,"%s norm. mean -log10(pValue)" %str(field)]
        tmp=tmp.groupby(field, as_index=False).sum()
        df=pd.merge(df,tmp,on=field,how="left")



        tmp=df[[field,'transcript_id',"transcript_id signalValue"]].drop_duplicates()
        tmp=tmp.drop(["transcript_id"],axis=1)
        tmp["transcript_id signalValue"]=tmp["transcript_id signalValue"].astype(float)
        tmp.columns=[field,"%s signalValue" %str(field)]
        tmp=tmp.groupby(field, as_index=False).sum()
        df=pd.merge(df,tmp,on=field,how="left")

        return df

    dfTargets=getCounts_GeneIDs(dfTargets)


    dfTargets=dfTargets.drop(["count"],axis=1)
    return dfTargets
393312
def from_genes(cls, genes: List[ExpGene]):
        """"""
        data = [g.to_dict() for g in genes]
        index = [d.pop('ensembl_id') for d in data]
        table = cls(data, index=index)
        return table