Skip to content

Commit

Permalink
applied 'prettier' to reformat code, and pre-commit as dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
jcschaff committed Aug 15, 2024
1 parent 5ecfb3b commit ac5cf8a
Show file tree
Hide file tree
Showing 31 changed files with 18,645 additions and 267 deletions.
5 changes: 1 addition & 4 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"editorconfig.editorconfig",
],
"extensions": ["ms-python.python", "editorconfig.editorconfig"],
"settings": {
"python.testing.pytestArgs": ["tests"],
"python.testing.unittestEnabled": false,
Expand Down
8 changes: 4 additions & 4 deletions .github/actions/setup-poetry-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: "setup-poetry-env"
description: "Composite action to setup the Python and poetry environment."

inputs:
python-version:
required: false
description: "The python version to use"
default: "3.11"
python-version:
required: false
description: "The python version to use"
default: "3.11"

runs:
using: "composite"
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ jobs:
- name: Check typing
run: poetry run mypy


- name: Upload coverage reports to Codecov with GitHub Action on Python 3.11
uses: codecov/codecov-action@v4
if: ${{ matrix.python-version == '3.11' }}
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/on-release-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on:
branches: [main]

jobs:

publish:
runs-on: ubuntu-latest
steps:
Expand All @@ -28,7 +27,7 @@ jobs:
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
RELEASE_VERSION: ${{ steps.vars.outputs.tag }}

deploy-docs:
needs: publish
runs-on: ubuntu-latest
Expand All @@ -41,4 +40,3 @@ jobs:

- name: Deploy documentation
run: poetry run mkdocs gh-deploy --force

1 change: 0 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6 changes: 3 additions & 3 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ plugins:
- mkdocstrings:
handlers:
python:
setup_commands:
- import sys
- sys.path.append('../')
setup_commands:
- import sys
- sys.path.append('../')
theme:
name: material
feature:
Expand Down
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ vtk = "^9.3.1"
pyvcell-fvsolver = "^0.0.4"
typer = "^0.12.3"
h5py-stubs = "^0.1.1"
pre-commit = "^3.8.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.2.0"
Expand Down
10 changes: 5 additions & 5 deletions pyvcell/simdata/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
import typer

from pyvcell.simdata.mesh import CartesianMesh
from pyvcell.simdata.simdata_models import PdeDataSet, DataFunctions
from pyvcell.simdata.simdata_models import DataFunctions, PdeDataSet
from pyvcell.simdata.zarr_writer import write_zarr

app = typer.Typer()


@app.command(name="vc_to_zarr", help="Convert a VCell FiniteVolume simulation dataset to Zarr")
def n5_to_zarr(
sim_data_dir: Path = typer.Argument(..., help="path to vcell dataset directory"),
sim_id: int = typer.Argument(..., help="simulation id (e.g. 946368938)"),
job_id: int = typer.Argument(..., help="job id (e.g. 0"),
zarr_path: Path = typer.Argument(..., help="path to zarr dataset to write to")
sim_data_dir: Path = typer.Argument(..., help="path to vcell dataset directory"),
sim_id: int = typer.Argument(..., help="simulation id (e.g. 946368938)"),
job_id: int = typer.Argument(..., help="job id (e.g. 0"),
zarr_path: Path = typer.Argument(..., help="path to zarr dataset to write to"),
) -> None:
pde_dataset = PdeDataSet(base_dir=sim_data_dir, log_filename=f"SimID_{sim_id}_{job_id}_.log")
pde_dataset.read()
Expand Down
21 changes: 14 additions & 7 deletions pyvcell/simdata/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class CartesianMesh:
}
}
"""

mesh_file: Path
size: list[int] # [x, y, z]
extent: list[float] # [x, y, z]
Expand Down Expand Up @@ -103,7 +104,7 @@ def dimension(self) -> int:

def read(self) -> None:
# read file as lines and parse
with (self.mesh_file.open('r') as f):
with self.mesh_file.open("r") as f:
# get line enumerator from f

iter_lines = iter(f.readlines())
Expand Down Expand Up @@ -157,7 +158,7 @@ def read(self) -> None:
compressed_bytes = bytes.fromhex(hex_string)
# assert len(compressed_bytes) == num_compressed_bytes
uncompressed_bytes: bytes = zlib.decompress(compressed_bytes)
self.volume_region_map = np.frombuffer(uncompressed_bytes, dtype='<u2') # unsigned 2-byte integers
self.volume_region_map = np.frombuffer(uncompressed_bytes, dtype="<u2") # unsigned 2-byte integers
assert self.volume_region_map.shape[0] == self.size[0] * self.size[1] * self.size[2]
assert num_volume_elements == self.volume_region_map.shape[0]
assert set(np.unique(self.volume_region_map)) == set([v[0] for v in self.volume_regions])
Expand Down Expand Up @@ -199,10 +200,16 @@ def get_membrane_region_index(self, mem_element_index: int) -> int:
return int(self.membrane_elements[mem_element_index, 7])

def get_membrane_region_ids(self, volume_domain_name: str) -> set[int]:
return set([mem_reg_id for mem_reg_id, vol_reg1, vol_reg2, surface in self.membrane_regions
if self.volume_regions[vol_reg1][3] == volume_domain_name or
self.volume_regions[vol_reg2][3] == volume_domain_name])
return set([
mem_reg_id
for mem_reg_id, vol_reg1, vol_reg2, surface in self.membrane_regions
if self.volume_regions[vol_reg1][3] == volume_domain_name
or self.volume_regions[vol_reg2][3] == volume_domain_name
])

def get_volume_region_ids(self, volume_domain_name: str) -> set[int]:
return set([vol_reg_id for vol_reg_id, subvol_id, volume, domain_name in self.volume_regions
if domain_name == volume_domain_name])
return set([
vol_reg_id
for vol_reg_id, subvol_id, volume, domain_name in self.volume_regions
if domain_name == volume_domain_name
])
61 changes: 35 additions & 26 deletions pyvcell/simdata/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
from pathlib import Path

import numpy as np
from h5py import Dataset, File as H5File, Group
from h5py import Dataset, Group
from h5py import File as H5File


class StatisticType(IntEnum):
Expand All @@ -28,10 +29,11 @@ def get_dataset(self, hdf5_file: H5File, time_index: int) -> Dataset:
if not isinstance(group_path_object, Group):
raise ValueError(f"Expected a group at {self.group_path} but found {type(group_path_object)}")
image_group: Group = group_path_object
dataset_path_object = image_group[f'time{time_index:06d}']
dataset_path_object = image_group[f"time{time_index:06d}"]
if not isinstance(dataset_path_object, Dataset):
raise ValueError(
f"Expected a dataset at {self.group_path}/time{time_index:06d} but found {type(dataset_path_object)}")
f"Expected a dataset at {self.group_path}/time{time_index:06d} but found {type(dataset_path_object)}"
)
image_ds: Dataset = dataset_path_object
return image_ds

Expand All @@ -45,17 +47,17 @@ def read(self, f: H5File) -> None:
extents_list = []
origin_list = []
if "ExtentX" in image_group.attrs:
extents_list.append(image_group.attrs['ExtentX'])
extents_list.append(image_group.attrs["ExtentX"])
if "ExtentY" in image_group.attrs:
extents_list.append(image_group.attrs['ExtentY'])
extents_list.append(image_group.attrs["ExtentY"])
if "ExtentZ" in image_group.attrs:
extents_list.append(image_group.attrs['ExtentZ'])
extents_list.append(image_group.attrs["ExtentZ"])
if "OriginX" in image_group.attrs:
origin_list.append(image_group.attrs['OriginX'])
origin_list.append(image_group.attrs["OriginX"])
if "OriginY" in image_group.attrs:
origin_list.append(image_group.attrs['OriginY'])
origin_list.append(image_group.attrs["OriginY"])
if "OriginZ" in image_group.attrs:
origin_list.append(image_group.attrs['OriginZ'])
origin_list.append(image_group.attrs["OriginZ"])
self.extents = np.array(extents_list)
self.origin = np.array(origin_list)
self.shape = self.get_dataset(f, 0).shape
Expand Down Expand Up @@ -94,12 +96,13 @@ def __init__(self, postprocessing_hdf5_path: Path):

def read(self) -> None:
# read the file as hdf5
with H5File(name=self.postprocessing_hdf5_path, mode='r') as file: # type: ignore
with H5File(name=self.postprocessing_hdf5_path, mode="r") as file: # type: ignore
# read dataset with path /PostProcessing/Times
postprocessing_times_object = file['/PostProcessing/Times']
postprocessing_times_object = file["/PostProcessing/Times"]
if not isinstance(postprocessing_times_object, Dataset):
raise ValueError(
f"Expected a dataset at /PostProcessing/Times but found {type(postprocessing_times_object)}")
f"Expected a dataset at /PostProcessing/Times but found {type(postprocessing_times_object)}"
)
times_ds: Dataset = postprocessing_times_object
# read array from times dataset into a ndarray
self.times = times_ds[()]
Expand All @@ -116,30 +119,35 @@ def read(self) -> None:
# key=comp_3_name, value=b'C_cyt_max'
# key=comp_3_unit, value=b'uM'
#
var_stats_grp_object = file['/PostProcessing/VariableStatistics']
var_stats_grp_object = file["/PostProcessing/VariableStatistics"]
if not isinstance(var_stats_grp_object, Group):
raise ValueError(
f"Expected a group at /PostProcessing/VariableStatistics but found {type(var_stats_grp_object)}")
f"Expected a group at /PostProcessing/VariableStatistics but found {type(var_stats_grp_object)}"
)
var_stats_grp: Group = var_stats_grp_object
# gather stat_var_name and stat_var_unit for each channel into dictionaries by channel
var_name_by_channel: dict[int, str] = {}
var_unit_by_channel: dict[int, str] = {}
for k, v in var_stats_grp.attrs.items():
parts = k.split('_')
parts = k.split("_")
channel = int(parts[1])
if not isinstance(v, bytes):
raise ValueError(f"Expected a bytes object for attribute {k} but found {type(v)}")
value = v.decode('utf-8')
value = v.decode("utf-8")
if parts[2] == "name":
var_name_by_channel[channel] = value
elif parts[2] == "unit":
var_unit_by_channel[channel] = value
# combine into a single list of VariableInfo objects, one for each channel
self.variables = [VariableInfo(stat_var_name=var_name_by_channel[i],
stat_var_unit=var_unit_by_channel[i],
stat_channel=i,
var_index=i // 4)
for i in range(len(var_name_by_channel))]
self.variables = [
VariableInfo(
stat_var_name=var_name_by_channel[i],
stat_var_unit=var_unit_by_channel[i],
stat_channel=i,
var_index=i // 4,
)
for i in range(len(var_name_by_channel))
]

# within /PostProcessing/VariableStatistics, there are datasets for each time point
# PostProcessing/VariableStatistics
Expand All @@ -152,11 +160,12 @@ def read(self) -> None:
# we can read the data for each time point into a list of ndarrays
statistics_raw: np.ndarray = np.zeros((len(self.times), len(self.variables)))
for time_index in range(len(self.times)):
time_ds_object = var_stats_grp[f'time{time_index:06d}']
time_ds_object = var_stats_grp[f"time{time_index:06d}"]
if not isinstance(time_ds_object, Dataset):
raise ValueError(
f"Expected a dataset at /PostProcessing/VariableStatistics/time{time_index:06d} "
f"but found {type(time_ds_object)}")
f"but found {type(time_ds_object)}"
)
time_ds: Dataset = time_ds_object
statistics_raw[time_index, :] = time_ds[()]

Expand All @@ -165,10 +174,10 @@ def read(self) -> None:

# get list of child groups from /PostProcessing which are not Times or VariableStatistics
# e.g. /PostProcessing/fluor
postprocessing_dataset = file['/PostProcessing']
postprocessing_dataset = file["/PostProcessing"]
if not isinstance(postprocessing_dataset, Group):
raise ValueError(f"Expected a group at /PostProcessing but found {type(postprocessing_dataset)}")
image_groups = [k for k in postprocessing_dataset.keys() if k not in ['Times', 'VariableStatistics']]
image_groups = [k for k in postprocessing_dataset.keys() if k not in ["Times", "VariableStatistics"]]

# for each image group, read the metadata to allow reading later
for image_group in image_groups:
Expand All @@ -177,6 +186,6 @@ def read(self) -> None:
self.image_metadata.append(metadata)

def read_image_data(self, image_metadata: ImageMetadata, time_index: int) -> np.ndarray:
with H5File(self.postprocessing_hdf5_path, 'r') as file: # type: ignore
with H5File(self.postprocessing_hdf5_path, "r") as file: # type: ignore
image_ds = image_metadata.get_dataset(hdf5_file=file, time_index=time_index)
return image_ds[()] # type: ignore
Loading

0 comments on commit ac5cf8a

Please sign in to comment.