Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: psf/black@stable
- uses: astral-sh/ruff-action@v3
with:
src: "viscy"
options: "--check --verbose"
- uses: chartboost/ruff-action@v1
with:
src: "viscy"
src: viscy
args: check --verbose
- run: ruff format --check viscy tests

test:
name: Test
Expand Down
9 changes: 2 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
4 changes: 2 additions & 2 deletions examples/virtual_staining/dlmbl_exercise/prepare-exercise.sh
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion examples/virtual_staining/dlmbl_exercise/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion examples/virtual_staining/img2img_translation/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions examples/virtual_staining/phase_contrast/prepare-exercise.sh
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion examples/virtual_staining/phase_contrast/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
5 changes: 1 addition & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ dev = [
"pytest-cov",
"hypothesis",
"ruff",
"black",
"profilehooks",
"onnxruntime",
]
Expand All @@ -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"]
10 changes: 4 additions & 6 deletions tests/unet/networks/Unet25D_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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
Expand All @@ -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
)
Expand All @@ -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:")
Expand Down
10 changes: 4 additions & 6 deletions tests/unet/networks/Unet2D_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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
Expand All @@ -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
)
Expand All @@ -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:")
Expand Down
10 changes: 4 additions & 6 deletions tests/unet/networks/layers/ConvBlock2D_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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
Expand All @@ -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
)
Expand All @@ -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:")
Expand Down
10 changes: 4 additions & 6 deletions tests/unet/networks/layers/ConvBlock3D_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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
Expand All @@ -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
)
Expand All @@ -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:")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 7 additions & 3 deletions viscy/scripts/profile_dataloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand All @@ -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"]
Expand All @@ -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")

# %%
4 changes: 2 additions & 2 deletions viscy/scripts/visualize_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
6 changes: 3 additions & 3 deletions viscy/unet/networks/Unet25D.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions viscy/unet/networks/Unet2D.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion viscy/utils/cli_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions viscy/utils/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions viscy/utils/mp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 = (
Expand Down