API Reference 📒
Core Runtime
These modules control configuration parsing, persistence, and the top-level benchmark entrypoint.
config.py
Configuration management for YAML-based configs, similar to the tf-binding project. Handles both YAML file loading and command-line argument parsing.
- class scTimeBench.config.Config
Bases:
objectConfig class for both yaml and cli arguments.
- class scTimeBench.config.CsvExportType(value)
Bases:
EnumAn enumeration.
- EMBEDDING = 'embedding'
- GEX_PRED = 'gex_pred'
- GRAPH_SIM = 'graph_sim'
- class scTimeBench.config.CsvWriteMode(value)
Bases:
EnumAn enumeration.
- MERGE = 'merge'
- SEPARATE = 'separate'
- class scTimeBench.config.RunType(value)
Bases:
EnumAn enumeration.
- AUTO_TRAIN_TEST = 'auto_train_test'
- EVAL_ONLY = 'eval_only'
- PREPROCESS = 'preprocess'
- TRAIN_ONLY = 'train_only'
- scTimeBench.config.check_yaml_optional(args=None)
Database manager using sqlite3.
This module provides a simple interface to interact with an SQLite database, including the setup of tables for storing: 1. Paths to processed datasets. 2. Paths to method checkpoints. 3. Paths to method predictions. 4. Metric results.
- class scTimeBench.database.DatabaseManager(config: Config)
Bases:
object- clear_tables()
- close()
- embedding_to_csv(output_csv_path, append=False)
- get_dataset_id(method: MethodManager)
- get_dataset_tag_from_id(dataset_id)
- get_evals_per_method(method: MethodManager)
- get_evals_per_metric(metric_name: str, metric_params: str)
- get_method_output_path(method: MethodManager)
- gex_pred_to_csv(output_csv_path, append=False)
- graph_sim_to_csv(output_csv_path, append=False)
- has_eval(method: MethodManager, metric_name: str, metric_params: str) bool
- has_metric(name: str, parameters: str) bool
- insert_dataset(dataset: BaseDataset)
- insert_dataset_metric(dataset: BaseDataset, metric_name, metric_params, result)
- insert_eval(method: MethodManager, metric_name: str, metric_params: str, result)
- insert_method_output(method: MethodManager, output_path: str)
- insert_metric(name: str, parameters: str)
- print_all()
- return_all()
main.py. Entrypoint for measuring trajectories in single-cell data, particularly involving gene regulatory networks and cell lineage information.
- scTimeBench.main.main()
Main entrypoint for the scTimeBench (crispy-fishstick) package.
Dataset Infrastructure
These modules define dataset loading, preprocessing, shared constants, and utility helpers used throughout the benchmark.
Bases:
EnumAn enumeration.
Bases:
EnumAn enumeration.
Bases:
objectCreate a directory for this dataset configuration under the given base path.
Generate a string representation of the dataset configuration.
This can be used to cache processed datasets.
Generate a string representation of the applied dataset preprocessors and their parameters.
This can be used to cache processed datasets.
We define a checkpoint as the ith preprocessor in the pipeline. This is used to save intermediate results that take a while to get to (such as pseudotime estimation).
Get the name of the dataset from the configuration.
Get the directory where the processed test dataset is stored.
If cached_train_dataset is provided, we will use a new output directory which is <cached_train_dataset_dir>/tests/<hash>, where <hash> is a hash of the dataset configuration and preprocessors.
Get the directory where the processed train dataset is stored.
If train_output_dir is provided, we will use that directly, otherwise, we will use the old way of generating a unique directory based on the dataset configuration and preprocessors.
Check if two datasets are equivalent based on their configuration and applied preprocessors.
This ensures that the dataset loading is done properly.
We require the following: 1. Load the data from the source. 2. Include observation metadata of cell_type, and timepoint. 3. Drop everything else not required, to speed up processing. 4. Apply the dataset preprocessors provided. 5. Return the train and test splits.
Update: > Because I’m getting annoyed about the dependency hell we need for psupertime… > I’ve decided that the best way forward is to simply add pypsupertime as a possible > thing to have, but not necessary. Instead, we would require them to run the preprocessing > ahead of time, which is what this function does – loads the data (running them through the preprocessor) > and saving them to their respective output directory.
Some datasets might require caching because they have preprocessors that take a long time to run (e.g., pseudotime estimation). By default, we assume that datasets do not require caching, but this can be overridden by specific datasets if necessary.
Bases:
objectSubclasses should implement this method to preprocessor and split the dataset according to the metric’s requirements.
By default, most preprocessors should be simple and not require external packages.
Decorator to register a dataset class in the DATASET_REGISTRY.
Decorator to register a dataset preprocessor class in the DATASET_PREPROCESSOR_REGISTRY.
Clear the in-memory dataset cache.
Get the dataset from the pickled dataset file in output_path.
- Args:
output_path: Path to the method output directory
- Returns:
The dataset object loaded from the pickled file
Heuristic to determine if the data is log-normalized to a certain counts threshold. Checks if ann_data.X is raw and if not, then checks to see that the data is log-normalized to counts=10_000.
- Args:
ann_data: The AnnData object to check counts: The expected counts value (default is 10_000)
- Returns:
True if the data is log-normalized to the expected counts, False otherwise
Returns whether the data is raw (i.e. not log-normalized) by checking that: 1. All the data is non-negative 2. All the data is integer-valued
Load the dataset from the pickled dataset file in output_path.
- Args:
output_path: Path to the method output directory cache_key_suffix: Optional key to use for caching the dataset in memory. If None, no caching will be used. index: Optional index to specify which dataset to load if the pickled file contains multiple datasets. If None, the first dataset will be loaded.
- Returns:
The dataset object loaded from the pickled file
Load a method output file from output_path.
- Args:
output_path: Path to the method output directory required_output: RequiredOutputFiles enum value specifying which file to load
- Returns:
For .npy files: numpy array For .parquet files: pandas DataFrame
Load the test dataset from the pickled dataset file in output_path.
- Args:
output_path: Path to the method output directory
- Returns:
The test AnnData object from the dataset
Load the train dataset from the pickled dataset file in output_path.
- Args:
output_path: Path to the method output directory
- Returns:
The train AnnData object from the dataset
Log-normalize the data to a certain counts threshold by applying log1p to the data after scaling it so that the total counts per cell equals the specified counts.
- Args:
ann_data: The AnnData object to normalize counts: The total counts threshold to normalize to (default is 10,000)
- Returns:
The log-normalized AnnData object
Undo log-normalization by applying the inverse of log1p, which is expm1. This will convert log-normalized data back to raw counts.
Method Execution
These modules provide the method runner interface and the helper used by the benchmark to launch methods and collect their outputs.
Note: for this file only, this will be used by other methods as a base class And so its context is outside the src/ folder, so we need to use scTimeBench.* imports instead of relative imports.
- class scTimeBench.method_utils.method_runner.BaseMethod(yaml_config)
Bases:
object- generate(test_ann_data)
Main generation method that dispatches to individual output generators. Each output is saved to its own file under self.output_path.
- generate_embedding(test_ann_data) ndarray
Generate embeddings for the current timepoint. Returns: np.ndarray of shape (n_cells, embedding_dim)
- generate_gex_from_t_to_t1(test_ann_data, t, t1) AnnData
Generate predicted gene expression from timepoint t to timepoint t1. Returns: sc.AnnData
- generate_next_cell_type(test_ann_data) DataFrame
Generate next cell type predictions. Returns: pd.DataFrame with cell type predictions
- generate_next_tp_embedding(test_ann_data) ndarray
Generate embeddings for the next timepoint. Returns: np.ndarray of shape (n_cells, embedding_dim)
- generate_next_tp_gex(test_ann_data) ndarray
Generate gene expression for the next timepoint. Returns: np.ndarray of shape (n_cells, n_genes)
- generate_pred_graph(test_ann_data) ndarray
Generate predicted graph. Returns: np.ndarray representing the predicted graph
- generate_zero_to_end_pred_gex(first_tp_cells, all_tps) AnnData
Generate predicted gene expression from the first to the last timepoint. Returns: AnnData object with predicted gene expression across all timepoints
- train(ann_data, all_tps=None, train_output_path=None)
- scTimeBench.method_utils.method_runner.get_parser()
- scTimeBench.method_utils.method_runner.main(method_class: BaseMethod)
- scTimeBench.method_utils.method_runner.process_yaml(yaml_path)
- class scTimeBench.method_utils.ot_method_runner.BaseOTMethod(yaml_config)
Bases:
BaseMethodBase class for OT-based methods.
- generate_embedding(test_ann_data) ndarray
Generate PCA embeddings from gene expression data.
- generate_next_cell_type(test_ann_data) DataFrame
Generate next cell type predictions using transport plan.
- generate_next_tp_embedding(test_ann_data) ndarray
Generate embeddings for the next timepoint using transport plan.
- generate_next_tp_gex(test_ann_data) ndarray
Generate gene expression for the next timepoint using transport plan.
- get_transport_plan(source_data, target_data, train_output_path)
Given source and target data, compute the transport plan. Subclasses representing OT methods should implement this method.
Parameters:
- source_datanp.ndarray
Source data matrix (cells x features)
- target_datanp.ndarray
Target data matrix (cells x features)
Returns:
- np.ndarray
Transport plan matrix (source cells x target cells)
- train(ann_data, all_tps=None, train_output_path=None)
Metric Framework
These modules define the metric base class and the method manager used to bind datasets to method outputs during evaluation.
Base class for all metrics. They should all implement the eval method, and depend on the dataset that they belong to.
- class scTimeBench.metrics.base.BaseMetric(config: Config, db_manager: DatabaseManager, metric_config: dict)
Bases:
object- final eval(filter_dataset: BaseDataset | None = None, filter_method: MethodManager | None = None)
Evaluation function that handles the calling of submetrics if applicable.
Basically it happens as follows:
If there are submetrics defined, we create an instance of each submetric.
We call the _eval function of each submetric.
From this _eval function, we further call the _submetric_eval function that each subclass must implement.
- class scTimeBench.metrics.base.EvalResultKeys(value)
Bases:
EnumAn enumeration.
- DATASET = 'dataset'
- METHOD = 'method'
- RESULT = 'result'
- scTimeBench.metrics.base.create_submetric_instance(config: Config, db_manager: DatabaseManager, metric_config: dict) BaseMetric
Factory that creates an instance of a submetric.
- scTimeBench.metrics.base.register_metric(cls)
Decorator to register a metric class in the METRIC_REGISTRY.
- scTimeBench.metrics.base.skip_metric(cls)
Decorator to register a skip metric class in the SKIP_METRIC_REGISTRY.
Method Base Class.
- class scTimeBench.metrics.method_manager.MethodManager(config, dataset: BaseDataset)
Bases:
object- is_equiv(other_method) bool
Check if two methods are equivalent based on their name and metadata.
- train_and_test(yaml_config_path)
Runs the train and test script provided in the config.
Trajectory Inference
These modules implement the trajectory inference abstractions and concrete inference strategies used by the metrics.
Base trajectory inference model.
This is the base class for all trajectory inference models, i.e. given an ann data and its timepoints, we want to infer the trajectory structure.
Examples are the kNN graph-based methods, or the optimal transport based methods.
- class scTimeBench.trajectory_infer.base.BaseTrajectoryInferMethod(traj_config)
Bases:
object- encode()
Hash the trajectory inference method based on its class name and parameters.
- encode_for_classifier()
Hash the trajectory inference method for the classifier based on its class name and parameters.
This is different from the regular encode because we want to ignore the from_tp_zero because that should be shared regardless of the from_tp_zero setting.
- final infer_trajectory(output_path, per_tp=False, eval_output_path=None)
Infer the trajectory using the kNN graph-based method.
Separate each embedding by time.
Find the k nearest neighbors in the next time point embedding space.
Consolidate the cell types per time point based on the kNN results.
- predict_next_tp(output_path, test_ann_data=None, traj_infer_path=None, eval_output_path=None)
Predict the next timepoint cell types using the trajectory inference model.
- supports_gex()
Function to be overwritten if the trajectory inference method can support By default, we assume it does not.
- final train_and_predict(output_path, train_only=False)
Trains and predicts using the trajectory inference model.
Note for this one here, we train on the train dataset subset instead of the test one. The rest uses the test dataset.
- train_and_predict_k_fold_cv(output_path, k)
Does the train and predict with k-fold cross validation.
We store everything under traj_infer_path/k_fold_<k>/fold_<i>/
- uses_gene_expr()
- class scTimeBench.trajectory_infer.base.TrajectoryInferenceMethodFactory
Bases:
object- get_trajectory_infer_method(traj_config) BaseTrajectoryInferMethod
- class scTimeBench.trajectory_infer.base.TrajectoryOutputConstants(value)
Bases:
EnumAn enumeration.
- CELLTYPE_COL = 'Cell Type'
- COUNT_COL = 'Count'
- PERCENTAGE_COL = 'Percentage'
- TIMEPOINT_COL = 'Time Point'
- scTimeBench.trajectory_infer.base.per_tp_trajectory_to_cell_type_proportions(per_tp_traj, unique_tps)
Helper function to trajectory the per timepoint trajectory into the cell type proportions per timepoint.
Args: - per_tp_traj: the trajectory inferred per timepoint, in the format of {tp: {source_cell_type: {target_cell_type: count}}} - unique_tps: the unique timepoints in the train data, sorted
- scTimeBench.trajectory_infer.base.register_trajectory_inference_method(cls)
Decorator to register a trajectory inference method.
Classifier implementation for trajectory inference.
- class scTimeBench.trajectory_infer.classifier.CellTypist(traj_config)
Bases:
BaseTrajectoryInferMethod
- class scTimeBench.trajectory_infer.classifier.Classifier(traj_config)
Bases:
BaseTrajectoryInferMethod
- class scTimeBench.trajectory_infer.classifier.ClassifierTypes(value)
Bases:
EnumAn enumeration.
- BOOSTING = 'boosting'
- RANDOM_FOREST = 'random_forest'
kNN implementation for trajectory inference.
- class scTimeBench.trajectory_infer.kNN.kNN(traj_config)
Bases:
BaseTrajectoryInferMethod- get_kNN_graph(output_path)
Function to get the kNN graph used in the trajectory inference.
This can be useful for visualization or further analysis.
- class scTimeBench.trajectory_infer.kNN.kNNStrategy(value)
Bases:
EnumAn enumeration.
- MAJORITY_VOTE = 'majority_vote'
- WEIGHTED_AVERAGE = 'weighted_average'
OT implementation for trajectory inference.
- class scTimeBench.trajectory_infer.ot.OptimalTransport(traj_config)
Bases:
BaseTrajectoryInferMethodWARNING: This is untested and deprecated.
Please switch to either kNN or Classifier with scikit-learn based classifiers for better performance and maintainability.
- cell_types_to_one_hot(cell_types)
Given a list of cell types, convert to one-hot encoding
- get_ot_labels(true_embed, pred_embed, one_hot_labels)
Given the true embeddings, predicted embeddings and one-hot encoding of true cell types, get the transport plan using optimal transport
- soft_labels_to_cell_types(labels, index_to_type)
Given the labels from get_ot_labels, and the index to type mapping, convert the soft labels to hard cell type labels
- supports_gex()
By default OT does not have enough capacity to support gene expression data, as it is primarily designed for embedding-based trajectory inference. This is because OT can be computationally intensive and may not scale well with high-dimensional gene expression data, leading to longer runtimes and potential memory issues.