From 9fd4394aa3846a23d8e205d100592eab29e01b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henning=20Schulze=20Ei=C3=9Fing?= Date: Thu, 12 Sep 2024 07:07:32 -0500 Subject: [PATCH 1/4] Add Dummy Map protocol --- fuse/context.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/fuse/context.py b/fuse/context.py index bda36abf..8a00ade2 100644 --- a/fuse/context.py +++ b/fuse/context.py @@ -293,3 +293,31 @@ def from_config(config_name, key): """Return a value from a json config file.""" config = straxen.get_resource(config_name, fmt="json") return config[key] + + +class DummyMap: + """Return constant results + the length match the length of input + but from the second dimensions the shape is user defined input + """ + def __init__(self, const, shape=()): + self.const = float(const) + self.shape = shape + + def __call__(self, x, **kwargs): + shape = [len(x)] + list(self.shape) + return np.ones(shape) * self.const + + def reduce_last_dim(self): + assert len(self.shape) >= 1, 'Need at least 1 dim to reduce further' + const = self.const * self.shape[-1] + shape = list(self.shape) + shape[-1] = 1 + + return DummyMap(const, shape) + +@URLConfig.register("constant_dummy_map") +def get_dummy(const, shape=()): + """Make an Dummy Map""" + itp_map = DummyMap(const, shape) + return itp_map \ No newline at end of file From 6fe05852031b90121ec31906d2f2038dff80cd43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henning=20Schulze=20Ei=C3=9Fing?= Date: Thu, 12 Sep 2024 07:22:30 -0500 Subject: [PATCH 2/4] Add example how to use the dummy map --- examples/4_Custom_Simulations.ipynb | 115 +++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 4 deletions(-) diff --git a/examples/4_Custom_Simulations.ipynb b/examples/4_Custom_Simulations.ipynb index eb668538..04b11e26 100644 --- a/examples/4_Custom_Simulations.ipynb +++ b/examples/4_Custom_Simulations.ipynb @@ -6,7 +6,7 @@ "source": [ "# Custom Simulation and Advanced Tricks\n", "\n", - "This notebook will demonstrate how one can use the modular structure of fuse to change parts of the simulation by exchanging or adding new pugins. To get the most out of this notebook, you should start with an empty `out_dir` when setting up the simulation context. \n", + "This notebook will demonstrate how one can use the modular structure of fuse to change parts of the simulation by exchanging or adding new pugins. To get the most out of this notebook, you should start with an empty `out_dir` when setting up the simulation context. Additionaly the notebook will show how a map can be replaced with a dummy map to disable certain parts of the simulation.\n", "\n", "## Imports & Simulation Context" ] @@ -434,13 +434,120 @@ "plugin_output = plugin.compute(microphysics_summary)\n", "print(plugin_output[0:10])" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Replacing a map with a dummy map\n", + "\n", + "Sometimes you might want to disable a certain feature of the simulation without going into the code and changing a plugin. One example can be that you might want to turn of the effects of a certain map. In this example we will use the `constant_dummy_map` URLConfig protocol to disable the effect of the s2_correction map.\n", + "\n", + "We can set up a new context. This time we will override the config option for the s2_correction map with the dummy map option. Instead of the real map values, the dummy map will return a constant value that can be configured by the user. In our case we set it to 1. You could also set it to other values if you want to test the effect of the map on the simulation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "st = fuse.context.full_chain_context(\n", + " output_folder=\"./fuse_data\", run_without_proper_corrections=True\n", + ")\n", + "\n", + "st.set_config(\n", + " {\n", + " \"path\": \"/project2/lgrandi/xenonnt/simulations/testing\",\n", + " \"file_name\": \"pmt_neutrons_100.root\",\n", + " \"entry_stop\": 10,\n", + " 's2_correction_map': \"constant_dummy_map://1\",\n", + " }\n", + ")\n", + "\n", + "run_number = \"00000\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To get a feeling how the map affects your simulation, lets take a look at the number of s2 photons. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "st.make(run_number, \"s2_photons\")\n", + "s2_photons = st.get_df(run_number, \"s2_photons\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have the data, lets change the map to a different value and rerun the simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "st.set_config(\n", + " {\n", + " 's2_correction_map': \"constant_dummy_map://2\",\n", + " }\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "st.make(run_number, \"s2_photons\")\n", + "s2_photons_changed_constant = st.get_df(run_number, \"s2_photons\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And now we can plot the data again. You should see that the distribution of s2 photons is different." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "bins = np.linspace(0, 100, 100)\n", + "\n", + "plt.hist(s2_photons[\"n_s2_photons\"], bins=bins, alpha=0.5, label=\"Original\")\n", + "plt.hist(s2_photons_changed_constant[\"n_s2_photons\"], bins=bins, alpha=0.5, label=\"Changed constant\")\n", + "\n", + "plt.legend()\n", + "plt.xlabel(\"Number of S2 photons\")\n", + "plt.ylabel(\"Counts\")\n", + "plt.show()" + ] } ], "metadata": { "kernelspec": { - "display_name": "Python [conda env:XENONnT_development] *", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "conda-env-XENONnT_development-py" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -452,7 +559,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.18" + "version": "3.9.19" }, "orig_nbformat": 4 }, From 342728439a163ddb3c9a4201779e85f21dc1073c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:25:43 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/4_Custom_Simulations.ipynb | 8 +++++--- fuse/context.py | 16 ++++++++-------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/examples/4_Custom_Simulations.ipynb b/examples/4_Custom_Simulations.ipynb index 04b11e26..1440ce3e 100644 --- a/examples/4_Custom_Simulations.ipynb +++ b/examples/4_Custom_Simulations.ipynb @@ -461,7 +461,7 @@ " \"path\": \"/project2/lgrandi/xenonnt/simulations/testing\",\n", " \"file_name\": \"pmt_neutrons_100.root\",\n", " \"entry_stop\": 10,\n", - " 's2_correction_map': \"constant_dummy_map://1\",\n", + " \"s2_correction_map\": \"constant_dummy_map://1\",\n", " }\n", ")\n", "\n", @@ -500,7 +500,7 @@ "source": [ "st.set_config(\n", " {\n", - " 's2_correction_map': \"constant_dummy_map://2\",\n", + " \"s2_correction_map\": \"constant_dummy_map://2\",\n", " }\n", ")" ] @@ -534,7 +534,9 @@ "bins = np.linspace(0, 100, 100)\n", "\n", "plt.hist(s2_photons[\"n_s2_photons\"], bins=bins, alpha=0.5, label=\"Original\")\n", - "plt.hist(s2_photons_changed_constant[\"n_s2_photons\"], bins=bins, alpha=0.5, label=\"Changed constant\")\n", + "plt.hist(\n", + " s2_photons_changed_constant[\"n_s2_photons\"], bins=bins, alpha=0.5, label=\"Changed constant\"\n", + ")\n", "\n", "plt.legend()\n", "plt.xlabel(\"Number of S2 photons\")\n", diff --git a/fuse/context.py b/fuse/context.py index 8a00ade2..d83bd8dc 100644 --- a/fuse/context.py +++ b/fuse/context.py @@ -296,10 +296,9 @@ def from_config(config_name, key): class DummyMap: - """Return constant results - the length match the length of input - but from the second dimensions the shape is user defined input - """ + """Return constant results the length match the length of input but from + the second dimensions the shape is user defined input.""" + def __init__(self, const, shape=()): self.const = float(const) self.shape = shape @@ -309,15 +308,16 @@ def __call__(self, x, **kwargs): return np.ones(shape) * self.const def reduce_last_dim(self): - assert len(self.shape) >= 1, 'Need at least 1 dim to reduce further' + assert len(self.shape) >= 1, "Need at least 1 dim to reduce further" const = self.const * self.shape[-1] shape = list(self.shape) shape[-1] = 1 return DummyMap(const, shape) - + + @URLConfig.register("constant_dummy_map") def get_dummy(const, shape=()): - """Make an Dummy Map""" + """Make an Dummy Map.""" itp_map = DummyMap(const, shape) - return itp_map \ No newline at end of file + return itp_map From 836d8bbaf175f9e96c17f43a0ab6000fea3f1b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Ram=C3=ADrez=20Garc=C3=ADa?= Date: Tue, 17 Sep 2024 09:31:30 +0200 Subject: [PATCH 4/4] Edit DummyMap docstrings --- fuse/context.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuse/context.py b/fuse/context.py index d83bd8dc..765a8580 100644 --- a/fuse/context.py +++ b/fuse/context.py @@ -296,8 +296,8 @@ def from_config(config_name, key): class DummyMap: - """Return constant results the length match the length of input but from - the second dimensions the shape is user defined input.""" + """Return constant results with length equal to that of the input and + second dimensions (constand correction) user-defined.""" def __init__(self, const, shape=()): self.const = float(const)