From 153ee0b57ec1edadfe94d3723e393aeed3ec8f54 Mon Sep 17 00:00:00 2001 From: chrisjonesBSU Date: Sun, 13 Sep 2026 12:58:17 +0100 Subject: [PATCH 1/4] make several precommit fixes --- .pre-commit-config.yaml | 2 +- cmeutils/__init__.py | 2 +- cmeutils/gsd_utils.py | 38 +++++++++++++++++--------------- cmeutils/sampling.py | 2 +- cmeutils/tests/test_gsd.py | 8 +++---- cmeutils/tests/test_sampling.py | 6 ++--- cmeutils/tests/test_structure.py | 10 ++++----- cmeutils/tests/test_visualize.py | 4 ++-- cmeutils/visualize.py | 11 +++++---- 9 files changed, 44 insertions(+), 39 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 251ced4..f5ea401 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ ci: submodules: false repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.22 # Ruff version + rev: v0.16.6 # Ruff version hooks: - id: ruff args: [--fix, --extend-ignore=E203] diff --git a/cmeutils/__init__.py b/cmeutils/__init__.py index 6de519e..2575a08 100644 --- a/cmeutils/__init__.py +++ b/cmeutils/__init__.py @@ -3,8 +3,8 @@ __all__ = [ "__version__", + "dynamics", "gsd_utils", "structure", - "dynamics", "visualize", ] diff --git a/cmeutils/gsd_utils.py b/cmeutils/gsd_utils.py index ae88af5..2164901 100644 --- a/cmeutils/gsd_utils.py +++ b/cmeutils/gsd_utils.py @@ -254,24 +254,26 @@ def ellipsoid_gsd(gsd_file, new_file, ellipsoid_types, lpar, lperp): Value of lperp of the ellipsoids """ - with gsd.hoomd.open(new_file, "w") as new_t: - with gsd.hoomd.open(gsd_file) as old_t: - for snap in old_t: - shape_dicts_list = [] - for ptype in snap.particles.types: - if ptype == ellipsoid_types or ptype in ellipsoid_types: - shapes_dict = { - "type": "Ellipsoid", - "a": lperp, - "b": lperp, - "c": lpar, - } - else: - shapes_dict = {"type": "Sphere", "diameter": 0.001} - shape_dicts_list.append(shapes_dict) - snap.particles.type_shapes = shape_dicts_list - snap.validate() - new_t.append(snap) + with ( + gsd.hoomd.open(new_file, "w") as new_t, + gsd.hoomd.open(gsd_file) as old_t, + ): + for snap in old_t: + shape_dicts_list = [] + for ptype in snap.particles.types: + if ptype == ellipsoid_types or ptype in ellipsoid_types: + shapes_dict = { + "type": "Ellipsoid", + "a": lperp, + "b": lperp, + "c": lpar, + } + else: + shapes_dict = {"type": "Sphere", "diameter": 0.001} + shape_dicts_list.append(shapes_dict) + snap.particles.type_shapes = shape_dicts_list + snap.validate() + new_t.append(snap) def xml_to_gsd(xmlfile, gsdfile): diff --git a/cmeutils/sampling.py b/cmeutils/sampling.py index c43455b..cb482d3 100644 --- a/cmeutils/sampling.py +++ b/cmeutils/sampling.py @@ -122,4 +122,4 @@ def autocorr1D(array): """ ft = np.fft.rfft(array - np.average(array)) acorr = np.fft.irfft(ft * np.conjugate(ft)) / (len(array) * np.var(array)) - return acorr[0 : len(acorr) // 2] # noqa: E203 + return acorr[0 : len(acorr) // 2] diff --git a/cmeutils/tests/test_gsd.py b/cmeutils/tests/test_gsd.py index 7164f96..228cc3b 100644 --- a/cmeutils/tests/test_gsd.py +++ b/cmeutils/tests/test_gsd.py @@ -51,7 +51,7 @@ def test_snapshot_to_graph(self, pekk_cg_gsd, p3ht_gsd): def test_get_centers(self, gsdfile): new_gsdfile = "centers.gsd" centers = get_centers(gsdfile, new_gsdfile) - assert isinstance(centers, type(None)) + assert centers is None def test_frame_to_freud_system(self, butane_gsd): with gsd.hoomd.open(butane_gsd) as traj: @@ -248,9 +248,9 @@ def test_identify_connection_no_connections(self): snapshot.particles.typeid = [0, 1] with pytest.warns(UserWarning): updated_snapshot = identify_snapshot_connections(snapshot) - assert updated_snapshot.bonds.N == 0 - assert updated_snapshot.angles.N == 0 - assert updated_snapshot.dihedrals.N == 0 + assert updated_snapshot.bonds.N == 0 + assert updated_snapshot.angles.N == 0 + assert updated_snapshot.dihedrals.N == 0 def test_identify_connections_pekk_cg(self, pekk_cg_gsd): with gsd.hoomd.open(pekk_cg_gsd) as traj: diff --git a/cmeutils/tests/test_sampling.py b/cmeutils/tests/test_sampling.py index f6a004b..2d46e91 100644 --- a/cmeutils/tests/test_sampling.py +++ b/cmeutils/tests/test_sampling.py @@ -63,7 +63,7 @@ def test_incorrect_threshold_neff(self, correlated_data_tau100_n10000): def test_return_trimmed_data(self, correlated_data_tau100_n10000): data = correlated_data_tau100_n10000 - [equil_data, uncorr_indices, prod_start, Neff] = equil_sample( + [equil_data, _uncorr_indices, _prod_start, _Neff] = equil_sample( data, threshold_fraction=0.2, threshold_neff=10 ) assert np.shape(equil_data)[0] < np.shape(data)[0] @@ -73,14 +73,14 @@ def test_trim_high_threshold(self, correlated_data_tau100_n10000): with pytest.raises( ValueError, match=r"Property does not have requisite threshold" ): - [equil_data, uncorr_indices, prod_start, Neff] = equil_sample( + [_equil_data, _uncorr_indices, _prod_start, _Neff] = equil_sample( data, threshold_fraction=0.98 ) with pytest.raises( ValueError, match=r"More production data is needed", ): - [equil_data, uncorr_indices, prod_start, Neff] = equil_sample( + [_equil_data, _uncorr_indices, _prod_start, _Neff] = equil_sample( data, threshold_fraction=0.75, threshold_neff=10000 ) diff --git a/cmeutils/tests/test_structure.py b/cmeutils/tests/test_structure.py index 34edc6a..9749ec8 100644 --- a/cmeutils/tests/test_structure.py +++ b/cmeutils/tests/test_structure.py @@ -322,7 +322,7 @@ def test_gsd_rdf(self, AB_chain_gsd): exclude_all_bonded=False, ) assert isinstance(rdf, freud.density.RDF) - rdf.rdf + _ = rdf.rdf assert scale_factor == 1 def test_gsd_rdf_exclude_all_bonded(self, AB_chain_gsd): @@ -370,7 +370,7 @@ def test_gsd_rdf_normalization(self, AB_chain_gsd): # All pairs are being used, N total = (10 * 9) / 2 = 45 # Exclude bond depth of 1 should exclude all bonded pairs = 9 # 45 / (45 - 9) = 1.25 - rdf, scale_factor = gsd_rdf( + _, scale_factor = gsd_rdf( gsdfile=AB_chain_gsd, start=0, stop=10, @@ -382,7 +382,7 @@ def test_gsd_rdf_normalization(self, AB_chain_gsd): # Excl bond depth of 2 should result in 9 (bonds) + 8 (angles) exclusions # 45 / (45 - 17) = 1.607 - rdf, scale_factor = gsd_rdf( + _, scale_factor = gsd_rdf( gsdfile=AB_chain_gsd, start=0, stop=10, @@ -393,7 +393,7 @@ def test_gsd_rdf_normalization(self, AB_chain_gsd): def test_gsd_rdf_r_max(self, LJ_gsd): """Test 2 RDFs with different r_cuts. The values of the shared r_cut region should be very close""" - rdf, scale_factor = gsd_rdf( + rdf, _ = gsd_rdf( gsdfile=LJ_gsd, start=0, stop=10, @@ -401,7 +401,7 @@ def test_gsd_rdf_r_max(self, LJ_gsd): exclude_bond_depth=0, exclude_all_bonded=False, ) - rdf2, scale_factor2 = gsd_rdf( + rdf2, _ = gsd_rdf( gsdfile=LJ_gsd, start=0, stop=10, diff --git a/cmeutils/tests/test_visualize.py b/cmeutils/tests/test_visualize.py index 9022c35..172dbd8 100644 --- a/cmeutils/tests/test_visualize.py +++ b/cmeutils/tests/test_visualize.py @@ -69,11 +69,11 @@ def test_set_bad_view(self, p3ht_fresnel): p3ht_fresnel.view_axis = 10 def test_bad_color_dict(self, p3ht_fresnel): - with pytest.raises(ValueError): + with pytest.raises(TypeError): p3ht_fresnel.color_dict = np.array([0.1, 0.1, 0.1]) def test_set_bad_unwrap_pos(self, p3ht_fresnel): - with pytest.raises(ValueError): + with pytest.raises(TypeError): p3ht_fresnel.unwrap_positions = "true" def set_set_colors(self, p3ht_fresnel): diff --git a/cmeutils/visualize.py b/cmeutils/visualize.py index 41e9def..3cc7519 100644 --- a/cmeutils/visualize.py +++ b/cmeutils/visualize.py @@ -19,7 +19,7 @@ def __init__( metal=0, up=(0, 0, 1), unwrap_positions=False, - device=fresnel.Device(), + device=None, show_box=True, box_radius=0.05, ): @@ -63,14 +63,17 @@ def __init__( If True, the particle positions are unwrapped in the image This requires the GSD file snapshot contain accurate values for gsd.hoomd.Frame.particles.image - device, fresnel.Device(), optional + device, None, optional Set the device to be used by the scene and in rendering. + If left as `None`, automatically set to fresnel.Device(). show_box: bool, optional, default True If True, the box is shown in the visualization. box_radius: float, optional, default 0.02 The radius of the box lines. """ + if device is None: + device = (fresnel.Device(),) self.scene = fresnel.Scene() self.gsd_file = gsd_file with gsd.hoomd.open(gsd_file) as traj: @@ -135,7 +138,7 @@ def color_dict(self): @color_dict.setter def color_dict(self, value): if not isinstance(value, dict): - raise ValueError( + raise TypeError( "Pass in a dicitonary with " "keys of particle type, values of color" ) @@ -171,7 +174,7 @@ def unwrap_positions(self): @unwrap_positions.setter def unwrap_positions(self, value): if not isinstance(value, bool): - raise ValueError( + raise TypeError( "Set to True or False where " "True uses unwrapped particle positions" ) From 17899cbc212d75b2fe0e3244c4f9564a6e48b3ce Mon Sep 17 00:00:00 2001 From: chrisjonesBSU Date: Sun, 13 Sep 2026 13:02:13 +0100 Subject: [PATCH 2/4] replace .join with fstrings --- cmeutils/structure.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmeutils/structure.py b/cmeutils/structure.py index b63f598..00b1ecc 100644 --- a/cmeutils/structure.py +++ b/cmeutils/structure.py @@ -107,8 +107,8 @@ def angle_distribution( theta_max = 180 trajectory = gsd.hoomd.open(gsd_file, mode="r") - name = "-".join([A_name, B_name, C_name]) - name_rev = "-".join([C_name, B_name, A_name]) + name = f"{A_name}-{B_name}-{C_name}" + name_rev = f"{C_name}-{B_name}-{A_name}" angles = [] for snap in trajectory[start:stop:stride]: @@ -237,8 +237,8 @@ def bond_distribution( ) trajectory = gsd.hoomd.open(gsd_file, mode="r") - name = "-".join([A_name, B_name]) - name_rev = "-".join([B_name, A_name]) + name = f"{A_name}-{B_name}" + name_rev = f"{B_name}-{A_name}" bonds = [] for snap in trajectory[start:stop:stride]: @@ -358,8 +358,8 @@ def dihedral_distribution( ) trajectory = gsd.hoomd.open(gsd_file, mode="r") - name = "-".join([A_name, B_name, C_name, D_name]) - name_rev = "-".join([D_name, C_name, B_name, A_name]) + name = f"{A_name}-{B_name}-{C_name}-{D_name}" + name_rev = f"{D_name}-{C_name}-{B_name}-{A_name}" dihedrals = [] for snap in trajectory[start:stop:stride]: From aa8bb06f0a3add275aa2b743400fb11c544d43c8 Mon Sep 17 00:00:00 2001 From: chrisjonesBSU Date: Sun, 13 Sep 2026 14:26:33 +0100 Subject: [PATCH 3/4] Update versions of actions/runners --- .github/workflows/pytest.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 686501b..ebdab61 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -36,10 +36,11 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Build environment - uses: mamba-org/setup-micromamba@v2 + uses: mamba-org/setup-micromamba@v3 + with: environment-file: environment-dev.yml create-args: >- @@ -54,7 +55,7 @@ jobs: run: python -m pytest -rs -v --cov=./ --cov-report=xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v7 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.xml From 7fa53c1f1350b7066f55596b7fe7f0b6fbaad9b8 Mon Sep 17 00:00:00 2001 From: chrisjonesBSU Date: Mon, 14 Sep 2026 11:35:08 +0100 Subject: [PATCH 4/4] precommit fixes --- cmeutils/dynamics.py | 2 +- cmeutils/geometry.py | 16 ++++++++++------ cmeutils/gsd_utils.py | 8 ++++---- cmeutils/plotting.py | 6 +++--- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cmeutils/dynamics.py b/cmeutils/dynamics.py index 8a623eb..297bfb2 100644 --- a/cmeutils/dynamics.py +++ b/cmeutils/dynamics.py @@ -33,7 +33,7 @@ def msd_from_gsd( with gsd.hoomd.open(gsdfile, "r") as trajectory: init_box = trajectory[start].configuration.box final_box = trajectory[stop].configuration.box - assert all([i == j for i, j in zip(init_box, final_box)]), ( + assert all(i == j for i, j in zip(init_box, final_box)), ( f"The box is not consistent over the range {start}:{stop}" ) diff --git a/cmeutils/geometry.py b/cmeutils/geometry.py index 7c72362..00621b8 100644 --- a/cmeutils/geometry.py +++ b/cmeutils/geometry.py @@ -126,7 +126,7 @@ def get_plane_normal(points): assert points.shape[0] >= 3, "Need at least 3 points to calculate a plane." ctr = points.mean(axis=0) shiftpoints = points - ctr - U, S, Vt = svd(shiftpoints.T @ shiftpoints) + U, _S, _Vt = svd(shiftpoints.T @ shiftpoints) normal = U[:, -1] return ctr, normal @@ -197,7 +197,7 @@ def dihedral_angle(pos1, pos2, pos3, pos4, degrees=False): return phi -def moit(points, masses, center=np.zeros(3)): +def moit(points, masses, center=(0, 0, 0)): """Calculates moment of inertia tensor (moit) for rigid bodies. Assumes rigid body center is at origin unless center is provided. @@ -218,6 +218,7 @@ def moit(points, masses, center=np.zeros(3)): moment of inertia tensor for the rigid body center """ + center = np.asarray(center) points -= center x = points[:, 0] y = points[:, 1] @@ -231,7 +232,7 @@ def moit(points, masses, center=np.zeros(3)): def radial_grid_positions( init_radius, final_radius, - init_position=np.zeros(2), + init_position=(0, 0), n_circles=10, circle_slice=1, circle_coverage=2 * np.pi, @@ -260,6 +261,7 @@ def radial_grid_positions( xy coordinates of the grid positions """ + init_position = np.asarray(init_position) grid_positions = [] for radius in np.linspace(init_radius, final_radius, n_circles): for d_theta in np.linspace(0, circle_coverage, circle_slice): @@ -278,7 +280,7 @@ def radial_grid_positions( def spherical_grid_positions( init_radius, final_radius, - init_position=np.zeros(3), + init_position=None, n_circles=10, circle_slice=1, circle_coverage=2 * np.pi, @@ -292,8 +294,9 @@ def spherical_grid_positions( initial radius of the grid (first circle) final_radius: float final radius of the grid (last circle) - init_position: numpy.ndarray (3,), default np.array([0,0,0]) + init_position: numpy.ndarray (3,), default None initial position of the grid (center of the first circle) + If left as `None`, defaults to (0,0,0). n_circles: int, default 10 number of circles in the grid circle_slice: int, default 1 @@ -308,7 +311,8 @@ def spherical_grid_positions( grid_positions: numpy.ndarray xyz coordinates of the grid positions """ - + if init_position is None: + init_position = np.zeros(3) z_slice = circle_slice * 2 grid_positions = [] for radius in np.linspace(init_radius, final_radius, n_circles): diff --git a/cmeutils/gsd_utils.py b/cmeutils/gsd_utils.py index 2164901..253e60d 100644 --- a/cmeutils/gsd_utils.py +++ b/cmeutils/gsd_utils.py @@ -174,9 +174,9 @@ def _validate_inputs(gsd_file, snap, gsd_frame): try: with gsd.hoomd.open(name=gsd_file, mode="r") as f: snap = f[gsd_frame] - except Exception as e: + except Exception: print("Unable to open the gsd_file") - raise e + raise elif snap: assert isinstance(snap, gsd.hoomd.Frame) return snap @@ -493,7 +493,7 @@ def _detect_connections(compound_line_graph, type_="angle"): conn_matches = _trim_duplicates(conn_matches) # Do more sorting of individual connection - sorted_conn_matches = list() + sorted_conn_matches = [] for match in conn_matches: if match[0] < match[-1]: sorted_conn = match @@ -526,7 +526,7 @@ def _detect_connections(compound_line_graph, type_="angle"): def _get_sorted_by_n_connections(m): """Return sorted by n connections for the matching graph.""" small = nx.Graph() - for k, v in m.items(): + for k in m: small.add_edge(k[0], k[1]) return sorted(small.adj, key=lambda x: len(small[x])), small diff --git a/cmeutils/plotting.py b/cmeutils/plotting.py index 7df1036..99e5ea2 100644 --- a/cmeutils/plotting.py +++ b/cmeutils/plotting.py @@ -100,9 +100,9 @@ def threedplot( """ fig = plt.figure(figsize=(10, 10), facecolor="white") ax = plt.axes(projection="3d") - ax.set_xlabel(xlabel, fontdict=dict(weight="bold"), fontsize=12) - ax.set_ylabel(ylabel, fontdict=dict(weight="bold"), fontsize=12) - ax.set_zlabel(zlabel, fontdict=dict(weight="bold"), fontsize=12) + ax.set_xlabel(xlabel, fontdict={"weight": "bold"}, fontsize=12) + ax.set_ylabel(ylabel, fontdict={"weight": "bold"}, fontsize=12) + ax.set_zlabel(zlabel, fontdict={"weight": "bold"}, fontsize=12) p = ax.scatter(x, y, z, c=z, cmap="rainbow", linewidth=7) plt.colorbar(p, pad=0.1, aspect=2.3)