
    h4_                        d Z ddlZddlZddlmZmZmZmZm	Z	m
Z
mZmZ ddlZddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlZ ddl!m"Z"m#Z# ddl$m%Z% de&de&fdZ'de j(        dee&         de&ddfdZ)de j*        dee&         de&ddfdZ+de#edf         dee&         de&ddfdZ,de#edf         dee&         de&ddfdZ- G d de          Z.	 	 	 d=ded e"ed!f         d"ee&         d#eee&ee&         f                  d$ee         d%ee	e/e/f                  ddfd&Z0d'Z1d(d)d*d+d,Z2 ed-.          Z3e1e2e3fd/ee&ee&e"ed0f         f         f         d1ee&ee&e	e/e/f         f         f         d2e&d3e&d#ee&e&f         d4eddfd5Z4d6ee&ee&e
e/e5f         f         f         de&ddfd7Z6d8e j*        dee&         d9e&d:e7d;e7ddfd<Z8dS )>a{  Visualization module for generating plots and reports for Fi-NeMo results.

This module provides functions for:
- Plotting motif contribution weight matrices (CWMs) as sequence logos
- Generating distribution plots for hit statistics
- Creating co-occurrence heatmaps
- Producing HTML reports with interactive visualizations
- Plotting confusion matrices and performance metrics
    N)ListOptionalDictAnyTupleUnionMappingIterable)ndarray)Axes)AbstractPathEffect)TextPath)Affine2D)FontProperties)Template)FloatInt   )	templatesnamereturnc                     	 |                      d          \  }}|dk    rd}n|dk    rd}nt          |                     d          d         }| d| S # t          $ r | cY S w xY w)	a`  Convert TF-MoDISco motif names to abbreviated format.

    Converts full TF-MoDISco pattern names to shorter, more readable format
    for display in plots and reports.

    Parameters
    ----------
    name : str
        Full motif name (e.g., 'pos_patterns.pattern_0').

    Returns
    -------
    str
        Abbreviated name (e.g., '+/0') or original name if parsing fails.

    Examples
    --------
    >>> abbreviate_motif_name('pos_patterns.pattern_0')
    '+/0'
    >>> abbreviate_motif_name('neg_patterns.pattern_1')
    '-/1'
    >>> abbreviate_motif_name('invalid_name')
    'invalid_name'
    .pos_patterns+neg_patterns-_r   /)split	Exception)r   groupmotifgroup_short	motif_nums        ;/srv/www/kundaje/kobbad/Fi-NeMo/src/finemo/visualization.pyabbreviate_motif_namer'      s    2zz#uN""KKn$$KKOKK$$Q'	++	+++   s   AA A$#A$hits_dfmotif_namesplot_dirc                 J   |                                  }|                    dd          }|                                }t          j                            |d          }t          j        |d           |D ])}|                    |f|          }|                    d          	                                }	|                    d          	                                }
|                    d          	                                }t          j        d	
          \  }}	 |                    |	dd           n(# t          $ r |                    |	dd           Y nw xY wt          j                            || d          }t          j        |d           t          j                            || d          }t          j        |           t          j        |           t          j        d	
          \  }}	 |                    |
dd           n(# t          $ r |                    |
dd           Y nw xY wt          j                            || d          }t          j        |d           t          j                            || d          }t          j        |           t          j        |           t          j        d	
          \  }}	 |                    |dd           n(# t          $ r |                    |dd           Y nw xY wt          j                            || d          }t          j        |d           t          j                            || d          }t          j        |           t          j        |           +dS )a  Plot distributions of hit statistics for each motif.

    Creates separate histogram plots for coefficient, similarity, and importance
    score distributions for each motif. Saves plots in both PNG (high-res) and
    SVG (vector) formats.

    Parameters
    ----------
    hits_df : pl.LazyFrame
        Lazy DataFrame containing hit data with required columns:
        - motif_name : str, name of the motif
        - hit_coefficient_global : float, global coefficient values
        - hit_similarity : float, similarity scores to motif CWM
        - hit_importance : float, importance scores from attribution
    motif_names : List[str]
        List of motif names to generate plots for. Motifs not present
        in hits_df will result in empty histograms.
    plot_dir : str
        Directory path where plots will be saved. Creates subdirectory
        'motif_stat_distributions' if it doesn't exist.

    Notes
    -----
    For each motif, creates three separate plots:
    - {motif_name}_coefficients.{png,svg} : coefficient distribution
    - {motif_name}_similarities.{png,svg} : similarity distribution
    - {motif_name}_importances.{png,svg} : importance distribution
    
motif_nameT)as_dictmotif_stat_distributionsexist_okhit_coefficient_globalhit_similarityhit_importance      figsize2   )binsdensityr   z_coefficients.png,  dpiz_coefficients.svgz_similarities.pngz_similarities.svgz_importances.pngz_importances.svgN)collectpartition_byclearospathjoinmakedirsget
get_columnto_numpypltsubplotshist
ValueErrorsavefigclose)r(   r)   r*   hits_df_collectedhits_by_motifdummy_df
motifs_dirmhitscoefficientssimilaritiesimportancesfigaxoutput_path_pngoutput_path_svgs                   r&   plot_hit_stat_distributionsr\   E   s   >  ))%22<2NNM &&((Hh(BCCJK
T**** . .  !x00'?@@IIKK'788AACCoo&677@@BB,v...R	8GGLr4G8888 	8 	8 	8GGLq$G77777	8 ',,za3J3J3JKKO----',,za3J3J3JKKO$$$	#,v...R	8GGLr4G8888 	8 	8 	8GGLq$G77777	8 ',,za3J3J3JKKO----',,za3J3J3JKKO$$$	#,v...R	7GGKb$G7777 	7 	7 	7GGKaG66666	7 ',,za3I3I3IJJO----',,za3I3I3IJJO$$$	#]. .s6    D99"EE>H"H<;H<K55"LLocc_dfc                    t           j                            |d          }t          j        |d           |D ]>}t	          j        d          \  }}t          j        |                     |          d          \  }}||	                                z  }	t          j
        |d          d	z   }
t          j        |
          }t          j        |
          }|	||<   |                    ||           t           j                            || d
          }t	          j        |d           t           j                            || d          }t	          j        |           t	          j        |           @t	          j        d          \  }}t          j        |                     d          d          \  }}||	                                z  }	t          j
        |d          d	z   }
t          j        |
          }t          j        |
          }|	||<   |                    ||           |                    d           |                    d           t           j                            |d          }t	          j        |d           t           j                            |d          }t	          j        |d           t	          j        |           dS )a  Plot distribution of hits per peak for each motif.

    Creates bar plots showing the frequency distribution of hit counts per peak
    for each motif, plus an overall distribution of total hits per peak.

    Parameters
    ----------
    occ_df : pl.DataFrame
        DataFrame containing motif occurrence counts per peak. Expected to have:
        - One column per motif name with integer hit counts
        - 'total' column with sum of all motif hits per peak
        - Each row represents a peak/genomic region
    motif_names : List[str]
        List of motif names corresponding to columns in occ_df.
    plot_dir : str
        Directory to save plots. Creates 'motif_hit_distributions' subdirectory.

    Notes
    -----
    Generates the following plots:
    - Individual motif hit distributions: {motif_name}.{png,svg}
    - Overall hit distribution: total_hit_distribution.{png,svg}

    Bar plots show frequency (proportion) on y-axis and hit count on x-axis.
    motif_hit_distributionsTr/   r4   r7   )return_countsr   )initialr   .pngr<   r=   .svg)      totalzTotal hits per region	Frequencyztotal_hit_distribution.pngztotal_hit_distribution.svgN)rB   rC   rD   rE   rI   rJ   npuniquerG   sumamaxarangezerosbarrM   rN   
set_xlabel
set_ylabel)r]   r)   r*   rR   rS   rX   rY   ri   countsfreqnum_binsxyrZ   r[   s                  r&   plot_hit_peak_distributionsrv      sr   8 h(ABBJK
T****  ,v...R6#4#4Q#7#7tLLL

$761---1IhHX&	
q!',,za:::>>O----',,za:::>>O$$$	#l6***GCYv0099NNNNFFFJJLL Dwvq)))A-H
	(A
AAfIFF1aLLLMM)***MM+gll8-IJJOKS))))gll8-IJJOKS))))IcNNNNN    peak_hit_countszM M
output_dirc                    dt          j        t          j        |                     z  }| |dddf         z  |dddf         z  }d |D             }t          j        dd          \  }}|                    |ddd	
          }|                    t          j        t          |                               |	                    |           |
                    t          j        t          |                               |                    |d           |                    d           |                    d           |                    dd           |                    ||ddd          }	|	j                            d           t"          j                            |d          }
t          j        |
d           t"          j                            |d          }t          j        |d           t          j                     dS )a=  Plot co-occurrence heatmap showing motif associations across peaks.

    Creates a normalized correlation heatmap showing how frequently pairs of
    motifs co-occur within the same genomic peaks. Values are normalized by
    the geometric mean of individual motif frequencies.

    Parameters
    ----------
    peak_hit_counts : Int[ndarray, "M M"]
        Co-occurrence matrix where M = len(motif_names).
        Entry (i,j) represents the number of peaks containing both motif i and j.
        Diagonal entries represent total peaks containing each individual motif.
    motif_names : List[str]
        List of motif names for axis labels. Order must match matrix dimensions.
    output_dir : str
        Directory path where the heatmap plots will be saved.

    Notes
    -----
    Saves plots as:
    - motif_cooocurrence.png : High-resolution raster format
    - motif_cooocurrence.svg : Vector format

    The heatmap uses correlation normalization: matrix[i,j] / sqrt(matrix[i,i] * matrix[j,j])
    Colors use the 'Greens' colormap with values typically in [0, 1] range.
    r   Nc                 ,    g | ]}t          |          S  r'   .0rS   s     r&   
<listcomp>z5plot_peak_motif_indicator_heatmap.<locals>.<listcomp>   !    @@@q'**@@@rw   rd   rd   constrainedr8   layoutnearestequalGreensinterpolationaspectcmapZ   rotationzMotif izMotif jbothrd   axis	labelsizevertical333333?   rY   orientationshrinkr   r   zmotif_cooocurrence.pngr<   r=   zmotif_cooocurrence.svg)rh   sqrtdiagrI   rJ   imshow
set_yticksrl   lenset_yticklabels
set_xticksset_xticklabelsro   rp   tick_paramscolorbarrY   rB   rC   rD   rM   rN   )rx   r)   ry   cov_normmatrix
motif_keysrX   rY   caxcbarrZ   r[   s               r&   !plot_peak_motif_indicator_heatmapr      s   : 2727?33444Hx4008D!!!G3DDF@@K@@@Jl6-@@@GC ))F)G()
S
SC MM")C
OO,,---z"""MM")C
OO,,---zB///MM)MM)NN!N,,,<<
3r<RRDG!$$$gll:/GHHOKS))))gll:/GHHOKS))))IKKKKKrw   seqlet_confusionc                    d |D             }t          j        dd          \  }}|                    | ddd          }|                    t	          j        t          |                               |                    |           |                    t	          j        t          |                               |	                    |d	
           |
                    d           |                    d           |                    dd           |                    ||ddd          }|j                            d           t          j                            |d          }t          j        |d           t          j                            |d          }	t          j        |	d           t          j                     dS )a  Plot confusion matrix heatmap comparing seqlets to hit calls.

    Creates a heatmap showing the overlap between TF-MoDISco seqlets and
    Fi-NeMo hit calls. Rows represent seqlet motifs, columns represent hit motifs.

    Parameters
    ----------
    seqlet_confusion : Int[ndarray, "M M"]
        Confusion matrix where M = len(motif_names).
        Entry (i,j) represents the number of seqlets of motif i that overlap
        with hits called for motif j.
    motif_names : List[str]
        List of motif names for axis labels. Order must match matrix dimensions.
    output_dir : str
        Directory path where the confusion matrix plots will be saved.

    Notes
    -----
    Saves plots as:
    - seqlet_confusion.png : High-resolution raster format
    - seqlet_confusion.svg : Vector format

    The heatmap uses 'Blues' colormap. Perfect agreement would show a diagonal
    pattern with high values along the diagonal and low off-diagonal values.
    c                 ,    g | ]}t          |          S r|   r}   r~   s     r&   r   z1plot_seqlet_confusion_heatmap.<locals>.<listcomp>8  r   rw   r   r   r   r   r   Bluesr   r   r   z	Hit motifzSeqlet motifr   rd   r   r   r   r   r   r   zseqlet_confusion.pngr<   r=   zseqlet_confusion.svgN)rI   rJ   r   r   rh   rl   r   r   r   r   ro   rp   r   r   rY   rB   rC   rD   rM   rN   )
r   r)   ry   r   rX   rY   r   r   rZ   r[   s
             r&   plot_seqlet_confusion_heatmapr     s   8 A@K@@@Jl6-@@@GC ))	'   C
 MM")C
OO,,---z"""MM")C
OO,,---zB///MM+MM.!!!NN!N,,,<<
3r<RRDG!$$$gll:/EFFOKS))))gll:/EFFOKS))))IKKKKKrw   c                   h     e Zd ZdZ	 	 	 ddededee         deeef         d	df
 fd
Z	d	e
fdZ xZS )	LogoGlypha  Path effect for creating sequence logo glyphs with normalized dimensions.

    This class creates properly scaled and positioned text glyphs for sequence
    logos by normalizing character dimensions and applying appropriate transforms.

    Parameters
    ----------
    glyph : str
        Single character to render (e.g., 'A', 'C', 'G', 'T').
    ref_glyph : str, default 'E'
        Reference character used for width normalization.
    font_props : FontProperties, optional
        Font properties for the glyph rendering.
    offset : Tuple[float, float], default (0., 0.)
        Offset for glyph positioning.
    **kwargs
        Additional graphics collection parameters.
    EN        r   glyph	ref_glyph
font_propsoffsetr   c                 P   t                                          |           t          d|d|          }|                                }t          d|d|                                          }d|j        z  }	t          |j        |j                  }
d|
z  }d|j        |
z  z
  dz  }|j         }|j         }t                      
                    ||                              ||	          
                    |d          }|                    |          | _        || _        d S )Nr   r   r   )sizepropr6   )txty)sxsyr   )super__init__r   get_extentsheightmaxwidthx0y0r   	translatescaletransform_pathrC   _gc)selfr   r   r   r   kwargs	path_origdimsref_dimsh_scale	ref_widthw_scalew_shiftx_shifty_shiftstretch	__class__s                   r&   r   zLogoGlyph.__init__j  s    	   VUDDD	$$&&FIAJGGGSSUUdk/
HN33	i-tzI--27(7(JJY'gY..Ug'U**Y'aY((	 	 **955	 rw   c                 <    |                     || j        ||          S )a,  Draw the glyph path using the renderer.

        Parameters
        ----------
        renderer : matplotlib renderer
            The renderer to draw with.
        gc : GraphicsContext
            Graphics context for drawing properties.
        tpath : Path
            Original text path (unused, using self.path instead).
        affine : Transform
            Affine transformation to apply.
        rgbFace : color
            Face color for the glyph.

        Returns
        -------
        Any
            Result from renderer.draw_path.
        )	draw_pathrC   )r   renderergctpathaffinergbFaces         r&   r   zLogoGlyph.draw_path  s     * !!"diAAArw   )r   Nr   )__name__
__module____qualname____doc__strr   r   r   floatr   r   r   __classcell__)r   s   @r&   r   r   V  s         , /3&0   ^,	
 eUl# 
     @B B B B B B B B Brw   r   rY   heightszB Wglyphscolorsr   shade_boundsc                    |d |D             }|                      dd           t          j        |dd          }t          j        |dd          }t          j        |d          }t          j        |d          dddddf         }	t          j        |d          }
t          j        |	d          }t          j        t          j        t          j        ||d          d          |
d          }t          j        t          j        t          j        ||	d          d          |d          }||z   |z
  }t          j        |j        d                   }t          |||          D ]7\  }}}| 	                    ||d|t          ||	          g||         
           8|$|\  }}|                     |dz
  |dz
  dd           |                     ddd           dS )a}  Plot sequence logo from contribution weight matrix.

    Creates a sequence logo visualization where letter heights represent
    the contribution or information content at each position. Supports
    both positive and negative contributions with proper stacking.

    Parameters
    ----------
    ax : Axes
        Matplotlib axes object to plot on.
    heights : Float[ndarray, "B W"]
        Height matrix where B = len(glyphs) and W = motif width.
        Entry (i,j) represents the height/contribution of base i at position j.
        Can contain both positive and negative values.
    glyphs : Iterable[str]
        Sequence of base characters corresponding to rows in heights matrix.
        Typically ['A', 'C', 'G', 'T'] for DNA.
    colors : Dict[str, str], optional
        Color mapping for each base. Keys should match glyphs.
        If None, all bases will use default matplotlib colors.
    font_props : FontProperties, optional
        Font properties for letter rendering. If None, uses default font.
    shade_bounds : Tuple[int, int], optional
        (start, end) position indices to shade in background.
        Useful for highlighting core motif regions.

    Notes
    -----
    Positive and negative contributions are handled separately:
    - Positive values are stacked above zero line in order of descending absolute value
    - Negative values are stacked below zero line in order of descending absolute value
    - A horizontal line is drawn at y=0 for reference

    The resulting plot has:
    - X-axis: Position in motif (0-indexed)
    - Y-axis: Contribution magnitude
    - Bar width: 0.95 (small gaps between positions)
    Nc                     i | ]}|d S )Nr|   )r   gs     r&   
<dictcomp>zplot_logo.<locals>.<dictcomp>  s    ***a!T***rw   r   )rt   ru   )r   r   gffffff?)r   )bottompath_effectscolorg      ?z0.9)r   zorderblack)r   	linewidthr   )marginsrh   clipargsorttake_along_axiscumsumrl   shapeziprn   r   axvspanaxhline)rY   r   r   r   r   r   
pos_values
neg_values	pos_order	neg_orderpos_reorderneg_reorderpos_offsetsneg_offsetsbottomsrt   r   r   r   startends                        r&   	plot_logor    s    \ ~**6***JJaJ!T**J$**J
:A...I
:A...tttQQQw7I*YQ///K*YQ///K$
	"$ZCCC!LLL  K
 $
	"$ZCCC!LLL  K
 K''1G
	'-"##A!$VWg!>!> 
 
vv
#EjAAAB- 	 	
 	
 	
 	
 !
s


53;c	r
BBBJJbCwJ77777rw   ACGTz#109648z#255C99z#F7B32Bz#D62839)ACGTbold)weightmotifsz4 Wtrim_boundsout_diralphabetfontc                    |                                  D ]G\  }}t          j                            ||          }t          j        |d           |                                 D ]\  }	}
t          j        d          \  }}t          ||
|||||         |	                    |j                                         D ]\  }}|	                    d           t          j                            ||	 d          }t          j
        |d	           t          j                            ||	 d
          }t          j
        |           t          j        |           IdS )u  Plot contribution weight matrices as sequence logos.

    Creates sequence logo plots for all motifs and CWM types, with optional
    shading to highlight trimmed regions. Saves plots in both PNG and SVG formats.

    Parameters
    ----------
    motifs : Dict[str, Dict[str, Float[ndarray, "4 W"]]]
        Nested dictionary structure: {motif_name: {motif_type: motif_array}}.
        Each motif_array has shape (4, W) where W is motif width.
        Rows correspond to bases in alphabet order.
    trim_bounds : Dict[str, Dict[str, Tuple[int, int]]]
        Nested dictionary: {motif_name: {motif_type: (start, end)}}.
        Defines regions to shade in the sequence logos.
    out_dir : str
        Output directory where motif subdirectories will be created.
    alphabet : str, default LOGO_ALPHABET
        DNA alphabet string, typically 'ACGT'.
    colors : Dict[str, str], default LOGO_COLORS
        Color mapping for DNA bases. Keys should match alphabet characters.
    font : FontProperties, default LOGO_FONT
        Font properties for sequence logo rendering.

    Notes
    -----
    Directory structure created:
    ```
    out_dir/
    ├── motif1/
    │   ├── motif_type1.png
    │   ├── motif_type1.svg
    │   └── ...
    └── motif2/
        └── ...
    ```

    Each plot is 10x2 inches with trimmed regions shaded if specified.
    Spines (plot borders) are hidden for cleaner appearance.
    Tr/   )
   r6   r7   )r   r   r   Frb   d   r=   rc   N)itemsrB   rC   rD   rE   rI   rJ   r  spinesset_visiblerM   rN   )r  r  r  r  r   r  rS   v	motif_dir
motif_typer#   rX   rY   r   spinerZ   r[   s                    r&   plot_motifsr"    se   ^   1GLL!,,	
I----!" 	 	Jl7333GC(^J7     "y00 ) )e!!%(((( gll96I6I6IJJOKS1111 gll96I6I6IJJOK(((IcNNNN)	 rw   recall_datac                    g }g }g }|                                  D ]P\  }}|                    |d                    |                    |d                    |                    |           Qt          t          j        |          t          j        |                    }t          j        dd          \  }}	|	                    d||fddd	
           |	                    ||d           t          |          D ];\  }
}t          |          }|	                    |||
         ||
         fdd           <|	                    d           |	                    d           |	                    d           |	                    d           t           j                            |d          }t          j        |d           t           j                            |d          }t          j        |           t          j                     dS )a  Plot scatter plot comparing hit counts to seqlet counts per motif.

    Creates a log-log scatter plot showing the relationship between the number
    of hits called by Fi-NeMo and the number of seqlets identified by TF-MoDISco
    for each motif. Includes diagonal reference line and motif annotations.

    Parameters
    ----------
    recall_data : Dict[str, Dict[str, Union[int, float]]]
        Dictionary with motif names as keys and metrics dictionaries as values.
        Each metrics dictionary must contain:
        - 'num_hits_total' : int, total number of hits for the motif
        - 'num_seqlets' : int, total number of seqlets for the motif
    output_dir : str
        Directory path where the scatter plot will be saved.

    Notes
    -----
    Saves plots as:
    - hit_vs_seqlet_counts.png : High-resolution raster format
    - hit_vs_seqlet_counts.svg : Vector format

    Plot features:
    - Log-log scale on both axes
    - Diagonal reference line (y = x) as dashed line
    - Points annotated with abbreviated motif names
    num_hits_totalnum_seqletsr   r   r   r   z0.3gffffff?)r   )r5   r5   )r   r   	linestyler5   )srd   r  )fontsizer  logzHits per motifzSeqlets per motifzhit_vs_seqlet_counts.pngr<   r=   zhit_vs_seqlet_counts.svgN)r  appendr   rh   rk   rI   rJ   axlinescatter	enumerater'   annotate
set_yscale
set_xscalero   rp   rB   rC   rD   rM   rN   )r#  ry   rt   ru   rS   kr  limrX   rY   itxtshortrZ   r[   s                  r&   plot_hit_vs_seqlet_countsr7  H  s   < 	A
A
A!!##  1	#$%%%	=!"""	
bgajj"'!**
%
%Cl6-@@@GCIIfsCjITTTJJq!qJA,, D D3%c**
EAaD!A$<!FCCCCMM%MM%MM"###MM%&&&gll:/IJJOKS))))gll:/IJJOK   IKKKKKrw   	report_dfout_pathcompute_recalluse_seqletsc                    t           j                            t                                        d                                          }t          |          }|                    |                     d          |||          }t          |d          5 }|
                    |           ddd           dS # 1 swxY w Y   dS )aA  Generate and write HTML report from motif analysis results.

    Creates a comprehensive HTML report with tables and visualizations
    summarizing the Fi-NeMo motif discovery and hit calling results.

    Parameters
    ----------
    report_df : pl.DataFrame
        DataFrame containing motif statistics and performance metrics.
        Expected columns depend on compute_recall and use_seqlets flags.
    motif_names : List[str]
        List of motif names to include in the report.
        Order determines presentation sequence in the report.
    out_path : str
        File path where the HTML report will be written.
        Parent directory must exist.
    compute_recall : bool
        Whether recall metrics were computed and should be included
        in the report template.
    use_seqlets : bool
        Whether TF-MoDISco seqlet data was used in the analysis
        and should be referenced in the report.

    Notes
    -----
    Uses Jinja2 templating with the report.html template from the
    templates package. The template receives:
    - report_data: Iterator of DataFrame rows as named tuples
    - motif_names: List of motif names
    - compute_recall: Boolean flag for recall metrics
    - use_seqlets: Boolean flag for seqlet usage

    Raises
    ------
    OSError
        If the output path cannot be written.
    zreport.htmlT)named)report_datar)   r:  r;  wN)	importlib	resourcesfilesr   joinpath	read_textr   render	iter_rowsopenwrite)	r8  r)   r9  r:  r;  template_strtemplatereportfs	            r&   write_reportrM    s    Z 	!!),,55mDDNNPP  %%H__''d'33%	   F 
h		 	                 s   B99B= B=)NNN)9r   rB   importlib.resourcesr@  typingr   r   r   r   r   r   r	   r
   numpyrh   r   matplotlib.pyplotpyplotrI   matplotlib.axesr   matplotlib.patheffectsr   matplotlib.textpathr   matplotlib.transformsr   matplotlib.font_managerr   jinja2r   polarspl	jaxtypingr   r    r   r   r'   	LazyFramer\   	DataFramerv   r   r   r   intr  LOGO_ALPHABETLOGO_COLORS	LOGO_FONTr"  r   r7  boolrM  r|   rw   r&   <module>rd     s    
			     M M M M M M M M M M M M M M M M M M M M                             5 5 5 5 5 5 ( ( ( ( ( ( * * * * * * 2 2 2 2 2 2                                $ $ $ $ $ $NS\S(,S	S=@S	S S S SlCLC'+CyC<?C	C C C CL8%(87;Cy8NQ8	8 8 8 8v7'5.)78<S	7OR7	7 7 7 7tIB IB IB IB IB" IB IB IB` 59+/.2U8 U8U87E>"U8 SMU8 WS(3-/01	U8
 (U8 5c?+U8 
U8 U8 U8 U8p IIINNN&)))	 "($F Fd3gun 55667Fc4U38_ 4556F F 	F
 cNF F 
F F F FR:c4U3:%6 6778:FI:	: : : :z7|7c7 7 	7
 7 
7 7 7 7 7 7rw   