louvain
Detect communities in single-cell RNA sequencing data using the Louvain clustering algorithm. Customize resolution, random state, and clustering flavor (vtraag, igraph, RAPIDS) for precise cell grouping.
Instructions
Louvain clustering algorithm for community detection
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| directed | No | Interpret the adjacency matrix as directed graph. | |
| flavor | No | Package for computing the clustering: 'vtraag' (default, more powerful), 'igraph' (built-in method), or 'rapids' (GPU accelerated). | vtraag |
| key_added | No | Key under which to add the cluster labels. | louvain |
| neighbors_key | No | Use neighbors connectivities as adjacency. If specified, louvain looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities. | |
| obsp | No | Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time. | |
| partition_kwargs | No | Key word arguments to pass to partitioning, if 'vtraag' method is being used. | |
| random_state | No | Change the initialization of the optimization. | |
| resolution | No | For the default flavor ('vtraag') or for 'RAPIDS', you can provide a resolution (higher resolution means finding more and smaller clusters), which defaults to 1.0. | |
| use_weights | No | Use weights from knn graph. |
Implementation Reference
- src/scmcp/schema/tl.py:344-414 (schema)LouvainModel class defining the input schema and validation for the louvain tool.class LouvainModel(JSONParsingModel): """Input schema for the Louvain clustering algorithm.""" resolution: Optional[float] = Field( default=None, description="For the default flavor ('vtraag') or for 'RAPIDS', you can provide a resolution (higher resolution means finding more and smaller clusters), which defaults to 1.0." ) random_state: int = Field( default=0, description="Change the initialization of the optimization." ) key_added: str = Field( default='louvain', description="Key under which to add the cluster labels." ) flavor: Literal['vtraag', 'igraph', 'rapids'] = Field( default='vtraag', description="Package for computing the clustering: 'vtraag' (default, more powerful), 'igraph' (built-in method), or 'rapids' (GPU accelerated)." ) directed: bool = Field( default=True, description="Interpret the adjacency matrix as directed graph." ) use_weights: bool = Field( default=False, description="Use weights from knn graph." ) partition_kwargs: Optional[Dict[str, Any]] = Field( default=None, description="Key word arguments to pass to partitioning, if 'vtraag' method is being used." ) neighbors_key: Optional[str] = Field( default=None, description="Use neighbors connectivities as adjacency. If specified, louvain looks .obsp[.uns[neighbors_key]['connectivities_key']] for connectivities." ) obsp: Optional[str] = Field( default=None, description="Use .obsp[obsp] as adjacency. You can't specify both `obsp` and `neighbors_key` at the same time." ) @field_validator('resolution') def validate_resolution(cls, v: Optional[float]) -> Optional[float]: """Validate resolution is positive if provided""" if v is not None and v <= 0: raise ValueError("resolution must be a positive number") return v @field_validator('obsp', 'neighbors_key') def validate_graph_source(cls, v: Optional[str], info: ValidationInfo) -> Optional[str]: """Validate that obsp and neighbors_key are not both specified""" values = info.data if v is not None and 'obsp' in values and 'neighbors_key' in values: if values['obsp'] is not None and values['neighbors_key'] is not None: raise ValueError("Cannot specify both obsp and neighbors_key") return v @field_validator('flavor') def validate_flavor(cls, v: str) -> str: """Validate flavor is supported""" if v not in ['vtraag', 'igraph', 'rapids']: raise ValueError("flavor must be one of 'vtraag', 'igraph', or 'rapids'") return v
- src/scmcp/tool/tl.py:54-59 (registration)Registration of the 'louvain' MCP Tool object, specifying name, description, and input schema.# Add louvain tool louvain_tool = types.Tool( name="louvain", description="Louvain clustering algorithm for community detection", inputSchema=LouvainModel.model_json_schema(), )
- src/scmcp/tool/tl.py:125-142 (registration)Mapping of 'louvain' to sc.tl.louvain function for dispatch in tool execution.tl_func = { "tsne": sc.tl.tsne, "umap": sc.tl.umap, "draw_graph": sc.tl.draw_graph, "diffmap": sc.tl.diffmap, "embedding_density": sc.tl.embedding_density, "leiden": sc.tl.leiden, "louvain": sc.tl.louvain, "dendrogram": sc.tl.dendrogram, "dpt": sc.tl.dpt, "paga": sc.tl.paga, "ingest": sc.tl.ingest, "rank_genes_groups": sc.tl.rank_genes_groups, "filter_rank_genes_groups": sc.tl.filter_rank_genes_groups, "marker_gene_overlap": sc.tl.marker_gene_overlap, "score_genes": sc.tl.score_genes, "score_genes_cell_cycle": sc.tl.score_genes_cell_cycle, }
- src/scmcp/tool/tl.py:145-162 (registration)Registration of louvain_tool in the tl_tools dictionary, likely used for MCP server tool list.tl_tools = { "tsne": tsne_tool, "umap": umap_tool, "draw_graph": draw_graph_tool, "diffmap": diffmap_tool, "embedding_density": embedding_density_tool, "leiden": leiden_tool, "louvain": louvain_tool, "dendrogram": dendrogram_tool, "dpt": dpt_tool, "paga": paga_tool, "ingest": ingest_tool, "rank_genes_groups": rank_genes_groups_tool, "filter_rank_genes_groups": filter_rank_genes_groups_tool, "marker_gene_overlap": marker_gene_overlap_tool, "score_genes": score_genes_tool, "score_genes_cell_cycle": score_genes_cell_cycle_tool, }
- src/scmcp/tool/tl.py:164-177 (handler)Handler function that executes the tool by dispatching to sc.tl.louvain based on func='louvain', handling arguments and logging.def run_tl_func(ads, func, arguments): adata = ads.adata_dic[ads.active] if func not in tl_func: raise ValueError(f"Unsupported function: {func}") run_func = tl_func[func] parameters = inspect.signature(run_func).parameters kwargs = {k: arguments.get(k) for k in parameters if k in arguments} try: res = run_func(adata, **kwargs) add_op_log(adata, run_func, kwargs) except Exception as e: logger.error(f"Error running function {func}: {e}") raise return