From bf201ccfdc8179e87c82bc1536d5edd05893405c Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:08:28 -0700 Subject: [PATCH 01/14] move button --- docs/overrides/main.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 17f85b2..b68d6a3 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -2,7 +2,7 @@ {% block content %} {% if page.nb_url %} - + Download Notebook {% endif %} From 052b7ccfae08210267c753a9df8993754072fc06 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:08:39 -0700 Subject: [PATCH 02/14] fix lucretia --- pmd_beamphysics/interfaces/lucretia.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pmd_beamphysics/interfaces/lucretia.py b/pmd_beamphysics/interfaces/lucretia.py index 1f6e7d9..4704ec9 100644 --- a/pmd_beamphysics/interfaces/lucretia.py +++ b/pmd_beamphysics/interfaces/lucretia.py @@ -186,7 +186,9 @@ def write_lucretia( z_luc = (P.t - t_ref) * 299792458 ptot = P.p / 1e9 # total momentum in GeV/c - if all(x is None for x in stop_ix): + if stop_ix is None: + stop_ix = np.zeros(Np) + elif all(x is None for x in stop_ix): stop_ix = np.zeros(Np) else: if len(stop_ix) != Np: From 31e9e1b1ba7b9de0d0e9f29cdc555c4ccc2ee6de Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Fri, 18 Oct 2024 11:26:16 -0700 Subject: [PATCH 03/14] Add notebooks --- mkdocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 144f667..159f249 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,8 +17,8 @@ nav: - examples/fields/field_examples.ipynb - examples/fields/field_expansion.ipynb - examples/fields/field_tracking.ipynb - - Wavefronts: - - examples/wavefront.ipynb + - examples/fields/field_conversion.ipynb + - examples/fields/corrector_modeling.ipynb - Utilities: - examples/units.ipynb - examples/labels.ipynb From 84069ab68e1010ec71119b632cf6ce2cb1028630 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Sat, 19 Oct 2024 08:39:19 -0700 Subject: [PATCH 04/14] Create FUNDING.yml --- .github/FUNDING.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7da0d4c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +github: [ChristopherMayes] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +thanks_dev: # Replace with a single thanks.dev username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From 6b7e362d23e36daddeb1e5bbacb1ecf275b4356d Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Tue, 22 Oct 2024 10:33:10 -0700 Subject: [PATCH 05/14] Remove NotImplementedError --- pmd_beamphysics/interfaces/impact.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pmd_beamphysics/interfaces/impact.py b/pmd_beamphysics/interfaces/impact.py index 1bc554b..e91c4e5 100644 --- a/pmd_beamphysics/interfaces/impact.py +++ b/pmd_beamphysics/interfaces/impact.py @@ -1016,6 +1016,9 @@ def create_impact_emfield_cartesian_ele( radius=0.15, x_offset=0, y_offset=0, + x_rotation=0, + y_rotation=0, + z_rotation=0, file_id=666, output_path=None, ): @@ -1075,11 +1078,6 @@ def create_impact_emfield_cartesian_ele( output_file = os.path.join(output_path, fieldmap_filename) field_mesh.write_impact_emfield_cartesian(output_file) - if x_offset != 0: - raise NotImplementedError("x_offset is not yet implemented in Impact-T") - if y_offset != 0: - raise NotImplementedError("y_offset is not yet implemented in Impact-T") - ele = { "L": L, "type": "emfield_cartesian", @@ -1091,14 +1089,14 @@ def create_impact_emfield_cartesian_ele( "radius": radius, "x_offset": x_offset, "y_offset": y_offset, - "x_rotation": 0.0, - "y_rotation": 0.0, - "z_rotation": 0.0, # This is tilt, but shouldn't affect anything because of the cylindrical symmetry. + "x_rotation": x_rotation, + "y_rotation": y_rotation, + "z_rotation": z_rotation, "name": name, "s": s, } - line = f"{L} 0 0 111 {zedge} {scale} {freq} {theta0_deg} {file_id} {radius} {x_offset} {y_offset} 0 0 0 /name:{name}" + line = f"{L} 0 0 111 {zedge} {scale} {freq} {theta0_deg} {file_id} {radius} {x_offset} {y_offset} {x_rotation} {y_rotation} {z_rotation} /name:{name}" fmap = { "info": {"format": "emfield_cartesian_fieldmesh"}, From 285b68f5f8dd3156f71f006bdbbe3213f8f6aa35 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:39:52 -0700 Subject: [PATCH 06/14] Automatically generate many FieldMesh properties --- pmd_beamphysics/fields/fieldmesh.py | 141 +++++++++++++++------------- 1 file changed, 75 insertions(+), 66 deletions(-) diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index 29c98b2..3919cf2 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -820,7 +820,6 @@ def scaled_component(self, key): return dat # Convenient properties - # TODO: Automate this? @property def r(self): return self.coord_vec("r") @@ -834,86 +833,96 @@ def z(self): return self.coord_vec("z") # Deltas - ## cartesian - @property - def dx(self): - return self.deltas[self.axis_index("x")] - - @property - def dy(self): - return self.deltas[self.axis_index("y")] - - ## cylindrical - @property - def dr(self): - return self.deltas[self.axis_index("r")] - - @property - def dtheta(self): - return self.deltas[self.axis_index("theta")] - - @property - def dz(self): - return self.deltas[self.axis_index("z")] + @staticmethod + def _create_delta_property(name): + def getter(self): + return self.deltas[self.axis_index(name)] + + return property(getter) + + dx = _create_delta_property("x") + dy = _create_delta_property("y") + dz = _create_delta_property("z") + dr = _create_delta_property("r") + dtheta = _create_delta_property("theta") + + # Maxs + @staticmethod + def _create_max_property(name): + def getter(self): + return self.maxs[self.axis_index(name)] + + def setter(self, value): + # Setting the max => shift the min + i = self.axis_index(name) + mins = list(self.attrs["gridOriginOffset"]) + mins[i] = mins[i] + float(value) - self.maxs[i] + self.attrs["gridOriginOffset"] = tuple(mins) + + return property(getter, setter) + + # Create max properties dynamically + xmax = _create_max_property("x") + ymax = _create_max_property("y") + zmax = _create_max_property("z") + rmax = _create_max_property("r") + thetamax = _create_max_property("theta") + + # Mins + @staticmethod + def _create_min_property(name): + def getter(self): + return self.mins[self.axis_index(name)] + + def setter(self, value): + mins = list(self.attrs["gridOriginOffset"]) + mins[self.axis_index(name)] = float(value) + self.attrs["gridOriginOffset"] = tuple(mins) + + return property(getter, setter) + + # Create min properties dynamically + xmin = _create_min_property("x") + ymin = _create_min_property("y") + zmin = _create_min_property("z") + rmin = _create_min_property("r") + thetamin = _create_min_property("theta") # Scaled components # TODO: Check geometry - ## cartesian - @property - def Bx(self): - return self.scaled_component("Bx") - - @property - def By(self): - return self.scaled_component("By") - - @property - def Ex(self): - return self.scaled_component("Ex") - - @property - def Ey(self): - return self.scaled_component("Ey") - - ## cylindrical - @property - def Br(self): - return self.scaled_component("Br") - - @property - def Btheta(self): - return self.scaled_component("Btheta") - - @property - def Bz(self): - return self.scaled_component("Bz") - - @property - def Er(self): - return self.scaled_component("Er") - - @property - def Etheta(self): - return self.scaled_component("Etheta") - - @property - def Ez(self): - return self.scaled_component("Ez") + @staticmethod + def _create_scaled_component_property(name): + def getter(self): + return self.scaled_component(name) + + return property(getter) + + # Dynamically create scaled properties + Bx = _create_scaled_component_property("Bx") + By = _create_scaled_component_property("By") + Bz = _create_scaled_component_property("Bz") + Br = _create_scaled_component_property("Br") + Btheta = _create_scaled_component_property("Btheta") + Ex = _create_scaled_component_property("Ex") + Ey = _create_scaled_component_property("Ey") + Ez = _create_scaled_component_property("Ez") + Er = _create_scaled_component_property("Er") + Etheta = _create_scaled_component_property("Etheta") @property def B(self): if self.geometry == "cylindrical": if self.is_static: - return np.hypot(self["Br"], self["Bz"]) + return np.hypot(self.Br, self.Bz) else: - return np.abs(self["Btheta"]) + return np.abs(self.Btheta) else: raise ValueError(f"Unknown geometry: {self.geometry}") @property def E(self): if self.geometry == "cylindrical": - return np.hypot(np.abs(self["Er"]), np.abs(self["Ez"])) + return np.hypot(np.abs(self.Er), np.abs(self.Ez)) else: raise ValueError(f"Unknown geometry: {self.geometry}") From 5afe39f5a77736544ed6bd6952ebec750e0aa90c Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:45:09 -0700 Subject: [PATCH 07/14] Remove @staticmethod --- docs/examples/fields/field_examples.ipynb | 324 +++------------------- pmd_beamphysics/fields/fieldmesh.py | 3 - 2 files changed, 37 insertions(+), 290 deletions(-) diff --git a/docs/examples/fields/field_examples.ipynb b/docs/examples/fields/field_examples.ipynb index 47fb957..01c6368 100644 --- a/docs/examples/fields/field_examples.ipynb +++ b/docs/examples/fields/field_examples.ipynb @@ -11,12 +11,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:42.691718Z", - "iopub.status.busy": "2024-10-17T23:18:42.691369Z", - "iopub.status.idle": "2024-10-17T23:18:43.214968Z", - "shell.execute_reply": "2024-10-17T23:18:43.214709Z" - }, "tags": [] }, "outputs": [], @@ -34,12 +28,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.216530Z", - "iopub.status.busy": "2024-10-17T23:18:43.216397Z", - "iopub.status.idle": "2024-10-17T23:18:43.222631Z", - "shell.execute_reply": "2024-10-17T23:18:43.222403Z" - }, "tags": [] }, "outputs": [], @@ -59,12 +47,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.242901Z", - "iopub.status.busy": "2024-10-17T23:18:43.242783Z", - "iopub.status.idle": "2024-10-17T23:18:43.358240Z", - "shell.execute_reply": "2024-10-17T23:18:43.357983Z" - }, "tags": [] }, "outputs": [], @@ -83,12 +65,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.359545Z", - "iopub.status.busy": "2024-10-17T23:18:43.359444Z", - "iopub.status.idle": "2024-10-17T23:18:43.499704Z", - "shell.execute_reply": "2024-10-17T23:18:43.499473Z" - }, "tags": [] }, "outputs": [], @@ -107,14 +83,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.501037Z", - "iopub.status.busy": "2024-10-17T23:18:43.500949Z", - "iopub.status.idle": "2024-10-17T23:18:43.565691Z", - "shell.execute_reply": "2024-10-17T23:18:43.565442Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "z, Bz = FM.axis_values(\"z\", \"abs_B\", r=0.04)\n", @@ -136,14 +105,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.566956Z", - "iopub.status.busy": "2024-10-17T23:18:43.566877Z", - "iopub.status.idle": "2024-10-17T23:18:43.569243Z", - "shell.execute_reply": "2024-10-17T23:18:43.569030Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM.interpolate(\"Bz\", (0.01, 0, 0))" @@ -152,14 +114,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.570364Z", - "iopub.status.busy": "2024-10-17T23:18:43.570291Z", - "iopub.status.idle": "2024-10-17T23:18:43.572425Z", - "shell.execute_reply": "2024-10-17T23:18:43.572201Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM.interpolate(\"Bz\", [(0, 0, z) for z in np.linspace(-0.1, 0.1, 3)])" @@ -175,14 +130,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.573534Z", - "iopub.status.busy": "2024-10-17T23:18:43.573458Z", - "iopub.status.idle": "2024-10-17T23:18:43.575372Z", - "shell.execute_reply": "2024-10-17T23:18:43.575172Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM.axis_labels" @@ -201,12 +149,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.576439Z", - "iopub.status.busy": "2024-10-17T23:18:43.576368Z", - "iopub.status.idle": "2024-10-17T23:18:43.578631Z", - "shell.execute_reply": "2024-10-17T23:18:43.578342Z" - }, "tags": [] }, "outputs": [], @@ -227,12 +169,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.580371Z", - "iopub.status.busy": "2024-10-17T23:18:43.580300Z", - "iopub.status.idle": "2024-10-17T23:18:43.582105Z", - "shell.execute_reply": "2024-10-17T23:18:43.581905Z" - }, "tags": [] }, "outputs": [], @@ -244,12 +180,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.583181Z", - "iopub.status.busy": "2024-10-17T23:18:43.583109Z", - "iopub.status.idle": "2024-10-17T23:18:43.585004Z", - "shell.execute_reply": "2024-10-17T23:18:43.584813Z" - }, "tags": [] }, "outputs": [], @@ -268,12 +198,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.586311Z", - "iopub.status.busy": "2024-10-17T23:18:43.586238Z", - "iopub.status.idle": "2024-10-17T23:18:43.588336Z", - "shell.execute_reply": "2024-10-17T23:18:43.588142Z" - }, "tags": [] }, "outputs": [], @@ -292,12 +216,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.589652Z", - "iopub.status.busy": "2024-10-17T23:18:43.589587Z", - "iopub.status.idle": "2024-10-17T23:18:43.591656Z", - "shell.execute_reply": "2024-10-17T23:18:43.591460Z" - }, "tags": [] }, "outputs": [], @@ -305,6 +223,34 @@ "FM.mins, FM.maxs, FM.deltas" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "FM.zmin, FM.zmax" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Convenient setting" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "zmin_save = FM.zmin\n", + "FM.zmin = 0\n", + "print(FM.zmin, FM.zmax)\n", + "FM.zmin = zmin_save" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -316,12 +262,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.592947Z", - "iopub.status.busy": "2024-10-17T23:18:43.592876Z", - "iopub.status.idle": "2024-10-17T23:18:43.594932Z", - "shell.execute_reply": "2024-10-17T23:18:43.594728Z" - }, "tags": [] }, "outputs": [], @@ -340,12 +280,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.596009Z", - "iopub.status.busy": "2024-10-17T23:18:43.595943Z", - "iopub.status.idle": "2024-10-17T23:18:43.598174Z", - "shell.execute_reply": "2024-10-17T23:18:43.597976Z" - }, "tags": [] }, "outputs": [], @@ -364,12 +298,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.599301Z", - "iopub.status.busy": "2024-10-17T23:18:43.599229Z", - "iopub.status.idle": "2024-10-17T23:18:43.601120Z", - "shell.execute_reply": "2024-10-17T23:18:43.600931Z" - }, "tags": [] }, "outputs": [], @@ -388,12 +316,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.602182Z", - "iopub.status.busy": "2024-10-17T23:18:43.602111Z", - "iopub.status.idle": "2024-10-17T23:18:43.604082Z", - "shell.execute_reply": "2024-10-17T23:18:43.603894Z" - }, "tags": [] }, "outputs": [], @@ -412,14 +334,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.605160Z", - "iopub.status.busy": "2024-10-17T23:18:43.605092Z", - "iopub.status.idle": "2024-10-17T23:18:43.607118Z", - "shell.execute_reply": "2024-10-17T23:18:43.606922Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM[\"magneticField/z\"]" @@ -435,14 +350,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.608179Z", - "iopub.status.busy": "2024-10-17T23:18:43.608112Z", - "iopub.status.idle": "2024-10-17T23:18:43.610064Z", - "shell.execute_reply": "2024-10-17T23:18:43.609879Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM[\"Bz\"]" @@ -452,12 +360,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.611105Z", - "iopub.status.busy": "2024-10-17T23:18:43.611026Z", - "iopub.status.idle": "2024-10-17T23:18:43.613064Z", - "shell.execute_reply": "2024-10-17T23:18:43.612865Z" - }, "tags": [] }, "outputs": [], @@ -478,12 +380,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.614131Z", - "iopub.status.busy": "2024-10-17T23:18:43.614062Z", - "iopub.status.idle": "2024-10-17T23:18:43.705873Z", - "shell.execute_reply": "2024-10-17T23:18:43.705622Z" - }, "tags": [] }, "outputs": [], @@ -503,12 +399,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.707158Z", - "iopub.status.busy": "2024-10-17T23:18:43.707050Z", - "iopub.status.idle": "2024-10-17T23:18:43.795881Z", - "shell.execute_reply": "2024-10-17T23:18:43.795634Z" - }, "tags": [] }, "outputs": [], @@ -527,12 +417,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.797129Z", - "iopub.status.busy": "2024-10-17T23:18:43.797051Z", - "iopub.status.idle": "2024-10-17T23:18:43.799178Z", - "shell.execute_reply": "2024-10-17T23:18:43.798978Z" - }, "tags": [] }, "outputs": [], @@ -555,12 +439,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.800298Z", - "iopub.status.busy": "2024-10-17T23:18:43.800221Z", - "iopub.status.idle": "2024-10-17T23:18:43.906583Z", - "shell.execute_reply": "2024-10-17T23:18:43.906321Z" - }, "tags": [] }, "outputs": [], @@ -599,12 +477,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.907833Z", - "iopub.status.busy": "2024-10-17T23:18:43.907752Z", - "iopub.status.idle": "2024-10-17T23:18:43.909903Z", - "shell.execute_reply": "2024-10-17T23:18:43.909701Z" - }, "tags": [] }, "outputs": [], @@ -623,12 +495,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.911016Z", - "iopub.status.busy": "2024-10-17T23:18:43.910948Z", - "iopub.status.idle": "2024-10-17T23:18:43.912844Z", - "shell.execute_reply": "2024-10-17T23:18:43.912648Z" - }, "tags": [] }, "outputs": [], @@ -647,12 +513,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.914054Z", - "iopub.status.busy": "2024-10-17T23:18:43.913981Z", - "iopub.status.idle": "2024-10-17T23:18:43.918440Z", - "shell.execute_reply": "2024-10-17T23:18:43.918224Z" - }, "tags": [] }, "outputs": [], @@ -671,12 +531,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.919573Z", - "iopub.status.busy": "2024-10-17T23:18:43.919499Z", - "iopub.status.idle": "2024-10-17T23:18:43.924086Z", - "shell.execute_reply": "2024-10-17T23:18:43.923875Z" - }, "tags": [] }, "outputs": [], @@ -697,12 +551,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.925284Z", - "iopub.status.busy": "2024-10-17T23:18:43.925212Z", - "iopub.status.idle": "2024-10-17T23:18:43.931910Z", - "shell.execute_reply": "2024-10-17T23:18:43.931653Z" - }, "tags": [] }, "outputs": [], @@ -727,14 +575,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.933175Z", - "iopub.status.busy": "2024-10-17T23:18:43.933074Z", - "iopub.status.idle": "2024-10-17T23:18:43.936186Z", - "shell.execute_reply": "2024-10-17T23:18:43.935940Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM.write_astra_1d(\"astra_1d.dat\")" @@ -750,14 +591,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.937434Z", - "iopub.status.busy": "2024-10-17T23:18:43.937331Z", - "iopub.status.idle": "2024-10-17T23:18:43.939885Z", - "shell.execute_reply": "2024-10-17T23:18:43.939519Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM.to_astra_1d()" @@ -776,12 +610,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.941363Z", - "iopub.status.busy": "2024-10-17T23:18:43.941262Z", - "iopub.status.idle": "2024-10-17T23:18:43.964397Z", - "shell.execute_reply": "2024-10-17T23:18:43.964127Z" - }, "tags": [] }, "outputs": [], @@ -801,12 +629,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.965715Z", - "iopub.status.busy": "2024-10-17T23:18:43.965635Z", - "iopub.status.idle": "2024-10-17T23:18:43.967730Z", - "shell.execute_reply": "2024-10-17T23:18:43.967519Z" - }, "tags": [] }, "outputs": [], @@ -825,12 +647,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.968998Z", - "iopub.status.busy": "2024-10-17T23:18:43.968926Z", - "iopub.status.idle": "2024-10-17T23:18:43.970671Z", - "shell.execute_reply": "2024-10-17T23:18:43.970473Z" - }, "tags": [] }, "outputs": [], @@ -849,12 +665,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.971739Z", - "iopub.status.busy": "2024-10-17T23:18:43.971668Z", - "iopub.status.idle": "2024-10-17T23:18:43.973805Z", - "shell.execute_reply": "2024-10-17T23:18:43.973561Z" - }, "tags": [] }, "outputs": [], @@ -873,12 +683,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.974915Z", - "iopub.status.busy": "2024-10-17T23:18:43.974848Z", - "iopub.status.idle": "2024-10-17T23:18:43.976595Z", - "shell.execute_reply": "2024-10-17T23:18:43.976394Z" - }, "tags": [] }, "outputs": [], @@ -898,12 +702,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.978059Z", - "iopub.status.busy": "2024-10-17T23:18:43.977994Z", - "iopub.status.idle": "2024-10-17T23:18:43.979877Z", - "shell.execute_reply": "2024-10-17T23:18:43.979666Z" - }, "tags": [] }, "outputs": [], @@ -915,12 +713,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:43.980937Z", - "iopub.status.busy": "2024-10-17T23:18:43.980869Z", - "iopub.status.idle": "2024-10-17T23:18:44.178177Z", - "shell.execute_reply": "2024-10-17T23:18:44.177932Z" - }, "tags": [] }, "outputs": [], @@ -965,12 +757,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:44.179670Z", - "iopub.status.busy": "2024-10-17T23:18:44.179568Z", - "iopub.status.idle": "2024-10-17T23:18:50.267675Z", - "shell.execute_reply": "2024-10-17T23:18:50.267382Z" - }, "tags": [] }, "outputs": [], @@ -1001,12 +787,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.269190Z", - "iopub.status.busy": "2024-10-17T23:18:50.269066Z", - "iopub.status.idle": "2024-10-17T23:18:50.359403Z", - "shell.execute_reply": "2024-10-17T23:18:50.359183Z" - }, "tags": [] }, "outputs": [], @@ -1019,12 +799,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.360577Z", - "iopub.status.busy": "2024-10-17T23:18:50.360494Z", - "iopub.status.idle": "2024-10-17T23:18:50.413051Z", - "shell.execute_reply": "2024-10-17T23:18:50.412836Z" - }, "tags": [] }, "outputs": [], @@ -1045,12 +819,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.414206Z", - "iopub.status.busy": "2024-10-17T23:18:50.414126Z", - "iopub.status.idle": "2024-10-17T23:18:50.431076Z", - "shell.execute_reply": "2024-10-17T23:18:50.430841Z" - }, "tags": [] }, "outputs": [], @@ -1063,12 +831,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.432156Z", - "iopub.status.busy": "2024-10-17T23:18:50.432083Z", - "iopub.status.idle": "2024-10-17T23:18:50.433997Z", - "shell.execute_reply": "2024-10-17T23:18:50.433762Z" - }, "tags": [] }, "outputs": [], @@ -1087,12 +849,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.435203Z", - "iopub.status.busy": "2024-10-17T23:18:50.435012Z", - "iopub.status.idle": "2024-10-17T23:18:50.437347Z", - "shell.execute_reply": "2024-10-17T23:18:50.437118Z" - }, "tags": [] }, "outputs": [], @@ -1111,12 +867,6 @@ "cell_type": "code", "execution_count": null, "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.438472Z", - "iopub.status.busy": "2024-10-17T23:18:50.438391Z", - "iopub.status.idle": "2024-10-17T23:18:50.441445Z", - "shell.execute_reply": "2024-10-17T23:18:50.441213Z" - }, "tags": [] }, "outputs": [], @@ -1265,7 +1015,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.7" + "version": "3.12.6" } }, "nbformat": 4, diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index 3919cf2..2da8e7d 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -833,7 +833,6 @@ def z(self): return self.coord_vec("z") # Deltas - @staticmethod def _create_delta_property(name): def getter(self): return self.deltas[self.axis_index(name)] @@ -847,7 +846,6 @@ def getter(self): dtheta = _create_delta_property("theta") # Maxs - @staticmethod def _create_max_property(name): def getter(self): return self.maxs[self.axis_index(name)] @@ -869,7 +867,6 @@ def setter(self, value): thetamax = _create_max_property("theta") # Mins - @staticmethod def _create_min_property(name): def getter(self): return self.mins[self.axis_index(name)] From 41e460ed639501961ce719893cad0aa215e9150e Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:53:00 -0700 Subject: [PATCH 08/14] remove @staticmethod --- pmd_beamphysics/fields/fieldmesh.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index 2da8e7d..32bbed0 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -887,7 +887,6 @@ def setter(self, value): # Scaled components # TODO: Check geometry - @staticmethod def _create_scaled_component_property(name): def getter(self): return self.scaled_component(name) From b3c5ae459f8bf6eee14f8a4ea8a1f5060afd6ab6 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:14:43 -0700 Subject: [PATCH 09/14] remove openPMD-validator --- environment.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/environment.yml b/environment.yml index 5806a1a..e0625d1 100644 --- a/environment.yml +++ b/environment.yml @@ -22,4 +22,3 @@ dependencies: - pip - pip: - mkdocstrings-python - - git+https://github.com/openPMD/openPMD-validator@2.0.X From 5bd31c1e6401d595abba2eb444bce4d55953735b Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Wed, 23 Oct 2024 08:18:10 -0700 Subject: [PATCH 10/14] add tests --- tests/test_fieldmesh.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/test_fieldmesh.py b/tests/test_fieldmesh.py index 2290e76..294e404 100644 --- a/tests/test_fieldmesh.py +++ b/tests/test_fieldmesh.py @@ -3,13 +3,18 @@ import numpy as np import tempfile +import pytest -def test_dipole_corrector(): + +@pytest.fixture(scope="module") +def fm_dipole_corrector(): + """Fixture to create and return the FM object for dipole corrector fieldmesh.""" R = 0.02 L = 0.1 theta = np.pi / 2 current = 1 + # Create the FM object (this will only be done once per test module) FM = make_dipole_corrector_fieldmesh( current=current, xmin=-R, @@ -27,6 +32,12 @@ def test_dipole_corrector(): theta=theta, npts=20, ) + return FM + + +# First test using the FM fixture +def test_dipole_corrector_read_impact_emfield_cartesian(fm_dipole_corrector): + FM = fm_dipole_corrector # Test read/write impact_emfield_cartesian with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -37,3 +48,21 @@ def test_dipole_corrector(): ) assert FM == FM2 + + +# Another test that uses the same FM object +def test_fieldmesh_limits(fm_dipole_corrector): + FM = fm_dipole_corrector + + # Example test to check attributes + assert FM.xmax == 0.02 + assert FM.ymax == 0.02 + + # Test setting zmax + L1 = FM.zmax - FM.zmin + FM.zmax = 100 + L2 = FM.zmax - FM.zmin + assert L1 == L2 + FM.zmin = 100 + L3 = FM.zmax - FM.zmin + assert L1 == L3 From 923467c7de8e734818aa4b46b6ded8d9140d4934 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:37:25 -0700 Subject: [PATCH 11/14] Separate _create property functions, add doc= (thanks @ken-lauer ) --- docs/examples/fields/field_examples.ipynb | 45 ++----------- pmd_beamphysics/fields/fieldmesh.py | 81 ++++++++++++----------- 2 files changed, 49 insertions(+), 77 deletions(-) diff --git a/docs/examples/fields/field_examples.ipynb b/docs/examples/fields/field_examples.ipynb index 01c6368..eef00a9 100644 --- a/docs/examples/fields/field_examples.ipynb +++ b/docs/examples/fields/field_examples.ipynb @@ -889,14 +889,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.442628Z", - "iopub.status.busy": "2024-10-17T23:18:50.442530Z", - "iopub.status.idle": "2024-10-17T23:18:50.451459Z", - "shell.execute_reply": "2024-10-17T23:18:50.451257Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM3D = FieldMesh.from_ansys_ascii_3d(\n", @@ -912,14 +905,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.452610Z", - "iopub.status.busy": "2024-10-17T23:18:50.452525Z", - "iopub.status.idle": "2024-10-17T23:18:50.454832Z", - "shell.execute_reply": "2024-10-17T23:18:50.454618Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM3D.attrs" @@ -935,14 +921,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.456002Z", - "iopub.status.busy": "2024-10-17T23:18:50.455927Z", - "iopub.status.idle": "2024-10-17T23:18:50.461253Z", - "shell.execute_reply": "2024-10-17T23:18:50.461050Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM3D.write(\"../data/rfgun_rectangular.h5\")" @@ -958,14 +937,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.462395Z", - "iopub.status.busy": "2024-10-17T23:18:50.462304Z", - "iopub.status.idle": "2024-10-17T23:18:50.464240Z", - "shell.execute_reply": "2024-10-17T23:18:50.464026Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "FM2D = FM3D.to_cylindrical()\n", @@ -982,14 +954,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "execution": { - "iopub.execute_input": "2024-10-17T23:18:50.465256Z", - "iopub.status.busy": "2024-10-17T23:18:50.465160Z", - "iopub.status.idle": "2024-10-17T23:18:50.467295Z", - "shell.execute_reply": "2024-10-17T23:18:50.467076Z" - } - }, + "metadata": {}, "outputs": [], "source": [ "import os\n", diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index 32bbed0..c1687c7 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -60,6 +60,50 @@ } +def _create_delta_property(name): + def getter(self): + return self.deltas[self.axis_index(name)] + + return property(getter, doc=f"Mesh spacing in {name}") + + +def _create_max_property(name): + def getter(self): + return self.maxs[self.axis_index(name)] + + def setter(self, value): + # Setting the max => shift the min + i = self.axis_index(name) + mins = list(self.attrs["gridOriginOffset"]) + mins[i] = mins[i] + float(value) - self.maxs[i] + self.attrs["gridOriginOffset"] = tuple(mins) + + return property( + getter, setter, doc=f"Mesh maximum in {name}. This can also be set." + ) + + +def _create_min_property(name): + def getter(self): + return self.mins[self.axis_index(name)] + + def setter(self, value): + mins = list(self.attrs["gridOriginOffset"]) + mins[self.axis_index(name)] = float(value) + self.attrs["gridOriginOffset"] = tuple(mins) + + return property( + getter, setter, doc=f"Mesh minimim in {name}. This can also be set." + ) + + +def _create_scaled_component_property(name): + def getter(self): + return self.scaled_component(name) + + return property(getter, doc=f"Scaled 3D mesh for {name} in {pg_units(name)}") + + class FieldMesh: """ Class for openPMD External Field Mesh data. @@ -833,12 +877,6 @@ def z(self): return self.coord_vec("z") # Deltas - def _create_delta_property(name): - def getter(self): - return self.deltas[self.axis_index(name)] - - return property(getter) - dx = _create_delta_property("x") dy = _create_delta_property("y") dz = _create_delta_property("z") @@ -846,19 +884,6 @@ def getter(self): dtheta = _create_delta_property("theta") # Maxs - def _create_max_property(name): - def getter(self): - return self.maxs[self.axis_index(name)] - - def setter(self, value): - # Setting the max => shift the min - i = self.axis_index(name) - mins = list(self.attrs["gridOriginOffset"]) - mins[i] = mins[i] + float(value) - self.maxs[i] - self.attrs["gridOriginOffset"] = tuple(mins) - - return property(getter, setter) - # Create max properties dynamically xmax = _create_max_property("x") ymax = _create_max_property("y") @@ -867,17 +892,6 @@ def setter(self, value): thetamax = _create_max_property("theta") # Mins - def _create_min_property(name): - def getter(self): - return self.mins[self.axis_index(name)] - - def setter(self, value): - mins = list(self.attrs["gridOriginOffset"]) - mins[self.axis_index(name)] = float(value) - self.attrs["gridOriginOffset"] = tuple(mins) - - return property(getter, setter) - # Create min properties dynamically xmin = _create_min_property("x") ymin = _create_min_property("y") @@ -886,13 +900,6 @@ def setter(self, value): thetamin = _create_min_property("theta") # Scaled components - # TODO: Check geometry - def _create_scaled_component_property(name): - def getter(self): - return self.scaled_component(name) - - return property(getter) - # Dynamically create scaled properties Bx = _create_scaled_component_property("Bx") By = _create_scaled_component_property("By") From ec4b574da9190616c590704b011f3a9c2265a6a6 Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:49:06 -0700 Subject: [PATCH 12/14] Add units to docs --- pmd_beamphysics/fields/fieldmesh.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index c1687c7..3e077a8 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -64,7 +64,7 @@ def _create_delta_property(name): def getter(self): return self.deltas[self.axis_index(name)] - return property(getter, doc=f"Mesh spacing in {name}") + return property(getter, doc=f"Mesh spacing in {name} in units of {pg_units(name)}") def _create_max_property(name): @@ -79,7 +79,9 @@ def setter(self, value): self.attrs["gridOriginOffset"] = tuple(mins) return property( - getter, setter, doc=f"Mesh maximum in {name}. This can also be set." + getter, + setter, + doc=f"Mesh maximum in {name} in units of {pg_units(name)}. This can also be set.", ) @@ -93,7 +95,9 @@ def setter(self, value): self.attrs["gridOriginOffset"] = tuple(mins) return property( - getter, setter, doc=f"Mesh minimim in {name}. This can also be set." + getter, + setter, + doc=f"Mesh minimim in {name} in units of {pg_units(name)}. This can also be set.", ) @@ -101,7 +105,9 @@ def _create_scaled_component_property(name): def getter(self): return self.scaled_component(name) - return property(getter, doc=f"Scaled 3D mesh for {name} in {pg_units(name)}") + return property( + getter, doc=f"Scaled 3D mesh for {name} in units of {pg_units(name)}" + ) class FieldMesh: From 9db2970843a9f3a430bc367467018212476a521d Mon Sep 17 00:00:00 2001 From: Christopher Mayes <31023527+ChristopherMayes@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:52:39 -0700 Subject: [PATCH 13/14] typo --- pmd_beamphysics/fields/fieldmesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd_beamphysics/fields/fieldmesh.py b/pmd_beamphysics/fields/fieldmesh.py index 3e077a8..5fb153d 100644 --- a/pmd_beamphysics/fields/fieldmesh.py +++ b/pmd_beamphysics/fields/fieldmesh.py @@ -97,7 +97,7 @@ def setter(self, value): return property( getter, setter, - doc=f"Mesh minimim in {name} in units of {pg_units(name)}. This can also be set.", + doc=f"Mesh minimum in {name} in units of {pg_units(name)}. This can also be set.", ) From c828e6e8bb7f6036de8c40e7f90396dd183f1746 Mon Sep 17 00:00:00 2001 From: Ken Lauer <152229072+ken-lauer@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:57:41 -0700 Subject: [PATCH 14/14] ENH/FIX: support pathlib.Path for ParticleGroup filenames --- pmd_beamphysics/particles.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pmd_beamphysics/particles.py b/pmd_beamphysics/particles.py index 2bef90f..bca939b 100644 --- a/pmd_beamphysics/particles.py +++ b/pmd_beamphysics/particles.py @@ -1,5 +1,6 @@ import functools import os +import pathlib from copy import deepcopy import numpy as np @@ -178,7 +179,7 @@ def __init__(self, h5=None, data=None): if h5: # Allow filename - if isinstance(h5, str): + if isinstance(h5, (str, pathlib.Path)): fname = os.path.expandvars(h5) assert os.path.exists(fname), f"File does not exist: {fname}" @@ -974,7 +975,7 @@ def write(self, h5, name=None): Writes to an open h5 handle, or new file if h5 is a str. """ - if isinstance(h5, str): + if isinstance(h5, (str, pathlib.Path)): fname = os.path.expandvars(h5) g = File(fname, "w") pmd_init(g, basePath="/", particlesPath=".")