def generate_tree_config(tree_genome=None, season="autumn"):
    """
    Main latent params that we might want to control:
    - overall size/"age"
    - trunk straightness
    - additional "trunks"
    - starting height of branches
    - outgoing branch angle (parallel to ground vs angled up vs angled proporitionally to height)
    - branch density
    - branch length (fn of height)
    - branch straightness
    - pull direction (up/down/to the side)
    - outgrowth (space filling) / "density"
    - branch thickness (ideally this behaves reasonably based on everything else)
    """
    if tree_genome is None:
        tree_genome = np.random.rand(32)

    cfg = parse_genome(tree_genome)
    sz = calc_height(cfg["size"], min_ht=12)
    n_tree_pts = int(sz)
    n_trunks = int(10 ** (cfg["n_trunks"] ** 1.6))
    ex = np.exp((6 - (5 if n_trunks > 1 else 0)) * (cfg["trunk_warp"] - 0.1))
    trunk_std = ((1 - (ex / (1 + ex))) * 4) ** 2
    trunk_mtm = max(0.2, min(0.95, (1 / (trunk_std + 1)) + np.random.randn() * 0.2))
    radial_out = False  # False # np.random.rand() < .3
    avail_idxs = np.arange(n_tree_pts)
    start_idx = 1 + int(n_tree_pts * np.random.uniform(0.1, 0.7))
    sample_density = np.random.choice(
        np.arange(np.ceil(np.sqrt(n_tree_pts)), dtype=int) + 1
    )
    avail_idxs = avail_idxs[start_idx::sample_density]
    multi_branch = int(5 ** (cfg["multi_branch"] ** 1.6))
    avail_idxs = np.repeat(avail_idxs, multi_branch).flatten()

    n = len(avail_idxs)

    start_ht = sz * (start_idx / sz)
    box_ht = (sz - start_ht) * 0.6

    def tmp_att_fn(nodes):
        branch_pts = mesh.get_pts_from_shape(
            bpy.ops.mesh.primitive_cube_add,
            n=500,
            scaling=[sz / 2, sz / 2, box_ht],
            pt_offset=[0, 0, start_ht + sz * 0.4],
        )
        return branch_pts

    max_sz = 1

    if radial_out:
        start_ht = int(sz * 0.1)
        per_layer = np.random.randint(3, 6)
        branch_config = {
            "n": n * per_layer,
            "path_kargs": lambda idx: {
                "n_pts": np.random.randint(
                    np.floor(((n - idx // per_layer) / n) * 6),
                    np.ceil(((n - idx // per_layer) / n) * 8),
                )
                + 3,
                "std": 0.3,
                "momentum": 0.9,
                "sz": max_sz - (max_sz / sz) * (idx // per_layer),
                "pull_dir": [0, 0, np.random.rand()],
                "pull_factor": np.random.rand(),
            },
            "spawn_kargs": lambda idx: {
                "rnd_idx": avail_idxs[idx // per_layer],
                "ang_min": np.pi / 2,
                "ang_max": np.pi / 2 + np.pi / 16,
                "axis2": [np.random.randn(), np.random.randn(), 0.5],
            },
        }

    else:
        branch_config = {
            "n": n,
            "path_kargs": lambda idx: {
                "n_pts": int(n_tree_pts * np.random.uniform(0.4, 0.6)),
                "sz": 1,
                "std": 1.4,
                "momentum": 0.4,
                "pull_dir": [0, 0, np.random.rand()],
                "pull_factor": np.random.rand(),
            },
            "spawn_kargs": lambda idx: {"rnd_idx": avail_idxs[idx]},
        }

    tree_config = {
        "n": n_trunks,
        "path_kargs": lambda idx: (
            {
                "n_pts": n_tree_pts,
                "sz": 1,
                "std": trunk_std,
                "momentum": trunk_mtm,
                "pull_dir": [0, 0, 0],
            }
        ),
        "spawn_kargs": lambda idx: {"init_vec": [0, 0, 1]},
        "children": [branch_config],
    }

    tmp_D = 0.3 + 0.2 * (sz / 30)  # .3 * sz / 8
    tmp_s = tmp_D * 1.3
    if n < 5:
        n_updates = np.random.choice([2, 3, int(1 + sz // 2)])
    else:
        n_updates = np.random.choice([2, 2, 2, 3, 4, 5])

    max_radius = 0.2
    merge_size = 2.5 - cfg["branch_thickness"]

    if season == "winter":
        twig_density = 0.0 if cfg["twig_density"] < 0.5 else 0.5 * cfg["twig_density"]
        twig_inst = 1 + 0 * np.random.randint(3, 5)
    else:
        twig_density = 0.5 + 0.5 * cfg["twig_density"]
        twig_inst = np.random.randint(1, 3)

    return TreeParams(
        skeleton=tree_config,
        skinning={"Max radius": max_radius, "Min radius": 0.02, "Exponent": merge_size},
        trunk_spacecol={
            "atts": tmp_att_fn,
            "D": tmp_D,
            "s": tmp_s,
            "d": 10,
            "pull_dir": [0, 0, np.random.randn() * 0.3],
            "n_steps": n_updates,
        },
        roots_spacecol=None,  # {'atts': None, 'D': .05, 's': .1, 'd': 2, 'dir_rand': .05, 'mag_rand': .05, 'pull_dir': None, 'n_steps': 30},
        child_placement={
            "depth_range": (0, 5.0),
            "Density": twig_density,
            "Multi inst": twig_inst,
            "Pitch variance": 1.0,
            "Yaw variance": 10.0,
            "Min scale": 1.1,
            "Max scale": 1.3,
        },
    )

    Main latent params that we might want to control:
    - overall size/"age"
    - trunk straightness
    - additional "trunks"
    - starting height of branches
    - outgoing branch angle (parallel to ground vs angled up vs angled proporitionally to height)
    - branch density
    - branch length (fn of height)
    - branch straightness
    - pull direction (up/down/to the side)
    - outgrowth (space filling) / "density"
    - branch thickness (ideally this behaves reasonably based on everything else)
    
infinigen/assets/objects/trees/treeconfigs.py