diff --git a/README.md b/README.md index c347aae..b7bfaae 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,33 @@ save them to your local computer). In order to run the notebook on your local computer, please install `openPMD-viewer` first (see below), as well as `wget` (`pip install wget`). +#### MPI Support + +`openPMD-viewer` includes support for parallel data reading using MPI, which +depends on `mpi4py`. When running under MPI (detected automatically), the +library will use distributed I/O to accelerate data reading for large datasets. + +**Important**: MPI support is only available for the `openpmd-api` backend. +The `h5py` backend is serial-only and will always use the serial reader, +even when running under MPI. + +**MPI Behavior**: +- **Data distribution**: All ranks participate in distributed I/O, where each + rank reads a portion of the data in parallel. After reading, all ranks receive + the complete dataset (via MPI broadcast), ensuring all ranks have access to + the full data. +- **Plotting**: Only rank 0 performs plotting operations to avoid duplicate + plots. All ranks participate in data reading, but visualization is restricted + to rank 0. + +Tutorial notebooks demonstrating MPI usage are available: +- `6_mpi_2d.ipynb`: Example demonstrating MPI parallel reading for 2D data +- `7_mpi_3d.ipynb`: Example demonstrating MPI parallel reading for 3D data + +To use MPI support, ensure `mpi4py` is installed and run your Python script +with `mpirun` (e.g., `mpirun -n 4 python script.py`). Note that you must use +the `openpmd-api` backend (not `h5py`) to benefit from MPI parallel I/O. + ### Notebook quick-starter If you wish to use the **interactive GUI**, the installation of diff --git a/docs/source/tutorials/6_mpi_2d.ipynb b/docs/source/tutorials/6_mpi_2d.ipynb new file mode 100644 index 0000000..a3de849 --- /dev/null +++ b/docs/source/tutorials/6_mpi_2d.ipynb @@ -0,0 +1,386 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "id": "8ded34fa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing existing dataset directory: /Users/dec2023/Work/2026/cursor/checked_in/2d\n", + "Downloading 2D BP5 dataset from https://github.com/guj/openPMD-example-datasets/raw/add_bp5_files/bp5/2d.tar.gz...\n", + "Extracting to /Users/dec2023/Work/2026/cursor/checked_in...\n", + "Download and extraction complete!\n", + "Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/2d\n" + ] + } + ], + "source": [ + "import os\n", + "import urllib.request\n", + "import tarfile\n", + "import tempfile\n", + "import shutil\n", + "\n", + "# Check if MPI is available (for when running as converted Python script)\n", + "try:\n", + " import mpi4py.MPI as MPI\n", + " comm = MPI.COMM_WORLD\n", + " rank = comm.Get_rank()\n", + " is_mpi = True\n", + "except ImportError:\n", + " rank = 0\n", + " is_mpi = False\n", + "\n", + "# Download and extract 2D BP5 dataset (only on rank 0 if MPI is available)\n", + "if rank == 0:\n", + " data_url = \"https://github.com/guj/openPMD-example-datasets/raw/add_bp5_files/bp5/2d.tar.gz\"\n", + " data_dir = os.getcwd()\n", + " dataset_2d_dir = os.path.join(data_dir, '2d')\n", + " \n", + " # Remove existing directory if it exists\n", + " if os.path.exists(dataset_2d_dir):\n", + " print(f\"Removing existing dataset directory: {dataset_2d_dir}\")\n", + " shutil.rmtree(dataset_2d_dir)\n", + " \n", + " print(f\"Downloading 2D BP5 dataset from {data_url}...\")\n", + " print(f\"Extracting to {data_dir}...\")\n", + " \n", + " # Create directory if it doesn't exist\n", + " os.makedirs(data_dir, exist_ok=True)\n", + " \n", + " # Download to temporary file\n", + " with tempfile.NamedTemporaryFile(delete=False, suffix='.tar.gz') as tmp_file:\n", + " urllib.request.urlretrieve(data_url, tmp_file.name)\n", + " \n", + " # Extract tar.gz file - this will create a '2d' directory\n", + " with tarfile.open(tmp_file.name, 'r:gz') as tar:\n", + " tar.extractall(data_dir)\n", + " \n", + " # Clean up temporary file\n", + " os.remove(tmp_file.name)\n", + " \n", + " print(\"Download and extraction complete!\")\n", + "\n", + "# Wait for rank 0 to finish download before other ranks proceed\n", + "if is_mpi:\n", + " comm.Barrier()\n", + "\n", + "# Set the data directory path for use in the notebook (all ranks need this)\n", + "data_dir = os.getcwd()\n", + "dataset_2d_dir = os.path.join(data_dir, '2d')\n", + "opmd_2d_dir = dataset_2d_dir\n", + "if rank == 0:\n", + " print(f\"Using data directory: {opmd_2d_dir}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "02beda64-557d-444f-ba91-35517dcd2c35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 2 engines with \n", + "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 2/2 [00:06<00:00, 3.03s/engine]\n", + "Connected to 2 engines.\n" + ] + } + ], + "source": [ + "import ipyparallel as ipp\n", + "\n", + "# Create and start a cluster with 2 MPI engines\n", + "cluster = ipp.Cluster(engines=\"mpi\", n=2)\n", + "rc = cluster.start_and_connect_sync()\n", + "\n", + "# Activate the client to use all engines\n", + "rc.activate()\n", + "print(f\"Connected to {len(rc.ids)} engines.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ad2fe0be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:1] Rank 1: Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/2d\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[stdout:0] Rank 0: Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/2d\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Push the data directory path to all MPI engines\n", + "%px import os\n", + "%px import mpi4py.MPI as MPI\n", + "%px opmd_2d_dir = os.path.join(os.getcwd(), '2d')\n", + "%px opmd_2d_dir = os.path.abspath(opmd_2d_dir)\n", + "%px print(f\"Rank {MPI.COMM_WORLD.Get_rank()}: Using data directory: {opmd_2d_dir}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f91f0f1d-91ac-4775-a4dc-51c3104e8ff5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:1] Rank 1/2 running on host: JunminD023sMBP5.localdomain, PID: 79540\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[stdout:0] ..... use MPI reader (size=2)\n", + "Rank 0/2 running on host: JunminD023sMBP5.localdomain, PID: 79539\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[output:0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjwAAAHJCAYAAACBuOOtAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAArt5JREFUeJztnQfcHFX198/u09JDIIQECAlKNwgEIlJUmgE0VP8gGgQFUZTeREQEAQlFBBRBmiA1qBAEBAkIASI9gFJe6ZgQgpGWkPK03Xk/5+7c2XPv3jvb99ny++az2Xlm7ty5MzvlzKmJIAgCAgAAAABoYpIDPQAAAAAAgGoDgQcAAAAATQ8EHgAAAAA0PRB4AAAAAND0QOABAAAAQNMDgQcAAAAATQ8EHgAAAAA0PRB4AAAAAND0QOABAAAAQNMDgQdUheuuu44SiYT3M2fOnJoe+XvuuYfOOOOMgttzW9e4Bw0alHfdVCpFv/rVr2i33Xajtddem4YMGUIbb7wx/fjHP6aPP/44p/17771HRx55JH3qU5+iwYMH04QJE+jQQw+l+fPnU6W5+OKLad9996V1111X7c8OO+zgbPfAAw/Ql7/8ZVpzzTWpq6uLxowZQzvttJM6jvXEo48+qsb3n//8J5rH+yT3a8WKFer3rPU5ZxM3Dn29vP322zUf19y5c+m73/0ubbnllupYxo2jmHN18eLF9O1vf5tGjx6troFtttmG/v73v3vPN17O7bg9r8frS3jdYcOG0cKFCyu056Dl4NISAFSaa6+9lkuWqO/HH38857NkyZKaHvQjjjhCjadQTj/9dNX+b3/7mzHuJ598Mu+6n3zySTB8+PDge9/7XvCnP/0peOihh4ILL7wwGDVqVLDJJpsEK1asiNp2d3cH66+/fjB69Ojgt7/9rWr7u9/9LlhjjTWCtdZaK1i6dGlQSTbccMNg8uTJwSGHHBKsvvrqwZe+9CVnu5kzZwbHHHOM+p4zZ05w++23B1OnTlXH5IYbbgjqgXQ6rfaFf1vJSy+9pD6a//3vf2rc/JsOJHHjWLx4sTq/+HyoNWeccUYwYcKEYO+99w522GEHNca33norp10x5yq3nTRpUrD22msHN954YzB79uxgr732Ctrb29X5JOG/eT4v53bcnvvj9e3jseOOOwYHHXRQFY8GaGYg8ICqCjxPP/10XRzhUgUefkgVS39/f/D+++/nzGfhxxYY7r//fjXv6quvNtrefPPNaj4LGpUklUpF05/5zGe8Ao+L3t5e9SD6whe+ENQD99xzjzpG//73v2PbVUvg4ePR19dXcPt6EbzizokLLrjAK/AUc66yQMTzHnvssWgeHysW+D/3uc8Z60+ZMkXNl8fyH//4h1r/sssuM9r++c9/Dtra2oL58+eXudegFYFJCwwoM2fOVCr0Sy+91Jh/+umnU1tbG91///2x69966600depUGjdunFKxa9PR8uXLozasHv/tb3+rpqV5qlrmAx73aqutljP/c5/7nPpesGBBNK+jo0N9jxw50mi7yiqrqG/bhPbMM8/QnnvuSauuuqpatsUWW9Af//jHgseWTJZ+yfNYeVzt7e152z733HM0bdo0ZQpjMwmbxr761a/SO++8Q5Xi8ssvpylTptCGG25ozJcmLf6NV199dTX985//PPrt+ZzQvPbaa/TNb34zGiufQ/p80bAZite74YYb6IQTTqC11lpLtX399dfpf//7H/3whz+kTTbZRJlctPmPzW2afOPwmbR+//vf02abbaZ+a/7N99lnH/p//+//GW24D94uj+UrX/mKmh4/frwaZ09PT8XOiWLO1VmzZqnfhc1UGj5vDjzwQHrqqacisxR/P/300/Stb33LOK+23XZb2mCDDVQ/kj322EPt31VXXVXQmAGQQOABVYX9Wfr7+40Pz9MccMABdPjhh6ubMz/MmQcffJDOPvts+slPfqL8SOLghxXf5K+55hr629/+Rscee6wSAPjGqDnttNPo//7v/9T0448/Hn1YSMrHpptuqgSYNdZYgw466KCy/Gp4v5jPfOYz0bzttttO+U6wbwff+JctW0bPPvus2vfJkyfTLrvsErV96KGHVHv2A/rd735Hf/nLX2jzzTenr3/96+qBWQ3S6bT6zd59910lhL766qvqt4qDhU3+3f773/8qwYGFVvYdWmeddeiTTz6pyLh6e3uV38eOO+4Y245/Yz4vGPY10b89nxPMyy+/rISmF198kS688EK6++67lWB29NFHK8HE5pRTTlHnAB//u+66Swk3H374oVrGx+evf/0rXXvttcrHhYUu7a+TbxwuZsyYodry+XL77bfTJZdcQv/617+UEMHnvaSvr08JwjvvvLM6Lw455BC66KKL6LzzzqNKUcy5ysfzs5/9bE4fet5LL70UtZPz7bZ6uaazs1MJQ3ycASiagVYxgeY2abk+rJKWsJ1+iy22CNZdd93g5ZdfVj4BbGph01CxPh2sFn/44YfVdv75z3+WbNK6/vrrg1/84hfKbPLggw8G5557brDqqquqsb3zzjtBsfA6vO5WW21lmBAY9n3YY489jGPEvhQffPCB0W6jjTZSx8k2o0ybNi0YN25cTr/5KMSkteuuu0ZjGjFiREEmtmeeeUa1v+OOO4Jqwb5UvA32MbLhfZL7FWdK4v1jPxPbp+zII48MBg0aFHz44Yfqb/ZX4T6++MUv5h0bn7f8G+28887BPvvsU9A49PWiTUkfffRRMHjw4OArX/mK0Y5NOV1dXcE3v/nNaN7BBx+s1v3jH/9otOV12WerGOJMWsWcqx0dHcH3v//9nPXZxMXrsBmMuemmm9Tf7L9kwz5wnZ2dOfNPPfXUIJlMBsuWLStq3wCAhgdUleuvv169DcrPk08+abRh0wBrZT744AP1psi+ZbfccovSrOTjzTffVOaIsWPHqvasdv/Sl76kltmq/2JgFTu/ue6+++5Ki3DyySfTvffeq8wX559/flF9sQaAtVC8X2yCkyYEfjNnDc3zzz+v1PSPPPII/eEPf1CqftaSLFmyRLVjc8W///1vmj59uvpbasy470WLFtErr7ySs4w/vN1S+c1vfqNMEKw12HXXXdVY+beJY7311qNRo0apY8aaENaiVBrWODGsYSmV7u5uFfnDZiKODrKPKS9/4oknjHW+9rWvOfvi/eRzl806bJrh85D7LvUcZO3PypUrDdMbw6YqNpfZ0U5sDpNaTa0hkdFr5VLouSrH5MNe5mvrms+/OWseOWIMZOHfg88BNh/zcbvjjjuKOjzd3d3qfGOtNp/De++9t7Pdww8/rDR9fK6zJpPP/UYBAg+oKuwPsdVWWxkfvlhcD8kvfOEL6qLjh3oh5iZWqfM6LECxCYzNByxQsfqf4QdGJWEfHPYrsB+CcXz00UfqYcAPBTbt8A1CwqY4FqR4zBwazPvDpjM2f7C5gE1BDJuHmBNPPFE9TOWH/UeY999/X33by/mhVCrrr7++MvmwuYSFUjaZHHHEEeqB44N9PPimyOY2FhrZJMM3YTb58EOzEujftpA0AT5YwGbhhoU6+5ixwCOPqcZ1XnIKgh/84Ae09dZb02233abODz4POS1Bqecgj823PT6WermGBTb7WPCLBF9PlaLQc5VhHzZ7jIw2/7E/km7H+NrqdhK9n5W+vhsdNiWzv5ftD1koqVRK+UGyOVeaJyVvvfWWujb4t2c/Pb6+uT2f941Afu9DAGrA1VdfrezyLFTwBctvkvwAyecTw2/6LOhorQ7jynVTKVhbUqiTJws7fOPgmwS/kbv8FPhtmTVTrB2QsGDEDwPtw8C5SbQPCefRcaGdd/lhK+GcO5WCfx9+wLGmi/2afPBbIjuk8/FivxP2MTrzzDPVDZWdystFHw/9AC0F1kLxsWdtHgtxLuxj59I43Hjjjcpfh52oJeX4K2lBgDV3NnzO6/2vJYWeq/r3f+GFF3L60PMmTZpkfPN8LWTKtnq5RP/mA3EM6hnWRvMnzu/tpz/9Kd10003qHsnHln28tIP/0KFDo3P4H//4h/M+ytoc9sXTwi2/0LLv5S9/+Uuv9rOegIYHDDh8Y+O3BH5b5MgWFgxY4GGBIQ798OE3WckVV1yR01a3KeetkN/c2Vn085//fMHCDpvcZs+eraKpXPDbOr9Z2UIKOwfzWy8nLtTCDGtb/vnPf+ZozPRn+PDhqq093xUxVgosvLDmhqNyCu2TfyN+62QHWl6PNQGVgG+0zBtvvJG3re+3Z60Imyv5TZXPOdcxLWQ/eR/tc5CFPDZLFTIOF+yYzMIhC1MSjnJjQZ81bbWm0HOVYTMhm2Cl+Zq1abw//CLDfTEc7cZCNM+XwQx8rbGJ1iXc8zXFv0ucwA1y+c53vqMEGX4R4fNzv/32U1pI2wE+Dj6nOSpWwqZuFnoqpb2tJtDwgKrCb318o7P59Kc/rcJ0WQ27//77qzfpyy67TEVhsOmE3yL5Ao2zQ3O0Br+lc5QXm0vYFMFvLywU2PAbJ8NvNPwWxG+q/JDj7bnghzSH0PKDlVXo7MdywQUXKF+hH/3oRznmOO1nox9ofBPgBym/CfH+SzMY7zfvP8P7yMIAvx3x2xcLNnxDP+ecc9QbF++bFOR47Nw329r5YcFvu+wnwoLEn/70p7y/B9+YdOjz0qVLlRDz5z//Wf3NpivOnMvstdde6hiwWYofLqxVYC0NCzwceRUXms6RTvxbsg8Av/3zNtgMwm+M+aLuCoUfrtw3H1cWluNgQZD3i/2QWFBgMwlrByZOnKgin7bffnulomezFM9jzQz/lhyFpSPr4uDw+7POOkudg6xp5Ac1a7P4nJbnftw4bFg45AguNhnwi8A3vvENJVRw5Bifj7ytSsHaOv5dpQaGTVd8nvJHa0+LOVc5SozPE36onnvuucrvhs8JPjYcXSfha5LPC27L5lnOsMxaQNZA8DZt+DfnMcX5CAETfjG45ZZblMCshU02j7O2lqMK+TcsBPabsgVN/pvPczb/FuKKMKDAbxvUOkqLP1dddZVqd+CBBwZDhgwxMuPKJH0XXXRR7HY46mObbbZRfXDm4O9+97vBs88+G2V51vT09Khl3CaRSMRGojAHHHBAsN566wVDhw5VESecifbwww8P3n333Zy2vIw/Gu43bt85qkby2muvBd/61reCiRMnqgicddZZJ/j617+ec0wYjjzbf//9gzFjxqhxjR07Nthpp51UxttC0BE9ro88Xuedd55KCMfZoTmqbrXVVlMRTXfffXfebXAiwG984xvBpz/9aRVpNHLkSJVs7rrrrgsqyWmnnabGZ2fjtaO0mAceeEBFuPHxtX8D/r048zQnVeRjyufItttuG5x99tlRGx2lxeelDZ9bJ554olqfI7s4+zNHqPE25HkRNw47SkvDSf4++9nPqmglPo6cjdg+L7gPPk99yTPzoffN9bGPYzHn6nvvvaeyInN0Ix+Xz3/+8yp5oQvOsMzLuR235/X++9//5rR7/fXX1bhuu+22vPvVyvAxmjVrVvQ3R/ARkTpP5IczXPP9xIbPKT7XbDjT9jnnnGPMmzt3rup70aJFQb2T4P8GWugCAIBiYa0Ta1E4EpBNoKD5Ya0X/96ssSgkAWarwtovTtqoI604OnT69Okq/5Ed/cqJHFlzLWENMmtkbQ37F7/4RWWeZ82ohrfDWnquFaeTU9YrOGMAAA0Jq+Y50eQvfvELZQ4pJ4s0qH/4AcxmMo6qg7BTHCykpFIpZS5k822psG8Zm3ol7KPI/m71LuwwEHgAAA0L+5Kw8zGH/XOOGtC8cLQjRyly3i3gTtOh/Qj18eLIOvYV43Qa06dPV/5gnFGcBSD2uWEfNfZv1BFynDOLo7nYN5B92Xh9hn35GPbT4ija448/ng477DDlxMzpCvLl5qoXYNICAAAAGhxOz+EqtXLwwQergIO+vj6Vr4xNgvyCwMEIrLFhR3gd1MEO9K5kldLzhR3cjzvuOGUeYy0rJxiVDuv1TF0JPJwpkiNh5s2bp/JPSBsk4/PK58y3J510kprmYnnsfc4SJ0fLcDQERwfIkMlS4ZNEZ9zlvllqZunWlUgPAAAAAPVDspEyRbIQJD9cSZiFIJnwiG36LChxroG5c+cqNR+HjcocD6XAeVW4eB7bKVngYdUfqwZ1pWAAAAAA1C91peGJ8zJ3wcvYzqjrynAtF84bccMNN0RRGxzJwbb9e+65R+Uv0ZoatkGysxU7OnIeDvY6d+XD0HBeCE7axInxAAAAANBYNKzTMtcW4lIEsk4Qm8LYTikzQbKNkRNYPfbYY0rg4dA5tnOypzqb0Njbn+2anHGSs0/6EtHdeeedan2OBmEbJid94yRZ7Ljlg81r/NFw/SF2BmPbKZJmAQAAiIP1EfxSz8+xakYhdnd3K2flcuHnZzn17apO0CCJk2w4MRonHVu5cmU076abblIJumy+/OUvB9/73vfU9DXXXBNsuOGGQTqdNhKHcYK0++67z7s9TrLFn1NOOUUltuNEb5wk6w9/+IN3HZ34Cx8cA5wDOAdwDuAcKPUcWLBgQVAtVq5cGYwd01aR85MTocpncr3RsBoe9t/hMLtCpEmWn7RGhbVAHLqn6w5JCZeTWbHJShZg43T+vB3WznCuAZ2Cm8P62Eudi61xqJ8LDqFk05mGTW5ceG2ts06lZD1LwQAAAAacdHc3LTztFznPq0rS29tL7y1O0X/mTaQRw0vXIi39JE0Ttnxb9VevWp6GFHhYKOGaLJw9UsLZIvlgs4Mx11jScLIlrrvEsODCUVVcc8mG/X9YJadzDzC6bgjXCNlkk02M9lxn6bbbbvOOk4sF2kUFGRZ2koPr84QAAABQX9TCBWLY8IT6lEqa6r+2WUMKPDoUnCO6JDyPo6juv/9+leqa4WguLmDJoesMF6VkQYmL2Y0YMcLZvy4GKeEILRay7CrButgiAAAA0KikgjSlgvLWr3fqKiydQ8hZu6I1LDpT5Pz586M2XOGZq0J/97vfzVl/5MiRdOihh9IJJ5ygIre4WjVXvOakSrvssotqw+YprlDM1aBZU8TbYCfkY445RlWS9cGJlrhKL5u02CR2880305VXXklHHHFEVY4FAAAAUCvSFJT9qXfqSuB55plnlG8Mfxj2f+Hpn/3sZ1Ebzq/DPjnf+MY3nH1cdNFFKlydNTysleG081z7QxdM4785Oot9afbdd19lljrkkENUIkGfxoeZMmWKCpPnhIYc9XXWWWfRxRdfrAQoAAAAANQ3dZuHpxlh7RRrocZfcBZ8eAAAAMSSXtlNC046TQW8xL2QV+K59O4ra5fttLzmhu9Udawt6cMDAAAAgMqRCgL1KWf9eqeuTFoAAAAAANUAGh4AAACgxUmX6XjcCE7LEHgAAACAFidNAaWaXOCBSQsAAAAATQ80PAAAAECLA5MWAAAAAJqeFKK0AAAAAAAaH5i0AAAAgBYnHX7KWb/egcADAAAAtDipMqO0ylm3VkDgAQAAAFqcVJD5lLN+vYOwdAAAAAA0PdDwAAAAAC1OGj48AAAAAGh20pSgFCXKWr/egUkLAAAAAE0PBB4AAACgxUkH5X+KZeHChXTggQfSaqutRkOGDKHNN9+c5s2bR9UCPjwAAABAi5Mq06RV7LofffQRbbfddrTjjjvSvffeS2PGjKE33niDVlllFaoWEHgAAAAAUFPOO+88Gj9+PF177bXRvIkTJ1Z1mzBpAQAAAC1OKtTwlPMphjvvvJO22mor2m+//ZR2Z4sttqCrrrqKqgkEHgAAAKDFSQeJsj/M0qVLjU9PT49ze2+++SZdfvnltP7669N9991Hhx9+OB199NF0/fXXV20fIfAAAAAAoCKwmWrkyJHRZ8aMGc526XSaJk+eTOecc47S7nz/+9+nww47TAlB1QI+PAAAAECLk6qQ0/KCBQtoxIgR0fyuri5n+3HjxtEmm2xizNt4443ptttuo2oBgQcAAABocVKUVJ/S18/Awo4UeHxwhNYrr7xizHv11VdpwoQJVC0g8AAAAAAtTiD8cEpdvxiOO+442nbbbZVJa//996ennnqKrrzySvWpFvDhAQAAAEBNmTJlCs2aNYtuueUWmjRpEp111ll08cUX0/Tp06u2TWh4AAAAgBYnVePEg8y0adPUp1ZA4AEAAABanFSQVJ/S16e6ByYtAAAAADQ90PAAAAAALU6aEpQuQweSpvpX8UDgAQAAAFqc1AD48NQamLQAAAAA0PRAwwMAAAC0OKmynZZh0gIAAABAQ/jwJMpav96BSQsAAAAATQ9MWgAAAECLky6zlhaitAAAAABQ96TgwwMAAACAVtDwpJtcwwMfHgAAAAA0PfDhAQAAAFqcVJBQn3LWr3cg8AAAAAAtTqpMp+UUTFoAAAAAAAMPNDwAAABAi5MOkupT+vr177QMgQcAAABocVIwadWWRx55hPbYYw9ac801KZFI0B133JHT5v/9v/9He+65J40cOZKGDx9On//852n+/PnR8p6eHjrqqKNo9OjRNHToUNX2nXfeqcj4Fi5cSAceeCCtttpqNGTIENp8881p3rx5FekbAAAAAC0Slr58+XLabLPN6NJLL3Uuf+ONN2j77benjTbaiObMmUP//Oc/6bTTTqNBgwZFbY499liaNWsWzZw5k+bOnUvLli2jadOmUSqVKmtsH330EW233XbU0dFB9957L7388st04YUX0iqrrFJWvwAAAMBAkxaRWqV8eP16p65MWrvvvrv6+Dj11FPpK1/5Cp1//vnRvE996lPR9JIlS+iaa66hG264gXbZZRc178Ybb6Tx48fTAw88QLvuumukqTn++ONp9uzZlEwmlRB1ySWX0MSJE73bPu+881Q/1157bTQvrj0AAADQOokHk1Tv1P8IQ9LpNP31r3+lDTbYQAkuY8aMoa233towe7F5qa+vj6ZOnRrNY/PYpEmT6LHHHlN/r1ixgnbccUcaNmyYMqGxFoind9ttN+rt7fVu/84776StttqK9ttvP7XtLbbYgq666qoq7zUAAAAAWkrgWbx4sTJPnXvuuUo4Ye3MPvvsQ/vuuy89/PDDqs17771HnZ2dNGrUKGPdNdZYQy1j2NTFWp2rr76aNt10U9p4442V1ob9gNhM5uPNN9+kyy+/nNZff32677776PDDD6ejjz6arr/+eu867E+0dOlS4wMAAADUay2tVBmfeqeuTFr5NDzMXnvtRccdd5yaZqdh1tz87ne/oy996UvedYMgUE7QWgv0+uuvK4dnSXd3t/IRevTRRw2z2hVXXEHTp09X22cNzznnnKPms4bnpZdeUkLQQQcd5NzujBkz6Oc//3kF9h4AAACoHmliP5zSsyWXs26taBiBh6Ou2tvbaZNNNjHms4aGzVLM2LFjlVmKHYylloe1Q9tuu62aZsFlyy23pJtuuilnG6uvvrrSED3//POGdogZN26cc9u33Xabd8ynnHKK8hXSsIaH/YAAAACA5qqWnqR6p2EEHhZEpkyZQq+88oox/9VXX6UJEyaoaRZkOIrq/vvvp/3331/NW7RoEb344ouRo/PkyZPp1ltvVX44I0aMcG5rvfXWy5nHEVpx23bR1dWlPgAAAAAYWOpKJGMfHdauaA3LW2+9paZ1np2TTjpJCSvsLMxmKQ5fv+uuu+iHP/yhWs65eQ499FA64YQT6O9//zs999xzKm8O++roqC02T7G2iE1jbL7ibbAP0DHHHBObr4fNaE888YQyafG2b775ZrryyivpiCOOqMmxAQAAAKqdeDBVxqfeqSsNzzPPPKMiqDTaHHTwwQfTddddp5yU2V+HfWPYYXjDDTdUJiUOK9dcdNFFyvTFGp6VK1fSzjvvrNZta2tTyzlhIEdnnXzyycrh+ZNPPqG11lpLtfNpfBjWLnF+HzZTnXnmmbTuuuvSxRdfrAQoAAAAoJFJcy6dMiqel7NurUgE7NELagL78LAWavwFZ1FycDZZIgAAAGCTXtlNC046TeWYi3shr8Rz6fynv0CDh5WuA1m5rJ9+NOXRqo61qTQ8AAAAAKg96TLNUo2QeBACDwAAANDipMuull7/Ak/9jxAAAAAAoEyg4QEAAABanBQl1Kec9esdCDwAAABAi5OGSQsAAAAAoPGBhgcAAABocVJlmqV4/XoHAg8AAADQ4qRbwKQFgQcAAABocVItUDy0/kcIAAAAAFAm0PAAAAAALU5ACUqX4cPD69c7EHgAAACAFicFkxYAAAAAQHWZMWMGJRIJOvbYY6u2DWh4AAAAgBYnHSTUp5z1S+Xpp5+mK6+8kj772c9SNYHTMgAAANDipMJq6eV8SmHZsmU0ffp0uuqqq2jUqFFUTSDwAAAAAKAiLF261Pj09PTEtj/iiCPoq1/9Ku2yyy5UbSDwAAAAAC1OOjRplfNhxo8fTyNHjow+7JvjY+bMmfTss8/Gtqkk8OEBAAAAWpw0JdWnnPWZBQsW0IgRI6L5XV1dzvbc7phjjqHZs2fToEGDqBZA4AEAAABARWBhRwo8PubNm0eLFy+mLbfcMpqXSqXokUceoUsvvVSZwtra2qiSQOABAAAAWpxUkFCfctYvhp133pleeOEFY953vvMd2mijjejkk0+uuLDDQOABAAAAWpx0jcPShw8fTpMmTTLmDR06lFZbbbWc+ZUCAg8AAADQ4gRlVkvn9esdCDwAAAAAGHDmzJlT1f4h8AAAAAAtTooS6lPO+vUOBB4AAACgxUkH5ZWH4PXrnfo3ugEAAAAAlAk0PAAAAECLky7TabmcdWsFBB4AAACgxUlTQn3KWb/eqX+RDAAAAACgTKDhAQAAAFqcVI0zLQ8EEHgAAACAFifdAj489T9CAAAAAIAygYYHAAAAaHHS7LQcNLfTMgQeAAAAoMUJyozS4vXrHQg8AAAAQIuTrnG19IEAPjwAAAAAaHqg4QEAAABanHQLRGlB4AEAAABanDRMWgAAAAAAjQ80PAAAAECLk26BWloQeAAAAIAWJw2TFgAAAABA4wMNDwAAANDipFtAwwOBBwAAAGhx0i0g8NRV4PwjjzxCe+yxB6255pqUSCTojjvuMJZ/+9vfVvPl5/Of/7zRpqenh4466igaPXo0DR06lPbcc0965513KjK+hQsX0oEHHkirrbYaDRkyhDbffHOaN29eRfoGAAAAQIsIPMuXL6fNNtuMLr30Um+b3XbbjRYtWhR97rnnHmP5scceS7NmzaKZM2fS3LlzadmyZTRt2jRKpVJlje2jjz6i7bbbjjo6Oujee++ll19+mS688EJaZZVVyuoXAAAAqBcNT7qMT71TVyat3XffXX3i6OrqorFjxzqXLVmyhK655hq64YYbaJdddlHzbrzxRho/fjw98MADtOuuu0aamuOPP55mz55NyWSStt9+e7rkkkto4sSJ3u2ed955qp9rr702mhfXHgAAAGgUgjJDy3n9eqeuNDyFMGfOHBozZgxtsMEGdNhhh9HixYujZWxe6uvro6lTp0bz2Dw2adIkeuyxx9TfK1asoB133JGGDRumTGisBeJp1hz19vZ6t3vnnXfSVlttRfvtt5/a/hZbbEFXXXVV7FjZvLZ06VLjAwAAANQb6RbQ8DSUwMPan5tuuokefPBBZU56+umnaaeddlKCBfPee+9RZ2cnjRo1ylhvjTXWUMsYNnWxVufqq6+mTTfdlDbeeGOltZk/f74Spny8+eabdPnll9P6669P9913Hx1++OF09NFH0/XXX+9dZ8aMGTRy5MjowxoiAAAAALS4SSsfX//616Np1tqwxmXChAn017/+lfbdd1/vekEQKAdnrQV6/fXXafjw4Uab7u5ueuONN+jRRx81zGpXXHEFTZ8+ndLptNreOeeco+azhuell15SQtBBBx3k3O4pp5yiTGca1vBA6AEAAFBvpFsgSquhBB6bcePGKYHntddeU3+zbw+bpdjBWGp52Oy17bbbqmkWXLbcckulKbJZffXVlYbo+eefN7RDelubbLKJ0Z61Q7fddlusvxF/AAAAgHomDYGnvvnggw9owYIFShhhWJDhKKr777+f9t9/fzWPI7lefPFFOv/889XfkydPpltvvVX54YwYMcLZ73rrrZczjyO0XnnlFWPeq6++qgQuAAAAANQ3deXDwyHkrF3RGpa33npLTbN/DS878cQT6fHHH6e3335b+dtwzh7Ot7PPPvuo9uwnc+ihh9IJJ5xAf//73+m5555TeXPYV0dHbbF5itfZa6+9lPmKt/Hwww/TMcccE5uv57jjjqMnnnhCmbTYJHbzzTfTlVdeSUcccUSNjg4AAABQHdIt4LRcVyatZ555RkVQabT/y8EHH6x8ZV544QXlJPzxxx8rrQ63ZW2N9Me56KKLqL29XWl4Vq5cSTvvvDNdd9111NbWppZzwkCOzjr55JOV388nn3xCa621lmrn0/gwU6ZMUfl92C/nzDPPpHXXXZcuvvhiJUABAAAAjUwQJNSnnPXrnUTAHr2gJrDTsorWuuAsSg4ehKMOAADAS3plNy046TSVYy7uhbwSz6Xt/nIktQ8t3ee0f3kP/WOvS6s61qbS8AAAAACg9qQpUVbiwXLWrRUQeAAAAIAWJ90CUVp15bQMAAAAAFANoOEBAAAAWpygBZyWIfAAAAAALU66BUxaEHgAAACAFidoAQ0PfHgAAAAA0PRAwwMAAAC0OEGZJi1oeAAAAABQ9wRKaCnjU+T2ZsyYoSoYcKUErm25995759SrrDQwaQEAAACgpnANS65FyTUqueB3f38/TZ06lZYvX161bcKkBQAAALQ4aUqof+WsXwx/+9vfjL+vvfZapemZN28effGLX6RqAIEHAAAAaHGCCkVpcW0uSVdXl/rkg2twMauuuipVC5i0AAAAAFARxo8fr4qR6g/76uSDa5gff/zxtP3229OkSZOoWkDDAwAAALQ46SBBiQokHlywYIFRLb0Q7c6RRx5J//rXv2ju3LlUTSDwAAAAAC1OEEZblbM+w8KOFHjycdRRR9Gdd95JjzzyCK299tpUTSDwAAAAAKCmsBmLhZ1Zs2bRnDlzaN111636NiHwAAAAAC1OUOPSEhySfvPNN9Nf/vIXlYvnvffeU/PZ72fw4MFUDeC0DAAAALQ4QSjwlPMphssvv1xFZu2www40bty46HPrrbdWbR+h4QEAAABanHSFnJaLMWnVGmh4AAAAAND0QMMDAAAAtDhBhaK06hkIPAAAAECLEyiBpxynZap7YNICAAAAQNMDDQ8AAADQ4gQ1DksfCCDwAAAAAC1OEH7KWb/egUkLAAAAAE0PNDwAAABAixPApAUAAACApidofpsWNDwAAABAqxOU57TM69c78OEBAAAAQNMDDQ8AAADQ4gTItAwAAACAZidoAadlmLQAAAAA0PTApAUAAAC0OkGiPMfjBtDwQOABAAAAWpygBXx4YNICAAAAQNMDDQ8AAADQ6gRIPAgAAACAJidAlBYAAAAAQOMDkxYAAAAAqBHqYZUDBB4AAACgxQlawKQFgQcAAABodYLmd1pGWDoAAAAAmp66EngeeeQR2mOPPWjNNdekRCJBd9xxh7ft97//fdXm4osvNub39PTQUUcdRaNHj6ahQ4fSnnvuSe+8805Fxrdw4UI68MADabXVVqMhQ4bQ5ptvTvPmzatI3wAAAMDAkajAp76pK4Fn+fLltNlmm9Gll14a244FoSeffFIJRjbHHnsszZo1i2bOnElz586lZcuW0bRp0yiVSpU1to8++oi222476ujooHvvvZdefvlluvDCC2mVVVYpq18AAACgbkxaQRmfOqeufHh233139cmnZTnyyCPpvvvuo69+9avGsiVLltA111xDN9xwA+2yyy5q3o033kjjx4+nBx54gHbdddeoj+OPP55mz55NyWSStt9+e7rkkkto4sSJ3u2ed955qp9rr702mhfXHgAAAAD1Q11pePKRTqfpW9/6Fp100kn0mc98Jmc5m5f6+vpo6tSp0TzWAk2aNIkee+wx9feKFStoxx13pGHDhikTGmuBeHq33Xaj3t5e77bvvPNO2mqrrWi//fajMWPG0BZbbEFXXXVV7HjZvLZ06VLjAwAAANQdQfNreBpK4GEtS3t7Ox199NHO5e+99x51dnbSqFGjjPlrrLGGWsawqYu1OldffTVtuummtPHGGyutzfz582nOnDnebb/55pt0+eWX0/rrr6+0S4cffrgax/XXX+9dZ8aMGTRy5MjowxoiAAAAoG6rpQdlfOqchhF4WHvDZqfrrrtOOSsXQxAE0Trcz+uvv07Dhw9Xmh3+rLrqqtTd3U1vvPEGPfroo9F8/tx0002Rdmny5Ml0zjnnKO0OO00fdthhSgjyccoppygzm/4sWLCgzKMAAAAAgAHz4WFhgAUGjlyqFiyILF68mNZZZ51oHjsin3DCCSpS6+2336axY8cqsxQ7GEstD6+37bbbRmPdcsstI0FGsvrqqysN0fPPP29oh5hx48bRJptsYrRn7dBtt93mHXNXV5f6AAAAAPVMEGQ+5azflAIPCzdsGvrrX/9K//jHP5RAwVoUfrizULDTTjvR9OnTVcRVpWDfHe2IrGEnZJ7/ne98R/3NggxHUd1///20//77q3mLFi2iF198kc4//3z1N2tpbr31VuWHM2LECOe21ltvvZx5HKH1yiuvGPNeffVVmjBhQsX2EQAAABgQguZPPFiUwLNy5UolOLBpiU00G220Ee28885KeBg0aBB9+OGHyteFnXk5ZJu1Ktx+m222Kah/DiFnc5PmrbfeUtoWNjmxZofz30hYuGGtzoYbbqj+Zj+ZQw89VGl9uC2vd+KJJypfHS0ssSB2wQUX0F577UVnnnkmrb322sp/5/bbb1fO0Py3i+OOO07tD5u0WJh66qmn6Morr1QfAAAAADSRwMMOu5zM76c//akSHLS5x4a1PQ899JByBuaIKM6r893vfjdv/88884xqr+HQcebggw9WvjuFcNFFFynHZhZKWEBjgYzXbWtrU8vZ7MbRWSeffDLtu+++9Mknn9Baa62l2vk0PsyUKVNUfh/2y2FBad1111WmND4OAAAAQEMTlOl43ABOy4mApZMC+f3vf6+EDy08FAJrfFiDssMOO1Crw2HpKlrrgrMoOXjQQA8HAABAHZNe2U0LTjpNWVTiXsgr8ly65MyynktqrMf8rKpjramG55BDDil6A5/61KfUBwAAAAB1StD8PjwNE5YOAAAAADBgAg+rrzjUGwAAAAANStD8iQdLzsPDWYk5JPzdd99V0VJcvoHDwvnDJRg4MornAwAAAKDOCWDS8nLEEUeoaCgun/CjH/1IJea76667VMkFFnjq1WkJAAAAAPXBZZddpqKeObUNK0w4yXDdaXg4szEnH9xjjz2M+VyzisPLn3322UqMDwAAAABNqOG59dZb6dhjj1VCDyf3veKKK2j33Xenl19+2aiqMOA+PJxRmUs72HAiwGnTptHPfvazcscGAAAAgCatlv6rX/1KJQvmPH1cqolz23GR7bgalQMi8HAG49/85jeVHQ0AAAAAmp7e3l5VzHvq1KnGfP77scceqy+B5+tf/7qqlcXanJdeeqmyowIA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V0DpjsxHVV4PskJQsicRfpJGf/r+qTMzq347xEePrV3cl0P/xsjHsZYCT1DGp86pK4Fn+fLltNlmm9Gll17qXb7ddtvRueee6+3j2GOPpVmzZtHMmTNp7ty5tGzZMpo2bRqlUuWdOR999JHadkdHB91777308ssv04UXXkirrLJKWf0CAAAAoMVMWrvvvrv6+PjWt76lvt9++23n8iVLltA111xDN9xwA+2yyy5q3o033kjjx4+nBx54QGmHtKbm+OOPp9mzZ1MymaTtt9+eLrnkEpo4caJ32+edd57q59prr43mxbWPRWpeYqKqXOYq4y0pXWAdrDgTjWXyMrTiUXSE7NfTR3bQxhhylBt2pmXPqi61vuvF1aX5qavImCbJrlwUCDdz/ADiwirGZFVUW8/FUm0Tl89ElSi/jWGel+2ihKXCaVkmG2QNtS8SSikz3FFV1Jcww9xl+LhlopJ95Dg794v6WHq/RJFTV6RXjjktTZTur6HWJIBJq6Fg81JfXx9NnTo1msfmsUmTJtFjjz2m/l6xYgXtuOOONGzYMGVCYy0QT++2227U29vr7fvOO++krbbaivbbbz8aM2YMbbHFFnTVVVfFjofNa0uXLjU+Cm1a0upLaRJyZGRWalaH2tbMbVOAycpQFwuTV7RBofK1+7DVzlrdbPsIeU1dmW3pTMtRTg1tgrKOQdQutDzY929pKXK1KRqfyr2oPmqQGTXOpFIvILa+fpC23Vr8Lj4TVSFtZNvw3mMIBHp5ZHY322buOdko0eg+yUKMNDGFEVL6XmeYl9gEpt9H9bp9GTNVxlSVvf8afbDZqyutPsrspQpEmxnotYkqMx5hStP3dV22QpvvwjHVjHQFPnVOXZm0yuW9996jzs5OGjVqlDF/jTXWUMsYNnWxVufqq6+mTTfdlDbeeGOltZk/fz7NmTPH2/ebb75Jl19+Oa2//vp033330eGHH05HH300XX/99d51ZsyYQSNHjow+rCECAAAA6o1EGJZezqea/PWvf6Wtt96aBg8erHx0991338Y2aVULpXoM1ZSsBXr99ddp+PDhRpvu7m5644036NFHHzXMaldccQVNnz5dZbxkDc8555yj5rOG56WXXlJC0EEHHeTc7imnnKJMZxrW8CihR7+RRAN0m5i8JpxCIqxKidKS/bgipVxvaowr746tKja0UY62BdTB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oSeffNJo09PTQ0cddRSNHj1atdtzzz3pnXfeqciPtXDhQjrwwANptdVWoyFDhtDmm29O8+bNo1rS19dHJ598Mm266aZq/9Zcc0066KCD6N13322p46C5/fbbadddd1X7mUgk6Pnnn89p0yrHolQuu+wyWnfddVXisy233JIeffRRajQeeeQR2mOPPdT1wOfBHXfcYSznhPZ8/+DlgwcPph122IFeeumlimVwP+KII2jcuHHqGG688cZ0zz3llwkohRkzZtCUKVNo+PDhNGbMGNp7773plVdeabljcfnll9NnP/vZKLnqNttsQ/fee29LHYN6BAJPEWywwQZ06aWX0gsvvEBz586liRMn0tSpU+l///tf1ObYY4+lWbNm0cyZM1WbZcuW0bRp0yiVSpX1Q3Fq8e222446OjrUhfPyyy/ThRdeWNV04y5WrFhBzz77LJ122mnqmx/4r776qnqIS5r9OGiWL1+uxnPuued627TKsSiFW2+9VR2fU089lZ577jn6whe+QLvvvrsqv9JI8Hmw2WabqfuDi/PPP59+9atfqeVPP/20qjn05S9/mT755JOytsvlALift99+m/785z8r4eKqq66itdZaiwaChx9+WD1sn3jiCbr//vupv79f3SP5+LTSsVh77bXVPeGZZ55Rn5122on22muvSKhphWNQl3AtLVAaS5YsUfVtH3jgAfX3xx9/HHR0dAQzZ86M2ixcuDBIJpPB3/72t2jeO++8E+y///7BKqusEqy66qrBnnvuGbz11lux2zr55JOD7bffvi5/qqeeekodh//85z8texx43HwMnnvuOWN+Kx6LYvjc5z4XHH744ca8jTbaKPjxj38cNCp8HsyaNSv6O51OB2PHjg3OPffcaF53d3cwcuTI4He/+51xrhx22GHB6quvHgwfPjzYcccdg+effz52W5dffnnwqU99Kujt7Q3qkcWLF6vj8fDDDwetfixGjRoVXH311S19DAYaaHjKkKSvvPJKVReL3+wYNiWwyYffaDSsspw0aRI99thjkYZkxx13pGHDhik1OL/x8/Ruu+0WW7ztzjvvpK222or2228/pSreYostlOReLwXuWI2vNQutehxc4Fj44d+Zj488Txj+W58nzcBbb71F7733nrGfnHzzS1/6UrSfLCd99atfVe3Y/MDHZfLkybTzzjvThx9+GHs9sLmEtSprrLGGusbOOeecsrWHlbw3MKuuumrLHgvePmt3WcvF42vFY1A3DLTE1WjcddddwdChQ4NEIhGsueaaSruhuemmm4LOzs6cdb785S8H3/ve99T0NddcE2y44YZKytf09PQEgwcPDu677z7vdru6utTnlFNOCZ599ln1JjBo0KDgD3/4QzCQrFy5Mthyyy2D6dOnt/Rx8Gl4WvFYFApruviY/eMf/zDm/+IXvwg22GCDoFk0PLx/PI/3V8Jv71OnTlXTf//734MRI0aoN33Jpz/96eCKK67wbovPGz4HDjnkkOCZZ54JbrnlFqUh/PnPfx4MNHw+77HHHoYWspWOxb/+9S/1rGhra1Pam7/+9a8tdwzqDWh4PNx0001K46A/2pGStRLsmMqSOGsj9t9/f1q8eHE+oVJpQBiW1F9//XXl1Kf75ref7u5ueuONN9R25HZ5HEw6nVYSPkvrrNX4/ve/T4cddphyjhuI48CwFueAAw5QY2PH03w08nHIdyyKpdGPRSXRx8F1bJqJuP3kc4B9u9j5XP7WrA3gc4B9muR8/s31OcCaTtY2s8M3X4/sD1UP58CRRx5J//rXv+iWW25pyWOx4YYbqmcF+zP94Ac/oIMPPlj52bXSMag32gd6APUKO+FuvfXW0d/a6YujbNZbbz31+fznP0/rr78+XXPNNXTKKacoxzNW07MzKUdxaVgg2nbbbaMTkk9E/dCSrL766tTZ2WlE+rBakmGP+0022cRoz973t912Gw3EcWBhh4U9vgAffPBBFYmgacbjEHcs4mjWY1EJOGqtra1Nqe0lfGz0PjYDfA4wvJ/8m7n2k88BXjZnzpyc9dlUzB95DmgTEa/DTut8HOU5wNvi847PnYGAoxLZvMLmanbgbcVjwdvj5wTDZnh2Tr7kkktUlGurHIN6AwKPB37b5k8+WCrnsGOGH1p8snF0AgsDzKJFi+jFF19UXvkMv5FzZApL4VJIkOiLRMLROHZ4J0dHTZgwgWp9HLSw89prr9FDDz2k3kIkzXgcijknWuFYVAK++fLx4WOzzz77RPP5b45oaRY45J4f9LxfrIlj+OHDEU3nnXdedA7wQ6m9vV1FfxZzDtx8883qAZlMJqNzgB98A/Fw4/shCzsclcgPa973Vj0WvmdFKx+DAWegbWqNwrJly5SvxOOPPx68/fbbwbx584JDDz1U2UtffPHFqB1HnKy99toqcov9Knbaaadgs802C/r7+9Xy5cuXB+uvv36www47BI888kjw5ptvBnPmzAmOPvroYMGCBd7ts69Qe3u78m947bXXlG/IkCFDghtvvDGoJX19fSqCiPeRIwYWLVoUfdjvpFWOg+aDDz5Qfjtsn+fLiaOx+G8+Hq12LEqBjxdHsbEf08svvxwce+yxyu+Br7FG4pNPPlG/O3/4PPjVr36lpnXkIkfksB/H7bffHrzwwgvBN77xjWDcuHHB0qVLI38X9nXh84Kj99gnjH09Tj311ODpp5/2bnf+/PnBsGHDgiOPPDJ45ZVXgrvvvjsYM2ZMcPbZZwcDwQ9+8AO1n3z+ynvDihUrojatcCz4WcHXMo+dfXl+8pOfqMjM2bNnt8wxqEcg8BThnLvPPvsoR2V2QuWTkx/80mlZt+OTjR3F2Ol02rRp6iSU8A3goIMOCkaPHq0EJg4jZIc1DnPP5zA9adIktQ6H7l555ZXBQDnnuj4PPfRQyxwHzbXXXus8FqeffnrLHYtS+e1vfxtMmDBBXVeTJ0+OQpgbCT73XefBwQcfHD3A+JzgcGT+rb74xS+qB52EH3ZHHXWUusewEDh+/HgVDGCfKzaPPfZYsPXWW0fnDQvAWpiuNb57A18nmlY4Fuw0rM9pDivfeeedI2GnVY5BPZLg/wZaywQAAAAAUE0QpQUAAACApgcCDwAAAACaHgg8AAAAAGh6IPAAAAAAoOmBwAMAAACApgcCDwAAAACaHgg8AAAAAGh6IPAAAAAAoOmBwAMAAACApgcCDwCg5px55pmq0jsXOawU11xzjapgv3z58or1CQBoHiDwAABqyrvvvqsqxbPQoys6V4KDDz6Yhg4dGlWhBwAACQQeAEBNueSSS2iVVVahfffdt6L9tre30/e//33V/4oVKyraNwCg8YHAAwAomkWLFtGwYcPogAMOMObffffd1NHRQaeeeqpzvd7eXmV6+uY3v+nU7kydOpW23357mj17tvoeMmQITZw4kW699Va1nL+32morNZ9NYg899JCx/vTp02np0qU0c+ZM/KoAAANUSwcAlASbpM444wx6+umnacstt6Q5c+bQ7rvvTocddhj9+te/dq7z6KOP0he/+EW65557VFub1VdfnQYPHkxjx46l448/XmmCTj75ZPr3v/9NP/zhD+n555+no446itra2uiYY46hvr4+WrhwodEHC0Ibb7wx3XbbbfhlAQAR7dlJAAAonBNPPJGuuOIKJZDMmDGD9txzT/rGN76hTEo+Hn/8cfU9efLknGX/+c9/6P3336cpU6bQ3LlzqbOzU83/4IMP6MADD6RXXnmFHnzwQUokEmo+C0E//vGP6aOPPqJRo0ZF/XDfDzzwAH5KAIABTFoAgJJgs9LZZ59Nf//732nHHXdUGpurrroqEkh8Dsu8fPTo0TnL5s2bp77POuusSNhh2ETFnHvuuUbfy5YtU+az4cOHG/2MGTOGFi9eTP39/fhlAQAREHgAACWzwQYbqG8WRK677jplaopj5cqVSkhxtXv22Wepq6uLdtpppxxBaM0116TPfvazxvznnnuOJk2apJyVJYMGDaIgCKi7uxu/LAAgAgIPAKAk2J9m2rRptN122ylty+9///u867Bmhx2XXblyWLDZbLPNlEAkeeaZZ5Sjsqs9+w7ZfPjhh0pwYqdqAADQQOABABQN+9PsuuuutM0226hIqb322ks5MC9ZsiR2vY022kh9v/HGG04Njy3YsJbmpZdeypnPUWLvvfeeU+B58803leMyAABIIPAAAIri7bffpl122YU23HBDFQnFGhn2r2Hn4XPOOSd23R122EF9P/HEE8b8d955R/nd2ILNP//5T+WLY8/X/j72fM7c/NRTTymfIgAAkEDgAQAUDGtWWNhhx2DOucMh5Fpzc8ghh6gILRaIfIwfP56+8IUv0F/+8peCBJi4+SxobbrppsZ8Do1nLRPn4wEAAAny8AAAagprhb7+9a+rMHSufVVJvvWtbymT1j/+8Y+K9gsAaHwg8AAAagpHUG277bbK/+bSSy+tWL/sF8QJBzlXD2dpBgAACUxaAICawiHsnK+HQ80rWS19/vz5SoCCsAMAcAENDwAAAACaHmh4AAAAAND0QOABAAAAQNMDgQcAAAAATQ8EHgAAAAA0PRB4AAAAAND0QOABAAAAQNMDgQcAAAAATQ8EHgAAAAA0PRB4AAAAAND0QOABAAAAADU7/x/f52quB4d+vgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": { + "engine": 0 + }, + "output_type": "display_data" + } + ], + "source": [ + "%%px\n", + "import mpi4py.MPI as MPI\n", + "import os\n", + "\n", + "from openpmd_viewer import OpenPMDTimeSeries\n", + "\n", + "# Use the opmd_2d_dir variable that was set in the previous cell\n", + "ts = OpenPMDTimeSeries(opmd_2d_dir)\n", + "\n", + "comm = MPI.COMM_WORLD\n", + "rank = comm.Get_rank()\n", + "size = comm.Get_size()\n", + "host = os.uname().nodename\n", + "\n", + "print(f\"Rank {rank}/{size} running on host: {host}, PID: {os.getpid()}\")\n", + "Ex, info_Ex = ts.get_field( iteration=1800, field='E', coord='x', plot=True ) " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "e0a85894-0ef6-487e-8c03-6485fd9d44d6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:0] ..... use MPI reader (size=2)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[output:0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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VFVIyzRr1sxdPn36tDVu3NgmT56c5DnUvyitNEJt5syZrpmtcuXKqS6rpjxNAAAg58vQilD16tVd0NEIrRCFHnVODoUcBZw8efJELbNz505bs2ZNeJlGjRrZt99+6zo216xZM2pSc1W8VGVSJejdd9+1Tz75xK0fAABAuoOQhrqvXLnSTaEO0rqs/jtq2tLIreHDh7vRZAo3d911lxUsWNC6du3qlleQuffee61v37728ccf21dffWV33HGH6wvUtm1bt0y3bt3cOYY6d+5sn376qXsOhalHH300fL4hBazQeuiyRpnpsprUQjR0/o033rApU6a4ZjZVqjQdOXIkrZsNAAByoDQPn1dnZY3oitWjRw/717/+5aoww4YNsxdffNE1fzVt2tSeffbZqA7K6uvTr18/F1AUStq0aWPPPfdcVMdkBRYNwdeQep2DqFKlSm65sWPHumFwW7ZsSbbCoxFqoQ7VKfVLUsdrBbR4MHweyFkYPg/4YX+cw+fP6jxCPiAIATkLQQjww/5zcR4hAACA7IQgBAAAvEUQAgAA3iIIAQAAbxGEAACAtwhCAADAWwQhAADgLYIQAADwFkEIAAB4iyAEAAC8RRACAADeIggBAABvEYQAAIC3CEIAAMBbBCEAAOAtghAAAPAWQQgAAHiLIAQAALxFEAIAAN4iCAEAAG8RhAAAgLcIQgAAwFsEIQAA4C2CEAAA8BZBCAAAeIsgBAAAvEUQAgAA3iIIAQAAbxGEAACAtwhCAADAWwQhAADgLYIQAADwFkEIAAB4K8OD0MmTJ+0vf/mLVa9e3QoUKGA1atSwJ5980k6fPh1eJggCGzp0qFWsWNEt07p1a1u7dm2anmfnzp3WtWtXq127tuXKlct69+6dZJmXX37ZWrRoYSVKlHBT27Zt7fPPP8+Q7QQAANlfhgehUaNG2QsvvGATJ060b775xkaPHm1jxoyxf/zjH+FlNG/cuHFumeXLl1v58uWtXbt2duDAgbif59ixY1amTBkbNGiQNWjQINllFixYYLfffrvNnz/fli5dalWrVrX27dvb9u3bM2RbAQBA9pbhQUiBo3PnztahQwdLTEy0m266yYWPL774IlwNGj9+vAswN9xwg9WtW9dee+01O3z4sE2ZMiX8OPv27bP777/fypYta0WLFrWrrrrKvv766/DteuwJEyZY9+7drVixYsmuy+TJk+2hhx6yiy++2C644AJXIVJl6uOPP87ozQYAANlQhgeh5s2bu6CxYcMGd13hZfHixfb73//eXd+8ebPt2rXLhaOQfPnyWatWrWzJkiXhsKQgpeVmz55tK1assEaNGlmbNm3sl19+Sfe6KWydOHHCSpYsmWqlaf/+/VETAADImXJn9AP279/fVXNUgTnvvPPs1KlT9vTTT7smKlG4kXLlykXdT9e3bt3qLqspa/Xq1bZ7924XkmTs2LE2Y8YMe/vtt12lKD0GDBhglSpVcn2FUjJixAgbNmxYuh4fAAB4HoTefPNNe+ONN1wz10UXXWQrV650HZnVMbpHjx7h5RISEqLupypQaJ4qQAcPHrRSpUpFLXPkyBHbtGlTutZL/ZKmTp3q+g3lz58/xeUGDhxoffr0CV9XRahKlSrpek4AAOBZEOrXr5+rvNx2223uer169VylR5UWBSF1jA5VhipUqBC+n6o/oSqR+vHoNoWWWMWLF0/zOqmaNHz4cJs3b57Vr18/1WVVgQpVoQAAQM6W4UFI/XA0nD2SmshCw+c1rF5haO7cudawYUM37/jx47Zw4UI34kzUH0hBKXfu3K5T9NnQiLWnnnrK5syZY02aNDmrxwIAADlLhgehTp06uT5BGqquprGvvvrKDZW/55573O1q/lJTmSo0tWrVcpMuFyxY0J0XSNSH5/LLL7cuXbq4cKRzBe3YscN1nNa8UKBRs5uoGW3Pnj3uet68ee3CCy8MN4cNHjzYNdMpUIX6JxUuXNhNAADAbwmBOudkIJ0LSOFj+vTprrlLfYPUUfqJJ55wIUX0lOqQ/OKLL9revXutadOm9uyzz7qh9JGPoyH277zzjgs5qiK1bNnSNbGF+uzE9jOSatWq2ZYtW9xlhZ9QB+xIQ4YMcSd0jIf6CGl4vjqAaxg/gOwtccCsFG/bMrLDb7ouADJPvL/fGR6EchqCEJCzEIQAP+yPMwjxt8YAAIC3CEIAAMBbBCEAAOAtghAAAPAWQQgAAHiLIAQAALxFEAIAAN4iCAEAAG8RhAAAgLcIQgAAwFsEIQAA4C2CEAAA8BZBCAAAeIsgBAAAvEUQAgAA3iIIAQAAbxGEAACAtwhCAADAWwQhAADgLYIQAADwFkEIAAB4iyAEAAC8RRACAADeIggBAABvEYQAAIC3CEIAAMBbBCEAAOAtghAAAPAWQQgAAHiLIAQAALxFEAIAAN4iCAEAAG8RhAAAgLcyJQht377d7rjjDitVqpQVLFjQLr74YluxYkX49iAIbOjQoVaxYkUrUKCAtW7d2tauXZum59i5c6d17drVateubbly5bLevXsnWebll1+2Fi1aWIkSJdzUtm1b+/zzzzNkGwEAQPaX4UFo7969dsUVV1iePHnsgw8+sHXr1tnf/vY3K168eHiZ0aNH27hx42zixIm2fPlyK1++vLVr184OHDgQ9/McO3bMypQpY4MGDbIGDRoku8yCBQvs9ttvt/nz59vSpUutatWq1r59exfUAAAAEgKVZzLQgAED7L///a99+umnyd6up1MlSBWc/v37h0NNuXLlbNSoUfbAAw+4efv27bN+/frZjBkz7OjRo9akSRN75plnkg09qiip6jR+/PhU1+3UqVOuMqQA1r1797i2Z//+/VasWDG3PkWLFo3rPgCyrsQBs1K8bcvIDr/pugDIPPH+fmd4RWjmzJkutNx8881WtmxZa9iwoWuiCtm8ebPt2rXLVWZC8uXLZ61atbIlS5aEw1KHDh3ccrNnz3bNao0aNbI2bdrYL7/8ku51O3z4sJ04ccJKlix5llsJAAByggwPQt999509//zzVqtWLZszZ449+OCD9sgjj9i///1vd7vCjagCFEnXQ7epKWv16tX21ltvuVClxxo7dqxrXnv77bfPqlpVqVIl11coJapOKUVGTgAAIGfKndEPePr0aRdehg8f7q6rIqSO0ApHkc1RCQkJUfdTFSg0TxWggwcPus7WkY4cOWKbNm1K13qpX9LUqVNdv6H8+fOnuNyIESNs2LBh6XoOAADgeRCqUKGCXXjhhVHz6tSpY++88467rI7RouqPlg3ZvXt3uEqkMKXbFFpiRXa6jpeqSQpm8+bNs/r166e67MCBA61Pnz7h66oIValSJc3PCQAAPAxCGjG2fv36qHkbNmywatWqucvVq1d3YWju3LmuWiTHjx+3hQsXus7Sov5ACkq5c+e2xMTEs1qfMWPG2FNPPeWa6VSpOhP1V9IEAAByvgwPQo899pg1a9bMVWBuueUWd96el156yU2i5i+NGNPt6vujSZd1viGdF0jUh+fyyy+3Ll26uHCkcwXt2LHDdZzWvFCgWblypftfzWh79uxx1/PmzRuuSKk5bPDgwTZlyhQXqEJ9kAoXLuwmAADgtwwfPi/vv/++a2L69ttvXQVITU333Xdf+HY9pfrhvPjii+68Q02bNrVnn33W6tatG15G5xTSOYLUpKaQoypSy5YtXR+eUFNVbD8jUeVpy5Yt7rLCz9atW5MsM2TIEHdCx3gwfB7IWRg+D/hhf5zD5zMlCOUkBCEgZyEIAX7Yf67OIwQAAJBdEIQAAIC3CEIAAMBbBCEAAOAtghAAAPAWQQgAAHiLIAQAALxFEAIAAN4iCAEAAG8RhAAAgLcIQgAAwFsEIQAA4C2CEAAA8BZBCAAAeIsgBAAAvEUQAgAA3iIIAQAAbxGEAACAtwhCAADAWwQhAADgLYIQAADwFkEIAAB4iyAEAAC8RRACAADeIggBAABvEYQAAIC3CEIAAMBbBCEAAOAtghAAAPAWQQgAAHiLIAQAALxFEAIAAN4iCAEAAG9lehAaMWKEJSQkWO/evcPzgiCwoUOHWsWKFa1AgQLWunVrW7t2bZoed+fOnda1a1erXbu25cqVK+rxQ15++WVr0aKFlShRwk1t27a1zz//PEO2CwAAZH+ZGoSWL19uL730ktWvXz9q/ujRo23cuHE2ceJEt0z58uWtXbt2duDAgbgf+9ixY1amTBkbNGiQNWjQINllFixYYLfffrvNnz/fli5dalWrVrX27dvb9u3bz3rbAABA9pdpQejgwYPWrVs3V5VRNSayGjR+/HgXYG644QarW7euvfbaa3b48GGbMmVKeLl9+/bZ/fffb2XLlrWiRYvaVVddZV9//XX49sTERJswYYJ1797dihUrluw6TJ482R566CG7+OKL7YILLnDrcvr0afv4448za7MBAEA2kmlB6OGHH7YOHTq45qhImzdvtl27drnKTEi+fPmsVatWtmTJknBY0n213OzZs23FihXWqFEja9Omjf3yyy/pXieFrRMnTljJkiXPYssAAEBOkTszHnTatGn25ZdfumavWAo3Uq5cuaj5ur5161Z3WU1Zq1evtt27d7uQJGPHjrUZM2bY22+/7SpF6TFgwACrVKlSknAW2+SmKWT//v3pei4AAOBhEPr+++/t0UcftY8++sjy58+f4nLqQB1JVaDQPFWA1LRWqlSpqGWOHDlimzZtStd6qV/S1KlTXb+h1NZLnbuHDRuWrucAAACeByGFGFVyGjduHJ536tQpW7RokescvX79+nBl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5pvWu3dvF4auuOIKe/HFF+3aa6+1devWWdWqVS0nS0/4Sc/9M5NPH0YAOTtAZIXv1HglehSKEoIgCCwHa9q0qTVq1Mief/758Lw6depYly5dbMSIEWe8//79+61YsWK2b98+K1q0qGU12emDlZ3k9A++b9LzOWEfyFn4rswcW7Lwd2W8v985OggdP37cChYsaG+99ZZdf/314fmPPvqorVy50hYuXJhtghAf4qwpK38J5FTn6rPAe5018d2YPWw5B9+V8f5+5+imsZ9++slOnTpl5cqVi5qv67t27Ur2PseOHXNTiF7A0AsqdYfMydR1RvZS9bG3zvUq4DfCew1kr8/P6WOH3f9nqvfk6CAUkpCQEHVdL0rsvBA1lw0bNizJ/CpVqmTa+gEAgMxx4MABVxnyMgiVLl3azjvvvCTVn927dyepEoUMHDjQ+vTpE75++vRp++WXX6xUqVIphqecQBUvhb3vv/8+S/aFyky+bruv2+3ztvu63T5vu6/bHSp6KARVrFjRUpOjg1DevHmtcePGNnfu3Kg+QrreuXPnZO+TL18+N0UqXry4+UIfFN8+LL5vu6/b7fO2+7rdPm+7r9tdLJVKkBdBSFTdufPOO61JkyZ2+eWX20svvWTbtm2zBx988FyvGgAAOMdyfBC69dZb7eeff7Ynn3zSnVCxbt26Nnv2bKtWrdq5XjUAAHCO5fggJA899JCbkDI1Bw4ZMiRJs6APfN12X7fb5233dbt93nZftzstcvR5hAAAAFLDX58HAADeIggBAABvEYQAAIC3CEIAAMBbBKFs6t1337Wrr77anT1bZ7zWH5GN1bp1a3db5HTbbbdFLbN37153niWddEqTLv/6669nvX5Dhw61Cy64wAoVKmQlSpSwtm3b2meffWa/1bbr78X16tXLLaN1uO666+yHH37I9tse66677kryHl922WVpfi3S4/nnn7f69euHT9Sm83R98MEHltU999xzVr16dcufP7874eqnn35qWZ32qdj3uXz58uHbNeZFy+gMugUKFHCf/bVr12bIZ03nYNNJZbXvXHzxxfb6669bZlq0aJF16tTJbYu2c8aMGVG3x7Ot2XWfP9O283nPHAShbOrQoUN2xRVX2MiRI1Nd7r777nPnTwpNL774YtTtXbt2dUHiww8/dJMuKxCcrfPPP98mTpxoq1evtsWLF1ti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/ODyyy8PKlWqFOzfvz/u1+LQoUNBrVq1gtatWweLFi0Kvvvuu2DBggXBI488Enz//fcpPr+2U8vruVetWhX8+c9/diNzPvrooyCr0r6iEUWvvvqqGznYu3dvNyJQ71VWpvdZ74neG4101H6qkV+h9dYoKo2cevfdd4PVq1cHt99+e1ChQoXwfqDRVs2bN3fvu0ZO6T3773//GwwaNMh9R6Rk+PDh7v3Uvv/NN98Ef/vb34LcuXMHL7/8cqZtq/ZrfZ416fM9btw4d3nr1q1xbWt23udT23Y+75mHIJRNTZo0yX1QYicNs5Vt27YFLVu2dMNC8+bNG/zud79zH3KFiEi63q1bN/elqkmX9+7dG7XMhg0bguuvv94NMy1QoIALVPoB0Zdrco4cOeKWr1ixontufUlpaOrnn3/+m2x7aB169uzptl/rrB8OvSbZfdsjHT58OGjfvr0La/pxr1q1qhteG7ud8bwWCpHdu3cPSpcu7UJbjRo13FBrDf1PyT333BNUq1bNbafWoU2bNlk6BIU8++yz4fVu1KhRsHDhwiCru/XWW92+pPdZ+9YNN9zgTu0Qov1R+7+Gluv902dfISGSgkKvXr3c/fU4VapUcft87L4QSUGpZs2aQf78+d0wcQXtyGHpmUGBPrnPt/bteLc1u+7zqW07n/fMk6B/Mqq6BAAAkJ0wagwAAHiLIAQAALxFEAIAAN4iCAEAAG8RhAAAgLcIQgAAwFsEIQAA4C2CEAAA8BZBCAAAeIsgBAAAvEUQApBj3XXXXcn+tfWhQ4daQkKCuzxt2jR3eeLEiVHLDBkyxM477zz3V8wB5FwEIQBeu+222+zBBx+0vn372hdffOHmffLJJ/bUU0/Zn//8Z2vXrt25XkUAmYggBMB748ePt4suushuueUW++abb6xr167WokULVzkCkLMRhAB4L1++fPZ///d/9vPPP1ujRo0sCAKbOnWqaxoDkLMRhADAzGrWrOmqQEePHrVu3bpZhQoVeF0ADxCEAORY+fPnt2PHjiWZ/9NPPyWZ98orr9isWbPs0ksvdR2nP/vss99oLQGcSwQhADmWRozt3r3bfvzxx/C848eP25w5c6KWW716tT3yyCPWvXt3+/TTT61+/fp266232t69e8/BWgP4LSUEagwHgBxo8+bNVrt2bbviiiusX79+rtnr73//u23bts3dpq+/Q4cOWZMmTSxXrlz2+eefW6FChey7775zfYVat25tM2bMONebASATURECkGNVr17d3nvvPfv111/tpptucmHo5ptvdpWfEA2dVzB66623XAiSGjVquKYy3VcjygDkXFSEAACAt6gIAQAAbxGEAACAtwhCAADAWwQhAADgLYIQAADwFkEIAAB4iyAEAAC8RRACAADeIggBAABvEYQAAIC3CEIAAMBbBCEAAGC++n+XnG0M4hRF2QAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": { + "engine": 0 + }, + "output_type": "display_data" + } + ], + "source": [ + "%%px\n", + "import mpi4py.MPI as MPI\n", + "import os\n", + "\n", + "from openpmd_viewer import OpenPMDTimeSeries\n", + "\n", + "# Use the opmd_2d_dir variable that was set in the previous cell\n", + "ts = OpenPMDTimeSeries(opmd_2d_dir)\n", + "\n", + "ux = ts.get_particle( var_list=['ux'], iteration=600, species='electrons', plot=True )" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "85bc2a0e-6dfd-4fc1-ac97-44ffe2e1294f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:0] ..... use MPI reader (size=2)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[output:0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAHGCAYAAABuJ2HLAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAc2ZJREFUeJztnQmYFMXZx9/e5ZRTUG4Q5FQRuQyicigKKmowRolRMSAiUVTEC0QjGgQxeMsRjBERRBNFRCWA4UYw4RTigcqHcsitsoJybn/Pv3Z7prqne+7ZmZ75/3xadnqqq6uqq6fffq8yTNM0hRBCCCHEh+SluwGEEEIIIfFCQYYQQgghvoWCDCGEEEJ8CwUZQgghhPgWCjKEEEII8S0UZAghhBDiWyjIEEIIIcS3UJAhhBBCiG+hIEMIIYQQ30JBJsP55ptvxDAMmTx5ckrq//nnn2XEiBGyaNEiyUUysf9/+MMf1DV3bi1atIh4bEFBgTz++OPStWtXqVWrllSsWFHOPPNMGTNmjBw6dCik/Ndffy033nijNGjQQMqXLy+NGzeWIUOGyL59+5Ler4ceekguv/xyqVu3ruoP+unG9OnTpXPnzlKzZk0pW7as1KlTR6644gpZvny5ZBJTpkyRk08+WX766afAvoYNG9r69d1336n5tW7dujS1MnI7sB/XIx28//770qdPHzVHS5cuHbYdsczV//u//5Pf/OY3UrVqVXUPXHzxxbJmzRrXet944w1p3bq1lCtXTs21wYMHy4EDB2xlXn75ZTVvDx48mIRek6SDJQpI5rJ582YsIWG+8sorKal/z549qv5HHnnEzEUysf833XSTWb58eXPFihW2bd26dRGP3bBhg3nSSSeZd999t/nuu++a8+fPN0eMGGGWK1fO7Natm1lYWBgou3v3brN69epmo0aNzMmTJ5sLFiwwn3rqKbNixYpm69atzePHjye1XyeccIJ5zjnnmAMHDjTLlCmj+unGCy+8YA4dOtR86623zEWLFpnTp083zz77bDM/P199zgQOHjxo1q1b1/zLX/5i279mzRrz66+/DnxeuXJlSu/faAnXjq1bt6r5lQ769etnNm3a1Lz22mvNdu3aqTa6EctcRdk6deqYZ5xxhvn222+bH3zwgXn++eeblSpVMr/44gtbvVOnTlXn7N+/v6pz4sSJZpUqVcyLL77YVu7o0aOqnX/6059SNBIkESjIZDiZJsjgBzybyFRBpkKFCnEde+DAAbU5wQMX/Vy6dGlg30svvaT2/fvf/7aVHTVqlNqPh3Iy0R826J+XIOPGjz/+aJYuXdq88cYbzUxg/PjxSjj84YcfwpZLlSDz888/24TSSGSKQBVuTtx+++2egkwsc/W+++5Tc+Wbb74J7Nu/f78S8CEwWRw7dsysXbu22b17d1ud06ZNU3XOnj3btn/s2LFKyMm238BsgKalNPLVV1/J73//e6lRo4ZSoZ922mkybty4pB77448/yj333COnnnqqKofyl112mXzxxRfKbAXVOHj00UcDJgxLNW6pnKGS/e1vfysnnniiUucCmCmGDRsmjRo1kjJlyii16+23367OpwNVO8wJc+bMkbZt2yqVMEwkf//730NMPPfee6+qDyreatWqSfv27ZWZIVVE6r8fqVChgtqc/OpXv1L/bt26NbAPqnxQpUoVW1mo4wGug86///1v6datm1SuXFlOOOEEOe+882T+/PlRty0vL/6fm0qVKqn2lCpVKmLZBQsWKNNa9erV1XyDKeLqq69WcyxZTJgwQZm7rLFyMy3BXHn22Werv/v27RuYX7ivLFatWiVXXnmlmu/oX5s2beQf//iHrU6YlXHcvHnzpF+/fmrOYvwPHz6szC2ou2nTpmof7kO0a8OGDYHjI7XDzbRUWFgoTz75pLpXrd8NmIC2bdtmK4dxbtmypaxcuVI6deqk2oDfmieeeELVkaw5Ectcfeedd+TCCy+UU045JbAPcxampvfee0+OHTum9n388ceyY8cONSY611xzjTJHoR6d66+/XpluYYoiGUa6Jalc5dNPP1XS/ZlnnmlOmTLFnDdvnnnPPfeYeXl5yhQQTiMT7bEFBQVKvYq338cee8ycO3euUrXeddddSo166NAhc86cOar+m2++OWDCsFTj0FLgu1NOOcV84IEHzA8//NCcOXOmehPs0aOHWapUKfPhhx9W58fbCs7Tpk0bVa8Fjq1Xr555+umnq7aiDddcc42qd/HixYFyt956qzI9PP300+bChQvN999/33ziiSeUmcE5FrG8yYcjUv+9gJo5mi2WN2Yd9A/XsmbNmupfmDDwtrpv3744exq8lp988olNy9GgQQOzc+fO5v/+9z/zp59+UtcE+6644grb8a+99pppGIbZ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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "engine": 0 + }, + "output_type": "display_data" + } + ], + "source": [ + "%%px\n", + "import mpi4py.MPI as MPI\n", + "import os\n", + "\n", + "from openpmd_viewer import OpenPMDTimeSeries\n", + "\n", + "# Use the opmd_2d_dir variable that was set in the previous cell\n", + "ts = OpenPMDTimeSeries(opmd_2d_dir)\n", + "\n", + "x, uy = ts.get_particle( var_list=['x','uy'], iteration=1800, species='electrons', plot=True, vmax=3e12 )" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "13c0da20-c14e-4aa7-afe7-1227efffa736", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:0] ..... use MPI reader (size=2)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[output:0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "engine": 0 + }, + "output_type": "display_data" + } + ], + "source": [ + "%%px\n", + "%matplotlib inline\n", + "import mpi4py.MPI as MPI\n", + "import os\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "from openpmd_viewer import OpenPMDTimeSeries\n", + "\n", + "# Use the opmd_2d_dir variable that was set in the previous cell\n", + "ts = OpenPMDTimeSeries(opmd_2d_dir)\n", + "\n", + "x_selected, uy_selected = ts.get_particle( ['x', 'uy'], species='electrons', \n", + " iteration=300, select={'uy':[-0.002, 0.004]} )\n", + "if (rank == 0):\n", + " plt.plot(x_selected, uy_selected, 'g.')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/docs/source/tutorials/7_mpi_3d.ipynb b/docs/source/tutorials/7_mpi_3d.ipynb new file mode 100644 index 0000000..8da47b3 --- /dev/null +++ b/docs/source/tutorials/7_mpi_3d.ipynb @@ -0,0 +1,239 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "f4aa9a24", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading 3D BP5 dataset from https://github.com/guj/openPMD-example-datasets/raw/add_bp5_files/bp5/3d.tar.gz...\n", + "Extracting to /Users/dec2023/Work/2026/cursor/checked_in...\n", + "Download and extraction complete!\n", + "Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/3d\n" + ] + } + ], + "source": [ + "import os\n", + "import urllib.request\n", + "import tarfile\n", + "import tempfile\n", + "import shutil\n", + "\n", + "# Check if MPI is available (for when running as converted Python script)\n", + "try:\n", + " import mpi4py.MPI as MPI\n", + " comm = MPI.COMM_WORLD\n", + " rank = comm.Get_rank()\n", + " is_mpi = True\n", + "except ImportError:\n", + " rank = 0\n", + " is_mpi = False\n", + "\n", + "# Download and extract 3D BP5 dataset (only on rank 0 if MPI is available)\n", + "if rank == 0:\n", + " data_url = \"https://github.com/guj/openPMD-example-datasets/raw/add_bp5_files/bp5/3d.tar.gz\"\n", + " data_dir = os.getcwd()\n", + " dataset_3d_dir = os.path.join(data_dir, '3d')\n", + " \n", + " # Remove existing directory if it exists\n", + " if os.path.exists(dataset_3d_dir):\n", + " print(f\"Removing existing dataset directory: {dataset_3d_dir}\")\n", + " shutil.rmtree(dataset_3d_dir)\n", + " \n", + " print(f\"Downloading 3D BP5 dataset from {data_url}...\")\n", + " print(f\"Extracting to {data_dir}...\")\n", + " \n", + " # Create directory if it doesn't exist\n", + " os.makedirs(data_dir, exist_ok=True)\n", + " \n", + " # Download to temporary file\n", + " with tempfile.NamedTemporaryFile(delete=False, suffix='.tar.gz') as tmp_file:\n", + " urllib.request.urlretrieve(data_url, tmp_file.name)\n", + " \n", + " # Extract tar.gz file - this will create a '3d' directory\n", + " with tarfile.open(tmp_file.name, 'r:gz') as tar:\n", + " tar.extractall(data_dir)\n", + " \n", + " # Clean up temporary file\n", + " os.remove(tmp_file.name)\n", + " \n", + " print(\"Download and extraction complete!\")\n", + "\n", + "# Wait for rank 0 to finish download before other ranks proceed\n", + "if is_mpi:\n", + " comm.Barrier()\n", + "\n", + "# Set the data directory path for use in the notebook (all ranks need this)\n", + "data_dir = os.getcwd()\n", + "dataset_3d_dir = os.path.join(data_dir, '3d')\n", + "opmd_3d_dir = dataset_3d_dir\n", + "if rank == 0:\n", + " print(f\"Using data directory: {opmd_3d_dir}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e9de3e22-caca-4ac4-b98e-cf8b3677918c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting 2 engines with \n", + "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 2/2 [00:05<00:00, 3.00s/engine]\n", + "Connected to 2 engines.\n" + ] + } + ], + "source": [ + "import ipyparallel as ipp\n", + "\n", + "# Create and start a cluster with 2 MPI engines\n", + "cluster = ipp.Cluster(engines=\"mpi\", n=2)\n", + "rc = cluster.start_and_connect_sync()\n", + "\n", + "# Activate the client to use all engines\n", + "rc.activate()\n", + "print(f\"Connected to {len(rc.ids)} engines.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7c984e27", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:1] Rank 1: Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/3d\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[stdout:0] Rank 0: Using data directory: /Users/dec2023/Work/2026/cursor/checked_in/3d\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Push the data directory path to all MPI engines\n", + "%px import os\n", + "%px import mpi4py.MPI as MPI\n", + "%px opmd_3d_dir = os.path.join(os.getcwd(), '3d')\n", + "%px opmd_3d_dir = os.path.abspath(opmd_3d_dir)\n", + "%px print(f\"Rank {MPI.COMM_WORLD.Get_rank()}: Using data directory: {opmd_3d_dir}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ad63c59-a439-4470-aae5-1dcae4dfdf6f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "760e1538-f95e-406c-a32f-5fe8de6f5230", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[stdout:1] Rank 1/2 running on host: JunminD023sMBP5.localdomain, PID: 79681\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[stdout:0] ..... use MPI reader (size=2)\n", + "Rank 0/2 running on host: JunminD023sMBP5.localdomain, PID: 79680\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "[output:0]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "engine": 0 + }, + "output_type": "display_data" + } + ], + "source": [ + "%%px\n", + "import mpi4py.MPI as MPI\n", + "import os\n", + "\n", + "from openpmd_viewer import OpenPMDTimeSeries\n", + "# Use the opmd_3d_dir variable that was set in the previous cell\n", + "ts = OpenPMDTimeSeries(opmd_3d_dir)\n", + "\n", + "comm = MPI.COMM_WORLD\n", + "rank = comm.Get_rank()\n", + "size = comm.Get_size()\n", + "host = os.uname().nodename\n", + "\n", + "print(f\"Rank {rank}/{size} running on host: {host}, PID: {os.getpid()}\")\n", + "#Ex, info_Ex = ts.get_field( iteration=80, field='E', coord='x' )\n", + "Ex, info_Ex = ts.get_field( iteration=80, field='E', coord='x', plot=False ) ## can not plot 3D\n", + "\n", + "z, = ts.get_particle( var_list=['z'], iteration=80, plot=True)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/docs/source/tutorials/tutorials.rst b/docs/source/tutorials/tutorials.rst index 0e967aa..8705626 100644 --- a/docs/source/tutorials/tutorials.rst +++ b/docs/source/tutorials/tutorials.rst @@ -9,4 +9,6 @@ Tutorials 2_Specific-field-geometries.ipynb 3_Introduction-to-the-GUI.ipynb 4_Particle_selection.ipynb - 5_Laser-plasma_tools.ipynb \ No newline at end of file + 5_Laser-plasma_tools.ipynb + 6_mpi_2d.ipynb + 7_mpi_3d.ipynb diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/__init__.py b/openpmd_viewer/openpmd_timeseries/data_reader/__init__.py index 13280b4..f18fbe5 100644 --- a/openpmd_viewer/openpmd_timeseries/data_reader/__init__.py +++ b/openpmd_viewer/openpmd_timeseries/data_reader/__init__.py @@ -1,2 +1,10 @@ from .data_reader import DataReader, available_backends -__all__ = ['DataReader', 'available_backends'] + +# Try to import mpiDataReader (only available if mpi4py is installed) +try: + from .mpi_data_reader import mpiDataReader + __all__ = ['DataReader', 'mpiDataReader', 'available_backends'] + # Reference to satisfy pyflakes (exported via __all__) + _ = mpiDataReader +except ImportError: + __all__ = ['DataReader', 'available_backends'] diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_data_reader.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_data_reader.py new file mode 100644 index 0000000..d533ced --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_data_reader.py @@ -0,0 +1,332 @@ +""" +This file is part of the openPMD-viewer + +MPI-enabled data reader for parallel I/O operations. + +Copyright 2020, openPMD-viewer contributors +Authors: Remi Lehe +License: 3-Clause-BSD-LBNL +""" +import numpy as np +import os +import re + +from .data_reader import DataReader + +# Import necessary modules +try: + import openpmd_api as io + from . import mpi_io_reader +except ImportError: + io = None + mpi_io_reader = None + + + +class mpiDataReader(DataReader): + """ + MPI-enabled version of DataReader that uses MPI for parallel I/O. + + This class extends DataReader and overrides methods to use parallel + versions from mpi_io_reader module. Only supports 'openpmd-api' backend; + h5py backend must use serial DataReader. + """ + + def __init__(self, backend, comm): + """ + Initialize the mpiDataReader class. + + Parameters + ---------- + backend : str + The backend to use (must be 'openpmd-api', h5py backend is serial only) + comm : MPI communicator + MPI communicator to use for parallel I/O + """ + if backend == 'h5py': + raise RuntimeError( + "h5py backend does not support MPI. " + "Please use 'openpmd-api' backend for MPI parallel I/O.") + self.comm = comm + super(mpiDataReader, self).__init__(backend) + + def list_iterations(self, path_to_dir): + """ + Return a list of the iterations that correspond to the files + in this directory, using MPI for parallel I/O when using openpmd-api backend. + + Only rank 0 performs the file listing operation, and broadcasts + the results to all other ranks. + + Parameter + --------- + path_to_dir : string + The path to the directory where the hdf5 files are. + + Returns + ------- + an array of integers which correspond to the iteration of each file + (in sorted order) + """ + rank = self.comm.Get_rank() + + if self.backend == 'openpmd-api': + # Rank 0 discovers files and determines series_name + if rank == 0: + # guess file ending from first file in directory + first_file_name = None + + is_single_file = os.path.isfile(path_to_dir) + if is_single_file: + first_file_name = path_to_dir + else: + for file_name in os.listdir( path_to_dir ): + if file_name.split(os.extsep)[-1] in io.file_extensions: + first_file_name = file_name + if first_file_name is None: + raise RuntimeError( + "Found no valid files in directory {0}.\n" + "Please check that this is the path to the openPMD files." + "(valid files must have one of the following extensions: {1})" + .format(path_to_dir, io.file_extensions)) + + if is_single_file: + file_path = path_to_dir + series_name = file_path + else: + # match last occurrence of integers and replace + # with %T wildcards + # examples: data00000100.h5 diag4_00000500.h5 io12.0.bp + # te42st.1234.yolo.json scan7_run14_data123.h5 + file_path = re.sub(r'(\d+)(\.(?!\d).+$)', r'%T\2', first_file_name) + series_name = os.path.join( path_to_dir, file_path) + else: + series_name = None + + # Broadcast series_name from rank 0 to all ranks + series_name = self.comm.bcast(series_name, root=0) + + # All ranks create Series with MPI communicator (collective operation) + self.series = io.Series( + series_name, + io.Access.read_only, + self.comm ) + + # Rank 0 gets iterations and broadcasts to all ranks + if rank == 0: + iterations = np.array( self.series.iterations ) + iterations_list = iterations.tolist() + else: + iterations_list = None + + # Broadcast iterations from rank 0 to all ranks + iterations_list = self.comm.bcast(iterations_list, root=0) + + # Convert to numpy array + iterations = np.array(iterations_list) + + return iterations + + def read_openPMD_params(self, iteration, extract_parameters=True): + """ + Extract the time and some openPMD parameters from a file. + + Only rank 0 performs the reading operation, and broadcasts + the results to all other ranks. + + Parameter + --------- + iteration: int + The iteration at which the parameters should be extracted + + extract_parameters: bool, optional + Whether to extract all parameters or only the time + (Function execution is faster when extract_parameters is False) + + Returns + ------- + A tuple with: + - A float corresponding to the time of this iteration in SI units + - A dictionary containing several parameters, such as the geometry, etc + When extract_parameters is False, the second argument returned is None + """ + if self.backend == 'openpmd-api': + time, params = mpi_io_reader.read_openPMD_params( + self.series, iteration, self.comm, extract_parameters) + + return (time, params) + + def read_field_cartesian(self, iteration, field, coord, axis_labels, + slice_relative_position, slice_across): + """ + Extract a given field from an openPMD file in the openPMD format, + when the geometry is cartesian (1d, 2d or 3d). + + Workload is divided among ranks before calling get_data(), + each rank collects its share, and results are gathered to rank 0. + + Parameters + ---------- + iteration : int + The iteration at which to extract the fields + + field : string, optional + Which field to extract + + coord : string, optional + Which component of the field to extract + + axis_labels: list of strings + The name of the dimensions of the array (e.g. ['x', 'y', 'z']) + + slice_across : list of str or None + Direction(s) across which the data should be sliced + Elements can be: + - 1d: 'z' + - 2d: 'x' and/or 'z' + - 3d: 'x' and/or 'y' and/or 'z' + Returned array is reduced by 1 dimension per slicing. + + slice_relative_position : list of float or None + Number(s) between -1 and 1 that indicate where to slice the data, + along the directions in `slice_across` + -1 : lower edge of the simulation box + 0 : middle of the simulation box + 1 : upper edge of the simulation box + + Returns + ------- + A tuple with + F : a ndarray containing the required field + info : a FieldMetaInformation object + (contains information about the grid; see the corresponding docstring) + """ + if self.backend == 'openpmd-api': + return mpi_io_reader.read_field_cartesian( + self.series, iteration, field, coord, axis_labels, + slice_relative_position, slice_across, self.comm) + + def read_field_circ(self, iteration, field, coord, slice_relative_position, + slice_across, m=0, theta=0., max_resolution_3d=None): + """ + Extract a given field from an openPMD file in the openPMD format, + when the geometry is thetaMode. + + Workload is divided among ranks before calling get_data(), + each rank collects its share, and results are gathered to rank 0. + + Parameters + ---------- + iteration : int + The iteration at which to extract the fields + + field : string, optional + Which field to extract + Either 'rho', 'E', 'B' or 'J' + + coord : string, optional + Which component of the field to extract + Either 'r', 't' or 'z' + + m : int or string, optional + The azimuthal mode to be extracted + + theta : float or None + Angle of the plane of observation with respect to the x axis + If `theta` is not None, then this function returns a 2D array + corresponding to the plane of observation given by `theta` ; + otherwise it returns a full 3D Cartesian array + + slice_across : list of str or None + Direction(s) across which the data should be sliced + Elements can be 'r' and/or 'z' + Returned array is reduced by 1 dimension per slicing. + + slice_relative_position : list of float or None + Number(s) between -1 and 1 that indicate where to slice the data, + along the directions in `slice_across` + -1 : lower edge of the simulation box + 0 : middle of the simulation box + 1 : upper edge of the simulation box + + max_resolution_3d : list of int or None + Maximum resolution that the 3D reconstruction of the field (when + `theta` is None) can have. The list should contain two values, + e.g. `[200, 100]`, indicating the maximum longitudinal and + transverse resolution, respectively. This is useful for + performance reasons, particularly for 3D visualization. + + Returns + ------- + A tuple with + F : a 3darray or 2darray containing the required field, + depending on whether `theta` is None or not + info : a FieldMetaInformation object + (contains information about the grid; see the corresponding docstring) + """ + if self.backend == 'openpmd-api': + return mpi_io_reader.read_field_circ( + self.series, iteration, field, coord, slice_relative_position, + slice_across, self.comm, m, theta, max_resolution_3d) + + def read_species_data(self, iteration, species, record_comp, extensions): + """ + Extract a given species' record_comp. + + Workload is divided among ranks before calling get_data(), + each rank collects its share, and results are gathered to rank 0. + + Parameters + ---------- + iteration: int + The iteration at which to extract the species data + + species: string + The name of the species to extract (in the openPMD file) + + record_comp: string + The record component to extract + Either 'x', 'y', 'z', 'r', 'ux', 'uy', 'uz', 'ur', or 'w' + + extensions: list of strings + The extensions that the current OpenPMDTimeSeries complies with + """ + if self.backend == 'openpmd-api': + return mpi_io_reader.read_species_data( + self.series, iteration, species, record_comp, extensions, self.comm) + + def get_grid_parameters(self, iteration, avail_fields, metadata): + """ + Return the parameters of the spatial grid (grid size and grid range) + in two dictionaries. + + Only rank 0 performs the work and broadcasts the results to all other ranks. + + Parameters: + ----------- + iteration: int + The iteration at which to extract the parameters + + avail_fields: list + A list of the available fields + e.g. ['B', 'E', 'rho'] + + metadata: dictionary + A dictionary whose keys are the fields of `avail_fields` and + whose values are dictionaries that contain metadata (e.g. geometry) + + Returns: + -------- + A tuple with `grid_size_dict` and `grid_range_dict` + Both objects are dictionaries, with their keys being the labels of + the axis of the grid (e.g. 'x', 'y', 'z') + The values of `grid_size_dict` are the number of gridpoints along + each axis. + The values of `grid_range_dict` are lists of two floats, which + correspond to the min and max of the grid, along each axis. + """ + if self.backend == 'openpmd-api': + grid_size_dict, grid_range_dict = mpi_io_reader.get_grid_parameters( + self.series, iteration, avail_fields, metadata, self.comm) + + return (grid_size_dict, grid_range_dict) diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/__init__.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/__init__.py new file mode 100644 index 0000000..1fcb938 --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/__init__.py @@ -0,0 +1,12 @@ +""" +MPI-enabled parallel versions of io_reader functions. + +Copyright 2020, openPMD-viewer contributors +License: 3-Clause-BSD-LBNL +""" +from .params_reader import read_openPMD_params +from .field_reader import read_field_cartesian, read_field_circ, get_grid_parameters +from .particle_reader import read_species_data + +__all__ = ['read_openPMD_params', 'read_field_cartesian', + 'read_field_circ', 'read_species_data', 'get_grid_parameters'] diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/field_reader.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/field_reader.py new file mode 100644 index 0000000..a76b53c --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/field_reader.py @@ -0,0 +1,573 @@ +""" +MPI-enabled parallel versions of io_reader field_reader functions. + +Copyright 2020, openPMD-viewer contributors +License: 3-Clause-BSD-LBNL +""" +import numpy as np +from .utilities import _read_field_portion, _read_field_circ_portion +from openpmd_viewer.openpmd_timeseries.data_reader.io_reader.utilities import get_data +from ...data_order import RZorder, order_error_msg +from openpmd_viewer.openpmd_timeseries.field_metainfo import FieldMetaInformation +from openpmd_viewer.openpmd_timeseries.utilities import construct_3d_from_circ + + +def read_field_cartesian(series, iteration, field_name, component_name, + axis_labels, slice_relative_position, slice_across, comm): + """ + Extract a given field from a file in the openPMD format, + when the geometry is cartesian (1d, 2d or 3d). + + Workload is divided among ranks, each rank collects its share, + and results are gathered to rank 0. + + Parameters + ---------- + series: openpmd_api.Series + An open, readable openPMD-api series object + + iteration: integer + Iteration from which parameters should be extracted + + field_name : string, optional + Which field to extract + + component_name : string, optional + Which component of the field to extract + + axis_labels: list of strings + The name of the dimensions of the array (e.g. ['x', 'y', 'z']) + + slice_across : list of str or None + Direction(s) across which the data should be sliced + Elements can be: + - 1d: 'z' + - 2d: 'x' and/or 'z' + - 3d: 'x' and/or 'y' and/or 'z' + Returned array is reduced by 1 dimension per slicing. + + slice_relative_position : list of float or None + Number(s) between -1 and 1 that indicate where to slice the data, + along the directions in `slice_across` + -1 : lower edge of the simulation box + 0 : middle of the simulation box + 1 : upper edge of the simulation box + + comm : MPI communicator + MPI communicator for parallel operations + + Returns + ------- + A tuple with + F : a ndarray containing the required field + info : a FieldMetaInformation object + (contains information about the grid; see the corresponding docstring) + """ + rank = comm.Get_rank() + size = comm.Get_size() + + it = series.iterations[iteration] + + # Extract the dataset and corresponding group + field = it.meshes[field_name] + if field.scalar: + component = next(field.items())[1] + else: + component = field[component_name] + + # Dimensions of the grid + full_shape = component.shape + + # Handle dataOrder 'F' (Fortran order) + if field.get_attribute('dataOrder') == 'F': + grid_spacing = field.grid_spacing[::-1] + global_offset = field.grid_global_offset[::-1] + grid_position = component.position[::-1] + else: + grid_spacing = field.grid_spacing + global_offset = field.grid_global_offset + grid_position = component.position + + grid_unit_SI = field.grid_unit_SI + time = (it.time + field.time_offset) * it.time_unit_SI + + field_attrs = {a: field.get_attribute(a) for a in field.attributes} + component_attrs = {a: component.get_attribute(a) for a in component.attributes} + + # Determine final shape after slicing + if slice_across is not None: + # Get the integer that correspond to the slicing direction + list_slicing_index = [] + list_i_cell = [] + for count, slice_across_item in enumerate(slice_across): + slicing_index = axis_labels.index(slice_across_item) + list_slicing_index.append(slicing_index) + # Number of cells along the slicing direction + n_cells = full_shape[slicing_index] + # Index of the slice (prevent stepping out of the array) + i_cell = int(0.5 * (slice_relative_position[count] + 1.) * n_cells) + i_cell = max(i_cell, 0) + i_cell = min(i_cell, n_cells - 1) + list_i_cell.append(i_cell) + + # Calculate final shape after slicing + final_shape = [x for index, x in enumerate(full_shape) + if index not in list_slicing_index] + final_grid_spacing = [x for index, x in enumerate(grid_spacing) + if index not in list_slicing_index] + final_global_offset = [x for index, x in enumerate(global_offset) + if index not in list_slicing_index] + final_axis_labels = [x for index, x in enumerate(axis_labels) + if index not in list_slicing_index] + else: + final_shape = list(full_shape) + final_grid_spacing = list(grid_spacing) + final_global_offset = list(global_offset) + final_axis_labels = list(axis_labels) + list_slicing_index = None + list_i_cell = None + + # Divide workload along the first dimension + if len(final_shape) == 0: + # Scalar data - no parallelization needed + if rank == 0: + if slice_across is not None: + F = get_data(series, component, list_i_cell, list_slicing_index) + else: + F = get_data(series, component) + else: + F = None + F = comm.bcast(F, root=0) + else: + # Divide work along the first dimension + dim0_size = final_shape[0] + chunk_size = dim0_size // size + remainder = dim0_size % size + + # Calculate start and end indices for this rank + start_idx = rank * chunk_size + min(rank, remainder) + if rank < remainder: + end_idx = start_idx + chunk_size + 1 + else: + end_idx = start_idx + chunk_size + + # Each rank reads only its portion using a helper function + F = _read_field_portion(series, component, slice_across, list_slicing_index, + list_i_cell, final_shape, start_idx, end_idx) + + # Gather all chunks to rank 0 + gathered_data = comm.gather(F, root=0) + + if rank == 0: + # Concatenate all chunks along the first dimension + F = np.concatenate(gathered_data, axis=0) + else: + F = None + # Rank 0 will broadcast the final result + F = comm.bcast(F, root=0) + + # Create FieldMetaInformation (same for all ranks) + axes = {i: final_axis_labels[i] for i in range(len(final_axis_labels))} + info = FieldMetaInformation(axes, F.shape, final_grid_spacing, final_global_offset, + grid_unit_SI, grid_position, + time, iteration, field_attrs=field_attrs, + component_attrs=component_attrs) + + return F, info + + +def read_field_circ(series, iteration, field_name, component_name, + slice_relative_position, slice_across, comm, + m=0, theta=0., max_resolution_3d=None): + """ + Extract a given field from a file in the openPMD format, + when the geometry is thetaMode. + + Workload is divided among ranks, each rank collects its share, + and results are gathered to rank 0. + + Parameters + ---------- + series: openpmd_api.Series + An open, readable openPMD-api series object + + iteration: integer + Iteration from which parameters should be extracted + + field_name : string, optional + Which field to extract + + component_name : string, optional + Which component of the field to extract + + m : int or string, optional + The azimuthal mode to be extracted + + theta : float or None + Angle of the plane of observation with respect to the x axis + If `theta` is not None, then this function returns a 2D array + corresponding to the plane of observation given by `theta` ; + otherwise it returns a full 3D Cartesian array + + slice_across : list of str or None + Direction(s) across which the data should be sliced + Elements can be 'r' and/or 'z' + Returned array is reduced by 1 dimension per slicing. + + slice_relative_position : list of float or None + Number(s) between -1 and 1 that indicate where to slice the data, + along the directions in `slice_across` + -1 : lower edge of the simulation box + 0 : middle of the simulation box + 1 : upper edge of the simulation box + + max_resolution_3d : list of int or None + Maximum resolution that the 3D reconstruction of the field (when + `theta` is None) can have. The list should contain two values, + e.g. `[200, 100]`, indicating the maximum longitudinal and + transverse resolution, respectively. This is useful for + performance reasons, particularly for 3D visualization. + + comm : MPI communicator + MPI communicator for parallel operations + + Returns + ------- + A tuple with + F : a 3darray or 2darray containing the required field, + depending on whether `theta` is None or not + info : a FieldMetaInformation object + (contains information about the grid; see the corresponding docstring) + """ + rank = comm.Get_rank() + size = comm.Get_size() + + it = series.iterations[iteration] + + # Extract the dataset and corresponding group + field = it.meshes[field_name] + if field.scalar: + component = next(field.items())[1] + else: + component = field[component_name] + + field_attrs = {a: field.get_attribute(a) for a in field.attributes} + component_attrs = {a: component.get_attribute(a) for a in component.attributes} + + # Extract the metainformation + coord_labels = {ii: coord for (ii, coord) in enumerate(field.axis_labels)} + + if coord_labels[0] == 'r': + coord_order = RZorder.mrz + Nm, Nr, Nz = component.shape + N_pair = (Nr, Nz) + elif coord_labels[1] == 'r': + Nm, Nz, Nr = component.shape + N_pair = (Nz, Nr) + coord_order = RZorder.mzr + else: + raise Exception(order_error_msg) + + time = (it.time + field.time_offset) * it.time_unit_SI + + info = FieldMetaInformation(coord_labels, N_pair, + field.grid_spacing, field.grid_global_offset, + field.grid_unit_SI, component.position, time, iteration, + thetaMode=True, field_attrs=field_attrs, + component_attrs=component_attrs) + + # Convert to a 3D Cartesian array if theta is None + if theta is None: + # Get cylindrical info (will be updated if max_resolution_3d is used) + rmax = info.rmax + inv_dr = 1./info.dr + + # Divide workload: each rank reads portion of modes + # For simplicity, divide along the first spatial dimension (r or z) + if coord_order is RZorder.mrz: + dim_size = Nr + else: # RZorder.mzr + dim_size = Nz + + chunk_size = dim_size // size + remainder = dim_size % size + start_idx = rank * chunk_size + min(rank, remainder) + if rank < remainder: + end_idx = start_idx + chunk_size + 1 + else: + end_idx = start_idx + chunk_size + + # Each rank reads its portion of the data using helper function + if coord_order is RZorder.mrz: + Fcirc = _read_field_circ_portion(series, component, start_idx, end_idx, + coord_order, dim=1) + else: # RZorder.mzr + Fcirc = _read_field_circ_portion(series, component, start_idx, end_idx, + coord_order, dim=2) + + # Handle max_resolution_3d if needed (on full data before division) + if max_resolution_3d is not None: + max_res_lon, max_res_transv = max_resolution_3d + if Nz > max_res_lon: + excess_z = int(np.round(Nz/max_res_lon)) + if coord_order is RZorder.mrz: + Fcirc = Fcirc[:, :, ::excess_z] + else: # RZorder.mzr + Fcirc = Fcirc[:, ::excess_z, :] + # Update info (only rank 0 needs to do this, then broadcast) + if rank == 0: + info.z = info.z[::excess_z] + info.dz = info.z[1] - info.z[0] + if Nr > max_res_transv/2: + excess_r = int(np.round(Nr/(max_res_transv/2))) + if coord_order is RZorder.mrz: + Fcirc = Fcirc[:, ::excess_r, :] + else: # RZorder.mzr + Fcirc = Fcirc[:, :, ::excess_r] + # Update info (only rank 0 needs to do this, then broadcast) + if rank == 0: + info.r = info.r[::excess_r] + info.dr = info.r[1] - info.r[0] + inv_dr = 1./info.dr + rmax = info.rmax # Update rmax after downsampling r + Nr = Fcirc.shape[1] if coord_order is RZorder.mrz else Fcirc.shape[2] + + # Broadcast updated info from rank 0 + if max_resolution_3d is not None: + if rank == 0: + info_to_bcast = { + 'z': getattr(info, 'z', None), + 'dz': getattr(info, 'dz', None), + 'r': getattr(info, 'r', None), + 'dr': getattr(info, 'dr', None), + 'inv_dr': inv_dr, + 'rmax': rmax, + 'Nr': Nr + } + else: + info_to_bcast = None + info_to_bcast = comm.bcast(info_to_bcast, root=0) + if rank != 0: + if info_to_bcast['z'] is not None: + info.z = info_to_bcast['z'] + info.dz = info_to_bcast['dz'] + if info_to_bcast['r'] is not None: + info.r = info_to_bcast['r'] + info.dr = info_to_bcast['dr'] + inv_dr = info_to_bcast['inv_dr'] + rmax = info_to_bcast['rmax'] + Nr = info_to_bcast['Nr'] + + # Determine modes to extract + if m == 'all': + modes = [mode for mode in range(0, int(Nm / 2) + 1)] + else: + modes = [m] + modes = np.array(modes, dtype='int') + nmodes = len(modes) + + # Convert cylindrical data to Cartesian data + # First, gather all Fcirc portions to rank 0 to reconstruct full Fcirc + gathered_Fcirc = comm.gather(Fcirc, root=0) + + if rank == 0: + # Concatenate along the divided dimension to reconstruct full Fcirc + if coord_order is RZorder.mrz: + Fcirc_full = np.concatenate(gathered_Fcirc, axis=1) + else: # RZorder.mzr + Fcirc_full = np.concatenate(gathered_Fcirc, axis=2) + else: + Fcirc_full = None + + # Convert cylindrical data to Cartesian data + info._convert_cylindrical_to_3Dcartesian() + nx, ny, nz = len(info.x), len(info.y), len(info.z) + + # Rank 0 performs the full 3D conversion + if rank == 0: + F_total = np.zeros((nx, ny, nz), dtype=component.dtype) + construct_3d_from_circ(F_total, Fcirc_full, info.x, info.y, modes, + nx, ny, nz, Nr, nmodes, inv_dr, rmax, coord_order) + else: + F_total = None + + # Broadcast final result to all ranks + F_total = comm.bcast(F_total, root=0) + + else: + # theta is not None - 2D projection + # Divide workload along the first spatial dimension (r or z) + if coord_order is RZorder.mrz: + dim_size = Nr + else: # RZorder.mzr + dim_size = Nz + + chunk_size = dim_size // size + remainder = dim_size % size + start_idx = rank * chunk_size + min(rank, remainder) + if rank < remainder: + end_idx = start_idx + chunk_size + 1 + else: + end_idx = start_idx + chunk_size + + # Extract the modes and recombine them properly + if m == 'all': + # Sum of all the modes + # - Prepare the multiplier arrays + mult_above_axis = [1] + mult_below_axis = [1] + for mode in range(1, int(Nm / 2) + 1): + cos = np.cos( mode * theta ) + sin = np.sin( mode * theta ) + mult_above_axis += [cos, sin] + mult_below_axis += [ (-1) ** mode * cos, (-1) ** mode * sin ] + mult_above_axis = np.array( mult_above_axis ) + mult_below_axis = np.array( mult_below_axis ) + # - Sum the modes (read full 2D data, then slice locally) + F = get_data( series, component ) # (Extracts all modes) + # Slice locally + if coord_order is RZorder.mrz: + F_local = F[:, start_idx:end_idx, :] + F_total_local = np.zeros( (2 * Nr, Nz ), dtype=F.dtype ) + F_total_local[Nr:, :] = np.tensordot( mult_above_axis, + F_local, axes=(0, 0) )[:, :] + F_total_local[:Nr, :] = np.tensordot( mult_below_axis, + F_local, axes=(0, 0) )[::-1, :] + # Extract only our portion + F_total_local = F_total_local[start_idx:end_idx, :] + elif coord_order is RZorder.mzr: + F_local = F[:, :, start_idx:end_idx] + F_total_local = np.zeros( (Nz, 2 * Nr ), dtype=F.dtype ) + F_total_local[:, Nr:] = np.tensordot( mult_above_axis, + F_local, axes=(0, 0) )[:, :] + F_total_local[:, :Nr] = np.tensordot( mult_below_axis, + F_local, axes=(0, 0) )[:, ::-1] + # Extract only our portion + F_total_local = F_total_local[:, start_idx:end_idx] + elif m == 0: + # Extract mode 0 + F = get_data( series, component, 0, 0 ) + if coord_order is RZorder.mrz: + F_local = F[start_idx:end_idx, :] + F_total_local = np.zeros( (2 * Nr, Nz ), dtype=F.dtype ) + F_total_local[Nr:, :] = F_local[:, :] + F_total_local[:Nr, :] = F_local[::-1, :] + F_total_local = F_total_local[start_idx:end_idx, :] + elif coord_order is RZorder.mzr: + F_local = F[:, start_idx:end_idx] + F_total_local = np.zeros( (Nz, 2 * Nr ), dtype=F.dtype ) + F_total_local[:, Nr:] = F_local[:, :] + F_total_local[:, :Nr] = F_local[:, ::-1] + F_total_local = F_total_local[:, start_idx:end_idx] + else: + # Extract higher mode + cos = np.cos( m * theta ) + sin = np.sin( m * theta ) + F_cos = get_data( series, component, 2 * m - 1, 0 ) + F_sin = get_data( series, component, 2 * m, 0 ) + if coord_order is RZorder.mrz: + F_cos_local = F_cos[start_idx:end_idx, :] + F_sin_local = F_sin[start_idx:end_idx, :] + F_local = cos * F_cos_local + sin * F_sin_local + F_total_local = np.zeros( (2 * Nr, Nz ), dtype=F_local.dtype ) + F_total_local[Nr:, :] = F_local[:, :] + F_total_local[:Nr, :] = (-1) ** m * F_local[::-1, :] + F_total_local = F_total_local[start_idx:end_idx, :] + elif coord_order is RZorder.mzr: + F_cos_local = F_cos[:, start_idx:end_idx] + F_sin_local = F_sin[:, start_idx:end_idx] + F_local = cos * F_cos_local + sin * F_sin_local + F_total_local = np.zeros( (Nz, 2 * Nr ), dtype=F_local.dtype ) + F_total_local[:, Nr:] = F_local[:, :] + F_total_local[:, :Nr] = (-1) ** m * F_local[:, ::-1] + F_total_local = F_total_local[:, start_idx:end_idx] + + # Gather all portions to rank 0 + gathered_data = comm.gather(F_total_local, root=0) + + if rank == 0: + # Concatenate along the divided dimension + if coord_order is RZorder.mrz: + F_total = np.concatenate(gathered_data, axis=0) + else: # RZorder.mzr + F_total = np.concatenate(gathered_data, axis=1) + else: + F_total = None + + # Broadcast final result + F_total = comm.bcast(F_total, root=0) + + # Perform slicing if needed + if slice_across is not None: + # Slice field and clear metadata + inverted_axes_dict = {info.axes[key]: key for key in info.axes.keys()} + for count, slice_across_item in enumerate(slice_across): + slicing_index = inverted_axes_dict[slice_across_item] + coord_array = getattr( info, slice_across_item ) + # Number of cells along the slicing direction + n_cells = len(coord_array) + # Index of the slice (prevent stepping out of the array) + i_cell = int( 0.5 * (slice_relative_position[count] + 1.) * n_cells ) + i_cell = max( i_cell, 0 ) + i_cell = min( i_cell, n_cells - 1) + F_total = np.take( F_total, [i_cell], axis=slicing_index ) + F_total = np.squeeze(F_total) + # Remove the sliced labels from the FieldMetaInformation + for slice_across_item in slice_across: + info._remove_axis(slice_across_item) + + return F_total, info + + +def get_grid_parameters(series, iteration, avail_fields, metadata, comm): + """ + Return the parameters of the spatial grid (grid size and grid range) + in two dictionaries. + + Only rank 0 performs the grid parameter extraction, and broadcasts + the results to all other ranks. + + Parameters: + ----------- + series: openpmd_api.Series + An open, readable openPMD-api series object + + iteration: integer + Iteration from which parameters should be extracted + + avail_fields: list + A list of the available fields + e.g. ['B', 'E', 'rho'] + + metadata: dictionary + A dictionary whose keys are the fields of `avail_fields` and + whose values are dictionaries that contain metadata (e.g. geometry) + + comm : MPI communicator + MPI communicator for parallel operations + + Returns: + -------- + A tuple with `grid_size_dict` and `grid_range_dict` + Both objects are dictionaries, with their keys being the labels of the axis + of the grid (e.g. 'x', 'y', 'z') + The values of `grid_size_dict` are the number of gridpoints along each axis + The values of `grid_range_dict` are lists of two floats, which correspond + to the min and max of the grid, along each axis. + """ + from ..io_reader.field_reader import get_grid_parameters as _get_grid_parameters + + rank = comm.Get_rank() + + if rank == 0: + grid_size_dict, grid_range_dict = _get_grid_parameters( + series, iteration, avail_fields, metadata) + else: + grid_size_dict = None + grid_range_dict = None + + # Broadcast results from rank 0 to all ranks + grid_size_dict = comm.bcast(grid_size_dict, root=0) + grid_range_dict = comm.bcast(grid_range_dict, root=0) + + return grid_size_dict, grid_range_dict diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/params_reader.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/params_reader.py new file mode 100644 index 0000000..e2400fe --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/params_reader.py @@ -0,0 +1,51 @@ +""" +MPI-enabled parallel versions of io_reader params_reader functions. + +Copyright 2020, openPMD-viewer contributors +License: 3-Clause-BSD-LBNL +""" +from ..io_reader.params_reader import read_openPMD_params as _read_openPMD_params + + +def read_openPMD_params(series, iteration, comm, extract_parameters=True): + """ + Extract the time and some openPMD parameters from a file. + + Only rank 0 performs the parameter reading operation, and broadcasts + the results to all other ranks. + + Parameter + --------- + series: openpmd_api.Series + An open, readable openPMD-api series object + + iteration: integer + Iteration from which parameters should be extracted + + comm : MPI communicator + MPI communicator for parallel operations + + extract_parameters: bool, optional + Whether to extract all parameters or only the time + (Function execution is faster when extract_parameters is False) + + Returns + ------- + A tuple with: + - A float corresponding to the time of this iteration in SI units + - A dictionary containing several parameters, such as the geometry, etc. + When extract_parameters is False, the second argument returned is None. + """ + rank = comm.Get_rank() + + if rank == 0: + time, params = _read_openPMD_params(series, iteration, extract_parameters) + else: + time = None + params = None + + # Broadcast time and params from rank 0 to all ranks + time = comm.bcast(time, root=0) + params = comm.bcast(params, root=0) + + return time, params diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/particle_reader.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/particle_reader.py new file mode 100644 index 0000000..f1d8c8e --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/particle_reader.py @@ -0,0 +1,196 @@ +""" +MPI-enabled parallel versions of io_reader particle_reader functions. + +Copyright 2020, openPMD-viewer contributors +License: 3-Clause-BSD-LBNL +""" +import numpy as np +from scipy import constants +from .utilities import _read_species_portion +from ..io_reader.utilities import get_data + + +def read_species_data(series, iteration, species_name, component_name, + extensions, comm): + """ + Extract a given species' record_comp. + + Workload is divided among ranks, each rank collects its share, + and results are gathered to rank 0. + + Parameters + ---------- + series: openpmd_api.Series + An open, readable openPMD-api series object + + iteration: integer + Iteration from which parameters should be extracted + + species_name: string + The name of the species to extract (in the openPMD file) + + component_name: string + The record component to extract + Either 'x', 'y', 'z', 'r', 'ux', 'uy', 'uz', 'ur', or 'w' + + extensions: list of strings + The extensions that the current OpenPMDTimeSeries complies with + + comm : MPI communicator + MPI communicator for parallel operations + """ + rank = comm.Get_rank() + size = comm.Get_size() + + it = series.iterations[iteration] + + # Translate the record component to the openPMD format + dict_record_comp = {'x': ['position', 'x'], + 'y': ['position', 'y'], + 'z': ['position', 'z'], + 'r': ['position', 'r'], + 'ux': ['momentum', 'x'], + 'uy': ['momentum', 'y'], + 'uz': ['momentum', 'z'], + 'ur': ['momentum', 'r'], + 'w': ['weighting', None]} + + if component_name in dict_record_comp: + ompd_record_name, ompd_record_comp_name = \ + dict_record_comp[component_name] + elif component_name.find('/') != -1: + ompd_record_name, ompd_record_comp_name = \ + component_name.split('/') + else: + ompd_record_name = component_name + ompd_record_comp_name = None + + species_obj = it.particles[species_name] + record = species_obj[ompd_record_name] + if record.scalar: + component = next(record.items())[1] + else: + component = record[ompd_record_comp_name] + + if rank == 0: + shape = component.shape + if len(shape) > 0: + total_particles = shape[0] + else: + # Scalar value + total_particles = 1 + else: + total_particles = None + + total_particles = comm.bcast(total_particles, root=0) + + if total_particles > 1: + chunk_size = total_particles // size + remainder = total_particles % size + + start_idx = rank * chunk_size + min(rank, remainder) + if rank < remainder: + end_idx = start_idx + chunk_size + 1 + else: + end_idx = start_idx + chunk_size + else: + # Scalar or single particle + start_idx = 0 + end_idx = total_particles + + if ompd_record_name == 'id': + output_type = np.uint64 + else: + output_type = np.float64 + + if total_particles > 1: + data = _read_species_portion(series, component, start_idx, end_idx, output_type) + else: + if rank == 0: + if ompd_record_name == 'id': + output_type = np.uint64 + else: + output_type = np.float64 + data = get_data(series, component, output_type=output_type) + else: + data = None + data = comm.bcast(data, root=0) + if component_name in ['x', 'y', 'z', 'r']: + if rank == 0: + offset = get_data(series, species_obj['positionOffset'][component_name]) + else: + offset = None + offset = comm.bcast(offset, root=0) + data += offset + elif component_name in ['ux', 'uy', 'uz', 'ur']: + if rank == 0: + mass_component = next(species_obj['mass'].items())[1] + m = get_data(series, mass_component) + else: + m = None + m = comm.bcast(m, root=0) + if np.all(m != 0): + norm_factor = 1. / (m * constants.c) + data *= norm_factor + return data + + if 'ED-PIC' in extensions and ompd_record_name != 'weighting': + macro_weighted = record.get_attribute('macroWeighted') + weighting_power = record.get_attribute('weightingPower') + if (macro_weighted == 1) and (weighting_power != 0): + w_component = next(species_obj['weighting'].items())[1] + w = _read_species_portion(series, w_component, start_idx, end_idx, np.float64) + data *= w ** (-weighting_power) + + if component_name in ['x', 'y', 'z', 'r']: + if rank == 0: + offset_full = get_data(series, species_obj['positionOffset'][component_name]) + else: + offset_full = None + offset_full = comm.bcast(offset_full, root=0) + + if np.isscalar(offset_full) or (hasattr(offset_full, 'shape') and offset_full.shape == ()): + data += offset_full + else: + offset_portion = offset_full[start_idx:end_idx] + data += offset_portion + + elif component_name in ['ux', 'uy', 'uz', 'ur']: + mass_component = next(species_obj['mass'].items())[1] + + if rank == 0: + mass_shape = mass_component.shape + if len(mass_shape) > 0 and mass_shape[0] > 1: + mass_is_per_particle = True + else: + mass_is_per_particle = False + else: + mass_is_per_particle = None + + mass_is_per_particle = comm.bcast(mass_is_per_particle, root=0) + + if mass_is_per_particle: + m = _read_species_portion(series, mass_component, start_idx, end_idx, np.float64) + if np.all(m != 0): + norm_factor = 1. / (m * constants.c) + data *= norm_factor + else: + if rank == 0: + m = get_data(series, mass_component) + else: + m = None + m = comm.bcast(m, root=0) + if np.all(m != 0): + norm_factor = 1. / (m * constants.c) + data *= norm_factor + + gathered_data = comm.gather(data, root=0) + + if rank == 0: + data = np.concatenate(gathered_data) + else: + data = None + + data = comm.bcast(data, root=0) + + return data diff --git a/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/utilities.py b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/utilities.py new file mode 100644 index 0000000..659114a --- /dev/null +++ b/openpmd_viewer/openpmd_timeseries/data_reader/mpi_io_reader/utilities.py @@ -0,0 +1,279 @@ +""" +MPI-enabled parallel versions of io_reader utilities. + +Copyright 2020, openPMD-viewer contributors +License: 3-Clause-BSD-LBNL +""" +import numpy as np +from ..io_reader.utilities import get_data, chunk_to_slice +from ...data_order import RZorder + + +def _read_field_portion(series, component, slice_across, list_slicing_index, + list_i_cell, final_shape, start_idx, end_idx): + """ + Helper function to read only a portion of the field data. + Reads only chunks that overlap with the specified range along the first dimension. + + Parameters + ---------- + series : openpmd_api.Series + The openPMD series object + component : openPMD Record_Component + The component to read from + slice_across : list or None + Slicing directions + list_slicing_index : list or None + Indices of slicing directions + list_i_cell : list or None + Cell indices for slicing + final_shape : list + Final shape after slicing + start_idx : int + Start index along first dimension for this rank + end_idx : int + End index along first dimension for this rank + + Returns + ------- + numpy array with the portion of data for this rank + """ + # Determine the shape we need to allocate + portion_shape = [end_idx - start_idx] + final_shape[1:] + + # Get NaN value for masking + NaN_value = np.nan if (np.issubdtype(component.dtype, np.floating) or + np.issubdtype(component.dtype, np.complexfloating)) else 0 + + # Allocate array for this rank's portion + data = np.full(portion_shape, NaN_value, dtype=component.dtype) + + # Get available chunks + chunks = component.available_chunks() + + # Build the slice for reading from the full dataset + if slice_across is not None: + # For sliced data, first read the full slice, then extract portion + F_full = get_data(series, component, list_i_cell, list_slicing_index) + return F_full[start_idx:end_idx] + else: + # For non-sliced data, read only chunks that overlap with our portion + for chunk in chunks: + chunk_slice = chunk_to_slice(chunk) + + # Check if chunk overlaps with our portion along first dimension + chunk_start = chunk_slice[0].start + chunk_end = chunk_slice[0].stop + + # Calculate overlap + overlap_start = max(chunk_start, start_idx) + overlap_end = min(chunk_end, end_idx) + + if overlap_start < overlap_end: + # This chunk overlaps with our portion + # Read the overlapping region + read_slice_list = [] + for i, cs in enumerate(chunk_slice): + if i == 0: + # First dimension: only the overlap region + read_slice_list.append(slice(overlap_start, overlap_end)) + else: + # Other dimensions: full chunk extent + read_slice_list.append(cs) + read_slice = tuple(read_slice_list) + + # Read data + x = component[read_slice] + series.flush() + + # Place in our portion array + # Calculate target slice: offset by start_idx for first dimension + target_slice_list = [slice(overlap_start - start_idx, overlap_end - start_idx)] + # For remaining dimensions, use absolute coordinates + # (our portion array has full extent in those dimensions) + for i in range(1, len(chunk_slice)): + chunk_dim_start = chunk_slice[i].start + chunk_dim_end = chunk_slice[i].stop + target_slice_list.append(slice(chunk_dim_start, chunk_dim_end)) + target_slice = tuple(target_slice_list) + + data[target_slice] = x + + # Scale by unit_SI if needed + if component.unit_SI != 1.0: + if np.issubdtype(data.dtype, np.floating) or \ + np.issubdtype(data.dtype, np.complexfloating): + data *= component.unit_SI + else: + data = data * component.unit_SI + + return data + + +def _read_field_circ_portion(series, component, start_idx, end_idx, coord_order, dim): + """ + Helper function specifically for 3D cylindrical field data (theta is None case). + + Parameters + ---------- + series : openpmd_api.Series + The openPMD series object + component : openPMD Record_Component + The component to read from + start_idx : int + Start index along the divided dimension for this rank + end_idx : int + End index along the divided dimension for this rank + coord_order : RZorder + Coordinate order (mrz or mzr) + dim : int + Dimension to divide along (1 for r in mrz, 2 for z in mzr) + + Returns + ------- + numpy array with the portion of cylindrical data for this rank + """ + # Get full shape + full_shape = component.shape + Nm = full_shape[0] + + # Determine local shape + if coord_order is RZorder.mrz: + # Shape: (Nm, local_size, Nz) + local_size = end_idx - start_idx + local_shape = (Nm, local_size, full_shape[2]) + else: # RZorder.mzr + # Shape: (Nm, Nz, local_size) + local_size = end_idx - start_idx + local_shape = (Nm, full_shape[1], local_size) + + # Get NaN value for masking + NaN_value = np.nan if (np.issubdtype(component.dtype, np.floating) or + np.issubdtype(component.dtype, np.complexfloating)) else 0 + + # Allocate array for this rank's portion + data = np.full(local_shape, NaN_value, dtype=component.dtype) + + # Get available chunks + chunks = component.available_chunks() + + # Read only chunks that overlap with our portion along the divided dimension + for chunk in chunks: + chunk_slice = chunk_to_slice(chunk) + + # Check overlap along the divided dimension + chunk_start = chunk_slice[dim].start + chunk_end = chunk_slice[dim].stop + + overlap_start = max(chunk_start, start_idx) + overlap_end = min(chunk_end, end_idx) + + if overlap_start < overlap_end: + # This chunk overlaps with our portion + # Build read slice + read_slice_list = [] + for i, cs in enumerate(chunk_slice): + if i == dim: + # Divided dimension: only the overlap region + read_slice_list.append(slice(overlap_start, overlap_end)) + else: + # Other dimensions: full chunk extent + read_slice_list.append(cs) + read_slice = tuple(read_slice_list) + + # Read data + x = component[read_slice] + series.flush() + + # Place in our portion array + target_slice_list = [] + for i in range(len(chunk_slice)): + if i == dim: + # Offset by start_idx for divided dimension + target_slice_list.append(slice(overlap_start - start_idx, + overlap_end - start_idx)) + else: + # Use absolute coordinates for other dimensions + chunk_dim_start = chunk_slice[i].start + chunk_dim_end = chunk_slice[i].stop + target_slice_list.append(slice(chunk_dim_start, chunk_dim_end)) + target_slice = tuple(target_slice_list) + + data[target_slice] = x + + # Scale by unit_SI if needed + if component.unit_SI != 1.0: + if np.issubdtype(data.dtype, np.floating) or \ + np.issubdtype(data.dtype, np.complexfloating): + data *= component.unit_SI + else: + data = data * component.unit_SI + + return data + + +def _read_species_portion(series, component, start_idx, end_idx, output_type=np.float64): + """ + Helper function to read a portion of particle/species data. + + Parameters + ---------- + series : openpmd_api.Series + The openPMD series object + component : openPMD Record_Component + The component to read from + start_idx : int + Start particle index for this rank + end_idx : int + End particle index for this rank + output_type : numpy dtype, optional + Output data type (default: np.float64, use np.uint64 for 'id' field) + + Returns + ------- + numpy array with the portion of particle data for this rank + """ + # Get NaN value for masking + NaN_value = np.nan if (np.issubdtype(output_type, np.floating) or + np.issubdtype(output_type, np.complexfloating)) else 0 + + # Allocate array for this rank's portion + portion_size = end_idx - start_idx + data = np.full(portion_size, NaN_value, dtype=output_type) + + # Get available chunks + chunks = component.available_chunks() + + # Read only chunks that overlap with our portion + for chunk in chunks: + chunk_slice = chunk_to_slice(chunk) + + # For 1D particle data, check overlap along first dimension + chunk_start = chunk_slice[0].start + chunk_end = chunk_slice[0].stop + + overlap_start = max(chunk_start, start_idx) + overlap_end = min(chunk_end, end_idx) + + if overlap_start < overlap_end: + # This chunk overlaps with our portion + read_slice = (slice(overlap_start, overlap_end),) + + # Read data + x = component[read_slice] + series.flush() + + # Place in our portion array + target_start = overlap_start - start_idx + target_end = overlap_end - start_idx + data[target_start:target_end] = x + + # Scale by unit_SI if needed + if component.unit_SI != 1.0: + if np.issubdtype(data.dtype, np.floating) or \ + np.issubdtype(data.dtype, np.complexfloating): + data *= component.unit_SI + else: + data = data * component.unit_SI + + return data diff --git a/openpmd_viewer/openpmd_timeseries/main.py b/openpmd_viewer/openpmd_timeseries/main.py index ed8a7e5..0e87fc9 100644 --- a/openpmd_viewer/openpmd_timeseries/main.py +++ b/openpmd_viewer/openpmd_timeseries/main.py @@ -17,6 +17,9 @@ from .data_reader import DataReader, available_backends from .interactive import InteractiveViewer +# Don't import MPI at module level to avoid segfaults when not running under mpirun +# We'll import it lazily only when we detect we're actually running under MPI + # Define a custom Exception class OpenPMDException(Exception): @@ -66,8 +69,38 @@ def __init__(self, path_to_dir, check_all_files=True, backend=None): .format(backend, available_backends) ) self.backend = backend - # Initialize data reader - self.data_reader = DataReader(backend) + # Check if we're running under MPI by looking for MPI environment variables + # This avoids importing mpi4py at module level which causes segfaults + use_mpi = False + import os + mpi_env_vars = ['OMPI_COMM_WORLD_SIZE', 'PMI_SIZE', 'MPI_LOCALNRANKS', 'MPIRUN_RANK'] + running_under_mpi = any(os.environ.get(var) is not None for var in mpi_env_vars) + + if running_under_mpi: + try: + from mpi4py import MPI + comm = MPI.COMM_WORLD + if comm.Get_size() > 1: + # Only use MPI reader for openpmd-api backend + # h5py backend must be serial + if backend == 'openpmd-api': + from .data_reader import mpiDataReader + if (comm.Get_rank() == 0): + print ("..... use MPI reader (size={})".format(comm.Get_size())) + self.data_reader = mpiDataReader(backend, comm) + use_mpi = True + else: + if (comm.Get_rank() == 0): + print ("..... use serial reader (h5py backend does not support MPI)") + use_mpi = False + else: + print ("..... use serial reader (MPI detected but size=1)") + except Exception as e: + print ("..... simple reader (MPI detected but failed: {})".format(e)) + use_mpi = False + + if not use_mpi: + self.data_reader = DataReader(backend) # Extract the iterations available in this timeseries self.iterations = self.data_reader.list_iterations(path_to_dir) @@ -122,6 +155,22 @@ def __init__(self, path_to_dir, check_all_files=True, backend=None): # - Initialize a plotter object, which holds information about the time self.plotter = Plotter(self.t, self.iterations) + self._mpi_rank = 0 + self._is_mpi = False + if hasattr(self.data_reader, 'comm'): + self._mpi_rank = self.data_reader.comm.Get_rank() + self._is_mpi = True + + self._is_jupyter = False + try: + from IPython import get_ipython + ipython = get_ipython() + if ipython is not None: + if hasattr(ipython, 'kernel') or 'IPKernelApp' in str(type(ipython)): + self._is_jupyter = True + except ImportError: + pass + def get_particle(self, var_list=None, species=None, t=None, iteration=None, select=None, plot=False, nbins=150, plot_range=[[None, None], [None, None]], @@ -281,9 +330,7 @@ def get_particle(self, var_list=None, species=None, t=None, iteration=None, data_list = select.extract_tracked_particles( iteration, self.data_reader, data_list, species, self.extensions ) - # Plotting if plot and len(var_list) in [1, 2]: - # Extract the weights, if they are available if 'w' in self.avail_record_components[species]: w = self.data_reader.read_species_data( @@ -343,19 +390,16 @@ def get_particle(self, var_list=None, species=None, t=None, iteration=None, fit_bins_to_grid(hist_bins[i_var], grid_size_dict[var], grid_range_dict[var] ) - # - In the case of only one quantity - if len(data_list) == 1: - # Do the plotting - self.plotter.hist1d(data_list[0], w, var_list[0], species, - self._current_i, hist_bins[0], hist_range, + if not self._is_mpi or self._mpi_rank == 0: + if len(data_list) == 1: + self.plotter.hist1d(data_list[0], w, var_list[0], species, + self._current_i, hist_bins[0], hist_range, + deposition=histogram_deposition, **kw) + elif len(data_list) == 2: + self.plotter.hist2d(data_list[0], data_list[1], w, + var_list[0], var_list[1], species, + self._current_i, hist_bins, hist_range, deposition=histogram_deposition, **kw) - # - In the case of two quantities - elif len(data_list) == 2: - # Do the plotting - self.plotter.hist2d(data_list[0], data_list[1], w, - var_list[0], var_list[1], species, - self._current_i, hist_bins, hist_range, - deposition=histogram_deposition, **kw) # Output the data return(data_list) @@ -521,9 +565,7 @@ def get_field(self, field=None, coord=None, t=None, iteration=None, field, coord, slice_relative_position, slice_across, m, theta) - # Plot the resulting field - # Deactivate plotting when there is no slice selection - if plot: + if plot and self._mpi_rank == 0: if F.ndim == 1: self.plotter.show_field_1d(F, info, field_label, self._current_i, plot_range=plot_range, **kw) diff --git a/tests/test_tutorials.py b/tests/test_tutorials.py index eb9c801..5b039b5 100644 --- a/tests/test_tutorials.py +++ b/tests/test_tutorials.py @@ -27,8 +27,22 @@ def test_tutorials(): tutorial_notebooks = [filename for filename in os.listdir('./') if filename[-6:] == '.ipynb'] + # Check if mpi4py is available + mpi4py_available = False + try: + import mpi4py.MPI + mpi4py_available = True + except ImportError: + pass + # Loop through the tutorials and test them for notebook_name in tutorial_notebooks: + + # Skip MPI notebooks if mpi4py is not available + if notebook_name in ['6_mpi_2d.ipynb', '7_mpi_3d.ipynb']: + if not mpi4py_available: + print(f"Skipping {notebook_name} - mpi4py not available") + continue # Do a first pass where only the non-IPython features are tested. # (This gives better debugging information.) @@ -62,10 +76,49 @@ def clean_ipython_features(script_name): with open(script_name) as script_file: lines = script_file.readlines() + # Remove ipyparallel setup code (not needed when converting %%px to regular Python) + # First, convert content to string for multi-line regex matching + content = ''.join(lines) + + # Remove the entire ipyparallel setup block (import through rc.activate()) + content = re.sub( + r"import ipyparallel as ipp\s*\n\s*# Create and start.*?\n.*?rc\.activate\(\)\s*\n", + "# Skipped ipyparallel setup (not needed for direct Python execution)\n", + content, + flags=re.DOTALL + ) + + # Remove individual ipyparallel-related lines that might remain + content = re.sub(r"^.*import ipyparallel.*$", "", content, flags=re.MULTILINE) + content = re.sub(r"^.*cluster\s*=\s*ipp\.Cluster.*$", "", content, flags=re.MULTILINE) + content = re.sub(r"^.*rc\s*=\s*cluster\.start_and_connect_sync.*$", "", content, flags=re.MULTILINE) + content = re.sub(r"^.*rc\.activate\(\).*$", "", content, flags=re.MULTILINE) + content = re.sub(r"^.*print\(.*Connected to.*engines.*\).*$", "", content, flags=re.MULTILINE) + content = re.sub(r"^.*\brc\.\w+.*$", "", content, flags=re.MULTILINE) + + # Convert back to lines + lines = content.splitlines(True) + # Go through the lines and replace the IPython-specific commands # using regular expressions for i in range(len(lines)): + # Handle %%px magic commands: get_ipython().run_line_magic('px', '...') + # Convert to regular Python code (remove the magic wrapper) + # Match single or double quotes, handling escaped quotes inside + px_magic_match = re.search(r"get_ipython\(\)\.run_line_magic\((['\"]px['\"]),\s*(['\"])((?:[^\\]|\\.)*?)\2\s*\)", lines[i]) + if px_magic_match: + # Extract the code inside the quotes (group 3) + code = px_magic_match.group(3) + # Unescape any escaped characters (quotes, newlines, etc.) + code = code.replace("\\'", "'").replace('\\"', '"').replace("\\n", "\n").replace("\\\\", "\\") + # Get the indentation of the original line + indent_match = re.match(r"^(\s*)", lines[i]) + indent = indent_match.group(1) if indent_match else "" + # Replace with just the code, preserving indentation + lines[i] = indent + code + "\n" + continue + # Replace the lines that activate matplotlib in a notebook # by a line that selects the PS backend if re.search(r"get_ipython.*matplotlib", lines[i]) is not None: @@ -86,6 +139,10 @@ def clean_ipython_features(script_name): command_line = matched.groups()[1] lines[i] = '%simport os; os.system%s\n' % (spaces, command_line) + # Remove any remaining get_ipython() calls that weren't caught above + if re.search(r"get_ipython\(\)", lines[i]) is not None: + lines[i] = '# Skipped get_ipython() call\n' + # Write the cleaned file with open(script_name, 'w') as script_file: for line in lines: