aboutsummaryrefslogtreecommitdiff
path: root/venv/lib/python3.8/site-packages/plotly/io/_html.py
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2025-07-31 17:27:24 -0400
committersotech117 <michael_foiani@brown.edu>2025-07-31 17:27:24 -0400
commit5bf22fc7e3c392c8bd44315ca2d06d7dca7d084e (patch)
tree8dacb0f195df1c0788d36dd0064f6bbaa3143ede /venv/lib/python3.8/site-packages/plotly/io/_html.py
parentb832d364da8c2efe09e3f75828caf73c50d01ce3 (diff)
add code for analysis of data
Diffstat (limited to 'venv/lib/python3.8/site-packages/plotly/io/_html.py')
-rw-r--r--venv/lib/python3.8/site-packages/plotly/io/_html.py517
1 files changed, 517 insertions, 0 deletions
diff --git a/venv/lib/python3.8/site-packages/plotly/io/_html.py b/venv/lib/python3.8/site-packages/plotly/io/_html.py
new file mode 100644
index 0000000..3e7b89c
--- /dev/null
+++ b/venv/lib/python3.8/site-packages/plotly/io/_html.py
@@ -0,0 +1,517 @@
+import uuid
+from pathlib import Path
+import webbrowser
+import hashlib
+import base64
+
+from _plotly_utils.optional_imports import get_module
+from plotly.io._utils import validate_coerce_fig_to_dict, plotly_cdn_url
+from plotly.offline.offline import _get_jconfig, get_plotlyjs
+
+_json = get_module("json")
+
+
+def _generate_sri_hash(content):
+ """Generate SHA256 hash for SRI (Subresource Integrity)"""
+ if isinstance(content, str):
+ content = content.encode("utf-8")
+ sha256_hash = hashlib.sha256(content).digest()
+ return "sha256-" + base64.b64encode(sha256_hash).decode("utf-8")
+
+
+# Build script to set global PlotlyConfig object. This must execute before
+# plotly.js is loaded.
+_window_plotly_config = """\
+<script type="text/javascript">\
+window.PlotlyConfig = {MathJaxConfig: 'local'};\
+</script>"""
+
+_mathjax_config = """\
+<script type="text/javascript">\
+if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: "STIX-Web"}});}\
+</script>"""
+
+
+def to_html(
+ fig,
+ config=None,
+ auto_play=True,
+ include_plotlyjs=True,
+ include_mathjax=False,
+ post_script=None,
+ full_html=True,
+ animation_opts=None,
+ default_width="100%",
+ default_height="100%",
+ validate=True,
+ div_id=None,
+):
+ """
+ Convert a figure to an HTML string representation.
+
+ Parameters
+ ----------
+ fig:
+ Figure object or dict representing a figure
+ config: dict or None (default None)
+ Plotly.js figure config options
+ auto_play: bool (default=True)
+ Whether to automatically start the animation sequence on page load
+ if the figure contains frames. Has no effect if the figure does not
+ contain frames.
+ include_plotlyjs: bool or string (default True)
+ Specifies how the plotly.js library is included/loaded in the output
+ div string.
+
+ If True, a script tag containing the plotly.js source code (~3MB)
+ is included in the output. HTML files generated with this option are
+ fully self-contained and can be used offline.
+
+ If 'cdn', a script tag that references the plotly.js CDN is included
+ in the output. The url used is versioned to match the bundled plotly.js.
+ HTML files generated with this option are about 3MB smaller than those
+ generated with include_plotlyjs=True, but they require an active
+ internet connection in order to load the plotly.js library.
+
+ If 'directory', a script tag is included that references an external
+ plotly.min.js bundle that is assumed to reside in the same
+ directory as the HTML file.
+
+ If a string that ends in '.js', a script tag is included that
+ references the specified path. This approach can be used to point
+ the resulting HTML file to an alternative CDN or local bundle.
+
+ If False, no script tag referencing plotly.js is included. This is
+ useful when the resulting div string will be placed inside an HTML
+ document that already loads plotly.js. This option is not advised
+ when full_html=True as it will result in a non-functional html file.
+ include_mathjax: bool or string (default False)
+ Specifies how the MathJax.js library is included in the output html
+ div string. MathJax is required in order to display labels
+ with LaTeX typesetting.
+
+ If False, no script tag referencing MathJax.js will be included in the
+ output.
+
+ If 'cdn', a script tag that references a MathJax CDN location will be
+ included in the output. HTML div strings generated with this option
+ will be able to display LaTeX typesetting as long as internet access
+ is available.
+
+ If a string that ends in '.js', a script tag is included that
+ references the specified path. This approach can be used to point the
+ resulting HTML div string to an alternative CDN.
+ post_script: str or list or None (default None)
+ JavaScript snippet(s) to be included in the resulting div just after
+ plot creation. The string(s) may include '{plot_id}' placeholders
+ that will then be replaced by the `id` of the div element that the
+ plotly.js figure is associated with. One application for this script
+ is to install custom plotly.js event handlers.
+ full_html: bool (default True)
+ If True, produce a string containing a complete HTML document
+ starting with an <html> tag. If False, produce a string containing
+ a single <div> element.
+ animation_opts: dict or None (default None)
+ dict of custom animation parameters to be passed to the function
+ Plotly.animate in Plotly.js. See
+ https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
+ for available options. Has no effect if the figure does not contain
+ frames, or auto_play is False.
+ default_width, default_height: number or str (default '100%')
+ The default figure width/height to use if the provided figure does not
+ specify its own layout.width/layout.height property. May be
+ specified in pixels as an integer (e.g. 500), or as a css width style
+ string (e.g. '500px', '100%').
+ validate: bool (default True)
+ True if the figure should be validated before being converted to
+ JSON, False otherwise.
+ div_id: str (default None)
+ If provided, this is the value of the id attribute of the div tag. If None, the
+ id attribute is a UUID.
+
+ Returns
+ -------
+ str
+ Representation of figure as an HTML div string
+ """
+ from plotly.io.json import to_json_plotly
+
+ # ## Validate figure ##
+ fig_dict = validate_coerce_fig_to_dict(fig, validate)
+
+ # ## Generate div id ##
+ plotdivid = div_id or str(uuid.uuid4())
+
+ # ## Serialize figure ##
+ jdata = to_json_plotly(fig_dict.get("data", []))
+ jlayout = to_json_plotly(fig_dict.get("layout", {}))
+
+ if fig_dict.get("frames", None):
+ jframes = to_json_plotly(fig_dict.get("frames", []))
+ else:
+ jframes = None
+
+ # ## Serialize figure config ##
+ config = _get_jconfig(config)
+
+ # Set responsive
+ config.setdefault("responsive", True)
+
+ # Get div width/height
+ layout_dict = fig_dict.get("layout", {})
+ template_dict = fig_dict.get("layout", {}).get("template", {}).get("layout", {})
+
+ div_width = layout_dict.get("width", template_dict.get("width", default_width))
+ div_height = layout_dict.get("height", template_dict.get("height", default_height))
+
+ # Add 'px' suffix to numeric widths
+ try:
+ float(div_width)
+ except (ValueError, TypeError):
+ pass
+ else:
+ div_width = str(div_width) + "px"
+
+ try:
+ float(div_height)
+ except (ValueError, TypeError):
+ pass
+ else:
+ div_height = str(div_height) + "px"
+
+ # ## Get platform URL ##
+ if config.get("showLink", False) or config.get("showSendToCloud", False):
+ # Figure is going to include a Chart Studio link or send-to-cloud button,
+ # So we need to configure the PLOTLYENV.BASE_URL property
+ base_url_line = """
+ window.PLOTLYENV.BASE_URL='{plotly_platform_url}';\
+""".format(plotly_platform_url=config.get("plotlyServerURL", "https://plot.ly"))
+ else:
+ # Figure is not going to include a Chart Studio link or send-to-cloud button,
+ # In this case we don't want https://plot.ly to show up anywhere in the HTML
+ # output
+ config.pop("plotlyServerURL", None)
+ config.pop("linkText", None)
+ config.pop("showLink", None)
+ base_url_line = ""
+
+ # ## Build script body ##
+ # This is the part that actually calls Plotly.js
+
+ # build post script snippet(s)
+ then_post_script = ""
+ if post_script:
+ if not isinstance(post_script, (list, tuple)):
+ post_script = [post_script]
+ for ps in post_script:
+ then_post_script += """.then(function(){{
+ {post_script}
+ }})""".format(post_script=ps.replace("{plot_id}", plotdivid))
+
+ then_addframes = ""
+ then_animate = ""
+ if jframes:
+ then_addframes = """.then(function(){{
+ Plotly.addFrames('{id}', {frames});
+ }})""".format(id=plotdivid, frames=jframes)
+
+ if auto_play:
+ if animation_opts:
+ animation_opts_arg = ", " + _json.dumps(animation_opts)
+ else:
+ animation_opts_arg = ""
+ then_animate = """.then(function(){{
+ Plotly.animate('{id}', null{animation_opts});
+ }})""".format(id=plotdivid, animation_opts=animation_opts_arg)
+
+ # Serialize config dict to JSON
+ jconfig = _json.dumps(config)
+
+ script = """\
+ if (document.getElementById("{id}")) {{\
+ Plotly.newPlot(\
+ "{id}",\
+ {data},\
+ {layout},\
+ {config}\
+ ){then_addframes}{then_animate}{then_post_script}\
+ }}""".format(
+ id=plotdivid,
+ data=jdata,
+ layout=jlayout,
+ config=jconfig,
+ then_addframes=then_addframes,
+ then_animate=then_animate,
+ then_post_script=then_post_script,
+ )
+
+ # ## Handle loading/initializing plotly.js ##
+ include_plotlyjs_orig = include_plotlyjs
+ if isinstance(include_plotlyjs, str):
+ include_plotlyjs = include_plotlyjs.lower()
+
+ # Init and load
+ load_plotlyjs = ""
+
+ if include_plotlyjs == "cdn":
+ # Generate SRI hash from the bundled plotly.js content
+ plotlyjs_content = get_plotlyjs()
+ sri_hash = _generate_sri_hash(plotlyjs_content)
+
+ load_plotlyjs = """\
+ {win_config}
+ <script charset="utf-8" src="{cdn_url}" integrity="{integrity}" crossorigin="anonymous"></script>\
+ """.format(
+ win_config=_window_plotly_config,
+ cdn_url=plotly_cdn_url(),
+ integrity=sri_hash,
+ )
+
+ elif include_plotlyjs == "directory":
+ load_plotlyjs = """\
+ {win_config}
+ <script charset="utf-8" src="plotly.min.js"></script>\
+ """.format(win_config=_window_plotly_config)
+
+ elif isinstance(include_plotlyjs, str) and include_plotlyjs.endswith(".js"):
+ load_plotlyjs = """\
+ {win_config}
+ <script charset="utf-8" src="{url}"></script>\
+ """.format(win_config=_window_plotly_config, url=include_plotlyjs_orig)
+
+ elif include_plotlyjs:
+ load_plotlyjs = """\
+ {win_config}
+ <script type="text/javascript">{plotlyjs}</script>\
+ """.format(win_config=_window_plotly_config, plotlyjs=get_plotlyjs())
+
+ # ## Handle loading/initializing MathJax ##
+ include_mathjax_orig = include_mathjax
+ if isinstance(include_mathjax, str):
+ include_mathjax = include_mathjax.lower()
+
+ mathjax_template = """\
+ <script src="{url}?config=TeX-AMS-MML_SVG"></script>"""
+
+ if include_mathjax == "cdn":
+ mathjax_script = (
+ mathjax_template.format(
+ url=("https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js")
+ )
+ + _mathjax_config
+ )
+
+ elif isinstance(include_mathjax, str) and include_mathjax.endswith(".js"):
+ mathjax_script = (
+ mathjax_template.format(url=include_mathjax_orig) + _mathjax_config
+ )
+ elif not include_mathjax:
+ mathjax_script = ""
+ else:
+ raise ValueError(
+ """\
+Invalid value of type {typ} received as the include_mathjax argument
+ Received value: {val}
+
+include_mathjax may be specified as False, 'cdn', or a string ending with '.js'
+ """.format(typ=type(include_mathjax), val=repr(include_mathjax))
+ )
+
+ plotly_html_div = """\
+<div>\
+ {mathjax_script}\
+ {load_plotlyjs}\
+ <div id="{id}" class="plotly-graph-div" \
+style="height:{height}; width:{width};"></div>\
+ <script type="text/javascript">\
+ window.PLOTLYENV=window.PLOTLYENV || {{}};{base_url_line}\
+ {script};\
+ </script>\
+ </div>""".format(
+ mathjax_script=mathjax_script,
+ load_plotlyjs=load_plotlyjs,
+ id=plotdivid,
+ width=div_width,
+ height=div_height,
+ base_url_line=base_url_line,
+ script=script,
+ ).strip()
+
+ if full_html:
+ return """\
+<html>
+<head><meta charset="utf-8" /></head>
+<body>
+ {div}
+</body>
+</html>""".format(div=plotly_html_div)
+ else:
+ return plotly_html_div
+
+
+def write_html(
+ fig,
+ file,
+ config=None,
+ auto_play=True,
+ include_plotlyjs=True,
+ include_mathjax=False,
+ post_script=None,
+ full_html=True,
+ animation_opts=None,
+ validate=True,
+ default_width="100%",
+ default_height="100%",
+ auto_open=False,
+ div_id=None,
+):
+ """
+ Write a figure to an HTML file representation
+
+ Parameters
+ ----------
+ fig:
+ Figure object or dict representing a figure
+ file: str or writeable
+ A string representing a local file path or a writeable object
+ (e.g. a pathlib.Path object or an open file descriptor)
+ config: dict or None (default None)
+ Plotly.js figure config options
+ auto_play: bool (default=True)
+ Whether to automatically start the animation sequence on page load
+ if the figure contains frames. Has no effect if the figure does not
+ contain frames.
+ include_plotlyjs: bool or string (default True)
+ Specifies how the plotly.js library is included/loaded in the output
+ div string.
+
+ If True, a script tag containing the plotly.js source code (~3MB)
+ is included in the output. HTML files generated with this option are
+ fully self-contained and can be used offline.
+
+ If 'cdn', a script tag that references the plotly.js CDN is included
+ in the output. The url used is versioned to match the bundled plotly.js.
+ HTML files generated with this option are about 3MB smaller than those
+ generated with include_plotlyjs=True, but they require an active
+ internet connection in order to load the plotly.js library.
+
+ If 'directory', a script tag is included that references an external
+ plotly.min.js bundle that is assumed to reside in the same
+ directory as the HTML file. If `file` is a string to a local file
+ path and `full_html` is True, then the plotly.min.js bundle is copied
+ into the directory of the resulting HTML file. If a file named
+ plotly.min.js already exists in the output directory then this file
+ is left unmodified and no copy is performed. HTML files generated
+ with this option can be used offline, but they require a copy of
+ the plotly.min.js bundle in the same directory. This option is
+ useful when many figures will be saved as HTML files in the same
+ directory because the plotly.js source code will be included only
+ once per output directory, rather than once per output file.
+
+ If a string that ends in '.js', a script tag is included that
+ references the specified path. This approach can be used to point
+ the resulting HTML file to an alternative CDN or local bundle.
+
+ If False, no script tag referencing plotly.js is included. This is
+ useful when the resulting div string will be placed inside an HTML
+ document that already loads plotly.js. This option is not advised
+ when full_html=True as it will result in a non-functional html file.
+
+ include_mathjax: bool or string (default False)
+ Specifies how the MathJax.js library is included in the output html
+ div string. MathJax is required in order to display labels
+ with LaTeX typesetting.
+
+ If False, no script tag referencing MathJax.js will be included in the
+ output.
+
+ If 'cdn', a script tag that references a MathJax CDN location will be
+ included in the output. HTML div strings generated with this option
+ will be able to display LaTeX typesetting as long as internet access
+ is available.
+
+ If a string that ends in '.js', a script tag is included that
+ references the specified path. This approach can be used to point the
+ resulting HTML div string to an alternative CDN.
+ post_script: str or list or None (default None)
+ JavaScript snippet(s) to be included in the resulting div just after
+ plot creation. The string(s) may include '{plot_id}' placeholders
+ that will then be replaced by the `id` of the div element that the
+ plotly.js figure is associated with. One application for this script
+ is to install custom plotly.js event handlers.
+ full_html: bool (default True)
+ If True, produce a string containing a complete HTML document
+ starting with an <html> tag. If False, produce a string containing
+ a single <div> element.
+ animation_opts: dict or None (default None)
+ dict of custom animation parameters to be passed to the function
+ Plotly.animate in Plotly.js. See
+ https://github.com/plotly/plotly.js/blob/master/src/plots/animation_attributes.js
+ for available options. Has no effect if the figure does not contain
+ frames, or auto_play is False.
+ default_width, default_height: number or str (default '100%')
+ The default figure width/height to use if the provided figure does not
+ specify its own layout.width/layout.height property. May be
+ specified in pixels as an integer (e.g. 500), or as a css width style
+ string (e.g. '500px', '100%').
+ validate: bool (default True)
+ True if the figure should be validated before being converted to
+ JSON, False otherwise.
+ auto_open: bool (default True)
+ If True, open the saved file in a web browser after saving.
+ This argument only applies if `full_html` is True.
+ div_id: str (default None)
+ If provided, this is the value of the id attribute of the div tag. If None, the
+ id attribute is a UUID.
+
+ Returns
+ -------
+ None
+ """
+
+ # Build HTML string
+ html_str = to_html(
+ fig,
+ config=config,
+ auto_play=auto_play,
+ include_plotlyjs=include_plotlyjs,
+ include_mathjax=include_mathjax,
+ post_script=post_script,
+ full_html=full_html,
+ animation_opts=animation_opts,
+ default_width=default_width,
+ default_height=default_height,
+ validate=validate,
+ div_id=div_id,
+ )
+
+ # Check if file is a string
+ if isinstance(file, str):
+ # Use the standard pathlib constructor to make a pathlib object.
+ path = Path(file)
+ elif isinstance(file, Path): # PurePath is the most general pathlib object.
+ # `file` is already a pathlib object.
+ path = file
+ else:
+ # We could not make a pathlib object out of file. Either `file` is an open file
+ # descriptor with a `write()` method or it's an invalid object.
+ path = None
+
+ # Write HTML string
+ if path is not None:
+ # To use a different file encoding, pass a file descriptor
+ path.write_text(html_str, "utf-8")
+ else:
+ file.write(html_str)
+
+ # Check if we should copy plotly.min.js to output directory
+ if path is not None and full_html and include_plotlyjs == "directory":
+ bundle_path = path.parent / "plotly.min.js"
+
+ if not bundle_path.exists():
+ bundle_path.write_text(get_plotlyjs(), encoding="utf-8")
+
+ # Handle auto_open
+ if path is not None and full_html and auto_open:
+ url = path.absolute().as_uri()
+ webbrowser.open(url)