[docs]deffilter_denovo_one_event_per_family(variant_events:list[VariantEvent],requested_effect_types:Iterable[str],)->list[list[str]]:""" For each variant returns list of affected gene syms. vs - generator for variants. This functions receives a generator for variants and transforms each variant into list of gene symbols, that are affected by the variant. The result is represented as list of lists. """seen:set[str]=set()res=[]forveinvariant_events:syms={ge.geneforaeinve.allele_eventsforgeinae.effect_genesifge.effectinrequested_effect_types}not_seen_genes=[gsforgsinsymsif(ve.family_id+gs)notinseen]ifnotnot_seen_genes:continueseen.update(ve.family_id+gene_symforgene_syminnot_seen_genes)res.append(not_seen_genes)returnres
[docs]defget_sym_2_fn(variant_events:list[VariantEvent],requested_effect_types:Iterable[str],)->dict[str,int]:"""Count the number of requested effect types events in genes."""gn_sorted=sorted([[ge.gene,ve]forveinvariant_eventsforaeinve.allele_eventsforgeinae.effect_genesifge.effectinrequested_effect_types],key=lambdax:(x[0],x[1].fvuid),# type: ignore)sym_2_vars:dict[str,list[VariantEvent]]={sym:[t[1]fortintpi]# type: ignoreforsym,tpiinitertools.groupby(gn_sorted,key=operator.itemgetter(0))}return{sym:len({ve.family_idforveinvariant_events})forsym,variant_eventsinlist(sym_2_vars.items())}
[docs]deffilter_denovo_one_gene_per_recurrent_events(variant_events:list[VariantEvent],requsted_effect_types:Iterable[str],)->list[list[str]]:"""Collect only events that occur in more than one family."""sym_2_fn=get_sym_2_fn(variant_events,requsted_effect_types)return[[gs]forgs,fninlist(sym_2_fn.items())iffn>1]
[docs]@dataclassclassEventCountersResult:"""Represents result of event counting."""all:intrec:intmale:intfemale:intunspecified:intrec_genes:set[str]|None=None
[docs]classEnrichmentSingleResult:"""Represents result of enrichment tool calculations. Supported fields are: `name` `events` -- list of events found `overlapped` -- list of overlapped events `expected` -- number of expected events `pvalue` """def__init__(self,name:str,events:int,overlapped:int,expected:float,pvalue:float,overlapped_genes:set[str]|None=None,):self.name:str=nameself.events=eventsself.overlapped=overlappedself.expected=expectedself.pvalue=pvalueself.overlapped_genes=overlapped_genesdef__repr__(self)->str:return(f"EnrichmentSingleResult({self.name}): "f"events={self.events}; "f"overlapped="f"{self.overlapped}; "f"expected={self.expected}; pvalue={self.pvalue}")
[docs]@dataclassclassEnrichmentResult:"""Represents result of calculating enrichment test."""all:EnrichmentSingleResultrec:EnrichmentSingleResultmale:EnrichmentSingleResultfemale:EnrichmentSingleResultunspecified:EnrichmentSingleResultrec_genes:set[str]|None=None
[docs]defoverlap_enrichment_result_dict(events_counts:EventsResult,gene_syms:Iterable[str],)->EventsResult:"""Calculate the overlap between all events and requested gene syms."""gene_syms_upper=[gs.upper()forgsingene_syms]returnEventsResult(filter_overlapping_events(events_counts.all,gene_syms_upper),filter_overlapping_events(events_counts.rec,gene_syms_upper),filter_overlapping_events(events_counts.male,gene_syms_upper),filter_overlapping_events(events_counts.female,gene_syms_upper),filter_overlapping_events(events_counts.unspecified,gene_syms_upper),)
[docs]defevent_counts(self,variant_events:list[VariantEvent],children_by_sex:ChildrenBySex,effect_types:Iterable[str],)->EventCountersResult:"""Calculate the event counts from the given variant events. Args: variant_events (list[VariantEvent]): A list of variant events. children_by_sex (dict[str, set[tuple[str, str]]]): A dictionary mapping sex to a set of child IDs. effect_types (Iterable[str]): An iterable of effect types. Returns: EventCountersResult: An object containing the event counters. """events_result=self.events(variant_events,children_by_sex,effect_types)returnEventCountersResult(len(events_result.all),len(events_result.rec),len(events_result.male),len(events_result.female),len(events_result.unspecified),)
[docs]defselect_events_in_person_set(self,variant_events:list[VariantEvent],persons:set[tuple[str,str]],)->list[VariantEvent]:"""Select variant events that occur in the passed persons."""return[veforveinvariant_eventsforaeinve.allele_eventsifpersons&ae.persons]
[docs]defsplit_events(self,variant_events:list[VariantEvent],children_by_sex:ChildrenBySex,)->VariantEventsResult:"""Split the passed variant events based on the children's sex. Args: variant_events (list[VariantEvent]): The list of variant events to be split. children_by_sex (dict[str, set[tuple[str, str]]]): A dictionary containing children grouped by sex. Returns: VariantEventsResult: An object containing the split variant events. """male=children_by_sex.malefemale=children_by_sex.femaleunspecified=children_by_sex.unspecifiedall_children=male|female|unspecifiedreturnVariantEventsResult(self.select_events_in_person_set(variant_events,all_children),[],self.select_events_in_person_set(variant_events,male),self.select_events_in_person_set(variant_events,female),self.select_events_in_person_set(variant_events,unspecified),)
[docs]classGeneEventsCounter(CounterBase):"""Counts events in genes."""def__init__(self)->None:super().__init__("enrichment_gene_counting")
[docs]defevents(self,variant_events:list[VariantEvent],children_by_sex:ChildrenBySex,effect_types:Iterable[str],)->EventsResult:"""Count the events by sex and effect type."""events_result=self.split_events(variant_events,children_by_sex)all_events=filter_denovo_one_gene_per_events(events_result.all,effect_types,)rec_events=filter_denovo_one_gene_per_recurrent_events(events_result.all,effect_types,)male_events=filter_denovo_one_gene_per_events(events_result.male,effect_types,)female_events=filter_denovo_one_gene_per_events(events_result.female,effect_types,)unspecified_events=filter_denovo_one_gene_per_events(events_result.unspecified,effect_types,)returnEventsResult(all_events,rec_events,male_events,female_events,unspecified_events,)