deadleaves ========== .. py:module:: deadleaves Submodules ---------- .. toctree:: :maxdepth: 1 /reference/deadleaves/acceleration/index /reference/deadleaves/deadleaves/index /reference/deadleaves/distributions/index /reference/deadleaves/leaf_masks/index /reference/deadleaves/utils/index Classes ------- .. autoapisummary:: deadleaves.LeafGeometryGenerator deadleaves.LeafAppearanceSampler deadleaves.ImageRenderer deadleaves.LeafTopology Package Contents ---------------- .. py:class:: LeafGeometryGenerator(leaf_shape: Literal['circular', 'ellipsoid', 'rectangular', 'polygon'], shape_param_distributions: dict[str, dict[str, dict[str, float | dict]]], image_shape: tuple[int, int], position_mask: torch.Tensor | numpy.ndarray | dict | None = None, n_sample: int | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None) Set up the geometrical dead leaves model. Args: leaf_shape (Literal["circular", "ellipsoid", "rectangular", "polygon"]): Shape of leaves. shape_param_distributions (dict[str, dict[str, [dict[str, float | dict]]]): Leaf shape parameters and their distributions and hyperparameter values. image_shape (tuple[int, int]): Height (y, M) and width (x, N) of the canvas. position_mask (torch.Tensor | np.ndarray | dict | None, optional): Boolean tensor containing allowed leaf positions to create images with different shapes. If None all positions on the canvas are allowed. Defaults to None. n_sample (int | None, optional): Number of leaves to sample. If None, the sampling will stop when the full area is partitioned. Default is None. device (Literal["cuda", "mps", "cpu"] | None, optional): Torch device to use, either 'cuda' or 'cpu'. If None, device will be chosen automatically. Defaults to None. .. py:attribute:: device :type: torch.device Chosen compute backend. .. py:attribute:: image_shape :type: tuple[int, int] Height (y, M) and width (x, N) of the canvas. .. py:attribute:: n_sample :type: int | None :value: None Number of leaves to sample. .. py:attribute:: leaf_shape :type: Literal['circular'] | Literal['ellipsoid'] | Literal['rectangular'] | Literal['polygon'] Shape of the leaves. .. py:attribute:: shape_param_distributions Shape parameters and their distributions and hyperparameter values. .. py:attribute:: generate_leaf_mask :type: Callable Method to generate mask of leaf on canvas. .. py:attribute:: position_mask :type: torch.Tensor Positions on canvas masked for sampling leaf positions. .. py:method:: _resolve_dependencies() -> list[str] Resolve model parameter dependencies. Raises: ValueError: Error on circular or unresolvable dependencies. Returns: list[str]: Sorted list of parameters. .. py:method:: _unpack_parameters() -> None Generate list of model parameters and distribution instances to sample from. Raises: ValueError: Provided parameters don't match provided leaf shape. .. py:method:: _sample_parameters() -> dict[str, torch.Tensor] Draw a sample from the model distributions. Returns: dict[str, torch.Tensor]: Sample for each model parameter. .. py:method:: _resolve_position_mask(position_mask: torch.Tensor | numpy.ndarray | dict) -> None Resolve position mask from tensor or geometric specification. Args: position_mask (torch.Tensor | np.ndarray | dict): Boolean tensor or array with allowed sampling positions or dictionary specifying a leaf shape and its parameters. Raises: ValueError: Position mask dict must contain 'shape' and 'params'. ValueError: Check for unsupported leaf shapes in dict. TypeError: Check argument type. ValueError: Check that position mask has same size as canvas. ValueError: Check that there are allowed positions. .. py:method:: generate_segmentation() -> tuple[pandas.DataFrame, torch.Tensor] Generate a dead leaves segmentation from the model. Uses a quadtree to track which canvas regions still contain uncovered pixels. Fully covered subtrees are pruned from future queries, so mask evaluation is restricted to the sparse frontier of remaining gaps. Returns: tuple[pd.DataFrame, torch.Tensor]: Dataframe listing the parameters of all generated leaves, along with an segmentation map assigning each image location to a leaf. .. py:class:: LeafAppearanceSampler(leaf_table: pandas.DataFrame, device: Literal['cuda', 'mps', 'cpu'] | None = None) Setup color and texture model for a dead leaves partition. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. device (Literal["cuda", "mps", "cpu"] | None, optional): Torch device to use, either 'cuda' or 'cpu'. If None, device will be chosen automatically. Defaults to None. .. py:attribute:: device :type: torch.device Chosen compute backend. .. py:attribute:: leaf_table :type: pandas.DataFrame Dataframe of leaves and their parameters. .. py:attribute:: n_leaves :type: int Number of leaves. .. py:method:: _unpack_color() -> None Generate color distribution instances to sample from. .. py:method:: _sample_grayscale_colors() -> torch.Tensor Sample a grayscale color for each leaf. Returns: torch.Tensor: Color values. .. py:method:: _sample_3d_colors() -> torch.Tensor Sample a 3d color for each leaf. Returns: torch.Tensor: Color values. .. py:method:: _sample_colors_from_images() -> torch.Tensor Sample a pixel value for each leaf from a random image in folder. Returns: torch.Tensor: Color values. .. py:method:: sample_color(color_param_distributions: dict[str, dict[str, dict[str, float]]] | dict[str, dict[str, dict[str, dict]]] | dict[str, dict[str, dict[str, str]]]) -> pandas.DataFrame Sample leaf colors according to the configured color space. Args: color_param_distributions (dict[str, dict[str, dict[str, float | dict | str]]]): Color parameters and their distribution setup. Returns: pd.DataFrame: Updated DataFrame with color parameters added to each leaf .. py:method:: _unpack_texture() -> None Generate texture distribution instances to sample from. .. py:method:: _sample_texture_parameters() -> pandas.DataFrame Materialize per-leaf texture parameters and distribution metadata. Returns: pd.DataFrame One row per leaf with resolved texture parameters for all channels. .. py:method:: sample_texture(texture_param_distributions: dict[str, dict[str, dict[str, float | str | dict[str, dict[str, float]]]]]) -> pandas.DataFrame Sample leaf textures according to the configured color space. Args: texture_param_distribution (dict[str, dict[str, dict[str, float | dict[str, dict[str, float]]]]]): Texture parameters and their distribution setup. Raises: ValueError: Chosen texture space is not supported. Return: pd.DataFrame: Updated DataFrame with texture parameters added to each leaf .. py:class:: ImageRenderer(leaf_table: pandas.DataFrame, segmentation_map: torch.Tensor | None = None, image_shape: tuple[int, int] | None = None, background_color: torch.Tensor | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None) Setup leaf geometry and appearance for rendering. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. segmentation_map (torch.Tensor | None, optional): Partition which assigns image locations to a leaf. If None the segmentation map will be generated from the leaf table. Defaults to None. image_shape (tuple[int,int] | None, optional): Height (y, M) and width (x, N) of the canvas. If None the image_shape will be set based on the segmentation map. Defaults to None. Either image_shape or segmentation_map need to be given. background_color (torch.Tensor | None, optional): For images which are not fully covered (due to a position mask or sparse sampling) one can set a RGB background color. If None the background will be black. Defaults to None. device (Literal["cuda", "mps", "cpu"] | None, optional): Torch device to use, either 'cuda' or 'cpu'. If None, device will be chosen automatically. Defaults to None. .. py:attribute:: device :type: torch.device Chosen compute backend. .. py:attribute:: background_color :type: torch.Tensor | None :value: None Color for pixels not belonging to any leaf. .. py:attribute:: leaf_table :type: pandas.DataFrame Dataframe of leaves and their parameters. .. py:attribute:: segmentation_map :type: torch.Tensor | None :value: None Partition of the image area. .. py:attribute:: image_shape :type: tuple[int, int] Height (y, M) and width (x, N) of the canvas. .. py:method:: _resolve_image_shape(image_shape: tuple[int, int] | None, segmentation_map: torch.Tensor | None) -> tuple[int, int] Resolve image shape from segmentation_map or explicit image_shape. Raises: ValueError: Shape of segmentation map and provided image shape don't match. ValueError: Neither image_shape nor segmentation map are given. .. py:method:: _generate_segmentation_map() -> None Generate segmentation map if None is provided. .. py:method:: _infer_texture_space() -> None Infer which color space the texture parameters are defined in. .. py:method:: _infer_color_space() -> None Infer which color space the color parameters are defined in. .. py:method:: _get_texture_param_columns(channel: str) -> list[str] Get all columns which contain texture parameters from leaf_table. Args: channel (str): Color channel to extract parameters for. Returns: list[str]: Columns with parameters for channel texture. .. py:method:: _get_leaf_texture_params(leaf_row: pandas.Series, channel: str) -> dict Get values from columns with texture parameters in leaf_table. Args: leaf_row (pd.Series): Single row from leaf table. channel (str): Channel name. Returns: dict: Parameters for leaf texture as dictionary. .. py:method:: _generate_leafwise_texture_1d(channel: str) -> torch.Tensor Generate grayscale texture from sampled distributions. Args: channel (str): Color channel name. Returns: torch.Tensor Texture image of shape (H, W). .. py:method:: _generate_leafwise_texture_from_source() -> torch.Tensor Generate grayscale texture from image sources stored in leaf_table. Returns: torch.Tensor Texture image of shape (H, W). .. py:method:: _generate_leafwise_texture() -> torch.Tensor Generate a per-pixel texture image from leafwise texture parameters. Raises: ValueError: Fallback for unknown specifications. Returns: torch.Tensor Texture RBG image of shape (H, W, 3). .. py:method:: render_image() -> torch.Tensor Generate a dead leaves image. Returns: torch.Tensor: Dead leaves image tensor. .. py:method:: apply_image_noise(noise: dict[str, dict | torch.Tensor], image: torch.Tensor | None = None) -> torch.Tensor Apply global noise to an image. Args: image (torch.Tensor): Input image tensor of shape (H, W, C), values in [0,1]. noise (dict): Dictionary or tensor/array specifying noise per channel. Examples: - Distribution-based: {"gray": {"normal": {"loc": 0, "scale": 0.1}}} - Array-based: {"R": torch.randn(H, W) * 0.05} Returns: torch.Tensor: Image with noise applied, clipped to [0,1]. .. py:method:: show(image: torch.Tensor | None = None, figsize: tuple[int, int] | None = None) -> None Show selected image. Args: image (torch.Tensor, optional): Image to show. If None the self.image will be used. figsize (tuple[int,int], optional): Figure size in inches (width, height). If None size is inferred from image size. Defaults to None. .. py:method:: save(save_to: pathlib.Path | str, image: torch.Tensor | None = None) -> None Save image to path. Args: save_to (Path): Path to file to save image to. image (torch.Tensor, optional): Image to save. If None the self.image will be used. .. py:method:: animate(fps: int = 10, save_to: pathlib.Path | None = None) -> matplotlib.animation.FuncAnimation Generate animation of dead leaves partition generation. Args: fps (int, optional): Frames per second of animation. In each frame a new leaf is sampled. Defaults to 10. save_to (Path, optional): Path to file to save animation to. If None the animation will not be saved. Defaults to None. Returns: animation.FuncAnimation: Animation of partition generation. .. py:class:: LeafTopology(image_shape: tuple[int, int] | None = None, device: Literal['cuda', 'mps', 'cpu'] | None = None) Topology-level operations on leaf tables to - Construct segmentation maps - Merge and relabel leaf tables - Manage leaf identities (leaf_idx) Args: image_shape (tuple[int, int] | None, optional): Height (y, M) and width (x, N) of the area to be partitioned. device (Literal["cuda", "mps", "cpu"] | None, optional): Torch device to use, either 'cuda' or 'cpu'. If None, device will be chosen automatically. Defaults to None. .. py:attribute:: image_shape :type: tuple[int, int] | None :value: None Height (y, M) and width (x, N) of the canvas. .. py:attribute:: device :type: torch.device Chosen compute backend. .. py:method:: _validate_geometry(leaf_table: pandas.DataFrame) -> None :staticmethod: Check if leaf table contains parameters necessary for constructing the geometry. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. Raises: ValueError: If required columns are missing, unknown shapes are present, or required parameters contain NaNs. .. py:method:: _cull_outside_canvas(leaf_table: pandas.DataFrame) -> pandas.DataFrame Remove leaves whose centers are outside the canvas. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. Returns: pd.DataFrame: Reduced table. .. py:method:: segmentation_map_from_table(leaf_table: pandas.DataFrame) -> torch.Tensor Construct a segmentation map from a leaf table. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. Returns: torch.Tensor: Segmentation map which assigns each image location to a leaf. .. py:method:: merge_leaf_tables(*leaf_tables: pandas.DataFrame) -> pandas.DataFrame :staticmethod: Merge multiple leaf tables and assign fresh leaf_idx. Args: leaf_tables (pd.DataFrame): List of tables to be merged. Returns: pd.DataFrame: Merged table. .. py:method:: reindex_by_group(leaf_table: pandas.DataFrame, groupby: str, shuffle: bool = True, group_order: str | None = None, seed: int | None = None) -> pandas.DataFrame :staticmethod: Reassign leaf_idx within groups. Args: leaf_table (pd.DataFrame): Dataframe of leaves and their parameters. groupby (str): Column containing the groups. shuffle (bool): If true shuffle leaf index within group. Defaults to true. group_order (str | None): Order of groups: "ascending", or "descending", or random (None). Defaults to None. seed (int | None): Set value for generating a random seed for reproducibility. If None a different random seed will be set at each execution. Defaults to None. Returns: pd.DataFrame: Reindexed (and shuffled) table. .. py:method:: randomize_index(leaf_table: pandas.DataFrame, seed: int | None = None) -> pandas.DataFrame :staticmethod: Randomly reassign a global index while preserving all row attributes. This shuffles depth ordering across all leaves, including across semantic groups (e.g. target vs background), while keeping group labels intact. Args: table (pd.DataFrame): Input leaf table. seed (int, optional): Random seed for reproducibility. Default to None. Returns: pd.DataFrame: Table with randomized index_col.