├── example.png ├── docs ├── figures │ ├── example_simplest.png │ └── generate_example_plots.py ├── _static │ └── my_theme.css ├── apidocs.rst ├── quickstart.rst ├── installation.rst ├── index.rst ├── Makefile ├── make.bat └── conf.py ├── .bumpversion.cfg ├── well_schematics ├── __init__.py ├── _deprecated.py ├── components.py ├── plots.py └── simple_model.py ├── .gitignore ├── setup.py ├── LICENSE ├── README.md ├── dev well + components.ipynb └── notebooks ├── Example tutorial.ipynb ├── SAG link.ipynb └── dev simple model.ipynb /example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinverarity1/well-schematics/HEAD/example.png -------------------------------------------------------------------------------- /docs/figures/example_simplest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kinverarity1/well-schematics/HEAD/docs/figures/example_simplest.png -------------------------------------------------------------------------------- /docs/_static/my_theme.css: -------------------------------------------------------------------------------- 1 | .wy-nav-content { 2 | max-width: none; 3 | /* max-width: 1200px !important; */ 4 | } 5 | 6 | table.docutils p { 7 | font-size: 0.96em !important; 8 | } -------------------------------------------------------------------------------- /docs/apidocs.rst: -------------------------------------------------------------------------------- 1 | well_schematics developer API 2 | ================================= 3 | 4 | Groundwater resources 5 | --------------------- 6 | 7 | .. autofunction:: well_schematics.plot_single_diameter_well 8 | 9 | -------------------------------------------------------------------------------- /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.2.0 3 | commit = False 4 | tag = False 5 | 6 | [bumpversion:file:setup.py] 7 | 8 | [bumpversion:file:well_schematics/__init__.py] 9 | 10 | [bumpversion:file:docs/conf.py] 11 | 12 | -------------------------------------------------------------------------------- /well_schematics/__init__.py: -------------------------------------------------------------------------------- 1 | from pkg_resources import get_distribution, DistributionNotFound 2 | 3 | try: 4 | __version__ = get_distribution(__name__).version 5 | except DistributionNotFound: 6 | # package is not installed 7 | pass 8 | 9 | from well_schematics.plots import * 10 | from well_schematics._deprecated import * 11 | 12 | __version__ = "0.2.0" -------------------------------------------------------------------------------- /docs/quickstart.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | .. code-block:: python 5 | 6 | import well_schematics as ws 7 | 8 | ws.plot_single_diameter_well( 9 | [ 10 | {"type": "casing", "top": -0.5, "bottom": 27}, 11 | {"type": "screen", "top": 27, "bottom": 36}, 12 | ] 13 | ) 14 | 15 | .. figure:: figures/example_simplest.png 16 | 17 | -------------------------------------------------------------------------------- /docs/figures/generate_example_plots.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import well_schematics as ws 4 | 5 | artists = ws.plot_single_diameter_well( 6 | [ 7 | {"type": "casing", "top": -0.5, "bottom": 27}, 8 | {"type": "screen", "top": 27, "bottom": 36}, 9 | ] 10 | ) 11 | 12 | artists[0].axes.figure.savefig( 13 | os.path.join(os.path.dirname(__file__), "example_simplest.png") 14 | ) 15 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ========================== 3 | 4 | well-schematics can be installed from PyPI: 5 | 6 | .. code-block:: bash 7 | 8 | $ pip install well-schematics 9 | 10 | And updated from PyPI: 11 | 12 | .. code-block:: bash 13 | 14 | $ pip install -U well-schematics 15 | 16 | The ``well-schematics`` PyPI package will install a Python module ``well_schematics``: 17 | 18 | .. code-block:: python 19 | 20 | >>> import well_schematics as ws 21 | 22 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ``well-schematics`` Python package documentation 2 | ============================================================================ 3 | 4 | ``well-schematics`` is a package to help with making schematic diagrams of the construction 5 | of boreholes and wells in matplotlib. 6 | 7 | This project is based at 8 | `GitHub `_. 9 | 10 | .. toctree:: 11 | :maxdepth: 5 12 | :caption: Contents: 13 | 14 | installation 15 | quickstart 16 | apidocs 17 | changelog 18 | 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`modindex` 25 | * :ref:`search` 26 | 27 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .egg* 2 | *.py[cod] 3 | *swp 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Packages 9 | *.egg 10 | *.egg-info 11 | dist 12 | build 13 | eggs 14 | parts 15 | bin 16 | var 17 | sdist 18 | develop-eggs 19 | .installed.cfg 20 | lib 21 | lib64 22 | __pycache__ 23 | .cache 24 | 25 | # Installer logs 26 | pip-log.txt 27 | 28 | # Unit test / coverage reports 29 | .coverage 30 | .tox 31 | nosetests.xml 32 | .ipynb_checkpoints 33 | docs/test* 34 | 35 | # Translations 36 | *.mo 37 | 38 | # Mr Developer 39 | .mr.developer.cfg 40 | .project 41 | .pydevproject 42 | 43 | README.rst 44 | CONTRIBUTING.rst 45 | LICENSE.rst 46 | CHANGELOG.rst 47 | CODE_OF_CONDUCT.rst 48 | 49 | .vscode* 50 | coverage.xml 51 | htmlcov/* 52 | docs/_build/* -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name="well-schematics", 5 | packages=("well_schematics",), 6 | use_scm_version=True, 7 | setup_requires=["setuptools_scm"], 8 | description="Drawing borehole schematic diagrams with matplotlib", 9 | long_description=open("README.md", "r").read(), 10 | long_description_content_type="text/markdown", 11 | url="https://github.com/kinverarity1/well-schematics", 12 | author="Kent Inverarity", 13 | author_email="kinverarity@hotmail.com", 14 | license="MIT", 15 | install_requires=("matplotlib"), 16 | classifiers=( 17 | "Programming Language :: Python :: 3.5", 18 | "Programming Language :: Python :: 3.6", 19 | ), 20 | keywords="groundwater data", 21 | ) 22 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /well_schematics/_deprecated.py: -------------------------------------------------------------------------------- 1 | from . import plots 2 | 3 | 4 | def draw_simple(pzone_top, pzone_bottom, casing_top=0, pzone_type="screen", **kwargs): 5 | """Draw simple well schematic. 6 | 7 | Args: 8 | pzone_top (float): top of the production zone 9 | pzone_bottom (float): bottom of the production zone 10 | casing_top (float): top of the casing 11 | pzone_type (str): either "screen", "slotted casing", or 12 | "open hole". 13 | 14 | All keyword arguments documented in :func:`plot_single_diameter_well` 15 | are also accepted here. 16 | 17 | The simple model used here assumes that a well consists of solid casing 18 | of one diameter from top, and then immediately below that, one type of 19 | production zone, of the same diameter. 20 | 21 | Returns: a list of the *matplotlib.Artists* created. 22 | 23 | """ 24 | segments = [ 25 | {"type": "casing", "top": casing_top, "bottom": pzone_top}, 26 | {"type": pzone_type, "top": pzone_top, "bottom": pzone_bottom}, 27 | ] 28 | 29 | return plots.plot_single_diameter_well(segments, **kwargs) 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Kent Inverarity 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # well-schematics 2 | 3 | [![Open Source Love svg2](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/kinverarity1/well-schematics/blob/master/LICENSE) 4 | [![PyPI pyversions](https://img.shields.io/pypi/pyversions/well-schematics.svg)](https://pypi.python.org/pypi/well-schematics/) 5 | [![PyPI version shields.io](https://img.shields.io/pypi/v/well-schematics.svg)](https://pypi.python.org/pypi/well-schematics/) 6 | [![Documentation Status](https://readthedocs.org/projects/well-schematics/badge/?version=latest)](http://well-schematics.readthedocs.io/?badge=latest) 7 | 8 | matplotlib code for drawing borehole/well schematic diagrams 9 | 10 | ## Install 11 | 12 | ```bash 13 | $ pip install -U well-schematics 14 | ``` 15 | 16 | ## Usage 17 | 18 | Check out the [documentation](http://well-schematics.readthedocs.io/?badge=latest). 19 | 20 | ![](example.png) 21 | 22 | ## Contributing / roadmap 23 | 24 | Any contributions at all are welcome! 25 | 26 | Please have a look at the current [list of ideas](https://github.com/kinverarity1/well-schematics/labels/enhancement) or check out the [simple roadmap](https://github.com/kinverarity1/well-schematics/milestone/1) for what I am personally planning to work on first. 27 | 28 | ## License 29 | 30 | Free to modify and re-distribute under the [MIT license](LICENSE). 31 | -------------------------------------------------------------------------------- /well_schematics/components.py: -------------------------------------------------------------------------------- 1 | from matplotlib import patches as mpatches 2 | 3 | 4 | class WellComponent: 5 | """Component of a well, e.g. casing, screen. 6 | 7 | Args: 8 | top (float): top depth 9 | bottom (float): bottom depth 10 | diameter (float): diameter 11 | 12 | """ 13 | def __init__(self, top: float, bottom: float, diameter: float): 14 | self.top = top 15 | self.bottom = bottom 16 | self.diameter = diameter 17 | self.left_diameter_fraction = 0.25 18 | self.right_diameter_fraction = 0.75 19 | 20 | 21 | class Casing(WellComponent): 22 | facecolor = "k" 23 | fill = True 24 | 25 | 26 | class SlottedCasing(WellComponent): 27 | facecolor = "k" 28 | fill = False 29 | hatch_density = 3 30 | hatch_symbol = "/" 31 | 32 | @property 33 | def hatch(self): 34 | return self.hatch_symbol * self.hatch_density 35 | 36 | def get_left_artist(self): 37 | return mpatches.Rectangle( 38 | (1 / 4, seg_from), 39 | pipe_width * 0.9, 40 | seg_length, 41 | facecolor="k", 42 | fill=False, 43 | hatch=hatch, 44 | transform=t, 45 | ) 46 | 47 | class WirewoundScreen(WellComponent): 48 | facecolor = "k" 49 | fill = False 50 | hatch_density = 3 51 | hatch_symbol = "-" 52 | 53 | @property 54 | def hatch(self): 55 | return self.hatch_symbol * self.hatch_density 56 | 57 | def get_left_artist(self): 58 | return mpatches.Rectangle( 59 | (1 / 4, seg_from), 60 | pipe_width * 0.9, 61 | seg_length, 62 | facecolor="k", 63 | fill=False, 64 | hatch=hatch, 65 | transform=t, 66 | ) 67 | 68 | class Well: 69 | 70 | diameters_to_fractions = { 71 | 1: ((0.25, 0.75), ), 72 | 2: ((0.2, 0.8), (0.3, 0.7)), 73 | } 74 | 75 | def __init__(self, components): 76 | self.components = components 77 | 78 | @property 79 | def diameters_mapping(self): 80 | diameters = {c.diameter: [] for c in self.components} 81 | for c in self.components: 82 | diameters[c.diameter].append(c) 83 | return diameters 84 | 85 | @property 86 | def diameters(self): 87 | return sorted(tuple([c.diameter for c in self.components])) 88 | 89 | def plot(self): 90 | # Go through and set diameter fractions on the whole well. 91 | for diameter in self.diameters: 92 | -------------------------------------------------------------------------------- /dev well + components.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "ename": "SyntaxError", 10 | "evalue": "unexpected EOF while parsing (components.py, line 92)", 11 | "output_type": "error", 12 | "traceback": [ 13 | "Traceback \u001b[1;36m(most recent call last)\u001b[0m:\n", 14 | " File \u001b[0;32m\"C:\\ProgramData\\miniconda3\\envs\\wrap\\lib\\site-packages\\IPython\\core\\interactiveshell.py\"\u001b[0m, line \u001b[0;32m3427\u001b[0m, in \u001b[0;35mrun_code\u001b[0m\n exec(code_obj, self.user_global_ns, self.user_ns)\n", 15 | "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[1;36m, in \u001b[1;35m\u001b[1;36m\u001b[0m\n\u001b[1;33m from well_schematics.components import *\u001b[0m\n", 16 | "\u001b[1;36m File \u001b[1;32m\"C:\\devapps\\kinverarity\\projects\\well-schematics\\well_schematics\\components.py\"\u001b[1;36m, line \u001b[1;32m92\u001b[0m\n\u001b[1;33m \u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m unexpected EOF while parsing\n" 17 | ] 18 | } 19 | ], 20 | "source": [ 21 | "from well_schematics.components import *" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "comps = [Casing(0, 36, 100), SlottedCasing(36, 40, 100)]\n", 31 | "well = Well(comps)" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "well.diameters" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "pairs = [(1, (0.25, )), (2, (0.2, 0.3))]" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": null, 55 | "metadata": {}, 56 | "outputs": [], 57 | "source": [ 58 | "x = [p[0] for p in pairs]\n", 59 | "y = [p[1] for p in pairs]" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [] 68 | } 69 | ], 70 | "metadata": { 71 | "kernelspec": { 72 | "display_name": "Python 3 (ipykernel)", 73 | "language": "python", 74 | "name": "python3" 75 | }, 76 | "language_info": { 77 | "codemirror_mode": { 78 | "name": "ipython", 79 | "version": 3 80 | }, 81 | "file_extension": ".py", 82 | "mimetype": "text/x-python", 83 | "name": "python", 84 | "nbconvert_exporter": "python", 85 | "pygments_lexer": "ipython3", 86 | "version": "3.10.10" 87 | } 88 | }, 89 | "nbformat": 4, 90 | "nbformat_minor": 4 91 | } 92 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = "well-schematics documentation" 21 | copyright = "2019-2020, Kent Inverarity" 22 | author = "Kent Inverarity" 23 | 24 | master_doc = 'index' 25 | 26 | # -- General configuration --------------------------------------------------- 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be 29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 30 | # ones. 31 | extensions = [ 32 | "sphinx.ext.autodoc", 33 | "sphinx.ext.doctest", 34 | "sphinx.ext.intersphinx", 35 | "sphinx.ext.todo", 36 | "sphinx.ext.coverage", 37 | "sphinx.ext.mathjax", 38 | "sphinx.ext.ifconfig", 39 | "sphinx.ext.viewcode", 40 | "sphinx.ext.githubpages", 41 | "sphinx.ext.napoleon", 42 | ] 43 | 44 | # Add any paths that contain templates here, relative to this directory. 45 | templates_path = ["_templates"] 46 | 47 | # List of patterns, relative to source directory, that match files and 48 | # directories to ignore when looking for source files. 49 | # This pattern also affects html_static_path and html_extra_path. 50 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 51 | 52 | 53 | # -- Options for HTML output ------------------------------------------------- 54 | 55 | # The theme to use for HTML and HTML Help pages. See the documentation for 56 | # a list of builtin themes. 57 | # 58 | html_theme = "sphinx_rtd_theme" 59 | 60 | # Add any paths that contain custom static files (such as style sheets) here, 61 | # relative to this directory. They are copied after the builtin static files, 62 | # so a file named "default.css" will overwrite the builtin "default.css". 63 | html_static_path = ["_static"] 64 | 65 | 66 | intersphinx_mapping = { 67 | "python": ("http://docs.python.org/", None), 68 | "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), 69 | } 70 | intersphinx_cache_limit = 1 71 | 72 | 73 | # -- Options for todo extension ---------------------------------------------- 74 | 75 | # If true, `todo` and `todoList` produce output, else they produce nothing. 76 | todo_include_todos = True 77 | 78 | 79 | def setup(app): 80 | app.add_stylesheet("my_theme.css") 81 | 82 | -------------------------------------------------------------------------------- /well_schematics/plots.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | from matplotlib import patches as mpatches 3 | from matplotlib import transforms as mtransforms 4 | 5 | 6 | PZONE_MAPPING = { 7 | "OH": "open hole", 8 | "open hole": "open hole", 9 | "open-hole": "open hole", 10 | "open": "open hole", 11 | "S": "wirewound screen", 12 | "screen": "wirewound screen", 13 | "wirewound screen": "wirewound screen", 14 | "SC": "slotted casing", 15 | "slots": "slotted casing", 16 | "slotted": "slotted casing", 17 | "slotted casing": "slotted casing", 18 | } 19 | 20 | 21 | def plot_single_diameter_well( 22 | segments, 23 | ax=None, 24 | tight_layout=True, 25 | depth_tick_markers=False, 26 | pipe_width=0.08, 27 | hatch_density=3, 28 | ): 29 | """Draw casing in a well which is a single diameter construction. 30 | 31 | Args: 32 | segments (sequence of dicts): each dict should be in the 33 | form ``{"type": , "top": , "bottom": }``. 34 | The "type" should be either "casing", "pipe", "blank", or "sump", 35 | or a production zone type (either "screen", "slotted casing" or 36 | "open hole"). "top" and "bottom" are the top and bottom of each 37 | segment. 38 | ax (matplotlib.Axes): to draw in 39 | tight_layout (bool): run tight_layout() on ax.figure to rearrange 40 | things to fit. 41 | depth_tick_markers (bool): show tick markers for the vertical 42 | depth axis. Labels will always appear. 43 | pipe_width (float): width of pipe 44 | hatch_density (int): density of screen hatching 45 | 46 | Returns: a list of the artists created. 47 | 48 | """ 49 | if ax is None: 50 | fig = plt.figure(figsize=(1, 5)) 51 | ax = fig.add_subplot(111) 52 | 53 | t = mtransforms.blended_transform_factory(ax.transAxes, ax.transData) 54 | patches = [] 55 | for segment in segments: 56 | seg_type = segment["type"] 57 | seg_from = segment["top"] 58 | seg_to = segment["bottom"] 59 | seg_length = seg_to - seg_from 60 | 61 | if seg_type in PZONE_MAPPING: 62 | seg_type = PZONE_MAPPING[seg_type] 63 | if seg_type == "wirewound screen": 64 | hatch = "-" * hatch_density 65 | elif seg_type == "slotted casing": 66 | hatch = "/" * hatch_density 67 | else: 68 | hatch = None 69 | seg_left = mpatches.Rectangle( 70 | (1 / 4, seg_from), 71 | pipe_width * 0.9, 72 | seg_length, 73 | facecolor="k", 74 | fill=False, 75 | hatch=hatch, 76 | transform=t, 77 | ) 78 | seg_right = mpatches.Rectangle( 79 | (3 / 4 - pipe_width, seg_from), 80 | pipe_width * 0.9, 81 | seg_length, 82 | facecolor="k", 83 | fill=False, 84 | hatch=hatch, 85 | transform=t, 86 | ) 87 | else: 88 | seg_type = "pipe" 89 | seg_left = mpatches.Rectangle( 90 | (1 / 4, seg_from), pipe_width, seg_length, facecolor="k", transform=t 91 | ) 92 | seg_right = mpatches.Rectangle( 93 | (3 / 4 - pipe_width, seg_from), 94 | pipe_width, 95 | seg_length, 96 | facecolor="k", 97 | transform=t, 98 | ) 99 | patches += [seg_left, seg_right] 100 | 101 | for patch in patches: 102 | ax.add_artist(patch) 103 | 104 | ax.grid(False) 105 | for side in ["left", "right", "bottom", "top"]: 106 | ax.spines[side].set_visible(False) 107 | if not depth_tick_markers: 108 | ax.yaxis.set_ticks_position("none") 109 | ax.set_facecolor("white") 110 | ax.set_xticks([]) 111 | ax.set_xlim(0, 1) 112 | ax.set_ylim( 113 | max([s["bottom"] for s in segments]) + 1, min([s["top"] for s in segments]) - 1 114 | ) 115 | if tight_layout: 116 | ax.figure.tight_layout() 117 | 118 | return patches 119 | -------------------------------------------------------------------------------- /well_schematics/simple_model.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | from matplotlib import patches as mpatches 5 | 6 | def parse_items(items, schema_type="drilled_hole_casing"): 7 | """Parse a well construction definition following a schema like:: 8 | 9 | items = [ 10 | {"type": "drilled_hole", "from": 0, "to": 12, "diam": 438, "drilling_order": 0, "label": ""}, 11 | {"type": "drilled_hole", "from": 186, "to": 998.8, "diam": 222, "drilling_order": 2, "label": "main hole"}, 12 | {"type": "drilled_hole", "from": 12, "to": 186, "diam": 311, "drilling_order": 1}, 13 | {"type": "cement_plug", "from": 867, "to": 998.8, "drilling_order": 3}, 14 | {"type": "drilled_hole", "from": 867, "to": 1100, "diam": 149, "drilling_order": 4 }, 15 | {"type": "casing", "from": 0, "to": 12, "inner_diam": 326, "label": "conductor"}, 16 | {"type": "cemented_annulus", "from": 0, "to": 12, "inner_annulus_diam": 326}, 17 | {"type": "casing", "from": 0, "to": 996.5, "inner_diam": 162, "label": "7\" API casing"}, 18 | {"type": "cemented_annulus", "from": 53, "to": 996.5, "inner_annulus_diam": 162}, 19 | {"type": "casing", "from": 0, "to": 184, "inner_diam": 227, "label": "artesian control"}, 20 | {"type": "cemented_annulus", "from": 0, "to": 184, "inner_annulus_diam": 227}, 21 | {"type": "casing", "from": 0, "to": 320, "inner_diam": 104, "label": "fictional reline"}, 22 | {"type": "cemented_annulus", "from": 0, "to": 50, "inner_annulus_diam": 104}, 23 | ] 24 | 25 | """ 26 | if schema_type == "drilled_hole_casing": 27 | return parse_items_for_drilled_hole_casing_schema(items) 28 | else: 29 | raise KeyError( 30 | f"schema_type {schema_type} is not recognised by well_schematics v{__version__}" 31 | ) 32 | 33 | 34 | def parse_items_for_drilled_hole_casing_schema(items): 35 | sorted_items = {} 36 | 37 | drilling_items = [x for x in items if x['type'] in ('drilled_hole', 'cement_plug')] 38 | dh_idxs = [x for x in range(len(drilling_items))] 39 | dh_order_diams = sorted(dh_idxs, key=lambda x: drilling_items[x].get('diam', 9999)) 40 | sorted_items['drilling'] = [dict(i=i, order_diam=dh_order_diams.index(i), **drilling_items[i]) for i in dh_idxs] 41 | 42 | cs_items = [x for x in items if x['type'] in ( 'casing', 'cemented_annulus')] 43 | cs_idxs = [x for x in range(len(cs_items))] 44 | cs_order_diams = sorted(cs_idxs, key=lambda x: cs_items[x]['inner_diam']) 45 | sorted_items['casing'] = [dict(i=i, order_diam=cs_order_diams.index(i), **cs_items[i]) for i in cs_idxs] 46 | 47 | return sorted_items 48 | 49 | 50 | 51 | def parsed_items_to_dataframe(sitems): 52 | """Convert parsed items to a dataframe.""" 53 | keys = [ 54 | "type", 55 | "i", 56 | "order_diam", 57 | "drilling_order", 58 | "from", 59 | "to", 60 | "diam", 61 | "inner_diam", 62 | "label", 63 | ] 64 | df = pd.concat([pd.DataFrame(t) for t in sitems.values()]) 65 | for key in keys: 66 | if not key in df: 67 | df[key] = None 68 | return df[keys] 69 | 70 | 71 | def get_intervals(df): 72 | depths = sorted(set(list(df["from"].unique()) + list(df["to"].unique()))) 73 | return [(depths[i], depths[i + 1]) for i in range(len(depths) - 1)] 74 | 75 | def subset_construction_by_intervals(df): 76 | intervals = get_intervals(df) 77 | for interval in intervals: 78 | subset = df[(df['from'] < interval[1]) & (df['to'] > interval[0])] 79 | # logger.debug(f'interval {interval}\n{str(subset)}\n') 80 | yield interval, subset 81 | 82 | 83 | def plot_simple_model_dataframe(df, fig=None, ax=None): 84 | if ax is None: 85 | if fig is None: 86 | fig = plt.figure(figsize=(10, 5)) 87 | ax = fig.add_subplot(111) 88 | 89 | dh_cols = ["order_diam", "drilling_order", "from", "to", "diam"] 90 | 91 | for ivl, sdf in subset_construction_by_intervals(df): 92 | ax.axhline(ivl[0], ls=':', color='grey', lw=0.5) 93 | ax.axhline(ivl[1], ls=':', color='grey', lw=0.5) 94 | ax.text(500, ivl[1] - (ivl[1] - ivl[0]) / 2, str(ivl), fontsize='xx-small', color='grey', ha='left', va='center') 95 | print(f"{ivl}") 96 | dholes = sdf[sdf.type == "drilled_hole"].sort_values("order_diam") 97 | print(f' > dhole {dholes[dh_cols]}') 98 | for dh_idx, dhole in dholes.iterrows(): 99 | later_dholes = df[df.drilling_order > dhole.drilling_order] 100 | later_max_dhole_diam = later_dholes.diam.max() 101 | if ivl[1] == dhole.to: 102 | ax.plot( 103 | [-1 * dhole.diam, -1 * later_max_dhole_diam], 104 | [ivl[1], ivl[1]], 105 | color="red", 106 | lw=0.5, 107 | ) 108 | ax.plot( 109 | [dhole.diam, later_max_dhole_diam], 110 | [ivl[1], ivl[1]], 111 | color="red", 112 | lw=0.5, 113 | ) 114 | ax.plot( 115 | [-1 * dhole.diam, -1 * dhole.diam], [ivl[0], ivl[1]], color="brown", lw=0.5 116 | ) 117 | ax.plot([dhole.diam, dhole.diam], [ivl[0], ivl[1]], color="brown", lw=0.5) 118 | 119 | 120 | casings = sdf[sdf.type == "casing"].sort_values("order_diam") 121 | for cs_idx, casing in casings.iterrows(): 122 | ax.plot( 123 | [-1 * casing.inner_diam, -1 * casing.inner_diam], 124 | [ivl[0], ivl[1]], 125 | color="black", 126 | lw=1, 127 | ) 128 | ax.plot( 129 | [casing.inner_diam, casing.inner_diam], 130 | [ivl[0], ivl[1]], 131 | color="black", 132 | lw=1, 133 | ) 134 | inner_casing_diam = casings.inner_diam.min() 135 | 136 | plugs = sdf[sdf.type == 'cement_plug'] 137 | print(f'{len(plugs)} plug(s)') 138 | for plug_ix, plug in plugs.iterrows(): 139 | print(plug) 140 | earlier_dholes_than_plug = dholes[dholes.drilling_order <= plug.drilling_order] 141 | later_dholes_than_plug = dholes[dholes.drilling_order > plug.drilling_order] 142 | plug_outer_diam = min(casings.inner_diam.min(), earlier_dholes_than_plug.diam.min()) 143 | plug_inner_diam = later_dholes_than_plug.diam.max() 144 | print(f'plug outer diam: {plug_outer_diam}') 145 | print(f'plug inner diam: {plug_inner_diam}') 146 | patch1 = mpatches.Rectangle((-1 * plug_outer_diam, ivl[0]), plug_outer_diam - plug_inner_diam, ivl[1] - ivl[0], facecolor='grey', alpha=0.25, lw=0) 147 | patch2 = mpatches.Rectangle((plug_inner_diam, ivl[0]), plug_outer_diam - plug_inner_diam, ivl[1] - ivl[0], facecolor='grey', alpha=0.25, lw=0) 148 | ax.add_artist(patch1) 149 | ax.add_artist(patch2) 150 | 151 | print() 152 | 153 | ax.invert_yaxis() 154 | ax.set_xticks(np.arange(0, 500, 100)) 155 | ax.set_xlim(500, -500) 156 | ax.set_xlabel("Diameter (mm)") 157 | ax.set_ylabel('Depth (m)') 158 | return ax -------------------------------------------------------------------------------- /notebooks/Example tutorial.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "53b59d85", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import well_schematics as ws" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 9, 16 | "id": "212f99dc", 17 | "metadata": {}, 18 | "outputs": [ 19 | { 20 | "data": { 21 | "text/plain": [ 22 | "[,\n", 23 | " ,\n", 24 | " ,\n", 25 | " ,\n", 26 | " ,\n", 27 | " ]" 28 | ] 29 | }, 30 | "execution_count": 9, 31 | "metadata": {}, 32 | "output_type": "execute_result" 33 | }, 34 | { 35 | "data": { 36 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFkAAAHpCAYAAADptpBuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAQkUlEQVR4nO3df0xV9ePH8ddN8grKaOm8F9ZQ3ChNavkj29CEfkgt1mxZM61la04lKVhbyaYp08SbMdcKBX+kq5GzP3BpW1tSFotoRRh1RadldG2tO8ZqihJh3vf3j+B+vUEfO9z3fem9vB7bXePcc97nzbPTPdc3V3IZYwwkpq650hMYDhSZQJEJFJlAkQkUmUCRCRSZQJEJFJkgZpG3bduGrKwsjBo1CjNmzMBnn30Wq1Nd/UwM7Nu3z1x77bVm586d5tixY6akpMSMHj3aBAKBWJzuqheTyLNmzTIrVqyI2DZ58mRTVlYWi9Nd9ay/XPT29qKlpQUFBQUR2wsKCtDU1GT7dHEhyfaAnZ2duHjxIjweT8R2j8eDYDBo+3RwuVwDthmHq7f/HMPp8ZcTsxvfYBMfLMhwYD3yuHHjMGLEiAFXbUdHx4Cre7iwHnnkyJGYMWMG6uvrI7bX19cjNzfX9uniQyzupv1v4d58801z7NgxU1paakaPHm1++ukn6+cCMOAR7RjW52h9xD5bt241EyZMMCNHjjTTp083DQ0NMTlPPER29Z0kbg3rdxfy/xSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZwFHkTZs24fbbb0dqairGjx+Phx56CCdOnIjYxxiD8vJyZGRkIDk5Gfn5+Whra7M66bhjHLjvvvvMnj17zNGjR01ra6spLCw0mZmZ5ty5c+F9fD6fSU1NNXV1dcbv95uFCxea9PR0c/bsWSen+s8ADHhEO4b1OUZzcEdHhwFgGhoajDHGhEIh4/V6jc/nC+/T09Nj0tLSTE1NTXQz/RfxEDmq1+QzZ84AAK6//noAQHt7O4LBIAoKCsL7uN1u5OXloampKZpTxbUhRzbG4Pnnn8ecOXOQk5MDAAgGgwAAj8cTsa/H4wk/NxwlDfXA4uJifPfdd2hsbBzwnMvlivjaGDNg23AypCv52WefxcGDB/HJJ5/ghhtuCG/3er0AMOCq7ejoGHB1DyeOIhtjUFxcjP379+Pw4cPIysqKeD4rKwterxf19fXhbb29vWhoaEBubq6dGccjJ3fJoqIik5aWZj799FPz66+/hh/d3d3hfXw+n0lLSzP79+83fr/fLFq0SG/hoplM/2PPnj3hfUKhkFm3bp3xer3G7XabuXPnGr/fb3ve/3NO0Y5hm6vvJHFrsBuq029psBu1TVq7IFBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkgqgib9q0CS6XC6WlpeFtxhiUl5cjIyMDycnJyM/PR1tbW7TzjGtDjtzc3IwdO3bg1ltvjdi+efNmbNmyBVVVVWhubobX68W8efPQ1dUV9WTjlhmCrq4uk52dberr601eXp4pKSkxxhgTCoWM1+s1Pp8vvG9PT49JS0szNTU1QznVZQEY8Ih2DNuGdCWvXLkShYWFuPfeeyO2t7e3IxgMoqCgILzN7XYjLy8PTU1NQ7oIEkGS0wP27duHI0eOoLm5ecBzwWAQAODxeCK2ezweBAKBIU4x/jmK/PPPP6OkpASHDh3CqFGj/nU/l8sV8bUxZsC24cTRy0VLSws6OjowY8YMJCUlISkpCQ0NDXj99deRlJQUvoL7r+h+HR0dA67u4cRR5HvuuQd+vx+tra3hx8yZM/H444+jtbUVkyZNgtfrRX19ffiY3t5eNDQ0IDc31/rk44Wjl4vU1FTk5OREbBs9ejTGjh0b3l5aWoqKigpkZ2cjOzsbFRUVSElJweLFi+3NOs44vvFdzosvvog//vgDzzzzDH7//XfccccdOHToEFJTU22fKm64+t4nxq3BbqhOv6XBbtQ2ae2CQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJHEf+5Zdf8MQTT2Ds2LFISUnBbbfdhpaWlvDzxhiUl5cjIyMDycnJyM/PR1tbm9VJxx3jwG+//WYmTJhgnnrqKfPll1+a9vZ289FHH5kffvghvI/P5zOpqammrq7O+P1+s3DhQpOenm7Onj3r5FT/GYABj2jHsD5HJzuvWrXKzJkz51+fD4VCxuv1Gp/PF97W09Nj0tLSTE1NzdBn+T/EQ2RHLxcHDx7EzJkz8eijj2L8+PGYNm0adu7cGX6+vb0dwWAQBQUF4W1utxt5eXloamoa6n9scc9R5B9//BHV1dXIzs7Ghx9+iBUrVuC5557D22+/DQAIBoMAAI/HE3Gcx+MJPzccJTnZORQKYebMmaioqAAATJs2DW1tbaiursaTTz4Z3s/lckUcZ4wZsG04cXQlp6en4+abb47YNmXKFJw+fRoA4PV6AWDAVdvR0THg6h5OHEWePXs2Tpw4EbHt5MmTmDBhAgAgKysLXq8X9fX14ed7e3vR0NCA3NxcC9ONU07ukl999ZVJSkoyGzduNN9//7155513TEpKiqmtrQ3v4/P5TFpamtm/f7/x+/1m0aJFegvn9ID333/f5OTkGLfbbSZPnmx27NgR8XwoFDLr1q0zXq/XuN1uM3fuXOP3+61N+J/iIbKr7yRxa7AbqtNvabAbtU1auyBQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRR5E/6/FtCWuI58+fRopKSkR21JSUhxFGmyMm266yWrouI7c2dmJ7u5u1NbWoqWlBbW1teju7kZnZ6fjMaqqqjBx4kRcd9116OnpcTTG5cR15H5TpkzB9OnTMWXKlCGPUVlZid7eXuzevdvizP7m6PcnJ7Jz587h888/x7lz56yPnRBXsg07duzAjTfeGJOxEypyIBAY8rH9vwM6FhIm8smTJ7Fs2bIrPY1BJUTkQCCAu+66C2PGjLnSUxlUQkRetmwZ0tLSsH379is9lUElROQxY8bg8OHDGDdu3JWeyqASIvL27dvD/2eIaJ0/f97KOJdKiMi2ruCuri4UFxdbGetSCRHZhvPnz+P+++/HqVOnrI+tyH2Ki4tx9OhRbNu2zfrY+mN1n1OnTuHw4cNISrKfRFdyn23btmHWrFkxGTuhIkezPJmTk2NxJpESJnIwGMTy5cuv9DQGlRCROzs7cffdd8dkmdKGhIi8fPlynDlzBjt27LjSUxlUQry7iOWCuw0JcSXbXHC/cOGClXEulRCRbS249/b2oqyszMpYl0qIyDZcuHABCxcuRGNjo/WxFblPWVkZPvjgA1RWVlofOyFufDY0NjbivffeQ3p6uvWxdSX3qaysRGFhYUzGTqjI0Sy433nnnRZnEilhIsdqwd2GhIgcywV3GxIiciwX3G1IiHcXsVxwtyEhrmSbC+6hUMjKOJdKiMi2FtxDoRB8Pp+VsS6VEJFtCIVCWLlyJerq6qyPrch9fD4ftm/fjrVr11ofW5H71NXVYdeuXZg/f771sR1F/uuvv7BmzRpkZWUhOTkZkyZNwvr16yNuFsYYlJeXIyMjA8nJycjPz0dbW5v1idu2du1aPP300zEZ21HkV155BTU1NaiqqsLx48exefNmvPrqq3jjjTfC+2zevBlbtmxBVVUVmpub4fV6MW/ePHR1dVmf/D9Fs+Aeiyu4n6PIX3zxBebPn4/CwkJMnDgRjzzyCAoKCvD1118D+Psqfu2117B69Wo8/PDDyMnJwVtvvYXu7m7s3bs3Jt9Av1gtuNvgKPKcOXPw8ccf4+TJkwCAb7/9Fo2NjXjggQcAAO3t7QgGgygoKAgf43a7kZeXh6amJovTjhTLBXcbHP0RadWqVThz5gwmT56MESNG4OLFi9i4cSMWLVoE4O/PPgCAx+OJOM7j8UT19zkup6ysDE1NTaisrERpaWnMzjNUjiK/++67qK2txd69ezF16lS0traitLQUGRkZWLJkSXg/l8sVcZwxZsA2m2K54G6Do8gvvPACysrK8NhjjwEAbrnlFgQCAWzatAlLliwJfxA7GAxGfMMdHR0Drm6b+hfcjxw5ErNzRMPRa3J3dzeuuSbykBEjRoTfwmVlZcHr9aK+vj78fG9vLxoaGpCbm2thuoOzueC+a9cua2P1c3QlP/jgg9i4cSMyMzMxdepUfPPNN9iyZUv4/aXL5UJpaSkqKiqQnZ2N7OxsVFRUICUlBYsXL7Y+edtefvllVFdX2x/YOHD27FlTUlJiMjMzzahRo8ykSZPM6tWrzZ9//hneJxQKmXXr1hmv12vcbreZO3eu8fv9Tk7zn7W0tBgApqWlZdCvnYxRVFQU8U8nY1yOo8hXG5uRAZgNGzYMaYzL0dpFn6KiIqxZsyYmYydU5GgW3JcuXWpxJpESJnKsFtxtSIjIsVxwtyEhIsdywd2GhIgcywV3GxIiciwX3G1IiMg2r+ADBw5YG6tfQkS2Zffu3Vi/fr31cRW5z4EDB7B06VIsWLDA+tiK3Gf9+vVYvny5/s5ILC1YsABbt24dsJRrgyL3KSsri0lgIMEiR7PgHqvAQAJFjtmCuwUJEXnXrl146aWXUFRUdKWnMqiEiFxdXY0NGzbEdLkyGgkROZYL7jZcnZ//d2j27Nk4cuQIjh8/PuQx+o+NycfJrP0g6woIBALhn89d+ggEAlGNkZyc7GiMy3EZY4z9f3U8g30yyem39M8xAoEAMjMzo5pXxPiKPPjHymxKiBvf1U6RCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQni/sdP8UBXMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiE/wfIeFUOMiStScAAAAASUVORK5CYII=", 37 | "text/plain": [ 38 | "
" 39 | ] 40 | }, 41 | "metadata": {}, 42 | "output_type": "display_data" 43 | } 44 | ], 45 | "source": [ 46 | "ws.plot_single_diameter_well([\n", 47 | " {\"type\": \"casing\", \"top\": 0, \"bottom\": 72},\n", 48 | " {\"type\": \"slotted casing\", \"top\": 72, \"bottom\": 85},\n", 49 | " {\"type\": \"sump\", \"top\": 85, \"bottom\": 89}, \n", 50 | "], pipe_width=0.11,)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 3, 56 | "id": "4694dc59", 57 | "metadata": {}, 58 | "outputs": [ 59 | { 60 | "data": { 61 | "text/plain": [ 62 | "[,\n", 63 | " ,\n", 64 | " ,\n", 65 | " ,\n", 66 | " ,\n", 67 | " ]" 68 | ] 69 | }, 70 | "execution_count": 3, 71 | "metadata": {}, 72 | "output_type": "execute_result" 73 | }, 74 | { 75 | "data": { 76 | "image/png": "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", 77 | "text/plain": [ 78 | "
" 79 | ] 80 | }, 81 | "metadata": {}, 82 | "output_type": "display_data" 83 | } 84 | ], 85 | "source": [ 86 | "ws.plot_single_diameter_well([\n", 87 | " {\"type\": \"casing\", \"top\": 0, \"bottom\": 72},\n", 88 | " {\"type\": \"screen\", \"top\": 72, \"bottom\": 85},\n", 89 | " {\"type\": \"sump\", \"top\": 85, \"bottom\": 89}\n", 90 | "], )" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 4, 96 | "id": "cfa027ce", 97 | "metadata": {}, 98 | "outputs": [ 99 | { 100 | "data": { 101 | "text/plain": [ 102 | "[,\n", 103 | " ,\n", 104 | " ,\n", 105 | " ]" 106 | ] 107 | }, 108 | "execution_count": 4, 109 | "metadata": {}, 110 | "output_type": "execute_result" 111 | }, 112 | { 113 | "data": { 114 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAFkAAAHpCAYAAADptpBuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAP1ElEQVR4nO3de2jV9R/H8dfRuelZx5Ganh1ic9ohL1MzVzYTDUzDlhRSeCmaSJCptVGkZhdH4NlaMCxXiiaiLLE/vGBEuFk6k27LWh4vTMV5jFCG5WU6L7S9f3/08/vruDN/fLezl558PeCA+36/fs53Tw7n++XAec9jZgbpVF1u9gncDhSZQJEJFJlAkQkUmUCRCRSZQJEJFJmg0yJ//PHHyMrKQvfu3TFq1Ch88803nfVUtz7rBBs3brRu3brZ6tWr7eDBg1ZQUGCpqakWiUQ64+lueZ0S+cEHH7Q5c+ZEbRs0aJAtWrSoM57ulhf3t4urV69i7969mDRpUtT2SZMm4dtvv4330yWEpHgvePr0aTQ3N6Nfv35R2/v164dTp07F++ng8XiifrZ2fnL7z3Xau0ZbOu3CF+uXv37b7SLukfv06YOuXbu2etU2NDS0enXfLuIeOTk5GaNGjUJVVVXU9qqqKowZMybeT5cYOuNqeu0Wbs2aNXbw4EErLCy01NRUO378eNyfC0DUIx7rxFunRDYz++ijjywzM9OSk5Pt/vvvt+rq6k55nkSI7PnvEySs2/ruQv5HkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJnAdeTdu3djypQpCAQC8Hg82Lp1a9R+M0NRURECgQB69OiBRx55BAcOHIjX+SYk15EvXryIESNGoLy8POb+0tJSlJWVoby8HDU1NfD7/Zg4cSIaGxs7fLIJqyMjBgDYli1bnJ9bWlrM7/dbSUmJs+3y5cuWlpZmK1eu7MhT3fAccIuPYojre3J9fT1OnToVNUkrJSUF48ePv20naQFxvvBdmzvEmqSVKDrl7kKTtKLFNbLf7wcATdK6TlwjZ2Vlwe/3R03Sunr1Kqqrq2/fSVpox4TDCxcu4OjRo87P9fX1qK2tRa9evZCRkYHCwkKEQiEEg0EEg0GEQiF4vV7MnDkzrieeUNzejuzcubPVbRMAy8/PN7O/b+OWLFlifr/fUlJSbNy4cRYOh+N8U/Q/159HPNaJN03TirFOvJPoswsCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCRSZQZAJFJlBkAkUmUGQCV5GLi4vxwAMPwOfzoW/fvnjqqadQV1cXdYxpmlZrbr7t/thjj9natWtt//79Vltba3l5eZaRkWEXLlxwjikpKTGfz2ebNm2ycDhs06ZNs/T0dDt//nw8v3jvQAJMCejQig0NDQbAqqurzUzTtNrSoffkc+fOAQB69eoFQNO02tLuyGaGV199FWPHjkV2djYATdNqi+vxONfMnz8f+/btw549e1rt0zStaO16Jb/88svYtm0bdu7cibvvvtvZrmlasbmKbGaYP38+Nm/ejK+//hpZWVlR+zVNqw1urpIvvfSSpaWl2a5du+zkyZPOo6mpyTmmpKTE0tLSbPPmzRYOh23GjBm6hWvvifzzsXbtWucYTdNqTdO0YqwT7yT67IJAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJlAkQkUmUCRCRSZQJEJFJnAVeQVK1Zg+PDh6NmzJ3r27Inc3Fx8+eWXzn7TJK3Y3Hzbfdu2bfbFF19YXV2d1dXV2eLFi61bt262f/9+M+NP0jJLjCkBHV7xzjvvtE8++eSmTNIyS4zI7X5Pbm5uxsaNG3Hx4kXk5uZqktYNuB70FA6HkZubi8uXL+OOO+7Ali1bMGTIECdkrElakUgkPmeboFxHvvfee1FbW4uzZ89i06ZNyM/PR3V1tbNfk7Rac/12kZycjHvuuQc5OTkoLi7GiBEj8MEHH2iS1g10+D7ZzHDlyhVN0roRN1fJN954w3bv3m319fW2b98+W7x4sXXp0sUqKyvNjD9Jyywx7i5crTh79mzLzMy05ORku+uuu2zChAlOYDP+JC2zxIisaVox1ol3En12QaDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTNChyMXFxfB4PCgsLHS2mSZqtdLuyDU1NVi1ahWGDx8etb20tBRlZWUoLy9HTU0N/H4/Jk6ciMbGxg6fbMJqz2iBxsZGCwaDVlVVZePHj7eCggIzs5syUQsJMIqhXa/kefPmIS8vD48++mjUdk3Uis31oKeNGzfi559/Rk1NTat91+YPaaJWNFeRf/vtNxQUFKCyshLdu3dv8zhN1Irm6u1i7969aGhowKhRo5CUlISkpCRUV1fjww8/RFJSkvMK1kStaK4iT5gwAeFwGLW1tc4jJycHzz77LGprazFgwABN1IrB1duFz+dDdnZ21LbU1FT07t3b2V5YWIhQKIRgMIhgMIhQKASv14uZM2fG76wTjOsL3/+zYMECXLp0CXPnzsWZM2cwevRoVFZWwufzxfupEoamacVYJ95J9NkFgSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiEygygSITKDKBIhMoMoEiE7iKXFRUBI/HE/Xw+/3OftOQp5hcv5KHDh2KkydPOo9wOOzs05CnNrgZWLRkyRIbMWJEzH03Y8iT2b900NORI0cQCASQlZWF6dOn49ixYwA05OlGXEUePXo01q9fj+3bt2P16tU4deoUxowZgz/++OOGQ56uH5dzu3E1VGTy5MnOv4cNG4bc3FwMHDgQ69atw0MPPQRAQ55i6dAtXGpqKoYNG4YjR444dxka8tRahyJfuXIFhw4dQnp6OrKysjTkqS1urpKvvfaa7dq1y44dO2bff/+9PfHEE+bz+ez48eNmZlZSUmJpaWm2efNmC4fDNmPGDEtPT7fz58/H/Yp9DRLg7sLVitOmTbP09HTr1q2bBQIBmzp1qh04cMDZ39LSYkuWLDG/328pKSk2btw4C4fDcT/pf0qEyBr0FGOdeCfRZxcEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDIBIpMoMgEikygyASKTKDI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", 115 | "text/plain": [ 116 | "
" 117 | ] 118 | }, 119 | "metadata": {}, 120 | "output_type": "display_data" 121 | } 122 | ], 123 | "source": [ 124 | "ws.plot_single_diameter_well([\n", 125 | " {\"type\": \"casing\", \"top\": 0, \"bottom\": 72},\n", 126 | " {\"type\": \"open hole\", \"top\": 72, \"bottom\": 85},\n", 127 | "], )" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "id": "40ae5147", 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "id": "bcf23b4d", 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [] 145 | } 146 | ], 147 | "metadata": { 148 | "kernelspec": { 149 | "display_name": "Python 3 (ipykernel)", 150 | "language": "python", 151 | "name": "python3" 152 | }, 153 | "language_info": { 154 | "codemirror_mode": { 155 | "name": "ipython", 156 | "version": 3 157 | }, 158 | "file_extension": ".py", 159 | "mimetype": "text/x-python", 160 | "name": "python", 161 | "nbconvert_exporter": "python", 162 | "pygments_lexer": "ipython3", 163 | "version": "3.10.10" 164 | } 165 | }, 166 | "nbformat": 4, 167 | "nbformat_minor": 5 168 | } 169 | -------------------------------------------------------------------------------- /notebooks/SAG link.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "ename": "DatabaseError", 10 | "evalue": "ORA-12154: TNS:could not resolve the connect identifier specified", 11 | "output_type": "error", 12 | "traceback": [ 13 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", 14 | "\u001b[1;31mDatabaseError\u001b[0m Traceback (most recent call last)", 15 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mdew_gwdata\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mgd\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mdb\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgd\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msageodata\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[0mwells\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdb\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfind_wells\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"GSN007\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 16 | "\u001b[1;32mc:\\devapps\\kinverarity\\projects\\dew_gwdata\\dew_gwdata\\_sageodata.py\u001b[0m in \u001b[0;36msageodata\u001b[1;34m(user, password, **kwargs)\u001b[0m\n\u001b[0;32m 66\u001b[0m \"\"\"\n\u001b[0;32m 67\u001b[0m \u001b[0mconnect_string\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmake_connection_string\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 68\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mSAGeodataConnection\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0muser\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0muser\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpassword\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mpassword\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdsn\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mconnect_string\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 69\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 70\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", 17 | "\u001b[1;32mc:\\devapps\\kinverarity\\projects\\dew_gwdata\\dew_gwdata\\_sageodata.py\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 87\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 88\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 89\u001b[1;33m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 90\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 91\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mdew_gwdata\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0m__version__\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", 18 | "\u001b[1;31mDatabaseError\u001b[0m: ORA-12154: TNS:could not resolve the connect identifier specified" 19 | ] 20 | } 21 | ], 22 | "source": [ 23 | "import dew_gwdata as gd\n", 24 | "db = gd.sageodata()\n", 25 | "wells = db.find_wells(\"GSN007\")" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "con = db.construction_events(db.find_wells('gsn7'))\n", 35 | "con" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 3, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/html": [ 46 | "
\n", 47 | "\n", 60 | "\n", 61 | " \n", 62 | " \n", 63 | " \n", 64 | " \n", 65 | " \n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | "
well_idconstruction_aquifercompletion_nocompletion_dateevent_typedrill_methoddepth_fromdepth_todiamcore_flaglengthwidthcommentscreated_bycreation_datemodified_bymodified_date
0GSN007None3293582017-04-30CRTM0.012.0438NNoneNoneNoneGAHJM2017-06-09 12:02:21NoneNaT
1GSN007None3293582017-04-30CRTM12.0186.0311NNoneNoneNoneGAHJM2017-06-09 12:02:21GAHJM2017-09-19 13:16:21
2GSN007None3293582017-04-30CRTM186.0998.8222NNoneNoneNoneGAHJM2017-06-09 12:02:21GAHJM2017-09-19 13:16:21
3GSN007None3293582017-04-30CRTM998.81100.0149NNoneNoneNoneGAHJM2017-06-09 12:02:21GAHJM2017-09-19 13:16:21
\n", 166 | "
" 167 | ], 168 | "text/plain": [ 169 | " well_id construction_aquifer completion_no completion_date event_type \\\n", 170 | "0 GSN007 None 329358 2017-04-30 C \n", 171 | "1 GSN007 None 329358 2017-04-30 C \n", 172 | "2 GSN007 None 329358 2017-04-30 C \n", 173 | "3 GSN007 None 329358 2017-04-30 C \n", 174 | "\n", 175 | " drill_method depth_from depth_to diam core_flag length width comments \\\n", 176 | "0 RTM 0.0 12.0 438 N None None None \n", 177 | "1 RTM 12.0 186.0 311 N None None None \n", 178 | "2 RTM 186.0 998.8 222 N None None None \n", 179 | "3 RTM 998.8 1100.0 149 N None None None \n", 180 | "\n", 181 | " created_by creation_date modified_by modified_date \n", 182 | "0 GAHJM 2017-06-09 12:02:21 None NaT \n", 183 | "1 GAHJM 2017-06-09 12:02:21 GAHJM 2017-09-19 13:16:21 \n", 184 | "2 GAHJM 2017-06-09 12:02:21 GAHJM 2017-09-19 13:16:21 \n", 185 | "3 GAHJM 2017-06-09 12:02:21 GAHJM 2017-09-19 13:16:21 " 186 | ] 187 | }, 188 | "execution_count": 3, 189 | "metadata": {}, 190 | "output_type": "execute_result" 191 | } 192 | ], 193 | "source": [ 194 | "drill = db.drilled_intervals(wells)\n", 195 | "drill.pipe(gd.cleanup_columns)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 4, 201 | "metadata": {}, 202 | "outputs": [ 203 | { 204 | "data": { 205 | "text/html": [ 206 | "
\n", 207 | "\n", 220 | "\n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | " \n", 261 | " \n", 262 | " \n", 263 | " \n", 264 | " \n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | "
well_idconstruction_aquifercompletion_nocompletion_dateevent_typecasing_typedepth_fromdepth_tomaterialcase_diam...cement_tocementing_methodpressure_cementpressure_cement_frompressure_cement_tocommentscreated_bycreation_datemodified_bymodified_date
0GSN007None3293582017-04-30CS0.012.0STLOFG326...12.0NDCNNoneNoneAPI 5LGAHJM2017-06-09 12:02:21GAHJM2017-09-19 13:16:21
1GSN007None3293582017-04-30CP0.0996.5STLOFG162...996.5DSPCNNoneNoneAPI 5LGAHJM2017-06-09 12:02:21NoneNaT
2GSN007None3293582017-04-30CS0.0184.0STLOFG227...184.0NDCNNoneNoneAPI 5LGAHJM2017-06-09 12:02:21GAHJM2017-09-19 13:16:21
\n", 322 | "

3 rows × 26 columns

\n", 323 | "
" 324 | ], 325 | "text/plain": [ 326 | " well_id construction_aquifer completion_no completion_date event_type \\\n", 327 | "0 GSN007 None 329358 2017-04-30 C \n", 328 | "1 GSN007 None 329358 2017-04-30 C \n", 329 | "2 GSN007 None 329358 2017-04-30 C \n", 330 | "\n", 331 | " casing_type depth_from depth_to material case_diam ... cement_to \\\n", 332 | "0 S 0.0 12.0 STLOFG 326 ... 12.0 \n", 333 | "1 P 0.0 996.5 STLOFG 162 ... 996.5 \n", 334 | "2 S 0.0 184.0 STLOFG 227 ... 184.0 \n", 335 | "\n", 336 | " cementing_method pressure_cement pressure_cement_from pressure_cement_to \\\n", 337 | "0 NDC N None None \n", 338 | "1 DSPC N None None \n", 339 | "2 NDC N None None \n", 340 | "\n", 341 | " comments created_by creation_date modified_by modified_date \n", 342 | "0 API 5L GAHJM 2017-06-09 12:02:21 GAHJM 2017-09-19 13:16:21 \n", 343 | "1 API 5L GAHJM 2017-06-09 12:02:21 None NaT \n", 344 | "2 API 5L GAHJM 2017-06-09 12:02:21 GAHJM 2017-09-19 13:16:21 \n", 345 | "\n", 346 | "[3 rows x 26 columns]" 347 | ] 348 | }, 349 | "execution_count": 4, 350 | "metadata": {}, 351 | "output_type": "execute_result" 352 | } 353 | ], 354 | "source": [ 355 | "casing = db.casing_strings(wells)\n", 356 | "casing.pipe(gd.cleanup_columns)" 357 | ] 358 | }, 359 | { 360 | "cell_type": "code", 361 | "execution_count": 5, 362 | "metadata": {}, 363 | "outputs": [ 364 | { 365 | "data": { 366 | "text/html": [ 367 | "
\n", 368 | "\n", 381 | "\n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | "
well_idconstruction_aquifercompletion_nocompletion_dateevent_typepzone_typepzone_frompzone_topzone_materialpzone_diam...trade_namebase_completioncommentscreation_datecreated_bymodified_datemodified_bypzone_nowcr_load_nowcr_load_data_no
0GSN007None3293582017-04-30COH996.51100.0NoneNone...NoneNoneNone2017-06-09 12:02:21GAHJMNoneNone9754111078
\n", 435 | "

1 rows × 22 columns

\n", 436 | "
" 437 | ], 438 | "text/plain": [ 439 | " well_id construction_aquifer completion_no completion_date event_type \\\n", 440 | "0 GSN007 None 329358 2017-04-30 C \n", 441 | "\n", 442 | " pzone_type pzone_from pzone_to pzone_material pzone_diam ... trade_name \\\n", 443 | "0 OH 996.5 1100.0 None None ... None \n", 444 | "\n", 445 | " base_completion comments creation_date created_by modified_date \\\n", 446 | "0 None None 2017-06-09 12:02:21 GAHJM None \n", 447 | "\n", 448 | " modified_by pzone_no wcr_load_no wcr_load_data_no \n", 449 | "0 None 97541 110 78 \n", 450 | "\n", 451 | "[1 rows x 22 columns]" 452 | ] 453 | }, 454 | "execution_count": 5, 455 | "metadata": {}, 456 | "output_type": "execute_result" 457 | } 458 | ], 459 | "source": [ 460 | "pzones = db.production_zones(wells)\n", 461 | "pzones.pipe(gd.cleanup_columns)" 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "execution_count": 6, 467 | "metadata": {}, 468 | "outputs": [ 469 | { 470 | "data": { 471 | "text/html": [ 472 | "
\n", 473 | "\n", 486 | "\n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | "
0
well_idGSN007
dh_no294482
unit_long664200024
unit_hyphen6642-24
obs_noGSN007
dh_nameMIRRA MITTA 2
easting277070
northing6.93188e+06
zone54
latitude-27.719
longitude138.739
aquiferJK-a+K-c
construction_aquiferNone
completion_no329358
completion_date2017-04-30 00:00:00
event_typeC
pzone_typeOH
pzone_from996.5
pzone_to1100
pzone_materialNone
pzone_diamNone
apertureNone
outer_diamNone
trade_nameNone
base_completionNone
commentsNone
creation_date2017-06-09 12:02:21
created_byGAHJM
modified_dateNone
modified_byNone
pzone_no97541
wcr_load_no110
wcr_load_data_no78
\n", 628 | "
" 629 | ], 630 | "text/plain": [ 631 | " 0\n", 632 | "well_id GSN007\n", 633 | "dh_no 294482\n", 634 | "unit_long 664200024\n", 635 | "unit_hyphen 6642-24\n", 636 | "obs_no GSN007\n", 637 | "dh_name MIRRA MITTA 2\n", 638 | "easting 277070\n", 639 | "northing 6.93188e+06\n", 640 | "zone 54\n", 641 | "latitude -27.719\n", 642 | "longitude 138.739\n", 643 | "aquifer JK-a+K-c\n", 644 | "construction_aquifer None\n", 645 | "completion_no 329358\n", 646 | "completion_date 2017-04-30 00:00:00\n", 647 | "event_type C\n", 648 | "pzone_type OH\n", 649 | "pzone_from 996.5\n", 650 | "pzone_to 1100\n", 651 | "pzone_material None\n", 652 | "pzone_diam None\n", 653 | "aperture None\n", 654 | "outer_diam None\n", 655 | "trade_name None\n", 656 | "base_completion None\n", 657 | "comments None\n", 658 | "creation_date 2017-06-09 12:02:21\n", 659 | "created_by GAHJM\n", 660 | "modified_date None\n", 661 | "modified_by None\n", 662 | "pzone_no 97541\n", 663 | "wcr_load_no 110\n", 664 | "wcr_load_data_no 78" 665 | ] 666 | }, 667 | "execution_count": 6, 668 | "metadata": {}, 669 | "output_type": "execute_result" 670 | } 671 | ], 672 | "source": [ 673 | "pzones.T" 674 | ] 675 | }, 676 | { 677 | "cell_type": "code", 678 | "execution_count": null, 679 | "metadata": {}, 680 | "outputs": [], 681 | "source": [ 682 | "items = [\n", 683 | " {\"type\": \"drilled_hole\", \"from\": 998.8, \"to\": 1100, \"diam\": 149, }\n", 684 | " {\"type\": \"drilled_hole\", \"from\": 0, \"to\": 12, \"diam\": 438, \"label\": \"\"},\n", 685 | " {\"type\": \"drilled_hole\", \"from\": 186, \"to\": 998.8, \"diam\": 222, \"label\": \"main hole\"},\n", 686 | " {\"type\": \"drilled_hole\", \"from\": 12, \"to\": 186, \"diam\": 311},\n", 687 | " {\"type\": \"casing\", \"from\": 0, \"to\": 12, \"inner_diam\": 326, \"label\": \"conductor\"},\n", 688 | " {\"type\": \"casing\", \"from\": 0, \"to\": 996.5, \"inner_diam\": 162, \"label\": \"7\\\" API casing\"},\n", 689 | " {\"type\": \"casing\", \"from\": 0, \"to\": 184, \"inner_diam\": 227, \"label\": \"artesian control\"},\n", 690 | "]" 691 | ] 692 | }, 693 | { 694 | "cell_type": "code", 695 | "execution_count": null, 696 | "metadata": {}, 697 | "outputs": [], 698 | "source": [] 699 | } 700 | ], 701 | "metadata": { 702 | "kernelspec": { 703 | "display_name": "Python 3 (ipykernel)", 704 | "language": "python", 705 | "name": "python3" 706 | }, 707 | "language_info": { 708 | "codemirror_mode": { 709 | "name": "ipython", 710 | "version": 3 711 | }, 712 | "file_extension": ".py", 713 | "mimetype": "text/x-python", 714 | "name": "python", 715 | "nbconvert_exporter": "python", 716 | "pygments_lexer": "ipython3", 717 | "version": "3.10.10" 718 | } 719 | }, 720 | "nbformat": 4, 721 | "nbformat_minor": 4 722 | } 723 | -------------------------------------------------------------------------------- /notebooks/dev simple model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import matplotlib.pyplot as plt\n", 10 | "from matplotlib import ticker as mticker\n", 11 | "from matplotlib import patches as mpatches\n", 12 | "import logging" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 2, 18 | "metadata": {}, 19 | "outputs": [], 20 | "source": [ 21 | "logger = logging.getLogger()\n", 22 | "logging.basicConfig(level=logging.INFO)" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 3, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "%matplotlib inline\n", 32 | "# plt.style.use('ggplot')\n", 33 | "plt.rcParams['figure.dpi'] = 120\n", 34 | "# plt.rcParams['axes.spines.right'] = False" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 4, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "import pandas as pd\n", 44 | "import numpy as np" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 14, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "def parse_items(items, schema_type=\"drilled_hole_casing\"):\n", 54 | " if schema_type == \"drilled_hole_casing\":\n", 55 | " return parse_items_for_drilled_hole_casing_schema(items)\n", 56 | " else:\n", 57 | " raise KeyError(\n", 58 | " f\"schema_type {schema_type} is not recognised by well_schematics v{__version__}\"\n", 59 | " )\n", 60 | "\n", 61 | "\n", 62 | "def parse_items_for_drilled_hole_casing_schema(items):\n", 63 | " sorted_items = {}\n", 64 | " \n", 65 | " drilling_items = [x for x in items if x['type'] in ('drilled_hole', 'cement_plug')]\n", 66 | " dh_idxs = [x for x in range(len(drilling_items))]\n", 67 | " dh_order_diams = sorted(dh_idxs, key=lambda x: drilling_items[x].get('diam', 9999))\n", 68 | " sorted_items['drilling'] = [dict(i=i, order_diam=dh_order_diams.index(i), **drilling_items[i]) for i in dh_idxs]\n", 69 | " \n", 70 | " cs_items = [x for x in items if x['type'] == 'casing']\n", 71 | " cs_idxs = [x for x in range(len(cs_items))]\n", 72 | " cs_order_diams = sorted(cs_idxs, key=lambda x: cs_items[x]['inner_diam'])\n", 73 | " sorted_items['casing'] = [dict(i=i, order_diam=cs_order_diams.index(i), **cs_items[i]) for i in cs_idxs]\n", 74 | " \n", 75 | " return sorted_items\n", 76 | " \n", 77 | "\n", 78 | "\n", 79 | "def parsed_items_to_dataframe(sitems):\n", 80 | " keys = [\n", 81 | " \"type\",\n", 82 | " \"i\",\n", 83 | " \"order_diam\",\n", 84 | " \"drilling_order\",\n", 85 | " \"from\",\n", 86 | " \"to\",\n", 87 | " \"diam\",\n", 88 | " \"inner_diam\",\n", 89 | " \"label\",\n", 90 | " ]\n", 91 | " df = pd.concat([pd.DataFrame(t) for t in sitems.values()])\n", 92 | " for key in keys:\n", 93 | " if not key in df:\n", 94 | " df[key] = None\n", 95 | " return df[keys]" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 15, 101 | "metadata": {}, 102 | "outputs": [], 103 | "source": [ 104 | "def get_intervals(df):\n", 105 | " depths = sorted(set(list(df[\"from\"].unique()) + list(df[\"to\"].unique())))\n", 106 | " return [(depths[i], depths[i + 1]) for i in range(len(depths) - 1)]\n", 107 | "\n", 108 | "def subset_construction_by_intervals(df):\n", 109 | " intervals = get_intervals(df)\n", 110 | " for interval in intervals:\n", 111 | " subset = df[(df['from'] < interval[1]) & (df['to'] > interval[0])]\n", 112 | " yield interval, subset" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 16, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "def parse(items):\n", 129 | " if isinstance(items, pd.DataFrame):\n", 130 | " items = items.to_dict(orient=\"records\")\n", 131 | " parsed_items = parse_items(items)\n", 132 | " return parsed_items_to_dataframe(parsed_items)\n", 133 | " " 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": null, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": 38, 146 | "metadata": {}, 147 | "outputs": [], 148 | "source": [ 149 | "def chart_parsed_dataframe(df):\n", 150 | "\n", 151 | " fig = plt.figure(figsize=(8, 6))\n", 152 | " ax = fig.add_subplot(111)\n", 153 | " dh_cols = [\"order_diam\", \"drilling_order\", \"from\", \"to\", \"diam\"]\n", 154 | "\n", 155 | " for ivl, sdf in subset_construction_by_intervals(df):\n", 156 | " logger.info(f\"Depth interval: {ivl}\")\n", 157 | " ax.axhline(ivl[0], ls=':', color='grey', lw=0.5)\n", 158 | " ax.axhline(ivl[1], ls=':', color='grey', lw=0.5)\n", 159 | " ax.text(500, ivl[1] - (ivl[1] - ivl[0]) / 2, str(ivl), fontsize='xx-small', color='grey', ha='left', va='center')\n", 160 | "\n", 161 | " dholes = sdf[sdf.type == \"drilled_hole\"].sort_values(\"order_diam\")\n", 162 | " with pd.option_context(\"display.width\", 1000):\n", 163 | " logger.info(f\"Drilled hole sections in interval, ordered by diameter:\\n{dholes}\")\n", 164 | " for dh_idx, dhole in dholes.iterrows():\n", 165 | " later_dholes = df[df.drilling_order > dhole.drilling_order]\n", 166 | " later_max_dhole_diam = later_dholes.diam.max()\n", 167 | " logger.info(f\"For drillhole {dh_idx}, later_max_dhole_diam={later_max_dhole_diam}\")\n", 168 | " if ivl[1] == dhole.to: \n", 169 | " ax.plot(\n", 170 | " [-1 * dhole.diam, -1 * later_max_dhole_diam],\n", 171 | " [ivl[1], ivl[1]],\n", 172 | " color=\"red\",\n", 173 | " lw=1,\n", 174 | " )\n", 175 | " ax.plot(\n", 176 | " [dhole.diam, later_max_dhole_diam],\n", 177 | " [ivl[1], ivl[1]],\n", 178 | " color=\"red\",\n", 179 | " lw=1,\n", 180 | " )\n", 181 | " ax.plot(\n", 182 | " [-1 * dhole.diam, -1 * dhole.diam], [ivl[0], ivl[1]], color=\"brown\", lw=0.5\n", 183 | " )\n", 184 | " ax.plot([dhole.diam, dhole.diam], [ivl[0], ivl[1]], color=\"brown\", lw=0.5)\n", 185 | "\n", 186 | "\n", 187 | " casings = sdf[sdf.type == \"casing\"].sort_values(\"order_diam\")\n", 188 | " for cs_idx, casing in casings.iterrows():\n", 189 | " ax.plot(\n", 190 | " [-1 * casing.inner_diam, -1 * casing.inner_diam],\n", 191 | " [ivl[0], ivl[1]],\n", 192 | " color=\"black\",\n", 193 | " lw=1,\n", 194 | " )\n", 195 | " ax.plot(\n", 196 | " [casing.inner_diam, casing.inner_diam],\n", 197 | " [ivl[0], ivl[1]],\n", 198 | " color=\"black\",\n", 199 | " lw=1,\n", 200 | " )\n", 201 | " inner_casing_diam = casings.inner_diam.min()\n", 202 | "\n", 203 | " \n", 204 | " # This doesn't always work.\n", 205 | " plugs = sdf[sdf.type == 'cement_plug']\n", 206 | " for plug_ix, plug in plugs.iterrows():\n", 207 | " earlier_dholes_than_plug = dholes[dholes.drilling_order <= plug.drilling_order]\n", 208 | " later_dholes_than_plug = dholes[dholes.drilling_order > plug.drilling_order]\n", 209 | " plug_outer_diam = min(casings.inner_diam.min(), earlier_dholes_than_plug.diam.min())\n", 210 | " plug_inner_diam = later_dholes_than_plug.diam.max()\n", 211 | " patch1 = mpatches.Rectangle(\n", 212 | " (-1 * plug_outer_diam, ivl[0]), \n", 213 | " plug_outer_diam - plug_inner_diam, \n", 214 | " ivl[1] - ivl[0], \n", 215 | " facecolor='grey', alpha=0.5, lw=0\n", 216 | " )\n", 217 | " patch2 = mpatches.Rectangle(\n", 218 | " (plug_inner_diam, ivl[0]), \n", 219 | " plug_outer_diam - plug_inner_diam, \n", 220 | " ivl[1] - ivl[0], \n", 221 | " facecolor='grey', alpha=0.5, lw=0\n", 222 | " )\n", 223 | " ax.add_artist(patch1)\n", 224 | " ax.add_artist(patch2)\n", 225 | "\n", 226 | " print()\n", 227 | "\n", 228 | " ax.invert_yaxis()\n", 229 | " ax.set_xticks(np.arange(0, 500, 100))\n", 230 | " ax.set_xlim(500, -500)\n", 231 | " ax.set_xlabel(\"Diameter (mm)\")\n", 232 | " ax.set_ylabel('Depth (m)')" 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": {}, 239 | "outputs": [], 240 | "source": [] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": 39, 245 | "metadata": {}, 246 | "outputs": [ 247 | { 248 | "data": { 249 | "text/html": [ 250 | "
\n", 251 | "\n", 264 | "\n", 265 | " \n", 266 | " \n", 267 | " \n", 268 | " \n", 269 | " \n", 270 | " \n", 271 | " \n", 272 | " \n", 273 | " \n", 274 | " \n", 275 | " \n", 276 | " \n", 277 | " \n", 278 | " \n", 279 | " \n", 280 | " \n", 281 | " \n", 282 | " \n", 283 | " \n", 284 | " \n", 285 | " \n", 286 | " \n", 287 | " \n", 288 | " \n", 289 | " \n", 290 | " \n", 291 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | "
typeiorder_diamdrilling_orderfromtodiaminner_diamlabel
0drilled_hole030.0012.0438.0
0casing03012.0326.0conductor
2casing220184.0227.0artesian control
3casing300320.0104.0fictional reline
1casing110996.5162.07\" API casing
2drilled_hole221.012186.0311.0
1drilled_hole112.0186998.8222.0main hole
3cement_plug343.0867998.8
4drilled_hole404.08671100.0149.0
\n", 390 | "
" 391 | ], 392 | "text/plain": [ 393 | " type i order_diam drilling_order from to diam inner_diam \\\n", 394 | "0 drilled_hole 0 3 0.0 0 12.0 438.0 \n", 395 | "0 casing 0 3 0 12.0 326.0 \n", 396 | "2 casing 2 2 0 184.0 227.0 \n", 397 | "3 casing 3 0 0 320.0 104.0 \n", 398 | "1 casing 1 1 0 996.5 162.0 \n", 399 | "2 drilled_hole 2 2 1.0 12 186.0 311.0 \n", 400 | "1 drilled_hole 1 1 2.0 186 998.8 222.0 \n", 401 | "3 cement_plug 3 4 3.0 867 998.8 \n", 402 | "4 drilled_hole 4 0 4.0 867 1100.0 149.0 \n", 403 | "\n", 404 | " label \n", 405 | "0 \n", 406 | "0 conductor \n", 407 | "2 artesian control \n", 408 | "3 fictional reline \n", 409 | "1 7\" API casing \n", 410 | "2 \n", 411 | "1 main hole \n", 412 | "3 \n", 413 | "4 " 414 | ] 415 | }, 416 | "execution_count": 39, 417 | "metadata": {}, 418 | "output_type": "execute_result" 419 | } 420 | ], 421 | "source": [ 422 | "items = [\n", 423 | " {\"type\": \"drilled_hole\", \"from\": 0, \"to\": 12, \"diam\": 438, \"drilling_order\": 0, \"label\": \"\"},\n", 424 | " {\"type\": \"drilled_hole\", \"from\": 186, \"to\": 998.8, \"diam\": 222, \"drilling_order\": 2, \"label\": \"main hole\"},\n", 425 | " {\"type\": \"drilled_hole\", \"from\": 12, \"to\": 186, \"diam\": 311, \"drilling_order\": 1},\n", 426 | " {\"type\": \"cement_plug\", \"from\": 867, \"to\": 998.8, \"drilling_order\": 3},\n", 427 | " {\"type\": \"drilled_hole\", \"from\": 867, \"to\": 1100, \"diam\": 149, \"drilling_order\": 4 },\n", 428 | " {\"type\": \"casing\", \"from\": 0, \"to\": 12, \"inner_diam\": 326, \"label\": \"conductor\"},\n", 429 | " {\"type\": \"cemented_annulus\", \"from\": 0, \"to\": 12, \"inner_annulus_diam\": 326},\n", 430 | " {\"type\": \"casing\", \"from\": 0, \"to\": 996.5, \"inner_diam\": 162, \"label\": \"7\\\" API casing\"},\n", 431 | " {\"type\": \"cemented_annulus\", \"from\": 53, \"to\": 996.5, \"inner_annulus_diam\": 162},\n", 432 | " {\"type\": \"casing\", \"from\": 0, \"to\": 184, \"inner_diam\": 227, \"label\": \"artesian control\"},\n", 433 | " {\"type\": \"cemented_annulus\", \"from\": 0, \"to\": 184, \"inner_annulus_diam\": 227},\n", 434 | " {\"type\": \"casing\", \"from\": 0, \"to\": 320, \"inner_diam\": 104, \"label\": \"fictional reline\"},\n", 435 | " {\"type\": \"cemented_annulus\", \"from\": 0, \"to\": 50, \"inner_annulus_diam\": 104},\n", 436 | "]\n", 437 | "\n", 438 | "sorted_items = parse_items(items)\n", 439 | "df = parsed_items_to_dataframe(sorted_items)\n", 440 | "df.sort_values(['from', 'to']).fillna('')" 441 | ] 442 | }, 443 | { 444 | "cell_type": "code", 445 | "execution_count": 40, 446 | "metadata": {}, 447 | "outputs": [ 448 | { 449 | "name": "stderr", 450 | "output_type": "stream", 451 | "text": [ 452 | "INFO:root:Depth interval: (0, 12)\n", 453 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 454 | " type i order_diam drilling_order from to diam inner_diam label\n", 455 | "0 drilled_hole 0 3 0.0 0 12.0 438.0 NaN \n", 456 | "INFO:root:For drillhole 0, later_max_dhole_diam=311.0\n", 457 | "INFO:root:Depth interval: (12, 184.0)\n", 458 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 459 | " type i order_diam drilling_order from to diam inner_diam label\n", 460 | "2 drilled_hole 2 2 1.0 12 186.0 311.0 NaN NaN\n", 461 | "INFO:root:For drillhole 2, later_max_dhole_diam=222.0\n", 462 | "INFO:root:Depth interval: (184.0, 186)\n", 463 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 464 | " type i order_diam drilling_order from to diam inner_diam label\n", 465 | "2 drilled_hole 2 2 1.0 12 186.0 311.0 NaN NaN\n", 466 | "INFO:root:For drillhole 2, later_max_dhole_diam=222.0\n", 467 | "INFO:root:Depth interval: (186, 320.0)\n", 468 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 469 | " type i order_diam drilling_order from to diam inner_diam label\n", 470 | "1 drilled_hole 1 1 2.0 186 998.8 222.0 NaN main hole\n", 471 | "INFO:root:For drillhole 1, later_max_dhole_diam=149.0\n", 472 | "INFO:root:Depth interval: (320.0, 867)\n", 473 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 474 | " type i order_diam drilling_order from to diam inner_diam label\n", 475 | "1 drilled_hole 1 1 2.0 186 998.8 222.0 NaN main hole\n", 476 | "INFO:root:For drillhole 1, later_max_dhole_diam=149.0\n", 477 | "INFO:root:Depth interval: (867, 996.5)\n", 478 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 479 | " type i order_diam drilling_order from to diam inner_diam label\n", 480 | "4 drilled_hole 4 0 4.0 867 1100.0 149.0 NaN NaN\n", 481 | "1 drilled_hole 1 1 2.0 186 998.8 222.0 NaN main hole\n", 482 | "INFO:root:For drillhole 4, later_max_dhole_diam=nan\n", 483 | "INFO:root:For drillhole 1, later_max_dhole_diam=149.0\n", 484 | "INFO:root:Depth interval: (996.5, 998.8)\n", 485 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 486 | " type i order_diam drilling_order from to diam inner_diam label\n", 487 | "4 drilled_hole 4 0 4.0 867 1100.0 149.0 NaN NaN\n", 488 | "1 drilled_hole 1 1 2.0 186 998.8 222.0 NaN main hole\n", 489 | "INFO:root:For drillhole 4, later_max_dhole_diam=nan\n", 490 | "INFO:root:For drillhole 1, later_max_dhole_diam=149.0\n", 491 | "INFO:root:Depth interval: (998.8, 1100.0)\n", 492 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 493 | " type i order_diam drilling_order from to diam inner_diam label\n", 494 | "4 drilled_hole 4 0 4.0 867 1100.0 149.0 NaN NaN\n", 495 | "INFO:root:For drillhole 4, later_max_dhole_diam=nan\n" 496 | ] 497 | }, 498 | { 499 | "name": "stdout", 500 | "output_type": "stream", 501 | "text": [ 502 | "\n", 503 | "\n", 504 | "\n", 505 | "\n", 506 | "\n", 507 | "\n", 508 | "\n", 509 | "\n" 510 | ] 511 | }, 512 | { 513 | "data": { 514 | "image/png": "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/vIXGYahrKws2+zO+WJjY7Vt2zbl5eXp7bffVrdu3XTzzTfrvvvu05IlSySdu3VuwIABF61v7969SktLU2RkpMLDw7Vv3z5Nnz5dbm5ueuCBB2ztjhw5ctHFIQAAAIBrCWGpCoSGhmrXrl0KCgqSs7OznnvuuTJtOnfubFuI4XwZGRlq1aqV6XNP3bt3V/fu3ctsDwkJ0YgRIy5a09ixY21/btGihW21PovFor59+5Zpn5+fr7Nnz17ys58AAACAawVhqQr4+vqaLvFdHg0aNNA999xzhSuquNOnT+vuu++u7jIAAACAKkNYqiIdOnSo7hIuS6NGjaq7BAAAAKBKscADAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACafqLuB6UFRUpPnz5+uxxx7T6dOntXDhQqWlpalXr17q1KmTrd3q1auVlJQkwzDUsWNHde3a1e4cM2fOVEREhO6+++4y10hNTdXSpUtVXFysG2+8UXfcccdFa9q/f7/Wrl2r9PR0jR49Wn5+fpKks2fPauHChcrOzpYk3XPPPQoJCbEds2bNGklSkyZN1KdPH2VlZSk2Nlb9+/e/rDECAAAAahrCUhU4ePCg2rRpI0lydXVVVFSU9u7da9fm2LFjOnr0qEaOHKni4mK999576tChg1xdXSVJsbGxCgoKuuA1Vq5cqUGDBsnPz08fffSRWrVqJX9//wu29/X11aBBg7RixQq77Tt27JC/v78eeeQRHTt2TF9//bWefPJJ5eXlad26dRoyZIg8PDx05swZSZKPj4/y8vJ0+vRp1atXr1LjAwAAANRE3IZXBVJSUtSiRQtJkpubm4KDg+Xo6FimXXFxsUpKSlRUVCQXFxdbm8zMTGVmZqp58+am58/JyZEk+fv7y8HBQW3bti0Txn7Px8dHDRo0MN1XWFgo6dwsU926dSVJ8fHxioiIkIeHhyTZ/itJ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F1emTVxcnMLCwuTm5ibpf88qxcXFqUuXLrZ2x44dU0ZGhiIiIi5ak7+/v/z9/S+nWwAAAABqkFoZlho1aqT169eX2f76669r48aN+uabb+Tn5ycnJyf17dtXixYt0ptvvilPT09J0pEjR7R+/Xo9++yztmN79eolNzc3RUdH24Wl6OhoWSwWZogAAACA60ytDEtubm7q0aNHme3R0dFydHS02zd58mTdfPPN6tOnj8aNG6eCggJNnDhRfn5+ev75523tfHx8NGHCBL300kvy8fFRVFSUfv75Z02aNEnDhg3jM5YAAACA60ytXjq8PFq2bKkNGzbI2dlZgwYN0uOPP66wsDDFxsaqQYMGdm3Hjx+vd955R1999ZWioqI0Y8YMjRs3TjNnzqym6gEAAABUl1o5s3Qh0dHRio6OLrO9Y8eOWrt2bbnOMWbMGI0ZM+YKVwYAAACgtrnmZ5YAAAAAoDIISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABgwqmyBx48eFArV67Upk2blJqaqvz8fPn5+al169a688471bNnTzk7O1/JWgEAAACgylR4ZmnDhg3q1auXmjdvrqefflrff/+9cnNz5ezsrIMHD2r27Nnq06ePgoODNXHiRGVnZ1+NugEAAADgqqpQWBowYICioqLk4uKizz77TMePH1dKSop++eUXbdq0SYmJiTp9+rR++eUXDR8+XPPnz1fz5s21du3aq1U/AAAAAFwVFboNz9PTU3v27NENN9xwwTaOjo7q0KGDOnTooEmTJum///2vUlNTL7tQAAAAAKhKFQpLn3zySYVO7uDgoCFDhlToGAAAAACoCVgNDwAAAABMVHo1vFIJCQk6fPiwCgoKyuwbOHDg5Z4eAAAAAKpFpcPSgQMHNGjQIO3atUuSZBiG3X6LxaKSkpLLqw4AAAAAqkmlw9KTTz6pY8eOadq0aWrVqpVcXFyuZF0AAAAAUK0qHZa2bt2q//znP3rooYeuZD0AAAAAUCNUeoGHBg0aqF69eleyFgAAAACoMSodlkaOHKn//Oc/V7IWAAAAAKgxKn0b3gsvvKDnn39eHTt2VO/eveXj42O332Kx6Nlnn73sAgEAAACgOlQ6LG3ZskXz5s1TVlaWduzYUWY/YQkAAABAbVbpsPTUU0/Jz89PH330EavhAQAAALjmVDosJSQk6PPPP1e/fv2uZD0AAAAAUCNUeoGHJk2alPkgWgAAAAC4VlQ6LI0bN05Tp05VQUHBlawHAAAAAGqESt+Gt337dqWmpio0NFSRkZGmq+G9++67l10gAAAAAFSHSoel9957z/bnTz/9tMx+whIAAACA2qzSYclqtV7JOgAAAACgRqn0M0sAAAAAcC2rUFg6c+ZMpS5S2eMAAAAAoLpUKCyFhIRo2rRpys7OLlf7n3/+Wf369dPbb79dqeIAAAAAoLpU6JmlqVOnavz48ZowYYL69u2ryMhI3XTTTfL395ebm5uysrJ04MABbd68WUuXLtXu3bv14IMP6s9//vPVqh8AAAAArooKhaU//elPGjx4sKKjozV79mx9+eWXslgsdm0Mw1CdOnU0aNAgRUdHq2PHjle0YAAAAACoChVeDa9OnToaOXKkRo4cqdTUVP34449KS0tTfn6+/Pz81LJlS3Xp0kXOzs5Xo14AAAAAqBKVXjpckoKCgjR48OArVQsAAAAA1BgsHQ4AAAAAJghLAAAAAGCCsAQAAAAAJghLAAAAAGCCsAQAAAAAJghLAAAAAGDispYOz8nJ0TfffKPDhw8rPz/fbp/FYtFLL710WcUBAAAAQHWpdFjasmWL7rvvPmVlZZnuJywBAAAAqM0qfRves88+q6CgIG3dulUFBQWyWq12XyUlJVeyTgAAAACoUpWeWYqLi9Onn36qTp06Xcl6AAAAAKBGqPTMUoMGDa5kHQAAAABQo1Q6LD399NOaPXu2DMO4kvUAAAAAQI1Qodvw3n77bbvXiYmJ6tChg+677z75+vra7bNYLHr22Wcvv0IAAAAAqAYVCkt//etfTbfv2rWrzDbCEgAAAIDarEJh6eDBg1erDgAAAACoUSoUlpo2bXq16gAAAACAGqXSCzw4Ojpq69atpvt++eUXOTo6VrooAAAAAKhulQ5LF1sFz2q1ymKxVPbUAAAAAFDtKh2WJF0wEP3yyy+qV6/e5ZwaAAAAAKpVhZ5Zevfdd/Xuu+9KOheU+vfvL1dXV7s2+fn5Sk9P16BBg65clQAAAABQxSoUlvz9/dWmTRtJ0qFDh3TDDTfI29vbro2rq6vatm2rZ5555ooVCQAAAABVrUJh6eGHH9bDDz8sSYqMjNT777+vli1bXpXCAAAAAKA6VSgsnW/9+vVXsg4AAAAAqFEqHZYkKTs7WzNnztT69euVmZkpX19fRUZGauTIkWVuzwMAAACA2qTSq+EdPHhQ7dq10/jx47V//365uLho//79Gj9+vG688UYlJydfyToBAAAAoEpVOiw988wzKigo0KZNm3Tw4EH99NNPOnjwoH744QedPXtWY8eOvYJlAgAAAEDVqnRY+u677/Tqq6/qlltusdt+6623asqUKfruu+8uuzgAAAAAqC6VDkuurq5q3Lix6b4mTZqU+fwlAAAAAKhNKr3Aw/3336+YmBhFRUWV2RcTE6M+ffpcVmHXkqKiIs2fP1+PPfaYUlNTtWzZMkmSo6OjevXqpcaNG+vIkSNatWqVSkpK5Orqqj59+sjf31+StG/fPq1evVqGYei2227TTTfdVOYaqampWrp0qYqLi3XjjTfqjjvuuGhNp0+f1uLFi1VQUCBHR0f169dPDRs2lCTt3LlTmzZtkiS1bdtW3bt319atW7V9+3ZJUnFxsXJzczVu3DhlZWUpNjZW/fv3v1LDBQAAANQIlZ5ZeuSRR7R69WoNHjxYixcv1k8//aTFixdr0KBBWrNmjf70pz9p+/bttq+r4YcfftC9996r+vXrq06dOmrevLleeeUVuzbbt2/X3Xffrbp168rb21sDBw684OITM2bMUMuWLeXq6qqQkBBNnjxZRUVFl13nwYMHbR/m6+/vryeffFIjRozQ/fffr2+++UaS5ObmpoceekgjR45UZGSkbbvVatXq1as1ZMgQDR8+XD/++KPy8/PLXGPlypUaNGiQnnrqKe3fv1/p6ekXremnn35SRESERowYoW7dumnjxo2SpBMnTmj79u168sknNXr0aHXs2FGS1LlzZ40YMUIjRozQ7bffrhYtWkiSfHx8lJeXp9OnT1/2OAEAAAA1SaVnlkpnlFJSUrRo0SLbdsMw7PYbhiGLxaKSkpLLqbOMTz/9VH/84x/14IMP6pNPPlHdunV14MABpaWl2drs2bNHPXr0UPv27fXll1+qoKBAEydOVLdu3bRz5041aNDA1vbVV1/VSy+9pHHjxikqKko///yzJkyYoNTUVH3wwQeXVWtKSoruueceSZKzs7Nte2FhoW28SmeRJKlRo0bKzs6WdG7GqGHDhvL09JQkNW/eXElJSWrbtq2tfU5Ojt052rZtq71799qd00xhYaEk6ezZs6pbt64kaceOHercubOtTg8PjzLH7d69W506dbK9DgsL0+7du8s8vwYAAADUZpUOSx9//PGVrKNCUlNT9eSTT2r48OGaNWuWbXtkZKRdu4kTJ8rV1VXLly+Xl5eXJKljx45q3ry5pk6dqjfeeEOSlJmZqSlTpuiJJ57Qa6+9Jknq0aOHioqKNGHCBI0dO1atW7euVK2Ojo4qLCyUu7u7bdvhw4e1fPly5ebm6pFHHilzzM6dOxUSEiLpXBAqDUqS5OXlZQtHpczaHDx48KJ1devWTf/973+1efNmOTg46IknnpAkZWVlyWKxaPPmzXJyclKvXr3UqFEj23EFBQVKS0tTaGiobVtAQIC2bNlSnuEAAAAAao1Kh6UhQ4ZcyToq5MMPP9SZM2f04osvXrBNcXGxli9frj/96U+2oCRJTZs2VWRkpBYvXmwLS6tWrVJBQYGGDh1qd46hQ4dq/PjxWrJkSaXDkru7u91sUmkNo0eP1tGjR7V+/Xr98Y9/tO1LS0vT9u3bbbWUzjxdTHna/N6uXbvUuXNn3XTTTfr111/17bffauDAgbJarcrOztZf/vIXHTlyREuXLtXw4cNtx+3Zs0dhYWFydHS062Nubm6FawAAAABqsko/s3S+vXv3atOmTTpz5syVON0lxcbGysfHR3v27FH79u3l5OQkf39/jRgxwnb72oEDB5Sfn6927dqVOb5du3ZKSkpSQUGBJCk+Pl6S7G5tk87NmPj5+dn2X0x6eroSEhLsvpKSklRcXCyr1Wp6THBwsHJzc23jlp2drUWLFmnw4MG2majfzyT9fhapvG1+b8eOHbYA2Lp1a6WkpEiSPD091aJFC1ksFjVt2lS5ubl2YSwhIcH2/FWpkpISOTlVOncDAAAANdJlhaVPPvlEwcHBat26tbp37669e/dKkh588EH95z//uSIFmklNTVVeXp4GDx6sP/zhD1q7dq1eeOEFffLJJ7r33ntlGIYyMzMlnVuA4Pd8fHxkGIZOnjwp6dxteK6urqbP5/j4+NjOdTGzZs1SRESE3Vf//v2Vn5+vkpISW+A4efKkLTydOHFCBQUFcnd3V2FhoT7//HNFRUXZPWsUFBSk48ePKzc3V4WFhdq3b5/dLXCSbMHoxIkTslqtiouLU3h4uCRp7dq1SkxMLFOvl5eXDh06JOncAhS+vr6SpPDwcB0+fFjSuQDo7u4ui8UiScrPz9dvv/2mG264we5cWVlZtuMBAACAa0WlpwNiYmL0+OOPq0+fPurdu7dGjx5t23fTTTfpyy+/tD0Hc6VZrVYVFBTo5Zdf1rhx4ySde8bIxcVFY8eO1bp162wzM6W/6Js5f195213IqFGjNHjwYLttSUlJ6t+/v3x9fZWWlqagoCAdOXJEmzZtkoODg5ycnDRgwABZLBbt3LlTGRkZ+u677/Tdd9/J2dlZf/nLX+Tg4KCePXvanhG79dZbbX1bsGCB+vXrJ09PT/Xu3VsxMTEqLi5Wu3btbMuAnzhxwrZy3fl69uypZcuWacOGDXJ2dla/fv0knQtL+/fv16xZs+Tk5KS+ffvajtmzZ4+aN29udwuedO4ZrLCwsEuOEQAAAFCbVDos/etf/9LQoUM1d+5clZSU2IWlVq1aacaMGVekQDO+vr7av3+/bYW5Ur1799bYsWO1fft23X///ZJkOitUuoiBt7e37XwFBQXKy8uzW4ihtG3p8tkX4+/vf8HV50JDQ7Vr1y4FBQXpxhtv1I033limTefOndW5c2fT41u0aGEaeB599FHbn4ODgzVq1KgybaxWq+mHBzds2FDDhg0rs91isVzwM7I6dOigDh06lDl/WlqaevbsaXoMAAAAUFtV+ja8xMREPfTQQ6b7ynvrWmWZPYck/W+hAwcHB4WGhqpOnTqKi4sr0y4uLk5hYWFyc3OT9L9nlX7f9tixY8rIyFBERMRl1evr62u3olxVOj9QXQ3Z2dnq0aOHHByuyONvAAAAQI1R6d9w3d3dL/hBpKmpqapfv36li7qUBx54QJJsH9xaauXKlZKkrl272m4hW7Rokd3iB0eOHNH69es1cOBA27ZevXrJzc1N0dHRdueLjo6WxWJR//79L7vm38/IXCu8vb1ty5wDAAAA15JK34Z322236b333rMFl/NFR0erR48el1PXRUVFRalv37765z//KavVqq5du2rbtm2aPHmy+vTpo9tvv12SNHnyZN18883q06ePxo0bZ/tQWj8/Pz3//PO28/n4+GjChAl66aWX5OPjY/tQ2kmTJmnYsGGVXjYcAAAAQO1V6ZmliRMnavPmzercubOmT58ui8WiRYsWqW/fvoqNjdX48eOvZJ1lfPHFFxo7dqw++OAD9e7dW++//76effZZffXVV7Y2LVu2tC1gMGjQID3++OMKCwtTbGysGjRoYHe+8ePH65133tFXX32lqKgozZgxQ+PGjdPMmTOvaj8AAAAA1EyVnlnq1KmTvvnmG40aNco2S/Paa6+pefPmWrly5WU/53MpderU0euvv67XX3/9ou06duyotWvXluucY8aM0ZgxY65EeQAAAABqucv6JNHIyEglJibqwIEDOn78uPz8/Gyf7wMAAAAAtdllhaVSoaGhZT4oFQAAAABqs0qFpRMnTmjOnDmKjY1VWlqaJCkwMFCRkZF68skn5evre0WLBAAAAICqVuGwtG7dOj3wwAPKzs6Wo6Oj/Pz8ZBiG9u7dq7Vr12rq1KlavHixunfvfjXqBQAAAIAqUaHV8E6cOKE//OEPqlevnr788kudPn1av/32m44dO6bTp0/r888/l4eHhwYNGnRVP5QWAAAAAK62CoWluXPnqqSkRJs2bdKgQYPk7u5u2+fu7q4HH3xQP/zwg4qKijR37twrXiwAAAAAVJUKhaXVq1frz3/+s4KDgy/YpkmTJho6dKhWrVp12cUBAAAAQHWpUFhKTEzU7bfffsl23bp1U2JiYqWLAgAAAIDqVqGwdOrUKfn7+1+ynb+/v06dOlXZmgAAAACg2lUoLJ09e1bOzs6XbOfk5KTCwsJKFwUAAAAA1a3CS4fv3btXTk4XP2zPnj2VLggAAAAAaoIKh6XHH3/8km0Mw5DFYqlMPQAAAABQI1QoLH388cdXqw4AAAAAqFEqFJaGDBlyteoAAAAAgBqlQgs8AAAAAMD1grAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABgotaGpR07dqh///4KDAyUu7u7WrZsqX/+85/Ky8uza7d9+3bdfffdqlu3rry9vTVw4EAlJyebnnPGjBlq2bKlXF1dFRISosmTJ6uoqKgqugMAAACghqmVYWn37t269dZbdejQIb3zzjtavny5HnroIf3zn//Uww8/bGu3Z88e9ejRQ4WFhfryyy/10Ucfad++ferWrZtOnDhhd85XX31VzzzzjAYOHKhvv/1Wo0aN0muvvabRo0dXdfcAAAAA1ABO1V1AZXz66acqKCjQwoULFRoaKkm688479dtvv+mDDz7QyZMnVb9+fU2cOFGurq5avny5vLy8JEkdO3ZU8+bNNXXqVL3xxhuSpMzMTE2ZMkVPPPGEXnvtNUlSjx49VFRUpAkTJmjs2LFq3bp19XQWAAAAQLWolTNLzs7OkqR69erZbff29paDg4NcXFxUXFys5cuX64EHHrAFJUlq2rSpIiMjtXjxYtu2VatWqaCgQEOHDrU739ChQ2UYhpYsWXL1OgMAAACgRqqVYWnIkCHy9vbWyJEjlZycrJycHC1fvlxz5szR6NGj5eHhoQMHDig/P1/t2rUrc3y7du2UlJSkgoICSVJ8fLwkqW3btnbtAgIC5OfnZ9t/Menp6UpISLD7SkpKugK9BQAAAFAdauVteM2aNdNPP/2kAQMG2G7Dk6QxY8bonXfekXTu1jpJ8vHxKXO8j4+PDMPQyZMnFRAQoMzMTLm6usrDw8O0bem5LmbWrFmaPHlyJXsEAAAAoKaplWHp0KFD6tu3rxo2bKivvvpKDRo00JYtWzRlyhTl5uZq7ty5trYWi+WC5zl/X3nbXcioUaM0ePBgu21JSUnq37//JY8FAAAAUPPUyrA0btw4ZWdna+fOnbbZoO7du8vPz09//vOf9ac//UmNGjWSJNNZoaysLFksFnl7e0uSfH19VVBQoLy8PLm7u5dp27Fjx0vW5O/vL39//8vsGQAAAICaolY+s7Rz5061bt26zG1zN998s6RzzyCFhoaqTp06iouLK3N8XFycwsLC5ObmJul/zyr9vu2xY8eUkZGhiIiIq9ENAAAAADVYrQxLgYGBSkhIUG5urt32n376SZIUHBwsJycn9e3bV4sWLVJOTo6tzZEjR7R+/XoNHDjQtq1Xr15yc3NTdHS03fmio6NlsVi4lQ4AAAC4DtXK2/DGjh2r/v37q2fPnnr22Wfl5+enzZs361//+pdat26t3r17S5ImT56sm2++WX369NG4ceNUUFCgiRMnys/PT88//7ztfD4+PpowYYJeeukl+fj4KCoqSj///LMmTZqkYcOG8RlLAAAAwHWoVs4s9evXT+vWrZOXl5eeeeYZ9enTR/PmzdPw4cMVGxsrFxcXSVLLli21YcMGOTs7a9CgQXr88ccVFham2NhYNWjQwO6c48eP1zvvvKOvvvpKUVFRmjFjhsaNG6eZM2dWRxcBAAAAVLNaObMkSZGRkYqMjLxku44dO2rt2rXlOueYMWM0ZsyYyy0NAAAAwDWgVs4sAQAAAMDVRlgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABOEJQAAAAAwQVgCAAAAABNO1V0AANR2R44cqe4SAFwG/g4DuBBmlqrAtm3btHnzZi1YsEBZWVmaPn26JGnq1KmSpDlz5ig5OVlLly7VmjVrtGPHDs2bN095eXmaNm2aXdu5c+dq9+7dWrlypVauXKndu3dr7ty5dm2mTZumvLw8zZs3Tzt27NCaNWu0dOlSJScna86cOXZtp0+frqysLC1YsECbN29WbGysYmJilJaWppkzZ9q1nTlzptLS0hQTE6PY2Fj6RJ+uap/yjh+vNX1ydnZWSUmJ3njjDa1cuVIzZszQ/PnzNW/ePM2cOVPLli3Tv//9b23YsEHRkZG1ok/X8/cefbr2+hTTt69ee+01bdiwQVOnTtXixYs1e/ZsffTRR/rss8/k4OBgq6+29EmSMjIzr6n36Vr83qNPNa9P27ZtU0VYDMMwKnQEyi0hIUERERGKj49XmzZtqrscoFZZ3rev+ixbVt1llEubNm105swZRUdHX7Jt7ltv1Zp+AdeKL++6S/4vvXTB/Y8//rg8PDyUkJBQhVVdvtr0cxKoKSr6+zkzSwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACYISwAAAABggrAEAAAAACacqruA60FRUZHmz5+vxx57TFarVUuXLtWxY8dkGIa6d++uiIgISVJqaqpWrFih4uJi1a9fXw8//LCOHj2q5cuX286Vnp6uJ598Uo0aNbrg9dLS0rRixQoVFRWpcePG6tOnjywWi06ePKmlS5cqPz9fPj4+GjhwoJydnSVJO3fu1KZNmyRJbdu2Vffu3e3OeejQIX3xxReqV6+eJKlTp07q1KmTsrKyFBsbq/79+1/JIQMAAACqHWGpChw8eFBt2rSRJO3bt09Wq1UjR47UmTNnNHv2bEVERKikpETLli3Tgw8+KB8fH505c0aSFBwcrBEjRkiSTp06pejo6IsGJUlavny5+vbtq4CAAK1evVp79uxRq1attHr1anXt2lUtW7bU1q1btW3bNt1yyy06ceKEtm/frieffFLOzs62a/9eaGioBg0aZLfNx8dHeXl5On36tC1IAQAAANcCbsOrAikpKWrRooXtdVFRkaxWqwoLC1W3bl1J0oEDBxQcHCwfHx9JkoeHR5nzJCQkqHXr1pe8Xk5OjgICAiRJISEh2rt3ryQpIyNDzZo1K7N9x44d6ty5s22WyezaFxMWFqbdu3dX6BgAAACgpmNm6SpzdHRUYWGh3N3dJUnh4eHavXu33n77bRUVFenhhx+WJGVmZqqkpETz5s3T2bNnddttt9lmo0rt3r1b99577yWvWa9ePR06dEhNmzbVnj17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CQmKiIhQfHy82rRpU93lAAAAANe1iv5+zswSAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJggLAEAAACACcISAAAAAJhwqu4CrmVnz56VJCUlJVVzJQAAAABKfy8v/T39UghLV1FKSookqX///tVbCAAAAACblJQU3XTTTZdsZzEMw6iCeq5Lp06d0saNG9W4cWO5urpWdzk1VlJSkvr3768lS5YoLCysusup0Rir8mGcyodxKj/GCgCuDWfPnlVKSoruuOMOeXt7X7I9M0tXkbe3t+6///7qLqPWCAsLU5s2baq7jFqBsSofxql8GKfyY6wAoPYrz4xSKRZ4AAAAAAAThCUAAAAAMEFYAgAAAAAThCVUuwYNGujll19WgwYNqruUGo+xKh/GqXwYp/JjrADg+sRqeAAAAABggpklAAAAADBBWAIAAAAAE4QlAAAAADBBWAIAAAAAE4QlXFUffvihLBaL6tatW2bf9u3bdffdd6tu3bry9vbWwIEDlZycbHqeGTNmqGXLlnJ1dVVISIgmT56soqKiq13+VbNz507dd999atKkierUqSMfHx/dcsstmj9/fpm21/M4fffdd/rzn/+sli1bysPDQ0FBQbr//vv1yy+/lGl7PY+TJOXk5Ohvf/uboqKi1KBBA1ksFk2aNMm07fU+VhWRm5ursWPHKjAwUG5ubmrfvr0+//zz6i4LAFBVDOAqOXr0qFGvXj0jMDDQ8PDwsNuXmJhoeHp6Gt26dTNWrFhhLFy40GjTpo0RGBhopKen27WdMmWKYbFYjL///e/G+vXrjTfffNNwcXExnnjiiarszhW1fv16Y/jw4cZ///tf47vvvjOWLVtmPPTQQ4Yk45VXXrG1u97HadCgQUZkZKQxa9YsY8OGDUZMTIzRtWtXw8nJyVi3bp2t3fU+ToZhGAcPHjTq1atndO/e3Rg2bJghyXj55ZfLtGOsKqZnz56Gt7e3MXv2bOO7776zje2CBQuquzQAQBUgLOGq6dOnj9G3b19jyJAhZcLS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3Yb3xRdfKCoqSgEBAapTp45atWqlcePG6cyZM3btHn/8cdWtW1d79uzRPffcIw8PDwUEBOj111+XJG3evFm33367PDw8FB4ernnz5pWp69ixYxo+fLiCg4Pl4uKikJAQTZ48WcXFxZKkQ4cOqUGDBpKkyZMn224xfPzxx23n2L9/vx555BH5+/vL1dVVrVq10syZM+2us2HDBlksFv33v//V888/r6CgILm6uiopKemCY/b++++rUaNG6tmzp932Hj16KCIiQj/99JNuvfVW1alTR82aNdPHH38sSVqxYoVuuukmubu7q23btmXCVumY79q1S4MHD1a9evXk4+Oj5557TsXFxdq7d6969eolT09PNWvWTG+++WaZ2jp27KhWrVpp9uzZF6wfAK4HzCwBAK6Ie++9V46OjoqNjb1ou/379+vee+/V2LFj5eHhoT179uiNN97Q1q1b9d1339m1LSoq0sCBAzVixAi98MIL+vTTT/X3v/9d2dnZWrhwoV588UUFBwdrxowZevzxxxUREaGOHTtKOheUOnfuLAcHB02cOFGhoaH66aefNGXKFB06dEgff/yxAgICtGrVKvXq1Ut/+ctfNGzYMEmyBajdu3fr1ltvtYXBRo0a6dtvv9WYMWOUkZGhl19+2a7ev//977rllls0e/ZsOTg4yN/f/4LjsGLFCnXv3l0ODmX/v+WxY8c0dOhQ/e1vf7P1789//rNSUlL01Vdf6R//+Ifq1aunf/7zn+rfv7+Sk5MVGBhod44HH3xQjz32mIYPH641a9bozTffVFFRkdauXatRo0bpr3/9qz799FO9+OKLCgsL08CBA+2O79Gjh2JiYmQYRo1/7gwArhoDAIBy+Pjjjw1Jxs8//3zBNg0bNjRatWple/3yyy8bF/unxmq1GkVFRcbGjRsNScavv/5q2zdkyBBDkrFw4ULbtqKiIqNBgwaGJGP79u227ZmZmYajo6Px3HPP2bYNHz7cqFu3rnH48GG7a06dOtWQZCQkJBiGYRgnTpwwJBkvv/xymfruueceIzg42Dh9+rTd9qeeespwc3MzsrKyDMMwjPXr1xuSjO7du1+wr+c7fvy4Icl4/fXXy+y74447DEnGtm3byvSvTp06Rmpqqm37zp07DUnG9OnTbdtKx/ytt96yO2/79u0NScaiRYts20rHc+DAgWXq+M9//mNIMhITE8vVJwC4FnEbHgDgijHKsWZQcnKyHnnkETVq1EiOjo5ydnbWHXfcIencczzns1gsuvfee22vnZycFBYWpoCAAHXo0MG23cfHR/7+/jp8+LBt2/LlyxUZGanAwEAVFxfbvnr37i1Jl1y8oKCgQOvWrdOAAQPk7u5ud457771XBQUF2rx5s90xDzzwwCX7L0lpaWmSdMGZp4CAANsM2fn9a9++vd0MUqtWrSTJrt+l+vTpY/e6VatWslgstv5L/xtPs+NLa0tNTS1XnwDgWsRteACAK+LMmTPKzMxU27ZtL9gmNzdX3bp1k5ubm6ZMmaLw8HC5u7srJSVFAwcOVH5+vl17d3d3ubm52W1zcXGRj49PmXO7uLiooKDA9vr48eNatmyZnJ2dTWvJyMi4aH8yMzNVXFysGTNmaMaMGeU6R0BAwEXPWaq0n7/vW6kL9e/3211cXCTJrt8XOoeLi8sFxzM7O7vM8aXtfv+eAMD1hLAEALgiVqxYoZKSEvXo0eOCbb777julpaVpw4YNttkkSTp16tQVr8fPz0/t2rXTq6++arr/98/4/F79+vXl6OioP/7xjxo9erRpm5CQELvX5X22x8/PT5KUlZVVrvbVobS20loB4HpEWAIAXLYjR47or3/9q+rVq6fhw4dfsF1pmHB1dbXbfv4KeldKnz59tHLlSoWGhqp+/foXbFdai9msVmRkpHbs2KF27drZZnGuhKZNm6pOnTo6cODAFTvnlZacnCwHBwe1aNGiuksBgGpDWAIAVEh8fLzt2Z309HR9//33tg+lXbx4sW0lOTO33nqr6tevrxEjRujll1+Ws7OzFixYoF9//fWK1/nPf/5Ta9as0a233qoxY8aoRYsWKigo0KFDh7Ry5UrNnj1bwcHB8vT0VNOmTbV06VLddddd8vHxkZ+fn5o1a6Z3331Xt99+u7p166aRI0eqWbNmysnJUVJSkpYtW1Zm9b7ycnFx0S233FLmmaeaZPPmzWrfvv1FgyYAXOsISwCAChk6dKikc7/we3t7q1WrVnrxxRc1bNiwiwYlSfL19dWKFSv0/PPP67HHHpOHh4fuv/9+ffHFF7rpppuuaJ0BAQHatm2bXnnlFf373//W0aNH5enpqZCQEPXq1csuBMydO1cvvPCC+vXrp7Nnz2rIkCGKjo5W69attX37dr3yyiuaMGGC0tPT5e3trebNm9stPFEZjz76qJ588kn99ttv5X7Wqark5uZq3bp1euWVV6q7FACoVhajPEsXAQCAK6qgoEBNmjTR888/rxdffLG6y7Ezd+5cPfPMM0pJSWFmCcB1jaXDAQCoBm5ubpo8ebLefvttnTlzprrLsSkuLtYbb7yhv//97wQlANc9bsMDAKCaPPnkkzp16pSSk5MvuuR6VUpJSdFjjz2m559/vrpLAYBqx214AAAAAGCC2/AAAAAAwARhCQAAAABMEJYAAAAAwARhCQAAAABMEJYAAAAAwARhCQAAAABMEJYAAAAAwARhCQAAAABMEJYAAAAAwARhCQAAAABM/B9pyPDhp07/YAAAAABJRU5ErkJggg==", 515 | "text/plain": [ 516 | "
" 517 | ] 518 | }, 519 | "metadata": {}, 520 | "output_type": "display_data" 521 | } 522 | ], 523 | "source": [ 524 | "chart_parsed_dataframe(df)" 525 | ] 526 | }, 527 | { 528 | "cell_type": "code", 529 | "execution_count": null, 530 | "metadata": {}, 531 | "outputs": [], 532 | "source": [] 533 | }, 534 | { 535 | "cell_type": "markdown", 536 | "metadata": {}, 537 | "source": [ 538 | "Much simpler example" 539 | ] 540 | }, 541 | { 542 | "cell_type": "code", 543 | "execution_count": 41, 544 | "metadata": {}, 545 | "outputs": [ 546 | { 547 | "name": "stdout", 548 | "output_type": "stream", 549 | "text": [ 550 | " type i order_diam drilling_order from to diam inner_diam label\n", 551 | "0 drilled_hole 0 1 0 0 100 200.0 \n", 552 | "1 drilled_hole 1 0 2 0 100 100.0 \n", 553 | "2 cement_plug 2 2 1 50 60 \n" 554 | ] 555 | } 556 | ], 557 | "source": [ 558 | "df = parse(pd.DataFrame([\n", 559 | " {\"type\": \"drilled_hole\", \"drilling_order\": 0, \"from\": 0, \"to\": 100, \"diam\": 200},\n", 560 | " {\"type\": \"drilled_hole\", \"drilling_order\": 2, \"from\": 0, \"to\": 100, \"diam\": 100},\n", 561 | " {\"type\": \"cement_plug\", \"drilling_order\": 1, \"from\": 50, \"to\": 60},\n", 562 | "]))\n", 563 | "with pd.option_context(\"display.width\", 1000):\n", 564 | " print(df.fillna(''))" 565 | ] 566 | }, 567 | { 568 | "cell_type": "code", 569 | "execution_count": 42, 570 | "metadata": {}, 571 | "outputs": [ 572 | { 573 | "name": "stderr", 574 | "output_type": "stream", 575 | "text": [ 576 | "INFO:root:Depth interval: (0, 50)\n", 577 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 578 | " type i order_diam drilling_order from to diam inner_diam label\n", 579 | "1 drilled_hole 1 0 2 0 100 100.0 None None\n", 580 | "0 drilled_hole 0 1 0 0 100 200.0 None None\n", 581 | "INFO:root:For drillhole 1, later_max_dhole_diam=nan\n", 582 | "INFO:root:For drillhole 0, later_max_dhole_diam=100.0\n", 583 | "INFO:root:Depth interval: (50, 60)\n", 584 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 585 | " type i order_diam drilling_order from to diam inner_diam label\n", 586 | "1 drilled_hole 1 0 2 0 100 100.0 None None\n", 587 | "0 drilled_hole 0 1 0 0 100 200.0 None None\n", 588 | "INFO:root:For drillhole 1, later_max_dhole_diam=nan\n", 589 | "INFO:root:For drillhole 0, later_max_dhole_diam=100.0\n", 590 | "INFO:root:Depth interval: (60, 100)\n", 591 | "INFO:root:Drilled hole sections in interval, ordered by diameter:\n", 592 | " type i order_diam drilling_order from to diam inner_diam label\n", 593 | "1 drilled_hole 1 0 2 0 100 100.0 None None\n", 594 | "0 drilled_hole 0 1 0 0 100 200.0 None None\n", 595 | "INFO:root:For drillhole 1, later_max_dhole_diam=nan\n", 596 | "INFO:root:For drillhole 0, later_max_dhole_diam=100.0\n" 597 | ] 598 | }, 599 | { 600 | "name": "stdout", 601 | "output_type": "stream", 602 | "text": [ 603 | "\n", 604 | "\n", 605 | "\n" 606 | ] 607 | }, 608 | { 609 | "data": { 610 | "image/png": "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zZkzR2fOnFG9evX08MMPKzQ0VJ6enkpISChyjoSEBIWFhV30fiAAAAAANVO13Alq0KCBVq9eXaR93LhxWrt2rb799lsFBgbKxcVFvXr10oIFC/TOO+/Ix8dHknTo0CGtXr1azz77bGWXDgAAAMDJqmUI8vDwUJcuXYq0z5gxQ7Vr13boi42NVYcOHdSzZ0+NHDlSubm5GjVqlAIDAzV8+PDKKxoAAABAlVAtL4crjVatWmnNmjVydXVVnz591L9/f4WFhWndunUKCgpydnkAAAAAKlm13Am6mBkzZmjGjBlF2iMjI7VixYrKLwgAAABAlVPjd4IAAAAA4I8IQQAAAACMQggCAAAAYJQy3xN04MABLV26VOvXr1dycrJycnIUGBioq6++Wrfeequ6du0qV1fX8qwVAAAAAC5bqXeC1qxZo+7du6t58+Z66qmn9P333ysrK0uurq46cOCApkyZop49e6px48YaNWqUMjIyKqJuAAAAACiTUoWge++9V926dZObm5vmzJmjlJQUHT58WFu2bNH69eu1e/dunT59Wlu2bNHgwYM1a9YsNW/enCezAQAAAKgySnU5nI+Pj/bs2aOrrrrqomNq166ta6+9Vtdee63GjBmjL774QsnJyZddKAAAAACUh1KFoM8//7xUJ69Vq5b69etXqmMAAAAAoCLxdDgAAAAARinz0+Eu2Llzp3777Tfl5uYW6YuJibnc0wMAAABAuSpzCNq/f7/69Omj7du3S5Isy3Lot9lsOnfu3OVVBwAAAADlrMwhaNCgQTp27Jjef/99tW7dWm5ubuVZFwAAAABUiDKHoE2bNumTTz7RAw88UJ71AAAAAECFKvODEYKCglS3bt3yrAUAAAAAKlyZQ9CQIUP0ySeflGctAAAAAFDhynw53PPPP6/hw4crMjJSd955p/z9/R36bTabnn322csuEAAAAADKU5lD0I8//qiZM2cqPT1d27ZtK9JPCAIAAABQFZU5BD355JMKDAzU9OnTeTocAAAAgGqjzCFo586d+uqrr3T33XeXZz0AAAAAUKHK/GCEJk2aFPmCVAAAAACo6socgkaOHKnx48crNze3POsBAAAAgApV5svhtm7dquTkZIWGhioqKqrYp8NNmDDhsgsEAAAAgPJU5hD04Ycf2v/9yy+/LNJPCAIAAABQFZU5BBUWFpZnHQAAAABQKcp8TxAAAAAAVEelCkFnzpwp05uU9TgAAAAAKG+lCkHNmjXT+++/r4yMjBKN/+mnn3T33XfrvffeK1NxAAAAAFDeSnVP0Pjx4/Xyyy/rlVdeUa9evRQVFaV27dopODhYHh4eSk9P1/79+7Vx40YtXrxYu3bt0n333adHH320ouoHAAAAgFIpVQj6+9//rr59+2rGjBmaMmWK5s2bJ5vN5jDGsix5enqqT58+mjFjhiIjI8u1YAAAAAC4HKV+Opynp6eGDBmiIUOGKDk5Wf/973915MgR5eTkKDAwUK1atdL1118vV1fXiqgXAAAAAC5LmR+RLUmNGjVS3759y6sWAAAAAKhwPCIbAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAol/WI7MzMTH377bf67bfflJOT49Bns9n06quvXlZxAAAAAFDeyhyCfvzxR911111KT08vtp8QBAAAAKAqKvPlcM8++6waNWqkTZs2KTc3V4WFhQ6vc+fOlWedAAAAAFAuyrwTlJCQoC+//FLt27cvz3oAAAAAoEKVeScoKCioPOsAAAAAgEpR5hD01FNPacqUKbIsqzzrqTY2b96sjRs3avbs2UpPT9cHH3wgSRo/frwkaerUqUpKStLixYu1fPlybdu2TTNnzlR2drbef/99h7HTpk3Trl27tHTpUi1dulS7du3StGnTHMa8//77ys7O1syZM7Vt2zYtX75cixcvVlJSkqZOneow9oMPPlB6erpmz56tjRs3at26dYqLi9ORI0c0adIkh7GTJk3SkSNHFBcXp3Xr1jEn5lSl53QyNbXGzamiPqdTqak1bk418XOqTnM6lZpa4+ZUEZ/T6ZSUGjenmvg5MaeaNafNmzertGxWKVLMe++95/Dzhx9+KF9fX911110KCAhwPLHNpmeffbbUBVV1O3fuVHh4uHbs2KE2bdo4uxzAKPG9eqnnkiXOLqNaYK1Q3vgzVTKsE1D5yvL7eanuCXruueeKbd++fXuRtpoaggAAAABUb6UKQQcOHKioOgAAAACgUpQqBDVt2rSi6gAAAACASlHmByPUrl1bmzZtKrZvy5Ytql27dpmLAgAAAICKUuYQdKnnKRQWFspms5X11AAAAABQYcocgiRdNOhs2bJFdevWvZxTAwAAAECFKNU9QRMmTNCECRMknQ9A0dHRcnd3dxiTk5Oj1NRU9enTp/yqBAAAAIByUqoQFBwcbH/29sGDB3XVVVfJz8/PYYy7u7vatm2rZ555ptyKBAAAAIDyUqoQ9OCDD+rBBx+UJEVFRemjjz5Sq1atKqQwAAAAAKgIpQpBf7R69eryrAMAAAAAKkWZQ5AkZWRkaNKkSVq9erXS0tIUEBCgqKgoDRkypMhlcgAAAABQFZT56XAHDhxQRESEXn75Ze3bt09ubm7at2+fXn75Zf3tb39TUlJSedYJAAAAAOWizCHomWeeUW5urtavX68DBw5ow4YNOnDggH744QedPXtWw4YNK8cyAQAAAKB8lDkErVq1Sm+88YZuvPFGh/abbrpJY8eO1apVqy67OAAAAAAob2UOQe7u7rriiiuK7WvSpEmR7w8CAAAAgKqgzCHonnvuUVxcXLF9cXFx6tmzZ5mLAgAAAICKUuanwz300EP6xz/+ob59++qhhx5SgwYNdOzYMc2ePVubN2/WtGnTtHXrVvv4du3alUvBAAAAAHA5yhyCunXrJkk6fPiwFixYYG+3LMuh37Is2Ww2nTt37nLqBAAAAIByUeYQ9Nlnn5VnHQAAAABQKcocgvr161eedQAAAABApShzCPqjX3/9VSdOnNA111yjOnXqlMcpq7z8/HzNmjVLjzzyiA4ePKi5c+eqbt26kqT27durffv2kqStW7dq/fr1stls6tatm1q0aPGX512yZImOHDkim82mvn37Kjg4WNnZ2YqLi1NGRoaCg4PVu3dvubi4aPXq1WratKmuuuqqCp8zAAAAUBNcVgj6/PPP9dJLL+no0aOSpJ9++knt2rXTfffdp65du+qxxx4rlyKrogMHDqhNmzb2n0NDQ9WnTx+HMdnZ2dqwYYMGDx6ss2fPasaMGQoLC1OtWhd/KN/atWvVsGFDxcTEqKCgwH4v1ffff682bdqoffv2+s9//qOtW7fquuuuU/v27bV48WJCEAAAAFBCZX5EdlxcnPr376927drpww8/tD8QQTr/JLh58+aVS4FV1eHDh9WyZctLjtm/f7+aN28uNzc3+fj4qH79+kpOTr7kMTt37tR1110nSXJxcbF/39K+ffvUtm1bSdLf/vY37d27V5Lk4+Oj3NxcZWdnX+6UAAAAACOUOQS99dZbGjBggP79739r0KBBDn2tW7fWrl27Lru4qqp27drKy8uTl5eXve3AgQOaMmWK5s6dq1OnTkmSMjMz5evrax/j4+OjzMzMi543JydHtWvX1rfffqupU6cqPj5eBQUFkqS8vDx7IPL19VVGRob9uJKEKwAAAADnlTkE7d69Ww888ECxff7+/kpLSytzUVWdl5eXXF1d7T83bNhQzzzzjB5//HG1bt1aixcvliSH3bGSKCwsVFpamlq2bKlBgwapsLBQmzdvLnaszWZzqCcrK6sMMwEAAADMU+YQ5OXlpdOnTxfbl5ycrHr16pW5qKquoKBAhYWF9p/d3d3l5uYmSYqIiNDx48clFd2xyczMlI+Pz0XP6+XlJXd3dzVv3lw2m02tW7dWSkqKJMnNzU15eXn283h7e9uPO3funFxcyuUZFwAAAECNV+YQdPPNNxe5F+iCGTNmqEuXLpdTV5WWk5Ojc+fO2ef+x12YpKQk+fn5STr/sITExETl5eUpMzNTKSkpatSokaTzD5X4Y0CSzu/uNGvWzH5p28GDBxUYGChJat68ubZv3y5J+uWXXxyeMpeenm4fBwAAAODSyrx9MGrUKHXs2FHXXXedHnroIdlsNi1YsECjR4/WunXrtGnTpvKss8oJCAjQkSNH1KhRI+3cuVNbtmxRrVq15OHhoXvuuUfS+Z2d66+/XlOnTpUkdevWTbVq1ZJlWUpPT5enp2eR83bt2lULFixQfn6+AgMD7WGyY8eOiouL04YNGxQUFGRvLyws1MmTJ1W/fv1KmTcAAABQ3ZU5BLVv317ffvuthg4dquHDh0uS3nzzTTVv3lxLly5VeHh4uRVZFYWGhmr79u1q1KiRrr/+el1//fXFjouMjFRkZKRD24kTJ9S6dWuH+4ou8Pf318CBA4u016lTR/379y/SnpSUpJYtW17ysdsAAAAA/ueybiSJiorS7t27tX//fqWkpCgwMPAvvwy0pggICLjk/T2XEhQUpDvuuKNc6igoKNCNN95YLucCAAAATFAud9OHhoYqNDS0PE5VrVx77bXOLkGtWrVydgkAAABAtVKmEHT8+HFNnTpV69at05EjRyRJISEhioqK0qBBgxQQEFCuRQIAAABAeSl1CFq5cqV69+6tjIwM1a5dW4GBgbIsS7/++qtWrFih8ePHa+HChercuXNF1AsAAAAAl6VUd9MfP35c999/v+rWrat58+bp9OnTOnr0qI4dO6bTp0/rq6++Up06ddSnT58a/WWpAAAAAKqvUoWgadOm6dy5c1q/fr369OkjLy8ve5+Xl5fuu+8+/fDDD8rPz9e0adPKvVgAAAAAuFylCkH/+c9/9Oijj6px48YXHdOkSRMNGDBAy5Ytu+ziAAAAAKC8lSoE7d69Wx07dvzLcZ06ddLu3bvLXBQAAAAAVJRShaBTp04pODj4L8cFBwfr1KlTZa0JAAAAACpMqULQ2bNn5erq+pfjXFxclJeXV+aiAAAAAKCilPoR2b/++qtcXC592J49e8pcEAAAAABUpFKHoP79+//lGMuyZLPZylIPAAAAAFSoUoWgzz77rKLqAAAAAIBKUaoQ1K9fv4qqAwAAAAAqRakejAAAAAAA1V21DkE//PCDevTooXr16snT01PNmzfX66+/7jBm69atuv322+Xt7S0/Pz/FxMQoKSnJSRUDAAAAcLZqG4K+/PJL3XLLLapbt64+//xzLV26VCNGjJBlWfYxe/bsUZcuXZSXl6d58+Zp+vTp2rt3rzp16qTjx487sXoAAAAAzlLqp8NVBcnJyRo0aJAGDx6syZMn29ujoqIcxo0aNUru7u6Kj4+Xr6+vJCkyMlLNmzfX+PHj9fbbb1dq3QAAAACcr1ruBH366ac6c+aMRowYcdExBQUFio+PV+/eve0BSJKaNm2qqKgoLVy4sDJKBQAAAFDFVMsQtG7dOvn7+2vPnj265ppr5OLiouDgYD3++OPKyMiQJO3fv185OTmKiIgocnxERIQSExOVm5t7yfdJTU3Vzp07HV6JiYkVMicAAAAAlaNahqDk5GRlZ2erb9++uv/++7VixQo9//zz+vzzz9WjRw9ZlqW0tDRJkr+/f5Hj/f39ZVmWTp48ecn3mTx5ssLDwx1e0dHRkqTNmzdr48aNmj17ttLT0/XBBx9IksaPHy9Jmjp1qpKSkrR48WItX75c27Zt08yZM5Wdna3333/fYey0adO0a9cuLV26VEuXLtWuXbs0bdo0hzHvv/++srOzNXPmTG3btk3Lly/X4sWLlZSUpKlTpzqM/eCDD5Senq7Zs2dr48aNWrduneLi4nTkyBFNmjTJYeykSZN05MgRxcXFad26dcyJOVXpOZ1MTa1xc6qoz+lUamqNm1NN/Jyq05xOpabWuDlVxOd0OiWlxs2pJn5OzKlmzWnz5s0qLZv1xycJVBMtWrTQvn379NZbb2nkyJH29gkTJmjYsGFavny5vLy8dPPNN+urr77S/fff73D8W2+9pZdeeklHjx5VgwYNLvo+qampRR6gkJiYqOjoaO3YsUNt2rQp34kBuKT4Xr3Uc8kSZ5dRLbBWKG/8mSoZ1gmofDt37lR4eHipfj+vljtBAQEBkqQ77rjDof3OO++UdP6x2BfGXNgR+qP09HTZbDb5+fld8n2Cg4PVpk0bh1dYWFg5zAAAAACAs1TLEFTcfT6S7I/HrlWrlkJDQ+Xp6amEhIQi4xISEhQWFiYPD48KrRMAAABA1VMtQ1Dv3r0lSd9++61D+9KlSyVJN9xwg1xcXNSrVy8tWLBAmZmZ9jGHDh3S6tWrFRMTU3kFAwAAAKgyquX3BHXr1k29evXSa6+9psLCQt1www3avHmzYmNj1bNnT3Xs2FGSFBsbqw4dOqhnz54aOXKkcnNzNWrUKAUGBmr48OFOngUAAAAAZ6iWO0GSNHfuXA0bNkwff/yx7rzzTn300Ud69tln9fXXX9vHtGrVSmvWrJGrq6v69Omj/v37KywsTOvWrVNQUJATqwcAAADgLNVyJ0iSPD09NW7cOI0bN+6S4yIjI7VixYpKqgoAAABAVVdtd4IAAAAAoCwIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGqbYhaNu2bYqOjlZISIi8vLzUqlUrvfbaa8rOznYYt3XrVt1+++3y9vaWn5+fYmJilJSU5KSqAQAAADhbtQxBu3bt0k033aSDBw/qX//6l+Lj4/XAAw/otdde04MPPmgft2fPHnXp0kV5eXmaN2+epk+frr1796pTp046fvy4E2cAAAAAwFlcnF1AWXz55ZfKzc3V/PnzFRoaKkm69dZbdfToUX388cc6efKk6tWrp1GjRsnd3V3x8fHy9fWVJEVGRqp58+YaP3683n777TLXkJ+fr1mzZumRRx6RJO3bt0/Lly+XJDVp0kQ9e/aUdH4nav369bLZbOrWrZtatGhxyfN+//332rx5s86dO6fnnnvO3p6dna24uDhlZGQoODhYvXv3louLiwoKCjR//nylpqbK19dXffv2lZeXl7Zt2ybLstSuXbsyzxEAAACoiarlTpCrq6skqW7dug7tfn5+qlWrltzc3FRQUKD4+Hj17t3bHoAkqWnTpoqKitLChQsvq4YDBw6oTZs2ks4HlJUrV6pfv34aOnSooqKi7O0bNmzQ4MGD1a9fP3333XcqLCy85HlDQ0M1cODAIu3ff/+92rRpo6eeekr16tXT1q1bJUlbtmxRQECAnnrqKbVu3Vo//PCDJKlt27basmXLZc0RAAAAqImqZQjq16+f/Pz8NGTIECUlJSkzM1Px8fGaOnWqnnjiCdWpU0f79+9XTk6OIiIiihwfERGhxMRE5ebmlrmGw4cPq2XLlpKkHTt2KDw8XHXq1JEk+z/379+v5s2by83NTT4+Pqpfv76Sk5Mved6QkBD5+PgUad+3b5/atm0rSfrb3/6mvXv3SpL27t1rn+Mf211cXFS3bl0dPXq0zHMEAAAAaqJqeTnclVdeqQ0bNujee++1Xw4nSU8//bT+9a9/SZLS0tIkSf7+/kWO9/f3l2VZOnnypBo2bHjR90lNTS1y71BiYqJq166tvLw8eXl52d/LsixNnz5dhYWFuu2229SsWTNlZmY67EL5+PgoMzOzTHPOy8uTu7u7JMnX11cZGRmS5PAe7u7uysvLsx/TsGFD/f7775ecIwAAAGCaahmCDh48qF69eql+/fr6+uuvFRQUpB9//FFjx45VVlaWpk2bZh9rs9kuep5L9UnS5MmTFRsbW6Tdx8fHfkmeJBUWFio1NVV///vfderUKc2aNUtPP/20LMsqw+xK5q9qlyQvLy97WAIAAABwXrUMQSNHjlRGRoZ+/vln+6VnnTt3VmBgoB599FH9/e9/V4MGDST9b0foj9LT02Wz2eTn53fJ9xk6dKj69u3r0JaYmKgHH3zQ4d4eX19f1a1bVy4uLgoMDJS3t7d9h+aPl6NlZmYWe6lbSbi5uSkvL09ubm7KzMyUt7e3pPOBLCMjQx4eHjp79qzc3Nzsx5w7d04uLtXyIwYAAAAqTLW8J+jnn3/W1VdfbQ9AF3To0EHS+Xt0QkND5enpqYSEhCLHJyQkKCwsTB4eHpd8n+DgYLVp08bhFRYWppycHJ07d86+09OiRQsdOnRIlmUpKytLWVlZ8vb2VmhoqBITE5WXl6fMzEylpKSoUaNGkqTPP/+8VLs0zZs31/bt2yVJv/zyi/0pcy1atLC3b9++Xc2bN7cfk56ersDAwBK/BwAAAGCCahmCQkJCtHPnTmVlZTm0b9iwQZLUuHFjubi4qFevXlqwYIHDfTiHDh3S6tWrFRMTc1k1BAQE6MiRI5Kk+vXrKyQkRJMnT9YXX3yhO++8U7Vr15aXl5euv/56TZ06VTNmzFC3bt1Uq1YtWZal9PR0eXp6FjnvunXr9N577yk7O1vvvfeefvrpJ0lSx44dtWPHDk2cOFFpaWn2R1+3a9dOJ06c0MSJE7Vz50517NjRfq7k5GRdeeWVlzVPAAAAoKapltdKDRs2TNHR0erataueffZZBQYGauPGjXrrrbd09dVX684775QkxcbGqkOHDurZs6dGjhyp3NxcjRo1SoGBgRo+fPhl1RAaGqrt27fbd3a6dOmiLl26FBkXGRmpyMhIh7YTJ06odevWDvcVXdC5c2d17ty5SHudOnXUv3//Iu2urq564IEHirQfP35c/v7+xQYtAAAAwGTVcifo7rvv1sqVK+Xr66tnnnlGPXv21MyZMzV48GCtW7fOfl9Mq1attGbNGrm6uqpPnz7q37+/wsLCtG7dOgUFBV1WDQEBAfb7jkorKChId9xxx2W9/185c+ZMsaEMAAAAMF213AmSpKioKPuXkl5KZGSkVqxYUSE1XHvttRVy3vLAZXAAAABA8arlThAAAAAAlBUhCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARqlyISgzM1MvvPCCunXrpqCgINlsNo0ZM6bYsVu3btXtt98ub29v+fn5KSYmRklJScWOnThxolq1aiV3d3c1a9ZMsbGxys/Pr8CZAAAAAKiKqlwISktL08cff6yzZ88qOjr6ouP27NmjLl26KC8vT/PmzdP06dO1d+9ederUScePH3cY+8Ybb+iZZ55RTEyMvvvuOw0dOlRvvvmmnnjiiQqeDQAAAICqxsXZBfxZ06ZNdfLkSdlsNp04cUKffvppseNGjRold3d3xcfHy9fXV5IUGRmp5s2ba/z48Xr77bclnQ9VY8eO1WOPPaY333xTktSlSxfl5+frlVde0bBhw3T11VdXzuQAAAAAOF2V2wmy2Wyy2WyXHFNQUKD4+Hj17t3bHoCk8wEqKipKCxcutLctW7ZMubm5GjBggMM5BgwYIMuytGjRonKtHwAAAEDVVuV2gkpi//79ysnJUURERJG+iIgILV++XLm5ufLw8NCOHTskSW3btnUY17BhQwUGBtr7i5Oamlrk0rrExMRymAGAUrv7bikpSWrTxtmVVAvt09KcXQJqkrvv1i1r1vDfX0m4ujq7AgAlUOV2gkoi7f//n7u/v3+RPn9/f1mWpZMnT9rHuru7q06dOsWOTbvELwqTJ09WeHi4w+vCfUqHDh3SwYMHtX79euXk5Nh3lObMmSPp/A5Uenq6tm3bpt27dys5OVlr165Vfn6+4uLiHMauXLlSKSkpSkhIUEJCglJSUrRy5UqHMXFxccrPz9fatWuVnJys3bt3a9u2bUpPT9eyZcscxi5atEg5OTlav369Dh48qMTERG3atEkZGRmKj493GBsfH6+MjAxt2rRJiYmJzIk5Vdk55eXny6WwUGfPnlV+QYHOZGfLsiydzsiQJJ0+fVqSlHXmjAoKCpR79qxyz55VQUGBss6ccRhzOiNDlmXpTHa28gsKdPbsWeXk5qrg3DllZmU5jM3IzFShZSk7O1t5+fk6m5en7JwcnSssVGZmpsPYzMxMnSssVHZOjs7m5SkvP1/Z2dkqtCxl/HlsVpYKzp1TTm5uhczJstn4s8ecym1OGRkZsmw2Y/97Ks2cXCT+7DEn5lTJczp06JBKy2ZZllXqoyrJiRMnFBQUpNGjRzs8Ie6///2vbr75Zn311Ve6//77HY5566239NJLL+no0aNq0KCBBg0apC+++EI5OTlFzt+yZUs1a9bM/gH82cV2gqKjo7Vjxw614W/EAAAAAKfauXOnwsPDS/X7ebW8HC4gIECSit3FSU9Pl81mk5+fn31sbm6usrOz5eXlVWRsZGTkRd8nODhYwcHB5Vc4AAAAAKerlpfDhYaGytPTUwkJCUX6EhISFBYWJg8PD0n/uxfoz2OPHTumEydOKDw8vOILBgAAAFBlVMsQ5OLiol69emnBggX2a4il8/fprF69WjExMfa27t27y8PDQzNmzHA4x4wZM2Sz2S75XUQAAAAAap4qeTnct99+qzNnztgDzq5du/T1119Lknr06CEvLy/FxsaqQ4cO6tmzp0aOHKnc3FyNGjVKgYGBGj58uP1c/v7+euWVV/Tqq6/K399f3bp1008//aQxY8Zo4MCBfEcQAAAAYJgq+WCEK6+8Ur/99luxfQcOHNCVV14pSdqyZYtGjBihDRs2yMXFRbfeeqvGjx+v0NDQIsd98MEHmjRpkg4ePKgGDRpowIABevnll+VaykdZluXGKwAAAAAVoyy/n1fJEFSVEYIAAACAqqMsv59Xy3uCAAAAAKCsCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBAEAAAAwCiEIAAAAgFEIQQAAAACMQggCAAAAYBRCEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUVycXUB1c/bsWUlSYmKikysBAAAAcOH38gu/p5cEIaiUDh8+LEmKjo52biEAAAAA7A4fPqx27dqVaKzNsiyrguupUU6dOqW1a9fqiiuukLu7u7PLqdISExMVHR2tRYsWKSwszNnlVFmsU8mwTiXHWpUM6wQANcPZs2d1+PBh3XLLLfLz8yvRMewElZKfn5/uueceZ5dRrYSFhalNmzbOLqPKY51KhnUqOdaqZFgnAKj+SroDdAEPRgAAAABgFEIQAAAAAKMQggAAAAAYhRCEChMUFKTRo0crKCjI2aVUaaxTybBOJcdalQzrBADm4ulwAAAAAIzCThAAAAAAoxCCAAAAABiFEAQAAADAKIQgAAAAAEYhBKFMPv30U9lsNnl7exfp27p1q26//XZ5e3vLz89PMTExSkpKKvY8EydOVKtWreTu7q5mzZopNjZW+fn5FV1+hfj555911113qUmTJvL09JS/v79uvPFGzZo1q8hYU9foglWrVunRRx9Vq1atVKdOHTVq1Ej33HOPtmzZUmSs6WuVmZmpF154Qd26dVNQUJBsNpvGjBlT7FjT16qksrKyNGzYMIWEhMjDw0PXXHONvvrqK2eXBQCoTBZQSr///rtVt25dKyQkxKpTp45D3+7duy0fHx+rU6dO1jfffGPNnz/fatOmjRUSEmKlpqY6jB07dqxls9msF1980Vq9erX1zjvvWG5ubtZjjz1WmdMpN6tXr7YGDx5sffHFF9aqVausJUuWWA888IAlyXr99dft40xeowv69OljRUVFWZMnT7bWrFljxcXFWTfccIPl4uJirVy50j6OtbKsAwcOWHXr1rU6d+5sDRw40JJkjR49usg41qrkunbtavn5+VlTpkyxVq1aZV/X2bNnO7s0AEAlIQSh1Hr27Gn16tXL6tevX5EQ1LdvXyswMNA6ffq0ve3gwYOWq6ur9cILL9jbTpw4YXl4eFiDBg1yOP6NN96wbDabtXPnzoqdRCW6/vrrrSuuuML+M2tkWSkpKUXaMjMzrfr161u33XabvY21sqzCwkKrsLDQsizLOn78+EVDEGtVMt98840lyfryyy8d2rt27WqFhIRYBQUFTqoMAFCZuBwOpTJr1iytXbtWkydPLtJXUFCg+Ph49e7dW76+vvb2pk2bKioqSgsXLrS3LVu2TLm5uRowYIDDOQYMGCDLsrRo0aIKm0NlCwwMlIuLiyTW6ILg4OAibd7e3rr66qt1+PBhSazVBTabTTab7ZJjWKuSW7hwoby9vdW3b1+H9gEDBujIkSP68ccfnVQZAKAyEYJQYqmpqRo2bJjGjRunxo0bF+nfv3+/cnJyFBERUaQvIiJCiYmJys3NlSTt2LFDktS2bVuHcQ0bNlRgYKC9vzoqLCxUQUGBjh8/rsmTJ+u7777TiBEjJLFGl3L69Glt3bpVbdq0kcRalQZrVXI7duxQ69at7X8xccGFtavp8wcAnEcIQokNHTpULVu21JAhQ4rtT0tLkyT5+/sX6fP395dlWTp58qR9rLu7u+rUqVPs2Avnqo6GDh0qV1dXBQcH69lnn9UHH3ygwYMHS2KNLuWJJ57QmTNn9PLLL0tirUqDtSq5tLS0i67ThX4AQM3n8tdDAGn+/PlasmSJtm3b9peX5lyq/499JR1X3bz00ksaOHCgUlNTtWTJEj355JM6c+aMnnvuOfsY09foz1599VXNnj1bEydOVGRkpEMfa1VyrFXJmD5/AAAhCCWQlZWlJ554Qk899ZRCQkJ06tQpSVJeXp4k6dSpU3J1dVVAQICk4v8mNT09XTabTX5+fpKkgIAA5ebmKjs7W15eXkXG/vkX4eqkSZMmatKkiSSpR48ekqQXX3xR/fr1Y42KERsbq7Fjx+qNN97Qk08+aW9nrUqOtSq5gICAi66TVPxuGgCg5uFyOPylEydOKCUlRe+++67q1atnf82ZM0dnzpxRvXr19PDDDys0NFSenp5KSEgoco6EhASFhYXJw8ND0v/uR/jz2GPHjunEiRMKDw+v+IlVkuuuu04FBQVKSkpijf4kNjZWY8aM0ZgxY/TSSy859LFWJcdalVzbtm21e/duFRQUOLRfWI+aPn8AwHmEIPylBg0aaPXq1UVed9xxhzw8PLR69WqNHTtWLi4u6tWrlxYsWKDMzEz78YcOHdLq1asVExNjb+vevbs8PDw0Y8YMh/eaMWOGbDaboqOjK2l2FW/16tWqVauWrrrqKtboD15//XWNGTNGr7zyikaPHl2kn7UqOdaq5O69915lZWVp/vz5Du0zZ85USEiIrr/+eidVBgCoVM57Ojequ+K+J2j37t2Wt7e31blzZ2vp0qXWggULrPDw8Et+YeNLL71krVmzxvrnP/9pubu7V9svbHzssces4cOHW3PnzrXWrFljff3119b9999vSbKef/55+ziT1+iC8ePHW5Ks7t27Wxs2bCjyuoC1Om/p0qVWXFycNX36dEuS1bdvXysuLs6Ki4uzzpw5Y1kWa1UaXbt2terVq2d9/PHH1qpVq6zHHnvMkmTNmjXL2aUBACoJIQhlVlwIsizL2rx5s3XbbbdZXl5elq+vrxUdHW0lJiYWe44JEyZYLVq0sNzc3KwmTZpYo0ePtvLy8iq69Aoxffp0q1OnTlZgYKDl4uJi+fn5Wbfccov1xRdfFBlr6hpdcMstt1iSLvr6I9PXyrIsq2nTphddqwMHDtjHsVYlk5mZaT399NNWgwYNLDc3NysiIsKaM2eOs8sCAFQim2VZVqVvPwEAAACAk3BPEAAAAACjEIIAAAAAGIUQBAAAAMAohCAAAAAARiEEAQAAADAKIQgAAACAUQhBAAAAAIxCCAIAAABgFEIQAAAAAKMQggDAcDNmzJDNZrO/PDw81KBBA0VFRemtt95SampqkWPGjBkjm83mhGpLLjs7W2PGjNGaNWsq/b33798vd3d3bdiwodLf+2L27t0rNzc3bd261dmlAIDT2SzLspxdBADAeWbMmKEBAwbos88+U6tWrZSfn6/U1FT98MMP+uyzz1S7dm3NnTtXt99+u/2Y33//Xb///rtuuOEGJ1Z+aSdOnFBQUJBGjx6tMWPGVOp733vvvcrPz1d8fHylvu9fGTBggJKSkrR27VpnlwIATuXi7AIAAFVDeHi42rdvb/+5d+/eevbZZ9WxY0fFxMRo3759ql+/viSpcePGaty4sbNKdar8/HzZbDa5uBT/v9Ddu3dr0aJFWrZsWSVX9teefPJJtW/fXv/973910003ObscAHAaLocDAFxUkyZN9O677yozM1NTp061txd3OdzcuXPVrVs3NWzYUJ6enmrdurVGjhypM2fOOIzr37+/vL29tWfPHt1xxx2qU6eOGjZsqHHjxkmSNm7cqI4dO6pOnTpq0aKFZs6cWaSuY8eOafDgwWrcuLHc3NzUrFkzxcbGqqCgQJJ08OBBBQUFSZJiY2Ptl/r179/ffo59+/bpoYceUnBwsNzd3dW6dWtNmjTJ4X3WrFkjm82mL774QsOHD1ejRo3k7u6uxMTEi67ZRx99pAYNGqhr164O7V26dFF4eLg2bNigm266SZ6enrryyiv12WefSZK++eYbtWvXTl5eXmrbtm2REHVhzbdv366+ffuqbt268vf31//93/+poKBAv/76q7p37y4fHx9deeWVeuedd4rUFhkZqdatW2vKlCkXrR8ATMBOEADgknr06KHatWtr3bp1lxy3b98+9ejRQ8OGDVOdOnW0Z88evf3229q0aZNWrVrlMDY/P18xMTF6/PHH9fzzz+vLL7/Uiy++qIyMDM2fP18jRoxQ48aNNXHiRPXv31/h4eGKjIyUdD4AXXfddapVq5ZGjRql0NBQbdiwQWPHjtXBgwf12WefqWHDhlq2bJm6d++uf/zjHxo4cKAk2YPRrl27dNNNN9lDXoMGDfTdd9/p6aef1okTJzR69GiHel988UXdeOONmjJlimrVqqXg4OCLrsM333yjzp07q1aton/PeOzYMQ0YMEAvvPCCfX6PPvqoDh8+rK+//lovvfSS6tatq9dee03R0dFKSkpSSEiIwznuu+8+PfLIIxo8eLCWL1+ud955R/n5+VqxYoWGDh2q5557Tl9++aVGjBihsLAwxcTEOBzfpUsXxcXFybKsKn9fFwBUGAsAYLTPPvvMkmT99NNPFx1Tv359q3Xr1vafR48ebV3qfyGFhYVWfn6+tXbtWkuS9csvv9j7+vXrZ0my5s+fb2/Lz8+3goKCLEnW1q1b7e1paWlW7dq1rf/7v/+ztw0ePNjy9va2fvvtN4f3HD9+vCXJ2rlzp2VZlnX8+HFLkjV69Ogi9d1xxx1W48aNrdOnTzu0P/nkk5aHh4eVnp5uWZZlrV692pJkde7c+aJz/aOUlBRLkjVu3Lgifbfccoslydq8eXOR+Xl6elrJycn29p9//tmSZH3wwQf2tgtr/u677zqc95prrrEkWQsWLLC3XVjPmJiYInV88sknliRr9+7dJZoTANREXA4HAPhLVgmeoZOUlKSHHnpIDRo0UO3ateXq6qpbbrlF0vn7ZP7IZrOpR48e9p9dXFwUFhamhg0b6tprr7W3+/v7Kzg4WL/99pu9LT4+XlFRUQoJCVFBQYH9deedd0rSX970n5ubq5UrV+ree++Vl5eXwzl69Oih3Nxcbdy40eGY3r17/+X8JenIkSOSdNGdooYNG9p3tP44v2uuucZhx6d169aS5DDvC3r27Onwc+vWrWWz2ezzl/63nsUdf6G25OTkEs0JAGoiLocDAFzSmTNnlJaWprZt2150TFZWljp16iQPDw+NHTtWLVq0kJeXlw4fPqyYmBjl5OQ4jPfy8pKHh4dDm5ubm/z9/Yuc283NTbm5ufafU1JStGTJErm6uhZby4kTJy45n7S0NBUUFGjixImaOHFiic7RsGHDS57zggvz/PPcLrjY/P7c7ubmJkkO877YOdzc3C66nhkZGUWOvzDuz58JAJiEEAQAuKRvvvlG586dU5cuXS46ZtWqVTpy5IjWrFlj3/2RpFOnTpV7PYGBgYqIiNAbb7xRbP+f76H5s3r16ql27dr6f//v/+mJJ54odkyzZs0cfi7pvTOBgYGSpPT09BKNd4YLtV2oFQBMRAgCAFzUoUOH9Nxzz6lu3boaPHjwRcddCAnu7u4O7X98olx56dmzp5YuXarQ0FDVq1fvouMu1FLcLlRUVJS2bdumiIgI+65LeWjatKk8PT21f//+cjtneUtKSlKtWrXUsmVLZ5cCAE5DCAIASJJ27NhhvzcmNTVV33//vf3LUhcuXGh/slpxbrrpJtWrV0+PP/64Ro8eLVdXV82ePVu//PJLudf52muvafny5brpppv09NNPq2XLlsrNzdXBgwe1dOlSTZkyRY0bN5aPj4+aNm2qxYsX67bbbpO/v78CAwN15ZVXasKECerYsaM6deqkIUOG6Morr1RmZqYSExO1ZMmSIk+zKyk3NzfdeOONRe4pqko2btyoa6655pIBEgBqOkIQAECSNGDAAEnnf5H38/NT69atNWLECA0cOPCSAUiSAgIC9M0332j48OF65JFHVKdOHd1zzz2aO3eu2rVrV651NmzYUJs3b9brr7+uf/7zn/r999/l4+OjZs2aqXv37g6/3E+bNk3PP/+87r77bp09e1b9+vXTjBkzdPXVV2vr1q16/fXX9corryg1NVV+fn5q3ry5wwMbyuLhhx/WoEGDdPTo0RLfS1RZsrKytHLlSr3++uvOLgUAnMpmleSRPwAAoERyc3PVpEkTDR8+XCNGjHB2OQ6mTZumZ555RocPH2YnCIDReEQ2AADlyMPDQ7GxsXrvvfd05swZZ5djV1BQoLffflsvvvgiAQiA8bgcDgCAcjZo0CCdOnVKSUlJl3y0eGU6fPiwHnnkEQ0fPtzZpQCA03E5HAAAAACjcDkcAAAAAKMQggAAAAAYhRAEAAAAwCiEIAAAAABGIQQBAAAAMAohCAAAAIBRCEEAAAAAjEIIAgAAAGAUQhAAAAAAoxCCAAAAABjl/wO/3/zDvbAL0AAAAABJRU5ErkJggg==", 611 | "text/plain": [ 612 | "
" 613 | ] 614 | }, 615 | "metadata": {}, 616 | "output_type": "display_data" 617 | } 618 | ], 619 | "source": [ 620 | "chart_parsed_dataframe(df)" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "execution_count": null, 626 | "metadata": {}, 627 | "outputs": [], 628 | "source": [] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "execution_count": null, 633 | "metadata": {}, 634 | "outputs": [], 635 | "source": [] 636 | } 637 | ], 638 | "metadata": { 639 | "kernelspec": { 640 | "display_name": "Python 3 (ipykernel)", 641 | "language": "python", 642 | "name": "python3" 643 | }, 644 | "language_info": { 645 | "codemirror_mode": { 646 | "name": "ipython", 647 | "version": 3 648 | }, 649 | "file_extension": ".py", 650 | "mimetype": "text/x-python", 651 | "name": "python", 652 | "nbconvert_exporter": "python", 653 | "pygments_lexer": "ipython3", 654 | "version": "3.10.10" 655 | } 656 | }, 657 | "nbformat": 4, 658 | "nbformat_minor": 4 659 | } 660 | --------------------------------------------------------------------------------