@@ -526,6 +526,307 @@ def plot_h12_gwss(
526526 else :
527527 return fig
528528
529+ @check_types
530+ @doc (
531+ summary = "Plot h12 GWSS data track with multiple traces overlaid." ,
532+ )
533+ def plot_h12_gwss_multi_overlay_track (
534+ self ,
535+ contig : base_params .contig ,
536+ cohorts : base_params .cohorts ,
537+ window_size : h12_params .multi_window_size ,
538+ cohort_size : Optional [base_params .cohort_size ] = h12_params .cohort_size_default ,
539+ sample_query : Optional [base_params .sample_query ] = None ,
540+ analysis : hap_params .analysis = base_params .DEFAULT ,
541+ min_cohort_size : Optional [
542+ base_params .min_cohort_size
543+ ] = h12_params .min_cohort_size_default ,
544+ max_cohort_size : Optional [
545+ base_params .max_cohort_size
546+ ] = h12_params .max_cohort_size_default ,
547+ title : Optional [gplt_params .title ] = None ,
548+ sample_query_options : Optional [base_params .sample_query_options ] = None ,
549+ sample_sets : Optional [base_params .sample_sets ] = None ,
550+ colors : gplt_params .colors = bokeh .palettes .d3 ["Category10" ][10 ],
551+ random_seed : base_params .random_seed = 42 ,
552+ sizing_mode : gplt_params .sizing_mode = gplt_params .sizing_mode_default ,
553+ width : gplt_params .width = gplt_params .width_default ,
554+ height : gplt_params .height = 200 ,
555+ show : gplt_params .show = True ,
556+ x_range : Optional [gplt_params .x_range ] = None ,
557+ output_backend : gplt_params .output_backend = gplt_params .output_backend_default ,
558+ ) -> gplt_params .figure :
559+ cohort_queries = self ._setup_cohort_queries (
560+ cohorts = cohorts ,
561+ sample_sets = sample_sets ,
562+ sample_query = sample_query ,
563+ sample_query_options = sample_query_options ,
564+ cohort_size = cohort_size ,
565+ min_cohort_size = None ,
566+ )
567+
568+ if isinstance (window_size , int ):
569+ window_size = {k : window_size for k in cohort_queries .keys ()}
570+ elif isinstance (window_size , Mapping ):
571+ if set (window_size .keys ()) != set (cohort_queries .keys ()):
572+ raise ValueError ("Cohorts and window_sizes should have the same keys." )
573+
574+ # Compute H12.
575+ res = {}
576+ for cohort_label , cohort_query in cohort_queries .items ():
577+ res [cohort_label ] = self .h12_gwss (
578+ contig = contig ,
579+ analysis = analysis ,
580+ window_size = window_size [cohort_label ],
581+ cohort_size = cohort_size ,
582+ min_cohort_size = min_cohort_size ,
583+ max_cohort_size = max_cohort_size ,
584+ sample_query = cohort_query ,
585+ sample_sets = sample_sets ,
586+ random_seed = random_seed ,
587+ )
588+
589+ # Determine X axis range.
590+ x , _ = res [list (cohort_queries .keys ())[0 ]]
591+ x_min = x [0 ]
592+ x_max = x [- 1 ]
593+ if x_range is None :
594+ x_range = bokeh .models .Range1d (x_min , x_max , bounds = "auto" )
595+
596+ # Create a figure.
597+ xwheel_zoom = bokeh .models .WheelZoomTool (
598+ dimensions = "width" , maintain_focus = False
599+ )
600+
601+ fig = bokeh .plotting .figure (
602+ title = title ,
603+ tools = [
604+ "xpan" ,
605+ "xzoom_in" ,
606+ "xzoom_out" ,
607+ xwheel_zoom ,
608+ "reset" ,
609+ "save" ,
610+ "crosshair" ,
611+ ],
612+ active_inspect = None ,
613+ active_scroll = xwheel_zoom ,
614+ active_drag = "xpan" ,
615+ sizing_mode = sizing_mode ,
616+ width = width ,
617+ height = height ,
618+ toolbar_location = "above" ,
619+ x_range = x_range ,
620+ y_range = (0 , 1 ),
621+ output_backend = output_backend ,
622+ )
623+
624+ # Plot H12.
625+ for i , (cohort_label , (x , h12 )) in enumerate (res .items ()):
626+ fig .scatter (
627+ x = x ,
628+ y = h12 ,
629+ marker = "circle" ,
630+ size = 3 ,
631+ line_width = 1 ,
632+ line_color = colors [i % len (colors )],
633+ fill_color = None ,
634+ legend_label = cohort_label ,
635+ )
636+
637+ # Tidy up the plot.
638+ fig .yaxis .axis_label = "H12"
639+ fig .yaxis .ticker = [0 , 1 ]
640+ self ._bokeh_style_genome_xaxis (fig , contig )
641+
642+ if show : # pragma: no cover
643+ bokeh .plotting .show (fig )
644+ return None
645+ else :
646+ return fig
647+
648+ @check_types
649+ @doc (
650+ summary = "Plot h12 GWSS data with multiple traces overlaid." ,
651+ )
652+ def plot_h12_gwss_multi_overlay (
653+ self ,
654+ contig : base_params .contig ,
655+ cohorts : base_params .cohorts ,
656+ window_size : h12_params .multi_window_size ,
657+ cohort_size : Optional [base_params .cohort_size ] = h12_params .cohort_size_default ,
658+ sample_query : Optional [base_params .sample_query ] = None ,
659+ analysis : hap_params .analysis = base_params .DEFAULT ,
660+ min_cohort_size : Optional [
661+ base_params .min_cohort_size
662+ ] = h12_params .min_cohort_size_default ,
663+ max_cohort_size : Optional [
664+ base_params .max_cohort_size
665+ ] = h12_params .max_cohort_size_default ,
666+ sample_query_options : Optional [base_params .sample_query_options ] = None ,
667+ sample_sets : Optional [base_params .sample_sets ] = None ,
668+ colors : gplt_params .colors = bokeh .palettes .d3 ["Category10" ][10 ],
669+ random_seed : base_params .random_seed = 42 ,
670+ title : Optional [gplt_params .title ] = None ,
671+ sizing_mode : gplt_params .sizing_mode = gplt_params .sizing_mode_default ,
672+ width : gplt_params .width = gplt_params .width_default ,
673+ track_height : gplt_params .track_height = 170 ,
674+ genes_height : gplt_params .genes_height = gplt_params .genes_height_default ,
675+ show : gplt_params .show = True ,
676+ output_backend : gplt_params .output_backend = gplt_params .output_backend_default ,
677+ ) -> gplt_params .figure :
678+ # Plot GWSS track.
679+ fig1 = self .plot_h12_gwss_multi_overlay_track (
680+ contig = contig ,
681+ sample_query = sample_query ,
682+ cohorts = cohorts ,
683+ cohort_size = cohort_size ,
684+ window_size = window_size ,
685+ analysis = analysis ,
686+ min_cohort_size = min_cohort_size ,
687+ max_cohort_size = max_cohort_size ,
688+ sample_query_options = sample_query_options ,
689+ sample_sets = sample_sets ,
690+ colors = colors ,
691+ random_seed = random_seed ,
692+ title = title ,
693+ sizing_mode = sizing_mode ,
694+ width = width ,
695+ height = track_height ,
696+ show = False ,
697+ output_backend = output_backend ,
698+ )
699+
700+ fig1 .xaxis .visible = False
701+ fig1 .legend .location = "top_right"
702+ fig1 .legend .click_policy = "hide"
703+
704+ # Plot genes.
705+ fig2 = self .plot_genes (
706+ region = contig ,
707+ sizing_mode = sizing_mode ,
708+ width = width ,
709+ height = genes_height ,
710+ x_range = fig1 .x_range ,
711+ show = False ,
712+ output_backend = output_backend ,
713+ )
714+
715+ # Combine plots into a single figure.
716+ fig = bokeh .layouts .gridplot (
717+ [fig1 , fig2 ],
718+ ncols = 1 ,
719+ toolbar_location = "above" ,
720+ merge_tools = True ,
721+ sizing_mode = sizing_mode ,
722+ toolbar_options = dict (active_inspect = None ),
723+ )
724+
725+ if show : # pragma: no cover
726+ bokeh .plotting .show (fig )
727+ return None
728+ else :
729+ return fig
730+
731+ @check_types
732+ @doc (
733+ summary = "Plot h12 GWSS data with multiple tracks." ,
734+ )
735+ def plot_h12_gwss_multi_panel (
736+ self ,
737+ contig : base_params .contig ,
738+ cohorts : base_params .cohorts ,
739+ window_size : h12_params .multi_window_size ,
740+ cohort_size : Optional [base_params .cohort_size ] = h12_params .cohort_size_default ,
741+ sample_query : Optional [base_params .sample_query ] = None ,
742+ analysis : hap_params .analysis = base_params .DEFAULT ,
743+ min_cohort_size : Optional [
744+ base_params .min_cohort_size
745+ ] = h12_params .min_cohort_size_default ,
746+ max_cohort_size : Optional [
747+ base_params .max_cohort_size
748+ ] = h12_params .max_cohort_size_default ,
749+ sample_query_options : Optional [base_params .sample_query_options ] = None ,
750+ sample_sets : Optional [base_params .sample_sets ] = None ,
751+ random_seed : base_params .random_seed = 42 ,
752+ sizing_mode : gplt_params .sizing_mode = gplt_params .sizing_mode_default ,
753+ width : gplt_params .width = gplt_params .width_default ,
754+ track_height : gplt_params .track_height = 170 ,
755+ genes_height : gplt_params .genes_height = gplt_params .genes_height_default ,
756+ show : gplt_params .show = True ,
757+ output_backend : gplt_params .output_backend = gplt_params .output_backend_default ,
758+ ) -> gplt_params .figure :
759+ cohort_queries = self ._setup_cohort_queries (
760+ cohorts = cohorts ,
761+ sample_sets = sample_sets ,
762+ sample_query = sample_query ,
763+ sample_query_options = sample_query_options ,
764+ cohort_size = cohort_size ,
765+ min_cohort_size = None ,
766+ )
767+
768+ if isinstance (window_size , int ):
769+ window_size = {k : window_size for k in cohort_queries .keys ()}
770+ elif isinstance (window_size , Mapping ):
771+ if set (window_size .keys ()) != set (cohort_queries .keys ()):
772+ raise ValueError ("Cohorts and window_sizes should have the same keys." )
773+
774+ # Plot GWSS track.
775+ figs : list [gplt_params .def_figure ] = []
776+ for i , (cohort_label , cohort_query ) in enumerate (cohort_queries .items ()):
777+ params = dict (
778+ contig = contig ,
779+ analysis = analysis ,
780+ window_size = window_size [cohort_label ],
781+ sample_sets = sample_sets ,
782+ sample_query = cohort_query ,
783+ cohort_size = cohort_size ,
784+ min_cohort_size = min_cohort_size ,
785+ max_cohort_size = max_cohort_size ,
786+ random_seed = random_seed ,
787+ title = cohort_label , # Deal with a choice of titles later
788+ sizing_mode = sizing_mode ,
789+ width = width ,
790+ height = track_height ,
791+ show = False ,
792+ output_backend = output_backend ,
793+ )
794+ if i > 0 :
795+ track = self .plot_h12_gwss_track (x_range = figs [0 ].x_range , ** params )
796+ else :
797+ track = self .plot_h12_gwss_track (** params )
798+ track .xaxis .visible = False
799+ figs .append (track )
800+
801+ # Plot genes.
802+ fig2 = self .plot_genes (
803+ region = contig ,
804+ sizing_mode = sizing_mode ,
805+ width = width ,
806+ height = genes_height ,
807+ x_range = figs [0 ].x_range ,
808+ show = False ,
809+ output_backend = output_backend ,
810+ )
811+
812+ figs .append (fig2 )
813+
814+ # Combine plots into a single figure.
815+ fig = bokeh .layouts .gridplot (
816+ figs ,
817+ ncols = 1 ,
818+ toolbar_location = "above" ,
819+ merge_tools = True ,
820+ sizing_mode = sizing_mode ,
821+ toolbar_options = dict (active_inspect = None ),
822+ )
823+
824+ if show : # pragma: no cover
825+ bokeh .plotting .show (fig )
826+ return None
827+ else :
828+ return fig
829+
529830
530831def haplotype_frequencies (h ):
531832 """Compute haplotype frequencies, returning a dictionary that maps
0 commit comments