From ac974faf641b9f3db5713b0b1dcaf1d76f529b38 Mon Sep 17 00:00:00 2001 From: Ziwen Liu Date: Tue, 17 Jun 2025 12:00:31 -0700 Subject: [PATCH 1/4] use ruff format --- .github/workflows/pr.yml | 7 ++----- CONTRIBUTING.md | 9 ++------- .../virtual_staining/dlmbl_exercise/prepare-exercise.sh | 4 ++-- examples/virtual_staining/dlmbl_exercise/setup.sh | 2 +- .../img2img_translation/prepare-exercise.sh | 4 ++-- examples/virtual_staining/img2img_translation/setup.sh | 2 +- .../virtual_staining/phase_contrast/prepare-exercise.sh | 4 ++-- examples/virtual_staining/phase_contrast/setup.sh | 2 +- pyproject.toml | 5 +---- 9 files changed, 14 insertions(+), 25 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3543cd357..0dd4c5fd8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,13 +8,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: psf/black@stable - with: - src: "viscy" - options: "--check --verbose" - - uses: chartboost/ruff-action@v1 + - uses: astral-sh/ruff-action@v3 with: src: "viscy" + - run: ruff format --check test: name: Test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 51602c83d..50499bc0c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,16 +12,11 @@ pip install -e ".[dev]" ## CI requirements -Lint with Ruff: +Lint and format with Ruff: ```sh ruff check viscy -``` - -Format the code with Black: - -```sh -black viscy +ruff format viscy tests ``` Run tests with `pytest`: diff --git a/examples/virtual_staining/dlmbl_exercise/prepare-exercise.sh b/examples/virtual_staining/dlmbl_exercise/prepare-exercise.sh index 3447327f7..630fb201e 100644 --- a/examples/virtual_staining/dlmbl_exercise/prepare-exercise.sh +++ b/examples/virtual_staining/dlmbl_exercise/prepare-exercise.sh @@ -1,5 +1,5 @@ -# Run black on .py files -# black solution.py +# Run ruff format on .py files +# ruff format viscy # Convert .py to ipynb diff --git a/examples/virtual_staining/dlmbl_exercise/setup.sh b/examples/virtual_staining/dlmbl_exercise/setup.sh index ffdb91828..9a8f7ac4f 100644 --- a/examples/virtual_staining/dlmbl_exercise/setup.sh +++ b/examples/virtual_staining/dlmbl_exercise/setup.sh @@ -7,7 +7,7 @@ conda deactivate conda create -y --name 06_image_translation python=3.11 # Install ipykernel in the environment. -conda install -y ipykernel nbformat nbconvert black jupytext ipywidgets --name 06_image_translation +conda install -y ipykernel nbformat nbconvert ruff jupytext ipywidgets --name 06_image_translation # Specifying the environment explicitly. # conda activate sometimes doesn't work from within shell scripts. diff --git a/examples/virtual_staining/img2img_translation/prepare-exercise.sh b/examples/virtual_staining/img2img_translation/prepare-exercise.sh index d58d69597..526b9fa3c 100644 --- a/examples/virtual_staining/img2img_translation/prepare-exercise.sh +++ b/examples/virtual_staining/img2img_translation/prepare-exercise.sh @@ -1,5 +1,5 @@ -# Run black on .py files -# black solution.py +# Run ruff format on .py files +# ruff format solution.py # Convert .py to ipynb diff --git a/examples/virtual_staining/img2img_translation/setup.sh b/examples/virtual_staining/img2img_translation/setup.sh index e58736a4f..f5f1890c2 100644 --- a/examples/virtual_staining/img2img_translation/setup.sh +++ b/examples/virtual_staining/img2img_translation/setup.sh @@ -7,7 +7,7 @@ conda deactivate conda create -y --name image2image python=3.11 # Install ipykernel in the environment. -conda install -y ipykernel nbformat nbconvert black jupytext ipywidgets --name img2img +conda install -y ipykernel nbformat nbconvert ruff jupytext ipywidgets --name img2img # Specifying the environment explicitly. # conda activate sometimes doesn't work from within shell scripts. diff --git a/examples/virtual_staining/phase_contrast/prepare-exercise.sh b/examples/virtual_staining/phase_contrast/prepare-exercise.sh index d58d69597..526b9fa3c 100644 --- a/examples/virtual_staining/phase_contrast/prepare-exercise.sh +++ b/examples/virtual_staining/phase_contrast/prepare-exercise.sh @@ -1,5 +1,5 @@ -# Run black on .py files -# black solution.py +# Run ruff format on .py files +# ruff format solution.py # Convert .py to ipynb diff --git a/examples/virtual_staining/phase_contrast/setup.sh b/examples/virtual_staining/phase_contrast/setup.sh index e1c1c4d57..6ac4e67ce 100644 --- a/examples/virtual_staining/phase_contrast/setup.sh +++ b/examples/virtual_staining/phase_contrast/setup.sh @@ -7,7 +7,7 @@ conda deactivate conda create -y --name vs_Phc python=3.11 # Install ipykernel in the environment. -conda install -y ipykernel nbformat nbconvert black jupytext ipywidgets --name vs_Phc +conda install -y ipykernel nbformat nbconvert ruff jupytext ipywidgets --name vs_Phc # Specifying the environment explicitly. # conda activate sometimes doesn't work from within shell scripts. diff --git a/pyproject.toml b/pyproject.toml index 32c3374dd..d2fb83788 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,6 @@ dev = [ "pytest-cov", "hypothesis", "ruff", - "black", "profilehooks", "onnxruntime", ] @@ -72,10 +71,8 @@ packages = ["viscy"] [tool.setuptools_scm] write_to = "viscy/_version.py" -[tool.black] -line-length = 88 - [tool.ruff] src = ["viscy", "tests"] +line-length = 88 lint.extend-select = ["I001"] lint.isort.known-first-party = ["viscy"] From a0c9221366e68130877afffaf21ab6ec6d8b030f Mon Sep 17 00:00:00 2001 From: Ziwen Liu Date: Tue, 17 Jun 2025 12:00:41 -0700 Subject: [PATCH 2/4] migrate old styles --- tests/unet/networks/Unet25D_tests.py | 10 ++++------ tests/unet/networks/Unet2D_tests.py | 10 ++++------ tests/unet/networks/layers/ConvBlock2D_tests.py | 10 ++++------ tests/unet/networks/layers/ConvBlock3D_tests.py | 10 ++++------ .../evaluation/dimensionality_reduction.py | 2 +- viscy/scripts/profile_dataloader.py | 10 +++++++--- viscy/scripts/visualize_features.py | 4 ++-- viscy/unet/networks/Unet25D.py | 6 +++--- viscy/unet/networks/Unet2D.py | 3 +-- viscy/utils/cli_utils.py | 2 +- viscy/utils/logging.py | 5 ++--- viscy/utils/mp_utils.py | 4 ++-- 12 files changed, 35 insertions(+), 41 deletions(-) diff --git a/tests/unet/networks/Unet25D_tests.py b/tests/unet/networks/Unet25D_tests.py index d190474f8..f954d8873 100644 --- a/tests/unet/networks/Unet25D_tests.py +++ b/tests/unet/networks/Unet25D_tests.py @@ -188,9 +188,7 @@ def _all_test_configurations(self, test, verbose=True): try: out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) - fail_message = ( - f"'Passing' input tests failed on config {i+1} \n args: {args}" - ) + fail_message = f"'Passing' input tests failed on config {i + 1} \n args: {args}" np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message ) @@ -208,7 +206,7 @@ def _all_test_configurations(self, test, verbose=True): out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) fail_message = ( - f"\t'Failing' tests failed on config {i+1} \n args: {args}" + f"\t'Failing' tests failed on config {i + 1} \n args: {args}" ) np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message @@ -222,7 +220,7 @@ def _all_test_configurations(self, test, verbose=True): if args[resid_index] == False: params, resid_params = self._get_residual_params(args, resid_index) try: - fail_message = f"\t Residual params tests failed on config {i+1} \n args: {args}" + fail_message = f"\t Residual params tests failed on config {i + 1} \n args: {args}" np.testing.assert_equal( len(list(params)), len(list(resid_params)), fail_message ) @@ -233,7 +231,7 @@ def _all_test_configurations(self, test, verbose=True): io_utils.show_progress_bar(configs_list, i, process="testing", interval=10) if verbose: print( - f"Testing complete! {len(configs_list)-len(failed_tests)}/{len(configs_list)} passed." + f"Testing complete! {len(configs_list) - len(failed_tests)}/{len(configs_list)} passed." ) if len(failed_tests) > 0: print(f"Failed messages:") diff --git a/tests/unet/networks/Unet2D_tests.py b/tests/unet/networks/Unet2D_tests.py index 70c6cc3d0..3f69f2145 100644 --- a/tests/unet/networks/Unet2D_tests.py +++ b/tests/unet/networks/Unet2D_tests.py @@ -174,9 +174,7 @@ def _all_test_configurations(self, test, verbose=True): try: out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) - fail_message = ( - f"'Passing' input tests failed on config {i+1} \n args: {args}" - ) + fail_message = f"'Passing' input tests failed on config {i + 1} \n args: {args}" np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message ) @@ -194,7 +192,7 @@ def _all_test_configurations(self, test, verbose=True): out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) fail_message = ( - f"\t'Failing' tests failed on config {i+1} \n args: {args}" + f"\t'Failing' tests failed on config {i + 1} \n args: {args}" ) np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message @@ -208,7 +206,7 @@ def _all_test_configurations(self, test, verbose=True): if args[resid_index] == False: params, resid_params = self._get_residual_params(args, resid_index) try: - fail_message = f"\t Residual params tests failed on config {i+1} \n args: {args}" + fail_message = f"\t Residual params tests failed on config {i + 1} \n args: {args}" np.testing.assert_equal( len(list(params)), len(list(resid_params)), fail_message ) @@ -219,7 +217,7 @@ def _all_test_configurations(self, test, verbose=True): io_utils.show_progress_bar(configs_list, i, process="testing", interval=10) if verbose: print( - f"Testing complete! {len(configs_list)-len(failed_tests)}/{len(configs_list)} passed." + f"Testing complete! {len(configs_list) - len(failed_tests)}/{len(configs_list)} passed." ) if len(failed_tests) > 0: print(f"Failed messages:") diff --git a/tests/unet/networks/layers/ConvBlock2D_tests.py b/tests/unet/networks/layers/ConvBlock2D_tests.py index 59aabd8b9..f708e8008 100644 --- a/tests/unet/networks/layers/ConvBlock2D_tests.py +++ b/tests/unet/networks/layers/ConvBlock2D_tests.py @@ -172,9 +172,7 @@ def _all_test_configurations(self, test, verbose=True): try: out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) - fail_message = ( - f"'Passing' input tests failed on config {i+1} \n args: {args}" - ) + fail_message = f"'Passing' input tests failed on config {i + 1} \n args: {args}" np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message ) @@ -192,7 +190,7 @@ def _all_test_configurations(self, test, verbose=True): out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) fail_message = ( - f"\t'Failing' tests failed on config {i+1} \n args: {args}" + f"\t'Failing' tests failed on config {i + 1} \n args: {args}" ) np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message @@ -206,7 +204,7 @@ def _all_test_configurations(self, test, verbose=True): if args[resid_index] == False: params, resid_params = self._get_residual_params(args, resid_index) try: - fail_message = f"\t Residual params tests failed on config {i+1} \n args: {args}" + fail_message = f"\t Residual params tests failed on config {i + 1} \n args: {args}" np.testing.assert_equal( len(list(params)), len(list(resid_params)), fail_message ) @@ -218,7 +216,7 @@ def _all_test_configurations(self, test, verbose=True): if verbose: print( - f"Testing complete! {len(configs_list)-len(failed_tests)}/{len(configs_list)} passed." + f"Testing complete! {len(configs_list) - len(failed_tests)}/{len(configs_list)} passed." ) if len(failed_tests) > 0: print(f"Failed messages:") diff --git a/tests/unet/networks/layers/ConvBlock3D_tests.py b/tests/unet/networks/layers/ConvBlock3D_tests.py index c4832d9ab..60fbd3ef2 100644 --- a/tests/unet/networks/layers/ConvBlock3D_tests.py +++ b/tests/unet/networks/layers/ConvBlock3D_tests.py @@ -172,9 +172,7 @@ def _all_test_configurations(self, test, verbose=True): try: out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) - fail_message = ( - f"'Passing' input tests failed on config {i+1} \n args: {args}" - ) + fail_message = f"'Passing' input tests failed on config {i + 1} \n args: {args}" np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message ) @@ -191,7 +189,7 @@ def _all_test_configurations(self, test, verbose=True): out_shapes = np.array(out_shapes, dtype=object) exp_out_shapes = np.array(exp_out_shapes, dtype=object) fail_message = ( - f"\t'Failing' tests failed on config {i+1} \n args: {args}" + f"\t'Failing' tests failed on config {i + 1} \n args: {args}" ) np.testing.assert_array_equal( out_shapes, exp_out_shapes, fail_message @@ -204,7 +202,7 @@ def _all_test_configurations(self, test, verbose=True): if args[resid_index] == False: params, resid_params = self._get_residual_params(args, resid_index) try: - fail_message = f"\t Residual params tests failed on config {i+1} \n args: {args}" + fail_message = f"\t Residual params tests failed on config {i + 1} \n args: {args}" np.testing.assert_equal( len(list(params)), len(list(resid_params)), fail_message ) @@ -214,7 +212,7 @@ def _all_test_configurations(self, test, verbose=True): io_utils.show_progress_bar(configs_list, i, process="testing", interval=10) if verbose: print( - f"Testing complete! {len(configs_list)-len(failed_tests)}/{len(configs_list)} passed." + f"Testing complete! {len(configs_list) - len(failed_tests)}/{len(configs_list)} passed." ) if len(failed_tests) > 0: print(f"Failed messages:") diff --git a/viscy/representation/evaluation/dimensionality_reduction.py b/viscy/representation/evaluation/dimensionality_reduction.py index 6a058ac78..5916f7124 100644 --- a/viscy/representation/evaluation/dimensionality_reduction.py +++ b/viscy/representation/evaluation/dimensionality_reduction.py @@ -61,7 +61,7 @@ def compute_phate( for i in range( min(2, phate_embedding.shape[1]) ): # Only update PHATE1 and PHATE2 - embedding_dataset[f"PHATE{i+1}"].values = phate_embedding[:, i] + embedding_dataset[f"PHATE{i + 1}"].values = phate_embedding[:, i] return phate_model, phate_embedding diff --git a/viscy/scripts/profile_dataloader.py b/viscy/scripts/profile_dataloader.py index e4fbcbe06..2b2af2cd6 100644 --- a/viscy/scripts/profile_dataloader.py +++ b/viscy/scripts/profile_dataloader.py @@ -73,7 +73,9 @@ for i in range(num_epochs): # Train dataloader train_dataloader = data_module.train_dataloader() - train_dataloader = tqdm(train_dataloader, desc=f"Epoch {i+1}/{num_epochs} - Train") + train_dataloader = tqdm( + train_dataloader, desc=f"Epoch {i + 1}/{num_epochs} - Train" + ) for batch in train_dataloader: anchor_batch = batch["anchor"] positive_batch = batch["positive"] @@ -87,7 +89,9 @@ # Validation dataloader val_dataloader = data_module.val_dataloader() - val_dataloader = tqdm(val_dataloader, desc=f"Epoch {i+1}/{num_epochs} - Validation") + val_dataloader = tqdm( + val_dataloader, desc=f"Epoch {i + 1}/{num_epochs} - Validation" + ) for batch in val_dataloader: anchor_batch = batch["anchor"] positive_batch = batch["positive"] @@ -110,7 +114,7 @@ print("Negative batch shape:", negative_batch.shape) print(f"Elapsed time for {num_epochs} iterations: {elapsed_time} seconds") -print(f"Average time per iteration: {elapsed_time/num_epochs} seconds") +print(f"Average time per iteration: {elapsed_time / num_epochs} seconds") print(f"Data transfer speed: {data_transfer_speed} MBPS") # %% diff --git a/viscy/scripts/visualize_features.py b/viscy/scripts/visualize_features.py index 00f1a6535..33c175e5e 100644 --- a/viscy/scripts/visualize_features.py +++ b/viscy/scripts/visualize_features.py @@ -97,7 +97,7 @@ def feature_map_pca(feature_map: np.array, n_components: int = 8) -> PCA: pc_first_3 = pca.components_[:3].reshape(3, *features[level].shape[-2:]) rgb = np.stack([rescale_intensity(pc) for pc in pc_first_3], axis=-1) ax[0, level + 1].imshow(rgb) - ax[0, level + 1].set_title(f"Level {level+1} {features[level].shape[1:]}") + ax[0, level + 1].set_title(f"Level {level + 1} {features[level].shape[1:]}") ax[1, level + 1].plot(range(1, n_components + 1), pca.explained_variance_ratio_) ax[1, level + 1].set_xlabel("Principal component") ax[1, level + 1].set_ylabel("Explained variance ratio") @@ -131,7 +131,7 @@ def feature_map_pca(feature_map: np.array, n_components: int = 8) -> PCA: g, axes = plt.subplots(2, 4, figsize=(16, 8)) for i, ax in enumerate(axes.ravel()): ax.imshow(level3_pcs[i], cmap="magma") - ax.set_title(f"PC{i+1}") + ax.set_title(f"PC{i + 1}") # axes[3].imshow(nuc_pcs, cmap="magma") # axes[3].set_title("normalized PC1 + PC2") # axes[4].imshow(mem_pcs, cmap="magma") diff --git a/viscy/unet/networks/Unet25D.py b/viscy/unet/networks/Unet25D.py index 72418538e..8a34042d7 100644 --- a/viscy/unet/networks/Unet25D.py +++ b/viscy/unet/networks/Unet25D.py @@ -56,9 +56,9 @@ def __init__( self.num_blocks = num_blocks self.kernel_size = xy_kernel_size self.residual = residual - assert ( - dropout >= 0 and dropout <= 0.5 - ), f"Dropout {dropout} not in allowed range: [0, 0.5]" + assert dropout >= 0 and dropout <= 0.5, ( + f"Dropout {dropout} not in allowed range: [0, 0.5]" + ) self.dropout = dropout self.task = task self.debug_mode = False diff --git a/viscy/unet/networks/Unet2D.py b/viscy/unet/networks/Unet2D.py index 05d9a17a2..0edd95362 100644 --- a/viscy/unet/networks/Unet2D.py +++ b/viscy/unet/networks/Unet2D.py @@ -186,8 +186,7 @@ def forward(self, x, validate_input=False): if validate_input: assert x.shape[-1] == x.shape[-2], "Input must be square in xy" assert x.shape[-3] == self.in_channels, ( - f"Input channels must equal network" - f" input channels: {self.in_channels}" + f"Input channels must equal network input channels: {self.in_channels}" ) x = x.squeeze(2) # encoder diff --git a/viscy/utils/cli_utils.py b/viscy/utils/cli_utils.py index c3a003e28..4223e6784 100644 --- a/viscy/utils/cli_utils.py +++ b/viscy/utils/cli_utils.py @@ -98,7 +98,7 @@ def save_figure(data, save_folder, name, title=None, vmax=0, ext=".png"): data = data.detach().cpu().numpy() elif not isinstance(data, np.ndarray): raise AttributeError( - f"'data' of type {type(data)} must be torch tensor" " or numpy array." + f"'data' of type {type(data)} must be torch tensor or numpy array." ) if vmax == 0: vmax = np.max(data) diff --git a/viscy/utils/logging.py b/viscy/utils/logging.py index 33c66f9da..5bdeac90b 100644 --- a/viscy/utils/logging.py +++ b/viscy/utils/logging.py @@ -26,8 +26,7 @@ def log_feature(feature_map, name, log_save_folder, debug_mode): if debug_mode: now = datetime.datetime.now() log_save_folder = ( - f"feature_map_{now.year}_{now.month}_" - f"{now.day}_{now.hour}_{now.minute}/" + f"feature_map_{now.year}_{now.month}_{now.day}_{now.hour}_{now.minute}/" ) logger = FeatureLogger( save_folder=log_save_folder, @@ -117,7 +116,7 @@ def log_feature_map( dim_names = ["dim_" + str(i) for i in range(len(num_dims))] else: assert len(dim_names) + self.spatial_dims == num_dims, ( - "dim_names must be " "same length as nonspatial tensor dim length" + "dim_names must be same length as nonspatial tensor dim length" ) self.dim_names = dim_names diff --git a/viscy/utils/mp_utils.py b/viscy/utils/mp_utils.py index 27a0d8ef5..ee46f7ea9 100644 --- a/viscy/utils/mp_utils.py +++ b/viscy/utils/mp_utils.py @@ -66,7 +66,7 @@ def add_channel( "except in the inferred channel dimension: " f"array shape: {position.data.shape}, " "expected channel shape: " - f"{(position.data.shape[0], ) + position.data.shape[2:]}, " + f"{(position.data.shape[0],) + position.data.shape[2:]}, " f"received channel shape: {new_channel_array.shape}" ) # determine whether to overwrite or append @@ -146,7 +146,7 @@ def create_and_write_mask( else: # print progress update if verbose: - time_progress = f"time {time_index+1}/{shape[0]}" + time_progress = f"time {time_index + 1}/{shape[0]}" channel_progress = f"chan {channel_index}/{channel_indices}" position_progress = f"pos {position.zgroup.name}" p = ( From e810058ab462858e040ea668a6c9545f0f9a52fa Mon Sep 17 00:00:00 2001 From: Ziwen Liu Date: Tue, 17 Jun 2025 12:02:28 -0700 Subject: [PATCH 3/4] only check src for now --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0dd4c5fd8..476180979 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -11,7 +11,7 @@ jobs: - uses: astral-sh/ruff-action@v3 with: src: "viscy" - - run: ruff format --check + - run: ruff format --check viscy tests test: name: Test From 76c115fb9c7bc79b5f01366a0ba07d4362ee9149 Mon Sep 17 00:00:00 2001 From: Ziwen Liu Date: Tue, 17 Jun 2025 13:17:07 -0700 Subject: [PATCH 4/4] restore verbosity --- .github/workflows/pr.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 476180979..e7b772ea0 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -10,7 +10,8 @@ jobs: - uses: actions/checkout@v3 - uses: astral-sh/ruff-action@v3 with: - src: "viscy" + src: viscy + args: check --verbose - run: ruff format --check viscy tests test: