hanhou/patchseq
0
1"""2Size mapping utilities for the scatter plot.3"""4 5from typing import Union6 7import pandas as pd8from bokeh.models import ColumnDataSource9 10 11class SizeMapping:12 """Handles size mapping for scatter plots."""13 14 def __init__(self, df_meta: pd.DataFrame):15 """Initialize with metadata dataframe."""16 self.df_meta = df_meta17 18 def determine_size_mapping(19 self,20 size_mapping: str,21 source: ColumnDataSource,22 min_size: int = 10,23 max_size: int = 20,24 gamma: float = 1,25 ) -> Union[int, str]:26 """27 Determine the size mapping for the scatter plot.28 29 Args:30 size_mapping: Column name to use for size mapping31 source: ColumnDataSource to add size values to32 min_size: Minimum marker size33 max_size: Maximum marker size34 gamma: Gamma value for nonlinear size scaling35 36 Returns:37 Either a fixed size or the name of the size column in the source38 """39 if size_mapping == "None":40 return 1041 42 if size_mapping in self.df_meta.columns:43 numeric_data = pd.Series(pd.to_numeric(self.df_meta[size_mapping], errors="coerce"))44 if not numeric_data.isna().all():45 # Get the min and max of the numeric data46 p5 = numeric_data.quantile(0.00)47 p95 = numeric_data.quantile(1.00)48 49 # Map the normalized values to sizes between min and max with50 # gamma control for nonlinearity51 normalized_values = ((numeric_data - p5) / (p95 - p5)).clip(0, 1)52 normalized_sizes = min_size + (normalized_values**gamma) * (max_size - min_size)53 54 # Replace NaN values with the minimum size55 normalized_sizes = normalized_sizes.fillna(5) # Fixed size for NaN values56 57 # Add the size values to the source data58 source.data["size_values"] = normalized_sizes59 return "size_values"60 61 return 1062 