Skip to content

Refactor/move typing to ty#223

Merged
noamteyssier merged 3 commits intocell-eval-0.7.0from
refactor/move-typing-to-ty
Feb 26, 2026
Merged

Refactor/move typing to ty#223
noamteyssier merged 3 commits intocell-eval-0.7.0from
refactor/move-typing-to-ty

Conversation

@noamteyssier
Copy link
Collaborator

No description provided.

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @noamteyssier, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on improving the type safety and clarity of the Python codebase by integrating the ty library and extensively using typing.cast. The changes involve adding ty as a development dependency, importing cast and pandas where necessary, and applying explicit type casting to anndata objects and their attributes. This refactoring aims to provide more precise type information for static analysis tools, leading to more maintainable and error-resistant code.

Highlights

  • Type Hinting Refinement: The pull request significantly refactors the codebase to enhance type hinting by introducing explicit cast operations from the typing module across multiple files. This improves static analysis and code clarity.
  • New Development Dependency: The ty library (version >=0.0.19) has been added as a development dependency in pyproject.toml, indicating a move towards more robust type checking practices.
  • Pandas Integration with Type Casting: Several modules now explicitly import pandas and utilize pd.Series and pd.DataFrame casts, particularly when interacting with anndata.obs and anndata.var attributes, to provide clearer type information to the type checker.
  • Type Ignore Adjustments: Existing type: ignore comments have been reviewed and adjusted, with some being removed due to improved type inference and others added for specific cases where type checkers might struggle without explicit guidance.
  • Notebook Example Update: A tutorial notebook (tutorials/vcc/vcc.ipynb) was updated to reflect the new typing practices, specifically using pd.Series for unique value checks and adding a type: ignore for adata.write_h5ad.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • pyproject.toml
    • Added ty>=0.0.19 to the dev dependencies.
  • src/cell_eval/_baseline.py
    • Imported cast from typing and pandas as pd.
    • Applied cast(pd.DataFrame, adata.var) for explicit type hinting.
    • Applied cast(pd.Series, adata.obs[pert_col]) for explicit type hinting.
    • Added type: ignore[invalid-argument-type] to baseline_adata.write_h5ad call.
  • src/cell_eval/_cli/_prep.py
    • Imported cast from typing.
    • Applied cast(pd.Series, adata.obs[pert_col]) for explicit type hinting.
    • Applied cast(pd.Series, adata.obs[celltype_col]) for explicit type hinting.
    • Added type: ignore[invalid-argument-type] to minimal.write_h5ad call.
  • src/cell_eval/_types/_anndata.py
    • Imported cast from typing and pandas as pd.
    • Applied cast(pd.Series, self.real.obs[self.pert_col]) and cast(pd.Series, self.pred.obs[self.pert_col]) for explicit type hinting.
  • src/cell_eval/metrics/_anndata.py
    • Imported cast from typing.
    • Removed type: ignore from pearsonr call.
    • Applied cast(pd.Series, adata.obs[category_key]) for explicit type hinting.
    • Applied cast(pd.DataFrame, ad_real_cent.obs) and cast(pd.DataFrame, ad_pred_cent.obs) for explicit type hinting.
  • src/cell_eval/metrics/base.py
    • Updated the return type hint of MetricResult.to_dict to dict[str, float | str | None] to correctly reflect the perturbation field being None.
  • src/cell_eval/utils.py
    • Imported cast from typing and pandas as pd.
    • Added type: ignore[unresolved-attribute] to adata.X.toarray() call.
    • Added type: ignore[no-matching-overload] to np.max(adata.X) and np.min(adata.X) calls.
    • Applied cast(pd.Series, adata.obs[celltype_col]) for explicit type hinting.
    • Applied cast(np.ndarray | csr_matrix | csc_matrix, adata.X) and cast(csr_matrix | csc_matrix, x).data.dtype for explicit type hinting.
  • tests/test_eval.py
    • Imported cast from typing and pandas as pd.
    • Applied cast(pd.DataFrame, adata_real.obs).drop and cast(pd.DataFrame, adata_pred.obs).drop for explicit type hinting.
    • Added type: ignore[unknown-argument] to de_method argument in MetricsEvaluator.
  • tutorials/vcc/vcc.ipynb
    • Updated notebook cell to import pandas as pd.
    • Changed adata.obs["target_gene"].unique() to pd.Series(adata.obs["target_gene"]).unique() for explicit type hinting.
    • Changed np.all(adata.var_names.values == ntc_adata.var_names.values) to np.array_equal(adata.var_names, ntc_adata.var_names).
    • Added type: ignore[invalid-argument-type] to adata.write_h5ad call.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/CI.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@noamteyssier noamteyssier merged commit 88023cf into cell-eval-0.7.0 Feb 26, 2026
11 checks passed
@noamteyssier noamteyssier deleted the refactor/move-typing-to-ty branch February 26, 2026 19:30
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request focuses on improving type safety across the codebase, primarily by adding typing.cast to guide the static type checker and addressing various typing-related issues. Most changes successfully enhance type correctness, such as removing unnecessary type: ignore comments and correcting return types. However, a new type: ignore added in src/cell_eval/utils.py masks a potential runtime bug, which I've detailed in a specific comment. Overall, it's a good step towards a more type-safe codebase, with one critical point to address.

Comment on lines 43 to +44
elif adata.isview:
frac, _ = np.modf(adata.X.toarray())
frac, _ = np.modf(adata.X.toarray()) # type: ignore[unresolved-attribute]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Adding type: ignore here hides a potential AttributeError at runtime. The adata.isview check doesn't guarantee that adata.X is a sparse matrix with a .toarray() method. If adata is a view of an AnnData object with a dense X matrix, adata.X will be a numpy.ndarray and won't have .toarray(), which would cause a crash.

A more robust approach would be to check for sparsity directly using scipy.sparse.issparse() and handle dense and sparse cases accordingly. This would also be more efficient for sparse matrices than calling .toarray().

Consider refactoring this logic to check for sparsity first, which is more reliable than checking isview:

    if adata.X is None:
        raise ValueError("adata.X is None")

    if sp.issparse(adata.X):
        frac, _ = np.modf(adata.X.data)
    else:
        frac, _ = np.modf(adata.X)

This simplified logic correctly handles both sparse and dense matrices, regardless of whether adata is a view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant