diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..a7d0fc7b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "esbonio.sphinx.confDir": "" +} \ No newline at end of file diff --git a/docs_using_sphinx/_build/doctrees/aboutus.doctree b/docs_using_sphinx/_build/doctrees/aboutus.doctree index 9cc89218..5af11c17 100644 Binary files a/docs_using_sphinx/_build/doctrees/aboutus.doctree and b/docs_using_sphinx/_build/doctrees/aboutus.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/contributorGuide.doctree b/docs_using_sphinx/_build/doctrees/contributorGuide.doctree index a67f0d69..806d3e02 100644 Binary files a/docs_using_sphinx/_build/doctrees/contributorGuide.doctree and b/docs_using_sphinx/_build/doctrees/contributorGuide.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/dev.doctree b/docs_using_sphinx/_build/doctrees/dev.doctree index f862b1d6..a1a6c54a 100644 Binary files a/docs_using_sphinx/_build/doctrees/dev.doctree and b/docs_using_sphinx/_build/doctrees/dev.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/dev/easygraph-doc-source.doctree b/docs_using_sphinx/_build/doctrees/dev/easygraph-doc-source.doctree index 6d361ea4..2c9be6d8 100644 Binary files a/docs_using_sphinx/_build/doctrees/dev/easygraph-doc-source.doctree and b/docs_using_sphinx/_build/doctrees/dev/easygraph-doc-source.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/dev/manual-releasing.doctree b/docs_using_sphinx/_build/doctrees/dev/manual-releasing.doctree index 06cfb5f0..a1e041a3 100644 Binary files a/docs_using_sphinx/_build/doctrees/dev/manual-releasing.doctree and b/docs_using_sphinx/_build/doctrees/dev/manual-releasing.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/dev/releasing.doctree b/docs_using_sphinx/_build/doctrees/dev/releasing.doctree index 442154f4..eb85fff3 100644 Binary files a/docs_using_sphinx/_build/doctrees/dev/releasing.doctree and b/docs_using_sphinx/_build/doctrees/dev/releasing.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/egeps.doctree b/docs_using_sphinx/_build/doctrees/egeps.doctree index ab19375a..467feda4 100644 Binary files a/docs_using_sphinx/_build/doctrees/egeps.doctree and b/docs_using_sphinx/_build/doctrees/egeps.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/egeps/egep-0001.doctree b/docs_using_sphinx/_build/doctrees/egeps/egep-0001.doctree index 7f93784f..110218c0 100644 Binary files a/docs_using_sphinx/_build/doctrees/egeps/egep-0001.doctree and b/docs_using_sphinx/_build/doctrees/egeps/egep-0001.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/egeps/egep-0002.doctree b/docs_using_sphinx/_build/doctrees/egeps/egep-0002.doctree index 643e1762..91cdf5f8 100644 Binary files a/docs_using_sphinx/_build/doctrees/egeps/egep-0002.doctree and b/docs_using_sphinx/_build/doctrees/egeps/egep-0002.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/environment.pickle b/docs_using_sphinx/_build/doctrees/environment.pickle index d640c29f..cfc5d5fb 100644 Binary files a/docs_using_sphinx/_build/doctrees/environment.pickle and b/docs_using_sphinx/_build/doctrees/environment.pickle differ diff --git a/docs_using_sphinx/_build/doctrees/example.doctree b/docs_using_sphinx/_build/doctrees/example.doctree index ec6e86f0..9260d9ba 100644 Binary files a/docs_using_sphinx/_build/doctrees/example.doctree and b/docs_using_sphinx/_build/doctrees/example.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/hypergraph.doctree b/docs_using_sphinx/_build/doctrees/hypergraph.doctree index ec71ae37..c735abfa 100644 Binary files a/docs_using_sphinx/_build/doctrees/hypergraph.doctree and b/docs_using_sphinx/_build/doctrees/hypergraph.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/index.doctree b/docs_using_sphinx/_build/doctrees/index.doctree index 8a557a54..1e27cf42 100644 Binary files a/docs_using_sphinx/_build/doctrees/index.doctree and b/docs_using_sphinx/_build/doctrees/index.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/install.doctree b/docs_using_sphinx/_build/doctrees/install.doctree index 1794284e..4968828f 100644 Binary files a/docs_using_sphinx/_build/doctrees/install.doctree and b/docs_using_sphinx/_build/doctrees/install.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/license.doctree b/docs_using_sphinx/_build/doctrees/license.doctree index b180e1bc..2df32938 100644 Binary files a/docs_using_sphinx/_build/doctrees/license.doctree and b/docs_using_sphinx/_build/doctrees/license.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference.doctree b/docs_using_sphinx/_build/doctrees/reference.doctree index c9b39aeb..292e2e27 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference.doctree and b/docs_using_sphinx/_build/doctrees/reference.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.classes.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.classes.doctree index 82560014..3baa453d 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.classes.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.classes.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.datapipe.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.datapipe.doctree index a8e41842..b479fbfa 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.datapipe.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.datapipe.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.doctree index d167f33f..1611506d 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.dynamic.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.dynamic.doctree new file mode 100644 index 00000000..4ee8c1c8 Binary files /dev/null and b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.dynamic.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.hypergraph.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.hypergraph.doctree index 4156f2d8..28f2b9dd 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.hypergraph.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.datasets.hypergraph.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.doctree index b0e2ec6e..5e65fe54 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.doctree index f7fd6b2a..6eee98e0 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.hypergraphs.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.hypergraphs.doctree index 8f6df1f8..b0174491 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.hypergraphs.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.experiments.hypergraphs.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.basic.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.basic.doctree index 0e19dd45..ebc9c4b1 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.basic.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.basic.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.centrality.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.centrality.doctree index ebd217ee..8d058e1e 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.centrality.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.centrality.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.community.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.community.doctree index e9da2264..da88be27 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.community.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.community.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.components.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.components.doctree index b93adcf3..09cb7e90 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.components.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.components.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.core.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.core.doctree index a4fee274..19e17d69 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.core.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.core.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.doctree index 9ce85ef5..d40582ed 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.drawing.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.drawing.doctree index ab47c908..ffdbc283 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.drawing.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.drawing.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_embedding.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_embedding.doctree index a8aa3c56..3f1b2f5d 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_embedding.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_embedding.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_generator.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_generator.doctree index 9eea0632..834e4788 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_generator.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.graph_generator.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.centrality.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.centrality.doctree index abb0c6d6..2e136df9 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.centrality.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.centrality.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.doctree index f7ebba99..b0bc21d4 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.hypergraph_generator.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.hypergraph_generator.doctree index 07ace9be..f1f246a6 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.hypergraph_generator.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.hypergraph.hypergraph_generator.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.path.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.path.doctree index e8cd2e74..c4512d6e 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.path.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.path.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.structural_holes.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.structural_holes.doctree index 83d67b44..c16b1648 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.structural_holes.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.functions.structural_holes.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.doctree index a00aa585..f5aefe07 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.hypergraphs.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.hypergraphs.doctree index fc8ae98f..8f7883a5 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.hypergraphs.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.ml_metrics.hypergraphs.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.model.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.model.doctree index 690942a5..c4223743 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.model.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.model.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.model.hypergraphs.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.model.hypergraphs.doctree index cbb31b5b..e33e9927 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.model.hypergraphs.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.model.hypergraphs.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.doctree index c7ceb928..a60ea286 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.hypergraphs.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.hypergraphs.doctree index 0c8fb519..ece761ff 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.hypergraphs.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.convs.hypergraphs.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.doctree index d577f783..2eb405e8 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.nn.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.doctree index e6fd3a41..6804635b 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.json_graph.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.json_graph.doctree index ba9c8c13..7c36d77c 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.json_graph.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.readwrite.json_graph.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/easygraph.utils.doctree b/docs_using_sphinx/_build/doctrees/reference/easygraph.utils.doctree index f2d6687c..9fc72015 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/easygraph.utils.doctree and b/docs_using_sphinx/_build/doctrees/reference/easygraph.utils.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/reference/modules.doctree b/docs_using_sphinx/_build/doctrees/reference/modules.doctree index 36af6770..bcad954a 100644 Binary files a/docs_using_sphinx/_build/doctrees/reference/modules.doctree and b/docs_using_sphinx/_build/doctrees/reference/modules.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/sourcecode.doctree b/docs_using_sphinx/_build/doctrees/sourcecode.doctree index bd94f86f..f52212f6 100644 Binary files a/docs_using_sphinx/_build/doctrees/sourcecode.doctree and b/docs_using_sphinx/_build/doctrees/sourcecode.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/tutorial.doctree b/docs_using_sphinx/_build/doctrees/tutorial.doctree index 58b553e1..47e93f45 100644 Binary files a/docs_using_sphinx/_build/doctrees/tutorial.doctree and b/docs_using_sphinx/_build/doctrees/tutorial.doctree differ diff --git a/docs_using_sphinx/_build/doctrees/videos.doctree b/docs_using_sphinx/_build/doctrees/videos.doctree index 52faad17..af4ab4ce 100644 Binary files a/docs_using_sphinx/_build/doctrees/videos.doctree and b/docs_using_sphinx/_build/doctrees/videos.doctree differ diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/datapipe/loader.html b/docs_using_sphinx/_build/html/_modules/easygraph/datapipe/loader.html new file mode 100644 index 00000000..3fb8caa4 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/datapipe/loader.html @@ -0,0 +1,517 @@ + + + + + + + + easygraph.datapipe.loader - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.datapipe.loader

+import json
+import pickle as pkl
+import re
+
+from pathlib import Path
+from typing import Callable
+from typing import List
+from typing import Optional
+from typing import Union
+
+
+
+[docs] +def load_from_pickle( + file_path: Path, keys: Optional[Union[str, List[str]]] = None, **kwargs +): + r"""Load data from a pickle file. + + Args: + ``file_path`` (``Path``): The local path of the file. + ``keys`` (``Union[str, List[str]]``, optional): The keys of the data. Defaults to ``None``. + """ + if isinstance(file_path, list): + raise ValueError("This function only support loading data from a single file.") + with open(file_path, "rb") as f: + data = pkl.load(f, **kwargs) + if keys is None: + return data + elif isinstance(keys, str): + return data[keys] + else: + return {key: data[key] for key in keys}
+ + + +
+[docs] +def load_from_json(file_path: Path, **kwargs): + r"""Load data from a json file. + + Args: + ``file_path`` (``Path``): The local path of the file. + """ + with open(file_path, "r") as f: + data = json.load(f, **kwargs) + return data
+ + + +
+[docs] +def load_from_txt( + file_path: Path, + dtype: Union[str, Callable], + sep: str = ",| |\t", + ignore_header: int = 0, +): + r"""Load data from a txt file. + + .. note:: + The separator is a regular expression of ``re`` module. Multiple separators can be separated by ``|``. More details can refer to `re.split <https://docs.python.org/3/library/re.html#re.split>`_. + + Args: + ``file_path`` (``Path``): The local path of the file. + ``dtype`` (``Union[str, Callable]``): The data type of the data can be either a string or a callable function. + ``sep`` (``str``, optional): The separator of each line in the file. Defaults to ``",| |\t"``. + ``ignore_header`` (``int``, optional): The number of lines to ignore in the header of the file. Defaults to ``0``. + """ + cast_fun = ret_cast_fun(dtype) + file_path = Path(file_path) + assert file_path.exists(), f"{file_path} does not exist." + data = [] + with open(file_path, "r") as f: + for _ in range(ignore_header): + f.readline() + data = [ + list(map(cast_fun, re.split(sep, line.strip()))) for line in f.readlines() + ] + return data
+ + + +
+[docs] +def ret_cast_fun(dtype: Union[str, Callable]): + r"""Return the cast function of the data type. The supported data types are: ``int``, ``float``, ``str``. + + Args: + ``dtype`` (``Union[str, Callable]``): The data type of the data can be either a string or a callable function. + """ + if isinstance(dtype, str): + if dtype == "int": + return int + elif dtype == "float": + return float + elif dtype == "str": + return str + else: + raise ValueError("dtype must be one of 'int', 'float', 'str'.") + else: + return dtype
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/exception.html b/docs_using_sphinx/_build/html/_modules/easygraph/exception.html new file mode 100644 index 00000000..d697d87b --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/exception.html @@ -0,0 +1,532 @@ + + + + + + + + easygraph.exception - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.exception

+"""
+**********
+Exceptions
+**********
+
+Base exceptions and errors for EasyGraph.
+"""
+
+__all__ = [
+    "HasACycle",
+    "NodeNotFound",
+    "EasyGraphAlgorithmError",
+    "EasyGraphException",
+    "EasyGraphError",
+    "EasyGraphNoCycle",
+    "EasyGraphNoPath",
+    "EasyGraphNotImplemented",
+    "EasyGraphPointlessConcept",
+    "EasyGraphUnbounded",
+    "EasyGraphUnfeasible",
+]
+
+
+
+[docs] +class EasyGraphException(Exception): + """Base class for exceptions in EasyGraph."""
+ + + +
+[docs] +class EasyGraphError(EasyGraphException): + """Exception for a serious error in EasyGraph"""
+ + + +
+[docs] +class EasyGraphPointlessConcept(EasyGraphException): + """Raised when a null graph is provided as input to an algorithm + that cannot use it. + + The null graph is sometimes considered a pointless concept [1]_, + thus the name of the exception. + + References + ---------- + .. [1] Harary, F. and Read, R. "Is the Null Graph a Pointless + Concept?" In Graphs and Combinatorics Conference, George + Washington University. New York: Springer-Verlag, 1973. + + """
+ + + +
+[docs] +class EasyGraphAlgorithmError(EasyGraphException): + """Exception for unexpected termination of algorithms."""
+ + + +
+[docs] +class EasyGraphUnfeasible(EasyGraphAlgorithmError): + """Exception raised by algorithms trying to solve a problem + instance that has no feasible solution."""
+ + + +
+[docs] +class EasyGraphNoPath(EasyGraphUnfeasible): + """Exception for algorithms that should return a path when running + on graphs where such a path does not exist."""
+ + + +
+[docs] +class EasyGraphNoCycle(EasyGraphUnfeasible): + """Exception for algorithms that should return a cycle when running + on graphs where such a cycle does not exist."""
+ + + +
+[docs] +class HasACycle(EasyGraphException): + """Raised if a graph has a cycle when an algorithm expects that it + will have no cycles. + + """
+ + + +
+[docs] +class EasyGraphUnbounded(EasyGraphAlgorithmError): + """Exception raised by algorithms trying to solve a maximization + or a minimization problem instance that is unbounded."""
+ + + +
+[docs] +class EasyGraphNotImplemented(EasyGraphException): + """Exception raised by algorithms not implemented for a type of graph."""
+ + + +
+[docs] +class NodeNotFound(EasyGraphException): + """Exception raised if requested node is not present in the graph"""
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/basic/predecessor_path_based.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/basic/predecessor_path_based.html new file mode 100644 index 00000000..4d7118a3 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/basic/predecessor_path_based.html @@ -0,0 +1,519 @@ + + + + + + + + easygraph.functions.basic.predecessor_path_based - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.basic.predecessor_path_based

+import easygraph as eg
+
+
+__all__ = [
+    "predecessor",
+]
+
+
+
+[docs] +def predecessor(G, source, target=None, cutoff=None, return_seen=None): + """Returns dict of predecessors for the path from source to all nodes in G. + + Parameters + ---------- + G : EasyGraph graph + + source : node label + Starting node for path + + target : node label, optional + Ending node for path. If provided only predecessors between + source and target are returned + + cutoff : integer, optional + Depth to stop the search. Only paths of length <= cutoff are returned. + + return_seen : bool, optional (default=None) + Whether to return a dictionary, keyed by node, of the level (number of + hops) to reach the node (as seen during breadth-first-search). + + Returns + ------- + pred : dictionary + Dictionary, keyed by node, of predecessors in the shortest path. + + + (pred, seen): tuple of dictionaries + If `return_seen` argument is set to `True`, then a tuple of dictionaries + is returned. The first element is the dictionary, keyed by node, of + predecessors in the shortest path. The second element is the dictionary, + keyed by node, of the level (number of hops) to reach the node (as seen + during breadth-first-search). + + Examples + -------- + >>> G = eg.path_graph(4) + >>> list(G) + [0, 1, 2, 3] + >>> eg.predecessor(G, 0) + {0: [], 1: [0], 2: [1], 3: [2]} + >>> eg.predecessor(G, 0, return_seen=True) + ({0: [], 1: [0], 2: [1], 3: [2]}, {0: 0, 1: 1, 2: 2, 3: 3}) + + + """ + + if source not in G: + raise eg.NodeNotFound(f"Source {source} not in G") + level = 0 # the current level + nextlevel = [source] # list of nodes to check at next level + seen = {source: level} # level (number of hops) when seen in BFS + pred = {source: []} # predecessor dictionary + while nextlevel: + level = level + 1 + thislevel = nextlevel + nextlevel = [] + for v in thislevel: + for w in list(G.neighbors(v)): + if w not in seen: + pred[w] = [v] + seen[w] = level + nextlevel.append(w) + elif seen[w] == level: # add v to predecessor list if it + pred[w].append(v) # is at the correct level + if cutoff and cutoff <= level: + break + + if target is not None: + if return_seen: + if target not in pred: + return ([], -1) # No predecessor + return (pred[target], seen[target]) + else: + if target not in pred: + return [] # No predecessor + return pred[target] + else: + if return_seen: + return (pred, seen) + else: + return pred
+ + + +# def main(): +# G = eg.path_graph(4) +# print(G.edges) + +# print(predecessor(G, 0)) + + +# if __name__ == "__main__": +# main() +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/assortativity.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/assortativity.html new file mode 100644 index 00000000..51b2fb7c --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/assortativity.html @@ -0,0 +1,606 @@ + + + + + + + + easygraph.functions.hypergraph.assortativity - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.assortativity

+"""Algorithms for finding the degree assortativity of a hypergraph."""
+
+import random
+
+from itertools import combinations
+
+import numpy
+import numpy as np
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = ["dynamical_assortativity", "degree_assortativity"]
+
+
+
+[docs] +def dynamical_assortativity(H): + """Computes the dynamical assortativity of a uniform hypergraph. + + Parameters + ---------- + H : xgi.Hypergraph + Hypergraph of interest + + Returns + ------- + float + The dynamical assortativity + + See Also + -------- + degree_assortativity + + Raises + ------ + EasyGraphError + If the hypergraph is not uniform, or if there are no nodes + or no edges + + References + ---------- + Nicholas Landry and Juan G. Restrepo, + Hypergraph assortativity: A dynamical systems perspective, + Chaos 2022. + DOI: 10.1063/5.0086905 + + """ + if len(H.v) == 0: + raise EasyGraphError("Hypergraph must contain nodes") + elif len(H.e[0]) == 0: + raise EasyGraphError("Hypergraph must contain edges!") + + if not H.is_uniform(): + raise EasyGraphError("Hypergraph must be uniform!") + + if 1 in H.unique_edge_sizes(): + raise EasyGraphError("No singleton edges!") + + degs = H.deg_v + k1 = sum(degs) / len(degs) + k2 = np.mean(numpy.array(degs) ** 2) + kk1 = np.mean( + [degs[n1] * degs[n2] for e in H.e[0] for n1, n2 in combinations(e, 2)] + ) + + return kk1 * k1**2 / k2**2 - 1
+ + + +
+[docs] +def degree_assortativity(H, kind="uniform", exact=False, num_samples=1000): + """Computes the degree assortativity of a hypergraph + + Parameters + ---------- + H : Hypergraph + The hypergraph of interest + kind : str, optional + the type of degree assortativity. valid choices are + "uniform", "top-2", and "top-bottom". By default, "uniform". + exact : bool, optional + whether to compute over all edges or sample randomly from the + set of edges. By default, False. + num_samples : int, optional + if not exact, specify the number of samples for the computation. + By default, 1000. + + Returns + ------- + float + the degree assortativity + + Raises + ------ + EasyGraphError + If there are no nodes or no edges + + See Also + -------- + dynamical_assortativity + + References + ---------- + Phil Chodrow, + Configuration models of random hypergraphs, + Journal of Complex Networks 2020. + DOI: 10.1093/comnet/cnaa018 + """ + + if len(H.v) == 0: + raise EasyGraphError("Hypergraph must contain nodes") + elif len(H.e[0]) == 0: + raise EasyGraphError("Hypergraph must contain edges!") + + degs = H.deg_v + if exact: + k1k2 = [_choose_degrees(e, degs, kind) for e in H.e[0] if len(e) > 1] + else: + edges = [e for e in H.e[0] if len(e) > 1] + k1k2 = [ + _choose_degrees(random.choice(H.e[0]), degs, kind) + for _ in range(num_samples) + ] + + rho = np.corrcoef(np.array(k1k2).T)[0, 1] + if np.isnan(rho): + return 0 + return rho
+ + + +def _choose_degrees(e, k, kind="uniform"): + """Choose the degrees of two nodes in a hyperedge. + + Parameters + ---------- + e : iterable + the members in a hyperedge + k : dict + the degrees where keys are node IDs and values are degrees + kind : str, optional + the type of degree assortativity, options are "uniform", "top-2", + and "top-bottom". By default, "uniform". + + Returns + ------- + tuple + two degrees selected from the edge + + Raises + ------ + EasyGraphError + if invalid assortativity function chosen + + See Also + -------- + degree_assortativity + + References + ---------- + Phil Chodrow, + Configuration models of random hypergraphs, + Journal of Complex Networks 2020. + DOI: 10.1093/comnet/cnaa018 + """ + e = list(e) + if len(e) > 1: + if kind == "uniform": + i = np.random.randint(len(e)) + j = i + while i == j: + j = np.random.randint(len(e)) + return (k[e[i]], k[e[j]]) + + elif kind == "top-2": + degs = sorted([k[i] for i in e])[-2:] + random.shuffle(degs) + return degs + + elif kind == "top-bottom": + # this selects the largest and smallest degrees in one line + degs = sorted([k[i] for i in e])[:: len(e) - 1] + random.shuffle(degs) + return degs + + else: + raise EasyGraphError("Invalid choice function!") + else: + raise EasyGraphError("Edge must have more than one member!") +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/cycle_ratio.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/cycle_ratio.html new file mode 100644 index 00000000..f81db5eb --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/cycle_ratio.html @@ -0,0 +1,631 @@ + + + + + + + + easygraph.functions.hypergraph.centrality.cycle_ratio - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.centrality.cycle_ratio

+import copy
+import itertools
+
+import easygraph as eg
+
+
+__all__ = [
+    "my_all_shortest_paths",
+    "getandJudgeSimpleCircle",
+    "getSmallestCycles",
+    "StatisticsAndCalculateIndicators",
+    "cycle_ratio_centrality",
+]
+
+
+SmallestCycles = set()
+CycleRatio = {}
+
+
+
+[docs] +def my_all_shortest_paths(G, source, target): + pred = eg.predecessor(G, source) + if target not in pred: + raise eg.EasyGraphNoPath( + f"Target {target} cannot be reached from given sources" + ) + sources = {source} + seen = {target} + stack = [[target, 0]] + top = 0 + while top >= 0: + node, i = stack[top] + if node in sources: + yield [p for p, n in reversed(stack[: top + 1])] + if len(pred[node]) > i: + stack[top][1] = i + 1 + next = pred[node][i] + if next in seen: + continue + else: + seen.add(next) + top += 1 + if top == len(stack): + stack.append([next, 0]) + else: + stack[top][:] = [next, 0] + else: + seen.discard(node) + top -= 1
+ + + +
+[docs] +def getandJudgeSimpleCircle(objectList): # + numEdge = 0 + for eleArr in list(itertools.combinations(objectList, 2)): + if G.has_edge(eleArr[0], eleArr[1]): + numEdge += 1 + if numEdge != len(objectList): + return False + else: + return True
+ + + +
+[docs] +def getSmallestCycles(G, NodeGirth, Coreness, DEF_IMPOSSLEN): + NodeList = list(G.nodes) + # print(NodeList) + NodeList.sort() + # setp 1 + curCyc = list() + for ix in NodeList[:-2]: # v1 + if NodeGirth[ix] == 0: + continue + curCyc.append(ix) + for jx in NodeList[NodeList.index(ix) + 1 : -1]: # v2 + if NodeGirth[jx] == 0: + continue + curCyc.append(jx) + if G.has_edge(ix, jx): + for kx in NodeList[NodeList.index(jx) + 1 :]: # v3 + if NodeGirth[kx] == 0: + continue + if G.has_edge(kx, ix): + curCyc.append(kx) + if G.has_edge(kx, jx): + SmallestCycles.add(tuple(curCyc)) + for i in curCyc: + NodeGirth[i] = 3 + curCyc.pop() + curCyc.pop() + curCyc.pop() + + # setp 2 + ResiNodeList = [] # Residual Node List + for nod in NodeList: + if NodeGirth[nod] == DEF_IMPOSSLEN: + ResiNodeList.append(nod) + if len(ResiNodeList) == 0: + return + else: + visitedNodes = dict.fromkeys(ResiNodeList, set()) + for nod in ResiNodeList: + if Coreness[nod] == 2 and NodeGirth[nod] < DEF_IMPOSSLEN: + continue + for nei in list(G.neighbors(nod)): + if Coreness[nei] == 2 and NodeGirth[nei] < DEF_IMPOSSLEN: + continue + if not nei in visitedNodes.keys() or not nod in visitedNodes[nei]: + visitedNodes[nod].add(nei) + if nei not in visitedNodes.keys(): + visitedNodes[nei] = set([nod]) + else: + visitedNodes[nei].add(nod) + if Coreness[nei] == 2 and NodeGirth[nei] < DEF_IMPOSSLEN: + continue + G.remove_edge(nod, nei) + if eg.single_source_dijkstra(G, nod, nei): + for path in my_all_shortest_paths(G, nod, nei): + lenPath = len(path) + path.sort() + SmallestCycles.add(tuple(path)) + for i in path: + if NodeGirth[i] > lenPath: + NodeGirth[i] = lenPath + G.add_edge(nod, nei) + + return SmallestCycles
+ + + +
+[docs] +def StatisticsAndCalculateIndicators(SmallestCyclesOfNodes, CycLenDict): # + global NumSmallCycles + NumSmallCycles = len(SmallestCycles) + for cyc in SmallestCycles: + lenCyc = len(cyc) + CycLenDict[lenCyc] += 1 + for nod in cyc: + SmallestCyclesOfNodes[nod].add(cyc) + for objNode, SmaCycs in SmallestCyclesOfNodes.items(): + if len(SmaCycs) == 0: + continue + cycleNeighbors = set() + NeiOccurTimes = {} + for cyc in SmaCycs: + for n in cyc: + if n in NeiOccurTimes.keys(): + NeiOccurTimes[n] += 1 + else: + NeiOccurTimes[n] = 1 + cycleNeighbors = cycleNeighbors.union(cyc) + cycleNeighbors.remove(objNode) + del NeiOccurTimes[objNode] + sum = 0 + for nei in cycleNeighbors: + sum += float(NeiOccurTimes[nei]) / len(SmallestCyclesOfNodes[nei]) + CycleRatio[objNode] = sum + 1 + return CycleRatio
+ + + +
+[docs] +def cycle_ratio_centrality(G): + """ + Parameters + ---------- + G : eg.Graph + + Returns + ------- + cycle ratio centrality of each node in G : dict + + Example + ------- + >>> G = eg.Graph() + >>> G.add_edges([(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (1, 5), (2, 5)]) + >>> cycle_ratio_centrality(G) + {1: 4.083333333333333, 2: 4.083333333333333, 3: 2.6666666666666665, 4: 2.6666666666666665, 5: 1.5} + + """ + CycLenDict = dict() + NumNode = G.number_of_nodes() # update + DEF_IMPOSSLEN = NumNode + 1 # Impossible simple cycle length + NodeGirth = dict() + CycLenDict = dict() + + SmallestCyclesOfNodes = {} # + removeNodes = set() + Coreness = dict(zip(list(G.nodes), eg.k_core(G))) + for i in list(G.nodes): # + SmallestCyclesOfNodes[i] = set() + CycleRatio[i] = 0 + if G.degree()[i] <= 1 or Coreness[i] <= 1: + NodeGirth[i] = 0 + removeNodes.add(i) + else: + NodeGirth[i] = DEF_IMPOSSLEN + # print('NodeGirth:', NodeGirth) + + G.remove_nodes_from(removeNodes) + + NodeNum = G.number_of_nodes() + for i in range(3, NodeNum + 2): + CycLenDict[i] = 0 + + getSmallestCycles(G, NodeGirth, Coreness, DEF_IMPOSSLEN) + cycle_ratio = StatisticsAndCalculateIndicators(SmallestCyclesOfNodes, CycLenDict) + return cycle_ratio
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/degree.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/degree.html new file mode 100644 index 00000000..31483faf --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/centrality/degree.html @@ -0,0 +1,445 @@ + + + + + + + + easygraph.functions.hypergraph.centrality.degree - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.centrality.degree

+__all__ = ["hyepergraph_degree_centrality"]
+
+
+
+[docs] +def hyepergraph_degree_centrality(G): + """ + + Parameters + ---------- + G : eg.Hypergraph + + Returns + ------- + degree centrality of each node in G : dict + + """ + res = {} + node_list = G.v + # Get hyperedge list + edge_list = G.e[0] + for node in node_list: + res[node] = 0 + + for e in edge_list: + for n in e: + res[n] += 1 + + return res
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_clustering.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_clustering.html new file mode 100644 index 00000000..26d2ffdb --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_clustering.html @@ -0,0 +1,719 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_clustering - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_clustering

+"""Algorithms for computing nodal clustering coefficients."""
+
+import numpy as np
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = [
+    "hypergraph_clustering_coefficient",
+    "hypergraph_local_clustering_coefficient",
+    "hypergraph_two_node_clustering_coefficient",
+]
+
+
+
+[docs] +def hypergraph_clustering_coefficient(H): + r"""Return the clustering coefficients for + each node in a Hypergraph. + + This clustering coefficient is defined as the + clustering coefficient of the unweighted pairwise + projection of the hypergraph, i.e., + :math:`c = A^3_{i,i}/\binom{k}{2},` + where :math:`A` is the adjacency matrix of the network + and :math:`k` is the pairwise degree of :math:`i`. + + Parameters + ---------- + H : Hypergraph + Hypergraph + + Returns + ------- + dict + nodes are keys, clustering coefficients are values. + + Notes + ----- + The clustering coefficient is undefined when the number of + neighbors is 0 or 1, but we set the clustering coefficient + to 0 in these cases. For more discussion, see + https://arxiv.org/abs/0802.2512 + + See Also + -------- + local_clustering_coefficient + two_node_clustering_coefficient + + References + ---------- + "Clustering Coefficients in Protein Interaction Hypernetworks" + by Suzanne Gallagher and Debra Goldberg. + DOI: 10.1145/2506583.2506635 + + Example + ------- + >>> import easygraph as eg + >>> H = eg.random_hypergraph(3, [1, 1]) + >>> cc = eg.clustering_coefficient(H) + >>> cc + {0: 1.0, 1: 1.0, 2: 1.0} + """ + adj = H.adjacency_matrix() + k = np.array(adj.sum(axis=1)) + l = [] + for i in k: + l.append(i[0]) + k = np.array(l) + denom = k * (k - 1) / 2 + mat = adj.dot(adj).dot(adj) + with np.errstate(divide="ignore", invalid="ignore"): + result = np.nan_to_num(0.5 * mat.diagonal() / denom) + r = {} + for i in range(0, len(H.v)): + r[i] = result[i] + return r
+ + + +
+[docs] +def hypergraph_local_clustering_coefficient(H): + """Compute the local clustering coefficient. + + This clustering coefficient is based on the + overlap of the edges connected to a given node, + normalized by the size of the node's neighborhood. + + Parameters + ---------- + H : Hypergraph + Hypergraph + + Returns + ------- + dict + keys are node IDs and values are the + clustering coefficients. + + Notes + ----- + The clustering coefficient is undefined when the number of + neighbors is 0 or 1, but we set the clustering coefficient + to 0 in these cases. For more discussion, see + https://arxiv.org/abs/0802.2512 + + See Also + -------- + clustering_coefficient + two_node_clustering_coefficient + + References + ---------- + "Properties of metabolic graphs: biological organization or representation + artifacts?" by Wanding Zhou and Luay Nakhleh. + https://doi.org/10.1186/1471-2105-12-132 + + "Hypergraphs for predicting essential genes using multiprotein complex data" + by Florian Klimm, Charlotte M. Deane, and Gesine Reinert. + https://doi.org/10.1093/comnet/cnaa028 + + Example + ------- + >>> import easygraph as eg + >>> H = eg.random_hypergraph(3, [1, 1]) + >>> cc = eg.local_clustering_coefficient(H) + >>> cc + {0: 1.0, 1: 1.0, 2: 1.0} + + """ + result = {} + # 节点属于哪些边 + memberships = [] + for n in H.v: + tmp = set() + for index, e in enumerate(H.e[0]): + if n in e: + tmp.add(index) + memberships.append(tmp) + + # 每条边包含哪些节点 + members = H.e[0] + for n in H.v: + ev = memberships[n] + dv = len(ev) + if dv <= 1: + result[n] = 0 + else: + total_eo = 0 + # go over all pairs of edges pairwise + for e1 in range(dv): + edge1 = members[e1] + for e2 in range(e1): + edge2 = members[e2] + # set differences for the hyperedges + D1 = set(edge1) - set(edge2) + D2 = set(edge2) - set(edge1) + # if edges are the same by definition the extra overlap is zero + if len(D1.union(D2)) == 0: + eo = 0 + else: + # otherwise we have to look at their neighbours + # the neighbours of D1 and D2, respectively. + neighD1 = {i for d in D1 for i in H.neighbor_of_node(d)} + neighD2 = {i for d in D2 for i in H.neighbor_of_node(d)} + # compute extra overlap [len() is used for cardinality of edges] + eo = ( + len(neighD1.intersection(D2)) + + len(neighD2.intersection(D1)) + ) / len( + D1.union(D2) + ) # add it up + # add it up + total_eo = total_eo + eo + + # include normalisation by degree k*(k-1)/2 + result[n] = 2 * total_eo / (dv * (dv - 1)) + return result
+ + + +
+[docs] +def hypergraph_two_node_clustering_coefficient(H, kind="union"): + """Return the clustering coefficients for + each node in a Hypergraph. + + This definition averages over all of the + two-node clustering coefficients involving the node. + + Parameters + ---------- + H : Hypergraph + Hypergraph + kind : string, optional + The type of two node clustering coefficient. Options + are "union", "max", and "min". By default, "union". + + Returns + ------- + dict + nodes are keys, clustering coefficients are values. + + Notes + ----- + The clustering coefficient is undefined when the number of + neighbors is 0 or 1, but we set the clustering coefficient + to 0 in these cases. For more discussion, see + https://arxiv.org/abs/0802.2512 + + See Also + -------- + clustering_coefficient + local_clustering_coefficient + + References + ---------- + "Clustering Coefficients in Protein Interaction Hypernetworks" + by Suzanne Gallagher and Debra Goldberg. + DOI: 10.1145/2506583.2506635 + + Example + ------- + >>> import easygraph as eg + >>> H = eg.random_hypergraph(3, [1, 1]) + >>> cc = eg.two_node_clustering_coefficient(H, kind="union") + >>> cc + {0: 0.5, 1: 0.5, 2: 0.5} + """ + result = {} + memberships = {} + for n in H.v: + tmp = set() + for index, e in enumerate(H.e[0]): + if n in e: + tmp.add(index) + memberships[n] = tmp + + for n in H.v: + neighbors = H.neighbor_of_node(n) + result[n] = 0.0 + for v in neighbors: + result[n] += _uv_cc(n, v, memberships, kind=kind) / len(neighbors) + return result
+ + + +def _uv_cc(u, v, memberships, kind="union"): + """Helper function to compute the two-node + clustering coefficient. + + Parameters + ---------- + u : hashable + First node + v : hashable + Second node + memberships : dict + node IDs are keys, edge IDs to which they belong + are values. + kind : str, optional + Type of clustering coefficient to compute, by default "union". + Options: + + - "union" + - "max" + - "min" + + Returns + ------- + float + The clustering coefficient + + Raises + ------ + EasyGraphError + If an invalid clustering coefficient kind + is specified. + + References + ---------- + "Clustering Coefficients in Protein Interaction Hypernetworks" + by Suzanne Gallagher and Debra Goldberg. + DOI: 10.1145/2506583.2506635 + """ + m_u = memberships[u] + m_v = memberships[v] + + num = len(m_u.intersection(m_v)) + + if kind == "union": + denom = len(m_u.union(m_v)) + elif kind == "min": + denom = min(len(m_u), len(m_v)) + elif kind == "max": + denom = max(len(m_u), len(m_v)) + else: + raise EasyGraphError("Invalid kind of clustering.") + + if denom == 0: + return np.nan + + return num / denom +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/hypergraph_classic.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/hypergraph_classic.html new file mode 100644 index 00000000..f8dcb342 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/hypergraph_classic.html @@ -0,0 +1,460 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_generator.hypergraph_classic - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_generator.hypergraph_classic

+import itertools
+
+import easygraph as eg
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = ["empty_hypergraph", "complete_hypergraph"]
+
+
+
+[docs] +def empty_hypergraph(N=1): + """ + + Parameters + ---------- + N number of node in Hypergraph, default 1 + + Returns + ------- + A eg.Hypergraph with n_num node, without any hyperedge. + + """ + return eg.Hypergraph(N)
+ + + +
+[docs] +def complete_hypergraph(n, include_singleton=False): + if n == 0: + raise EasyGraphError("The number of nodes in a Hypergraph can not be zero") + # init + # print("easygraph:",eg) + hypergraph = eg.Hypergraph(n) + total_hyperedegs = [] + if n > 1: + start = 1 if include_singleton else 2 + for size in range(start, n + 1): + hyperedges = itertools.combinations(list(range(n)), size) + total_hyperedegs.extend(list(hyperedges)) + hypergraph.add_hyperedges(total_hyperedegs) + return hypergraph
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/lattice.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/lattice.html new file mode 100644 index 00000000..0e38f7b4 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/lattice.html @@ -0,0 +1,487 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_generator.lattice - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_generator.lattice

+"""Generators for some lattice hypergraphs.
+
+All the functions in this module return a Hypergraph class (i.e. a simple, undirected
+hypergraph).
+
+"""
+
+from warnings import warn
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = [
+    "ring_lattice",
+]
+
+
+
+[docs] +def ring_lattice(n, d, k, l): + """A ring lattice hypergraph. + + A d-uniform hypergraph on n nodes where each node is part of k edges and the + overlap between consecutive edges is d-l. + + Parameters + ---------- + n : int + Number of nodes + d : int + Edge size + k : int + Number of edges of which a node is a part. Should be a multiple of 2. + l : int + Overlap between edges + + Returns + ------- + Hypergraph + The generated hypergraph + + Raises + ------ + EasyGraphError + If k is negative. + + Notes + ----- + ring_lattice(n, 2, k, 0) is a ring lattice graph where each node has k//2 edges on + either side. + + """ + from easygraph.classes.hypergraph import Hypergraph + + if k < 0: + raise EasyGraphError("Invalid k value!") + + if k < 2: + warn("This creates a completely disconnected hypergraph!") + + if k % 2 != 0: + warn("k is not divisible by 2") + + edges = [ + [node] + [(start + l + i) % n for i in range(d - 1)] + for node in range(n) + for start in range(node + 1, node + k // 2 + 1) + ] + H = Hypergraph(num_v=n) + H.add_hyperedges(edges) + return H
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/random.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/random.html new file mode 100644 index 00000000..8acb4761 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/random.html @@ -0,0 +1,797 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_generator.random - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_generator.random

+import math
+import random
+import warnings
+
+from collections import defaultdict
+from itertools import combinations
+
+import easygraph as eg
+import numpy as np
+
+# from easygraph.classes.hypergraph import Hypergraph
+from easygraph.utils.exception import EasyGraphError
+from scipy.special import comb
+
+from .lattice import *
+
+
+__all__ = [
+    "random_hypergraph",
+    "chung_lu_hypergraph",
+    "dcsbm_hypergraph",
+    "watts_strogatz_hypergraph",
+]
+
+
+
+[docs] +def dcsbm_hypergraph(k1, k2, g1, g2, omega, seed=None): + """A function to generate a Degree-Corrected Stochastic Block Model + (DCSBM) hypergraph. + + Parameters + ---------- + k1 : dict + This is a dictionary where the keys are node ids + and the values are node degrees. + k2 : dict + This is a dictionary where the keys are edge ids + and the values are edge sizes. + g1 : dict + This a dictionary where the keys are node ids + and the values are the group ids to which the node belongs. + The keys must match the keys of k1. + g2 : dict + This a dictionary where the keys are edge ids + and the values are the group ids to which the edge belongs. + The keys must match the keys of k2. + omega : 2D numpy array + This is a matrix with entries which specify the number of edges + between a given node community and edge community. + The number of rows must match the number of node communities + and the number of columns must match the number of edge + communities. + seed : int or None (default) + Seed for the random number generator. + + Returns + ------- + Hypergraph + + Warns + ----- + warnings.warn + If the sums of the edge sizes and node degrees are not equal, the + algorithm still runs, but raises a warning. + Also if the sum of the omega matrix does not match the sum of degrees, + a warning is raised. + + Notes + ----- + The sums of k1 and k2 should be the same. If they are not the same, this function + returns a warning but still runs. The sum of k1 (and k2) and omega should be the + same. If they are not the same, this function returns a warning but still runs and + the number of entries in the incidence matrix is determined by the omega matrix. + + References + ---------- + Implemented by Mirah Shi in HyperNetX and described for bipartite networks by + Larremore et al. in https://doi.org/10.1103/PhysRevE.90.012805 + + Examples + -------- + >>> import easygraph as eg; import random; import numpy as np + >>> n = 50 + >>> k1 = {i : random.randint(1, n) for i in range(n)} + >>> k2 = {i : sorted(k1.values())[i] for i in range(n)} + >>> g1 = {i : random.choice([0, 1]) for i in range(n)} + >>> g2 = {i : random.choice([0, 1]) for i in range(n)} + >>> omega = np.array([[n//2, 10], [10, n//2]]) + >>> H = eg.dcsbm_hypergraph(k1, k2, g1, g2, omega) + + """ + if seed is not None: + random.seed(seed) + + # sort dictionary by degree in decreasing order + node_labels = [n for n, _ in sorted(k1.items(), key=lambda d: d[1], reverse=True)] + edge_labels = [m for m, _ in sorted(k2.items(), key=lambda d: d[1], reverse=True)] + + # Verify that the sum of node and edge degrees and the sum of node degrees and the + # sum of community connection matrix differ by less than a single edge. + if abs(sum(k1.values()) - sum(k2.values())) > 1: + warnings.warn( + "The sum of the degree sequence does not match the sum of the size sequence" + ) + + if abs(sum(k1.values()) - np.sum(omega)) > 1: + warnings.warn( + "The sum of the degree sequence does not " + "match the entries in the omega matrix" + ) + + # get indices for each community + community1_nodes = defaultdict(list) + for label in node_labels: + group = g1[label] + community1_nodes[group].append(label) + + community2_nodes = defaultdict(list) + for label in edge_labels: + group = g2[label] + community2_nodes[group].append(label) + + H = eg.Hypergraph(num_v=len(node_labels)) + + kappa1 = defaultdict(lambda: 0) + kappa2 = defaultdict(lambda: 0) + for id, g in g1.items(): + kappa1[g] += k1[id] + for id, g in g2.items(): + kappa2[g] += k2[id] + + tmp_hyperedges = [] + for group1 in community1_nodes.keys(): + for group2 in community2_nodes.keys(): + # for each constant probability patch + try: + group_constant = omega[group1, group2] / ( + kappa1[group1] * kappa2[group2] + ) + except ZeroDivisionError: + group_constant = 0 + + for u in community1_nodes[group1]: + j = 0 + v = community2_nodes[group2][j] # start from beginning every time + # max probability + p = min(k1[u] * k2[v] * group_constant, 1) + while j < len(community2_nodes[group2]): + if p != 1: + r = random.random() + try: + j = j + math.floor(math.log(r) / math.log(1 - p)) + except ZeroDivisionError: + j = np.inf + if j < len(community2_nodes[group2]): + v = community2_nodes[group2][j] + q = min((k1[u] * k2[v]) * group_constant, 1) + r = random.random() + if r < q / p: + # no duplicates + if v < len(tmp_hyperedges): + tmp_hyperedges[v].append(u) + else: + tmp_hyperedges.append([u]) + + p = q + j = j + 1 + + H.add_hyperedges(tmp_hyperedges) + return H
+ + + +
+[docs] +def watts_strogatz_hypergraph(n, d, k, l, p, seed=None): + """ + + Parameters + ---------- + n : int + The number of nodes + d : int + Edge size + k: int + Number of edges of which a node is a part. Should be a multiple of 2. + l: int + Overlap between edges + p : float + The probability of rewiring each edge + seed + + Returns + ------- + + """ + if seed is not None: + np.random.seed(seed) + H = ring_lattice(n, d, k, l) + to_remove = [] + to_add = [] + H_edges = H.e[0] + for e in H_edges: + if np.random.random() < p: + to_remove.append(e) + node = min(e) + neighbors = np.random.choice(H.v, size=d - 1) + to_add.append(np.append(neighbors, node)) + H.remove_hyperedges(to_remove) + H.add_hyperedges(to_add) + return H
+ + + +
+[docs] +def chung_lu_hypergraph(k1, k2, seed=None): + """A function to generate a Chung-Lu hypergraph + + Parameters + ---------- + k1 : dict + Dict where the keys are node ids + and the values are node degrees. + k2 : dict + dict where the keys are edge ids + and the values are edge sizes. + seed : integer or None (default) + The seed for the random number generator. + + Returns + ------- + Hypergraph object + The generated hypergraph + + Warns + ----- + warnings.warn + If the sums of the edge sizes and node degrees are not equal, the + algorithm still runs, but raises a warning. + + Notes + ----- + The sums of k1 and k2 should be the same. If they are not the same, + this function returns a warning but still runs. + + References + ---------- + Implemented by Mirah Shi in HyperNetX and described for + bipartite networks by Aksoy et al. in https://doi.org/10.1093/comnet/cnx001 + + Example + ------- + >>> import easygraph as eg + >>> import random + >>> n = 100 + >>> k1 = {i : random.randint(1, 100) for i in range(n)} + >>> k2 = {i : sorted(k1.values())[i] for i in range(n)} + >>> H = eg.chung_lu_hypergraph(k1, k2) + + """ + if seed is not None: + random.seed(seed) + + # sort dictionary by degree in decreasing order + node_labels = [n for n, _ in sorted(k1.items(), key=lambda d: d[1], reverse=True)] + edge_labels = [m for m, _ in sorted(k2.items(), key=lambda d: d[1], reverse=True)] + + m = len(k2) + + if sum(k1.values()) != sum(k2.values()): + warnings.warn( + "The sum of the degree sequence does not match the sum of the size sequence" + ) + + S = sum(k1.values()) + + H = eg.Hypergraph(len(node_labels)) + + tmp_hyperedges = [] + for u in node_labels: + j = 0 + v = edge_labels[j] # start from beginning every time + p = min((k1[u] * k2[v]) / S, 1) + + while j < m: + if p != 1: + r = random.random() + try: + j = j + math.floor(math.log(r) / math.log(1 - p)) + except ZeroDivisionError: + j = np.inf + + if j < m: + v = edge_labels[j] + q = min((k1[u] * k2[v]) / S, 1) + r = random.random() + if r < q / p: + # no duplicates + if v < len(tmp_hyperedges): + tmp_hyperedges[v].append(u) + else: + tmp_hyperedges.append([u]) + p = q + j = j + 1 + + H.add_hyperedges(tmp_hyperedges) + return H
+ + + +
+[docs] +def random_hypergraph(N, ps, order=None, seed=None): + """Generates a random hypergraph + + Generate N nodes, and connect any d+1 nodes + by a hyperedge with probability ps[d-1]. + + Parameters + ---------- + N : int + Number of nodes + ps : list of float + List of probabilities (between 0 and 1) to create a + hyperedge at each order d between any d+1 nodes. For example, + ps[0] is the wiring probability of any edge (2 nodes), ps[1] + of any triangles (3 nodes). + order: int of None (default) + If None, ignore. If int, generates a uniform hypergraph with edges + of order `order` (ps must have only one element). + seed : integer or None (default) + Seed for the random number generator. + + Returns + ------- + Hypergraph object + The generated hypergraph + + References + ---------- + Described as 'random hypergraph' by M. Dewar et al. in https://arxiv.org/abs/1703.07686 + + Example + ------- + >>> import easygraph as eg + >>> H = eg.random_hypergraph(50, [0.1, 0.01]) + + """ + if seed is not None: + np.random.seed(seed) + + if order is not None: + if len(ps) != 1: + raise EasyGraphError("ps must contain a single element if order is an int") + + if (np.any(np.array(ps) < 0)) or (np.any(np.array(ps) > 1)): + raise EasyGraphError("All elements of ps must be between 0 and 1 included.") + + nodes = range(N) + hyperedges = [] + + for i, p in enumerate(ps): + if order is not None: + d = order + else: + d = i + 1 # order, ps[0] is prob of edges (d=1) + + potential_edges = combinations(nodes, d + 1) + n_comb = comb(N, d + 1, exact=True) + mask = np.random.random(size=n_comb) <= p # True if edge to keep + + edges_to_add = [e for e, val in zip(potential_edges, mask) if val] + + hyperedges += edges_to_add + + H = eg.Hypergraph(num_v=N) + H.add_hyperedges(hyperedges) + + return H
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/simple.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/simple.html new file mode 100644 index 00000000..84d3333b --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/simple.html @@ -0,0 +1,495 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_generator.simple - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_generator.simple

+from itertools import combinations
+
+import easygraph as eg
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = [
+    "star_clique",
+]
+
+
+
+[docs] +def star_clique(n_star, n_clique, d_max): + """Generate a star-clique structure + + That is a star network and a clique network, + connected by one pairwise edge connecting the centre of the star to the clique. + network, the each clique is promoted to a hyperedge + up to order d_max. + + Parameters + ---------- + n_star : int + Number of legs of the star + n_clique : int + Number of nodes in the clique + d_max : int + Maximum order up to which to promote + cliques to hyperedges + + Returns + ------- + H : Hypergraph + + Examples + -------- + >>> import easygraph as eg + >>> H = eg.star_clique(6, 7, 2) + + Notes + ----- + The total number of nodes is n_star + n_clique. + + """ + + if n_star <= 0: + raise ValueError("n_star must be an integer > 0.") + if n_clique <= 0: + raise ValueError("n_clique must be an integer > 0.") + if d_max < 0: + raise ValueError("d_max must be an integer >= 0.") + elif d_max > n_clique - 1: + raise ValueError("d_max must be <= n_clique - 1.") + + nodes_star = range(n_star) + nodes_clique = range(n_star, n_star + n_clique) + nodes = list(nodes_star) + list(nodes_clique) + + H = eg.Hypergraph(num_v=len(nodes)) + + # add star edges (center of the star is 0-th node) + H.add_hyperedges([[nodes_star[0], nodes_star[i]] for i in range(1, n_star)]) + + # connect clique and star by adding last star leg + H.add_hyperedges([nodes_star[0], nodes_clique[0]]) + + # add clique hyperedges up to order d_max + + H.add_hyperedges( + [ + e + for d in range(1, d_max + 1) + for e in list(combinations(nodes_clique, d + 1)) + ] + ) + + return H
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/uniform.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/uniform.html new file mode 100644 index 00000000..1c245186 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/hypergraph/hypergraph_generator/uniform.html @@ -0,0 +1,802 @@ + + + + + + + + easygraph.functions.hypergraph.hypergraph_generator.uniform - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.hypergraph.hypergraph_generator.uniform

+"""Generate random uniform hypergraphs."""
+import itertools
+import operator
+import random
+import warnings
+
+from functools import reduce
+
+import easygraph as eg
+import numpy as np
+
+from easygraph.utils.exception import EasyGraphError
+
+
+__all__ = [
+    "uniform_hypergraph_configuration_model",
+    "uniform_HSBM",
+    "uniform_HPPM",
+    "uniform_erdos_renyi_hypergraph",
+]
+
+
+
+[docs] +def uniform_hypergraph_configuration_model(k, m, seed=None): + """ + A function to generate an m-uniform configuration model + + Parameters + ---------- + k : dictionary + This is a dictionary where the keys are node ids + and the values are node degrees. + m : int + specifies the hyperedge size + seed : integer or None (default) + The seed for the random number generator + + Returns + ------- + Hypergraph object + The generated hypergraph + + Warns + ----- + warnings.warn + If the sums of the degrees are not divisible by m, the + algorithm still runs, but raises a warning and adds an + additional connection to random nodes to satisfy this + condition. + + Notes + ----- + This algorithm normally creates multi-edges and loopy hyperedges. + We remove the loopy hyperedges. + + References + ---------- + "The effect of heterogeneity on hypergraph contagion models" + by Nicholas W. Landry and Juan G. Restrepo + https://doi.org/10.1063/5.0020034 + + + Example + ------- + >>> import easygraph as eg + >>> import random + >>> n = 1000 + >>> m = 3 + >>> k = {1: 1, 2: 2, 3: 3, 4: 3} + >>> H = eg.uniform_hypergraph_configuration_model(k, m) + + """ + if seed is not None: + random.seed(seed) + + # Making sure we have the right number of stubs + remainder = sum(k.values()) % m + if remainder != 0: + warnings.warn( + "This degree sequence is not realizable. " + "Increasing the degree of random nodes so that it is." + ) + random_ids = random.sample(list(k.keys()), int(round(m - remainder))) + for id in random_ids: + k[id] = k[id] + 1 + + stubs = [] + # Creating the list to index through + for id in k: + stubs.extend([id] * int(k[id])) + + H = eg.Hypergraph(num_v=len(k)) + + while len(stubs) != 0: + u = random.sample(range(len(stubs)), m) + edge = set() + for index in u: + edge.add(stubs[index]) + if len(edge) == m: + H.add_hyperedges(list(edge)) + + for index in sorted(u, reverse=True): + del stubs[index] + + return H
+ + + +
+[docs] +def uniform_HSBM(n, m, p, sizes, seed=None): + """Create a uniform hypergraph stochastic block model (HSBM). + + Parameters + ---------- + n : int + The number of nodes + m : int + The hyperedge size + p : m-dimensional numpy array + tensor of probabilities between communities + sizes : list or 1D numpy array + The sizes of the community blocks in order + seed : integer or None (default) + The seed for the random number generator + + Returns + ------- + Hypergraph + The constructed SBM hypergraph + + Raises + ------ + EasyGraphError + - If the length of sizes and p do not match. + - If p is not a tensor with every dimension equal + - If p is not m-dimensional + - If the entries of p are not in the range [0, 1] + - If the sum of the vector of sizes does not equal the number of nodes. + Exception + If there is an integer overflow error + + See Also + -------- + uniform_HPPM + + References + ---------- + Nicholas W. Landry and Juan G. Restrepo. + "Polarization in hypergraphs with community structure." + Preprint, 2023. https://doi.org/10.48550/arXiv.2302.13967 + """ + # Check if dimensions match + if len(sizes) != np.size(p, axis=0): + raise EasyGraphError("'sizes' and 'p' do not match.") + if len(np.shape(p)) != m: + raise EasyGraphError("The dimension of p does not match m") + # Check that p has the same length over every dimension. + if len(set(np.shape(p))) != 1: + raise EasyGraphError("'p' must be a square tensor.") + if np.max(p) > 1 or np.min(p) < 0: + raise EasyGraphError("Entries of 'p' not in [0,1].") + if np.sum(sizes) != n: + raise EasyGraphError("Sum of sizes does not match n") + + if seed is not None: + np.random.seed(seed) + + node_labels = range(n) + H = eg.Hypergraph(num_v=n) + + block_range = range(len(sizes)) + # Split node labels in a partition (list of sets). + size_cumsum = [sum(sizes[0:x]) for x in range(0, len(sizes) + 1)] + partition = [ + list(node_labels[size_cumsum[x] : size_cumsum[x + 1]]) + for x in range(0, len(size_cumsum) - 1) + ] + + for block in itertools.product(block_range, repeat=m): + if p[block] == 1: # Test edges cases p_ij = 0 or 1 + edges = itertools.product((partition[i] for i in block_range)) + for e in edges: + H.add_hyperedges(list(e)) + elif p[block] > 0: + partition_sizes = [len(partition[i]) for i in block] + max_index = reduce(operator.mul, partition_sizes, 1) + if max_index < 0: + raise Exception("Index overflow error!") + index = np.random.geometric(p[block]) - 1 + + while index < max_index: + indices = _index_to_edge_partition(index, partition_sizes, m) + e = {partition[block[i]][indices[i]] for i in range(m)} + if len(e) == m: + H.add_hyperedges(list(e)) + index += np.random.geometric(p[block]) + return H
+ + + +
+[docs] +def uniform_HPPM(n, m, rho, k, epsilon, seed=None): + """Construct the m-uniform hypergraph planted partition model (m-HPPM) + + Parameters + ---------- + n : int > 0 + Number of nodes + m : int > 0 + Hyperedge size + rho : float between 0 and 1 + The fraction of nodes in community 1 + k : float > 0 + Mean degree + epsilon : float > 0 + Imbalance parameter + seed : integer or None (default) + The seed for the random number generator + + Returns + ------- + Hypergraph + The constructed m-HPPM hypergraph. + + Raises + ------ + EasyGraphError + - If rho is not between 0 and 1 + - If the mean degree is negative. + - If epsilon is not between 0 and 1 + + See Also + -------- + uniform_HSBM + + References + ---------- + Nicholas W. Landry and Juan G. Restrepo. + "Polarization in hypergraphs with community structure." + Preprint, 2023. https://doi.org/10.48550/arXiv.2302.13967 + """ + + if rho < 0 or rho > 1: + raise EasyGraphError("The value of rho must be between 0 and 1") + if k < 0: + raise EasyGraphError("The mean degree must be non-negative") + if epsilon < 0 or epsilon > 1: + raise EasyGraphError("epsilon must be between 0 and 1") + + sizes = [int(rho * n), n - int(rho * n)] + + p = k / (m * n ** (m - 1)) + # ratio of inter- to intra-community edges + q = rho**m + (1 - rho) ** m + r = 1 / q - 1 + p_in = (1 + r * epsilon) * p + p_out = (1 - epsilon) * p + + p = p_out * np.ones([2] * m) + p[tuple([0] * m)] = p_in + p[tuple([1] * m)] = p_in + + return uniform_HSBM(n, m, p, sizes, seed=seed)
+ + + +
+[docs] +def uniform_erdos_renyi_hypergraph(n, m, p, p_type="degree", seed=None): + """Generate an m-uniform Erdős–Rényi hypergraph + + This creates a hypergraph with `n` nodes where + hyperedges of size `m` are created at random to + obtain a mean degree of `k`. + + Parameters + ---------- + n : int > 0 + Number of nodes + m : int > 0 + Hyperedge size + p : float or int > 0 + Mean expected degree if p_type="degree" and + probability of an m-hyperedge if p_type="prob" + p_type : str + "degree" or "prob", by default "degree" + seed : integer or None (default) + The seed for the random number generator + + Returns + ------- + Hypergraph + The Erdos Renyi hypergraph + + + See Also + -------- + random_hypergraph + """ + if seed is not None: + np.random.seed(seed) + + node_labels = range(n) + H = eg.Hypergraph(num_v=n) + + if p_type == "degree": + q = p / (m * n ** (m - 1)) # wiring probability + elif p_type == "prob": + q = p + else: + raise EasyGraphError("Invalid p_type!") + + if q > 1 or q < 0: + raise EasyGraphError("Probability not in [0,1].") + + index = np.random.geometric(q) - 1 # -1 b/c zero indexing + max_index = n**m + while index < max_index: + e = set(_index_to_edge(index, n, m)) + if len(e) == m: + H.add_hyperedges(list(e)) + index += np.random.geometric(q) + return H
+ + + +def _index_to_edge(index, n, m): + """Generate a hyperedge given an index in the list of possible edges. + + Parameters + ---------- + index : int > 0 + The index of the hyperedge in the list of all possible hyperedges. + n : int > 0 + The number of nodes + m : int > 0 + The hyperedge size. + + Returns + ------- + list + The reconstructed hyperedge + + See Also + -------- + _index_to_edge_partition + + References + ---------- + https://stackoverflow.com/questions/53834707/element-at-index-in-itertools-product + """ + return [(index // (n**r) % n) for r in range(m - 1, -1, -1)] + + +def _index_to_edge_partition(index, partition_sizes, m): + """Generate a hyperedge given an index in the list of possible edges + and a partition of community labels. + + Parameters + ---------- + index : int > 0 + The index of the hyperedge in the list of all possible hyperedges. + n : int > 0 + The number of nodes + m : int > 0 + The hyperedge size. + + Returns + ------- + list + The reconstructed hyperedge + + See Also + -------- + _index_to_edge + + """ + try: + return [ + int(index // np.prod(partition_sizes[r + 1 :]) % partition_sizes[r]) + for r in range(m) + ] + except KeyError: + raise Exception("Invalid parameters") +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/functions/path/diameter.html b/docs_using_sphinx/_build/html/_modules/easygraph/functions/path/diameter.html new file mode 100644 index 00000000..50329874 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/functions/path/diameter.html @@ -0,0 +1,526 @@ + + + + + + + + easygraph.functions.path.diameter - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.functions.path.diameter

+import easygraph as eg
+import easygraph.functions.path
+
+
+
+[docs] +def eccentricity(G, v=None, sp=None): + """Returns the eccentricity of nodes in G. + + The eccentricity of a node v is the maximum distance from v to + all other nodes in G. + + Parameters + ---------- + G : EasyGraph graph + A graph + + v : node, optional + Return value of specified node + + sp : dict of dicts, optional + All pairs shortest path lengths as a dictionary of dictionaries + + Returns + ------- + ecc : dictionary + A dictionary of eccentricity values keyed by node. + + Examples + -------- + >>> G = eg.Graph([(1, 2), (1, 3), (1, 4), (3, 4), (3, 5), (4, 5)]) + >>> dict(eg.eccentricity(G)) + {1: 2, 2: 3, 3: 2, 4: 2, 5: 3} + + >>> dict(eg.eccentricity(G, v=[1, 5])) # This returns the eccentrity of node 1 & 5 + {1: 2, 5: 3} + + """ + # if v is None: # none, use entire graph + # nodes=G.nodes() + # elif v in G: # is v a single node + # nodes=[v] + # else: # assume v is a container of nodes + # nodes=v + order = G.order() + + e = {} + for n in G.nbunch_iter(v): + if sp is None: + length = eg.single_source_dijkstra(G, n) + L = len(length) + else: + try: + length = sp[n] + L = len(length) + except TypeError as err: + raise eg.EasyGraphError('Format of "sp" is invalid.') from err + if L != order: + if G.is_directed(): + msg = ( + "Found infinite path length because the digraph is not" + " strongly connected" + ) + else: + msg = "Found infinite path length because the graph is not connected" + raise eg.EasyGraphError(msg) + + e[n] = max(length.values()) + + if v in G: + return e[v] # return single value + else: + return e
+ + + +
+[docs] +def diameter(G, e=None): + """Returns the diameter of the graph G. + + The diameter is the maximum eccentricity. + + Parameters + ---------- + G : EasyGraph graph + A graph + + e : eccentricity dictionary, optional + A precomputed dictionary of eccentricities. + + Returns + ------- + d : integer + Diameter of graph + + Examples + -------- + >>> G = eg.Graph([(1, 2), (1, 3), (1, 4), (3, 4), (3, 5), (4, 5)]) + >>> eg.diameter(G) + 3 + + See Also + -------- + eccentricity + """ + + if e is None: + e = eccentricity(G) + return max(e.values())
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/ml_metrics.html b/docs_using_sphinx/_build/html/_modules/easygraph/ml_metrics.html new file mode 100644 index 00000000..e552247f --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/ml_metrics.html @@ -0,0 +1,463 @@ + + + + + + + + easygraph.ml_metrics - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.ml_metrics

+try:
+    from typing import Dict
+    from typing import List
+    from typing import Union
+
+    from easygraph._global import AUTHOR_EMAIL
+
+    from .base import BaseEvaluator
+    from .classification import VertexClassificationEvaluator
+    from .classification import available_classification_metrics
+    from .hypergraphs import HypergraphVertexClassificationEvaluator
+except:
+    print(
+        "Warning raise in module:ml_metrics. Please install Pytorch before you use"
+        " functions related to nueral network"
+    )
+
+
+
+[docs] +def build_evaluator( + task: str, + metric_configs: List[Union[str, Dict[str, dict]]], + validate_index: int = 0, +): + r"""Return the metric evaluator for the given task. + + Args: + ``task`` (``str``): The type of the task. The supported types include: ``graph_vertex_classification``, ``hypergraph_vertex_classification``, and ``user_item_recommender``. + ``metric_configs`` (``List[Union[str, Dict[str, dict]]]``): The list of metric names. + ``validate_index`` (``int``): The specified metric index used for validation. Defaults to ``0``. + """ + if task == "hypergraph_vertex_classification": + return HypergraphVertexClassificationEvaluator(metric_configs, validate_index) + else: + raise ValueError( + f"{task} is not supported yet. Please email '{AUTHOR_EMAIL}' to add it." + )
+ + + +# __all__ = [ +# "BaseEvaluator", +# "build_evaluator", +# "available_classification_metrics", +# "VertexClassificationEvaluator", +# "HypergraphVertexClassificationEvaluator", +# ] +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/utils/download.html b/docs_using_sphinx/_build/html/_modules/easygraph/utils/download.html new file mode 100644 index 00000000..ba4e13a1 --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/utils/download.html @@ -0,0 +1,519 @@ + + + + + + + + easygraph.utils.download - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.utils.download

+import hashlib
+import warnings
+
+from functools import wraps
+from pathlib import Path
+
+import requests
+
+
+__all__ = [
+    "check_file",
+    "download_file",
+    "download_and_check",
+]
+
+
+
+[docs] +def download_file(url: str, file_path: Path): + r"""Download a file from a url. + + Args: + ``url`` (``str``): the url of the file + ``file_path`` (``str``): the path to the file + """ + file_path.parent.mkdir(parents=True, exist_ok=True) + r = requests.get(url, stream=True, verify=True) + if r.status_code != 200: + raise requests.HTTPError(f"{url} is not accessible.") + with open(file_path, "wb") as f: + for chunk in r.iter_content(chunk_size=1024): + if chunk: + f.write(chunk)
+ + + +
+[docs] +def check_file(file_path: Path, md5: str): + r"""Check if a file is valid. + + Args: + ``file_path`` (``Path``): The local path of the file. + ``md5`` (``str``): The md5 of the file. + + Raises: + FileNotFoundError: Not found the file. + """ + if not file_path.exists(): + raise FileNotFoundError(f"{file_path} does not exist.") + else: + with open(file_path, "rb") as f: + data = f.read() + cur_md5 = hashlib.md5(data).hexdigest() + return cur_md5 == md5
+ + + +def _retry(n: int, exception_type=requests.HTTPError): + r"""A decorator for retrying a function for n times. + + Args: + ``n`` (``int``): The number of times to retry. + """ + + def decorator(fetcher): + @wraps(fetcher) + def wrapper(*args, **kwargs): + for i in range(n - 1): + try: + return fetcher(*args, **kwargs) + except exception_type as e: + warnings.warn(f"Retry downloading({i + 1}/{n}): {str(e)}") + except Exception as e: + raise e + return fetcher(*args, **kwargs) + # raise FileNotFoundError + + return wrapper + + return decorator + + +
+[docs] +@_retry(3) +def download_and_check(url: str, file_path: Path, md5: str): + r"""Download a file from a url and check its integrity. + + Args: + ``url`` (``str``): The url of the file. + ``file_path`` (``Path``): The path to the file. + ``md5`` (``str``): The md5 of the file. + """ + if not file_path.exists(): + download_file(url, file_path) + if not check_file(file_path, md5): + file_path.unlink() + raise ValueError( + f"{file_path} is corrupted. We will delete it, and try to download it" + " again." + ) + return True
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/easygraph/utils/logging.html b/docs_using_sphinx/_build/html/_modules/easygraph/utils/logging.html new file mode 100644 index 00000000..2e78537c --- /dev/null +++ b/docs_using_sphinx/_build/html/_modules/easygraph/utils/logging.html @@ -0,0 +1,465 @@ + + + + + + + + easygraph.utils.logging - EasyGraph 1.0 + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+
+ +
+ +
+
+

Source code for easygraph.utils.logging

+import logging
+import sys
+
+from pathlib import Path
+from typing import Union
+
+
+__all__ = ["default_log_formatter", "simple_stdout2file"]
+
+
+
+[docs] +def default_log_formatter() -> logging.Formatter: + r"""Create a default formatter of log messages for logging.""" + + return logging.Formatter("[%(levelname)s %(asctime)s]-> %(message)s")
+ + + +
+[docs] +def simple_stdout2file(file_path: Union[str, Path]) -> None: + r"""This function simply wraps the ``sys.stdout`` stream, and outputs messages to the ``sys.stdout`` and a specified file, simultaneously. + + Parameters: + ``file_path`` (``file_path: Union[str, Path]``): The path of the file to output the messages. + """ + + class SimpleLogger: + def __init__(self, file_path: Path): + file_path = Path(file_path).absolute() + assert ( + file_path.parent.exists() + ), f"The parent directory of {file_path} does not exist." + self.file_path = file_path + self.terminal = sys.stdout + self.file = open(file_path, "a") + + def write(self, message): + self.terminal.write(message) + self.file.write(message) + self.flush() + + def flush(self): + self.terminal.flush() + self.file.flush() + + file_path = Path(file_path) + sys.stdout = SimpleLogger(file_path)
+ +
+
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_modules/index.html b/docs_using_sphinx/_build/html/_modules/index.html index cbad9425..437696c3 100644 --- a/docs_using_sphinx/_build/html/_modules/index.html +++ b/docs_using_sphinx/_build/html/_modules/index.html @@ -1,15 +1,15 @@ - + - + Overview: module code - EasyGraph 1.0 - - - - + + + + @@ -143,7 +143,7 @@ - - - - - - - + + + + + \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.dynamic.rst.txt b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.dynamic.rst.txt new file mode 100644 index 00000000..e4f172c3 --- /dev/null +++ b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.dynamic.rst.txt @@ -0,0 +1,45 @@ +easygraph.datasets.dynamic package +================================== + +Submodules +---------- + +easygraph.datasets.dynamic.email\_enron module +---------------------------------------------- + +.. automodule:: easygraph.datasets.dynamic.email_enron + :members: + :undoc-members: + :show-inheritance: + +easygraph.datasets.dynamic.email\_eu module +------------------------------------------- + +.. automodule:: easygraph.datasets.dynamic.email_eu + :members: + :undoc-members: + :show-inheritance: + +easygraph.datasets.dynamic.hospital\_lyon module +------------------------------------------------ + +.. automodule:: easygraph.datasets.dynamic.hospital_lyon + :members: + :undoc-members: + :show-inheritance: + +easygraph.datasets.dynamic.load\_dataset module +----------------------------------------------- + +.. automodule:: easygraph.datasets.dynamic.load_dataset + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: easygraph.datasets.dynamic + :members: + :undoc-members: + :show-inheritance: diff --git a/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.hypergraph.rst.txt b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.hypergraph.rst.txt index f167acca..68b35407 100644 --- a/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.hypergraph.rst.txt +++ b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.hypergraph.rst.txt @@ -12,10 +12,10 @@ easygraph.datasets.hypergraph.House\_Committees module :undoc-members: :show-inheritance: -easygraph.datasets.hypergraph.base module +easygraph.datasets.hypergraph.Yelp module ----------------------------------------- -.. automodule:: easygraph.datasets.hypergraph.base +.. automodule:: easygraph.datasets.hypergraph.Yelp :members: :undoc-members: :show-inheritance: @@ -28,6 +28,14 @@ easygraph.datasets.hypergraph.cat\_edge\_Cooking module :undoc-members: :show-inheritance: +easygraph.datasets.hypergraph.coauthorship module +------------------------------------------------- + +.. automodule:: easygraph.datasets.hypergraph.coauthorship + :members: + :undoc-members: + :show-inheritance: + easygraph.datasets.hypergraph.cocitation module ----------------------------------------------- @@ -44,10 +52,18 @@ easygraph.datasets.hypergraph.contact\_primary\_school module :undoc-members: :show-inheritance: -easygraph.datasets.hypergraph.load\_dataset module --------------------------------------------------- +easygraph.datasets.hypergraph.cooking\_200 module +------------------------------------------------- + +.. automodule:: easygraph.datasets.hypergraph.cooking_200 + :members: + :undoc-members: + :show-inheritance: + +easygraph.datasets.hypergraph.hypergraph\_dataset\_base module +-------------------------------------------------------------- -.. automodule:: easygraph.datasets.hypergraph.load_dataset +.. automodule:: easygraph.datasets.hypergraph.hypergraph_dataset_base :members: :undoc-members: :show-inheritance: diff --git a/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.rst.txt b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.rst.txt index 715af066..2d6682e0 100644 --- a/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.rst.txt +++ b/docs_using_sphinx/_build/html/_sources/reference/easygraph.datasets.rst.txt @@ -7,19 +7,12 @@ Subpackages .. toctree:: :maxdepth: 4 + easygraph.datasets.dynamic easygraph.datasets.hypergraph Submodules ---------- -easygraph.datasets.base module ------------------------------- - -.. automodule:: easygraph.datasets.base - :members: - :undoc-members: - :show-inheritance: - easygraph.datasets.citation\_graph module ----------------------------------------- @@ -28,38 +21,6 @@ easygraph.datasets.citation\_graph module :undoc-members: :show-inheritance: -easygraph.datasets.cooking\_200 module --------------------------------------- - -.. automodule:: easygraph.datasets.cooking_200 - :members: - :undoc-members: - :show-inheritance: - -easygraph.datasets.eg\_dataset module -------------------------------------- - -.. automodule:: easygraph.datasets.eg_dataset - :members: - :undoc-members: - :show-inheritance: - -easygraph.datasets.email\_enron module --------------------------------------- - -.. automodule:: easygraph.datasets.email_enron - :members: - :undoc-members: - :show-inheritance: - -easygraph.datasets.email\_eu module ------------------------------------ - -.. automodule:: easygraph.datasets.email_eu - :members: - :undoc-members: - :show-inheritance: - easygraph.datasets.get\_sample\_graph module -------------------------------------------- @@ -76,10 +37,10 @@ easygraph.datasets.gnn\_benchmark module :undoc-members: :show-inheritance: -easygraph.datasets.hospital\_lyon module ----------------------------------------- +easygraph.datasets.graph\_dataset\_base module +---------------------------------------------- -.. automodule:: easygraph.datasets.hospital_lyon +.. automodule:: easygraph.datasets.graph_dataset_base :members: :undoc-members: :show-inheritance: diff --git a/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.centrality.rst.txt b/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.centrality.rst.txt index 87d19355..82dedfcb 100644 --- a/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.centrality.rst.txt +++ b/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.centrality.rst.txt @@ -20,6 +20,30 @@ easygraph.functions.hypergraph.centrality.degree module :undoc-members: :show-inheritance: +easygraph.functions.hypergraph.centrality.hypercoreness module +-------------------------------------------------------------- + +.. automodule:: easygraph.functions.hypergraph.centrality.hypercoreness + :members: + :undoc-members: + :show-inheritance: + +easygraph.functions.hypergraph.centrality.s\_centrality module +-------------------------------------------------------------- + +.. automodule:: easygraph.functions.hypergraph.centrality.s_centrality + :members: + :undoc-members: + :show-inheritance: + +easygraph.functions.hypergraph.centrality.vector\_centrality module +------------------------------------------------------------------- + +.. automodule:: easygraph.functions.hypergraph.centrality.vector_centrality + :members: + :undoc-members: + :show-inheritance: + Module contents --------------- diff --git a/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.rst.txt b/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.rst.txt index f070dc4c..166c0057 100644 --- a/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.rst.txt +++ b/docs_using_sphinx/_build/html/_sources/reference/easygraph.functions.hypergraph.rst.txt @@ -29,6 +29,14 @@ easygraph.functions.hypergraph.hypergraph\_clustering module :undoc-members: :show-inheritance: +easygraph.functions.hypergraph.hypergraph\_operation module +----------------------------------------------------------- + +.. automodule:: easygraph.functions.hypergraph.hypergraph_operation + :members: + :undoc-members: + :show-inheritance: + Module contents --------------- diff --git a/docs_using_sphinx/_build/html/_sources/tutorial.rst.txt b/docs_using_sphinx/_build/html/_sources/tutorial.rst.txt index 6f153740..368e09c9 100644 --- a/docs_using_sphinx/_build/html/_sources/tutorial.rst.txt +++ b/docs_using_sphinx/_build/html/_sources/tutorial.rst.txt @@ -291,4 +291,14 @@ The PageRank algorithm **Usage** - For class methods, calling and parameter passing are the same as python. -- For module function, easygraph will select specific codes to execute according to the class of the graph. \ No newline at end of file +- For module function, easygraph will select specific codes to execute according to the class of the graph. + +View the tutorials in Colab. +------------------------- +`tutorial1: Two brief tutorials of how to do graph analysis with EasyGraph. `_ + +`tutorial2: Using C++ code to achieve a better performance. `_ + +`tutorial3: Graph Embedding. `_ + +`tutorial4: Community Detection. `_ \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_static/pygments.css b/docs_using_sphinx/_build/html/_static/pygments.css index ed1f4cf6..17e498a6 100644 --- a/docs_using_sphinx/_build/html/_static/pygments.css +++ b/docs_using_sphinx/_build/html/_static/pygments.css @@ -17,7 +17,6 @@ .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #A00000 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #FF0000 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ @@ -99,7 +98,6 @@ body[data-theme="dark"] .highlight .c1 { color: #ababab; font-style: italic } /* body[data-theme="dark"] .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ body[data-theme="dark"] .highlight .gd { color: #d22323 } /* Generic.Deleted */ body[data-theme="dark"] .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ -body[data-theme="dark"] .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ body[data-theme="dark"] .highlight .gr { color: #d22323 } /* Generic.Error */ body[data-theme="dark"] .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ body[data-theme="dark"] .highlight .gi { color: #589819 } /* Generic.Inserted */ @@ -185,7 +183,6 @@ body:not([data-theme="light"]) .highlight .c1 { color: #ababab; font-style: ital body:not([data-theme="light"]) .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ body:not([data-theme="light"]) .highlight .gd { color: #d22323 } /* Generic.Deleted */ body:not([data-theme="light"]) .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ -body:not([data-theme="light"]) .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ body:not([data-theme="light"]) .highlight .gr { color: #d22323 } /* Generic.Error */ body:not([data-theme="light"]) .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ body:not([data-theme="light"]) .highlight .gi { color: #589819 } /* Generic.Inserted */ diff --git a/docs_using_sphinx/_build/html/_static/scripts/furo.js.map b/docs_using_sphinx/_build/html/_static/scripts/furo.js.map index 7b7ddb11..47053022 100644 --- a/docs_using_sphinx/_build/html/_static/scripts/furo.js.map +++ b/docs_using_sphinx/_build/html/_static/scripts/furo.js.map @@ -1 +1 @@ -{"version":3,"file":"scripts/furo.js","mappings":"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","sources":["webpack:///./src/furo/assets/scripts/gumshoe-patched.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/global","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./src/furo/assets/scripts/furo.js"],"sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight,\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1)),\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n },\n);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Gumshoe from \"./gumshoe-patched.js\";\n\n////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\nvar lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;\nconst GO_TO_TOP_OFFSET = 64;\n\nfunction scrollHandlerForHeader() {\n if (Math.floor(header.getBoundingClientRect().top) == 0) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForBackToTop(positionY) {\n if (positionY < GO_TO_TOP_OFFSET) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n } else {\n if (positionY < lastScrollTop) {\n document.documentElement.classList.add(\"show-back-to-top\");\n } else if (positionY > lastScrollTop) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n }\n }\n lastScrollTop = positionY;\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader();\n scrollHandlerForBackToTop(positionY);\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Theme Toggle\n////////////////////////////////////////////////////////////////////////////////\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n document.body.dataset.theme = mode;\n localStorage.setItem(\"theme\", mode);\n console.log(`Changed to ${mode} mode.`);\n}\n\nfunction cycleThemeOnce() {\n const currentTheme = localStorage.getItem(\"theme\") || \"auto\";\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) {\n // Auto (dark) -> Light -> Dark\n if (currentTheme === \"auto\") {\n setTheme(\"light\");\n } else if (currentTheme == \"light\") {\n setTheme(\"dark\");\n } else {\n setTheme(\"auto\");\n }\n } else {\n // Auto (light) -> Dark -> Light\n if (currentTheme === \"auto\") {\n setTheme(\"dark\");\n } else if (currentTheme == \"dark\") {\n setTheme(\"light\");\n } else {\n setTheme(\"auto\");\n }\n }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n let last_known_scroll_position = 0;\n let ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n offset: () => {\n let rem = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return header.getBoundingClientRect().height + 0.5 * rem + 1;\n },\n });\n}\n\nfunction setupTheme() {\n // Attach event handlers for toggling themes\n const buttons = document.getElementsByClassName(\"theme-toggle\");\n Array.from(buttons).forEach((btn) => {\n btn.addEventListener(\"click\", cycleThemeOnce);\n });\n}\n\nfunction setup() {\n setupTheme();\n setupScrollHandler();\n setupScrollSpy();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Main entrypoint\n////////////////////////////////////////////////////////////////////////////////\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"],"names":["root","g","window","this","defaults","navClass","contentClass","nested","nestedClass","offset","reflow","events","emitEvent","type","elem","detail","settings","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","parseFloat","getOffset","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","last","length","item","useLastItem","i","deactivateNested","nav","parentNode","li","closest","classList","remove","deactivate","items","link","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","active","activate","scrollHandler","cancelAnimationFrame","requestAnimationFrame","detect","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","setup","addEventListener","factory","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","n","getter","__esModule","d","a","definition","o","Object","defineProperty","enumerable","get","globalThis","Function","e","prop","tocScroll","header","lastScrollTop","scrollTop","GO_TO_TOP_OFFSET","cycleThemeOnce","currentTheme","localStorage","getItem","mode","matchMedia","matches","console","error","dataset","theme","setItem","log","buttons","getElementsByClassName","from","btn","setupTheme","last_known_scroll_position","ticking","scrollY","positionY","floor","scrollHandlerForBackToTop","scrollTo","querySelector","scrollHandlerForTOC","scroll","setupScrollHandler","recursive","rem","getComputedStyle","fontSize","height"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"scripts/furo.js","mappings":"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","sources":["webpack:///./src/furo/assets/scripts/gumshoe-patched.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/global","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./src/furo/assets/scripts/furo.js"],"sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight,\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1)),\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n },\n);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Gumshoe from \"./gumshoe-patched.js\";\n\n////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\nvar lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;\nconst GO_TO_TOP_OFFSET = 64;\n\nfunction scrollHandlerForHeader() {\n if (Math.floor(header.getBoundingClientRect().top) == 0) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForBackToTop(positionY) {\n if (positionY < GO_TO_TOP_OFFSET) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n } else {\n if (positionY < lastScrollTop) {\n document.documentElement.classList.add(\"show-back-to-top\");\n } else if (positionY > lastScrollTop) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n }\n }\n lastScrollTop = positionY;\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader();\n scrollHandlerForBackToTop(positionY);\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Theme Toggle\n////////////////////////////////////////////////////////////////////////////////\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n document.body.dataset.theme = mode;\n localStorage.setItem(\"theme\", mode);\n console.log(`Changed to ${mode} mode.`);\n}\n\nfunction cycleThemeOnce() {\n const currentTheme = localStorage.getItem(\"theme\") || \"auto\";\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) {\n // Auto (dark) -> Light -> Dark\n if (currentTheme === \"auto\") {\n setTheme(\"light\");\n } else if (currentTheme == \"light\") {\n setTheme(\"dark\");\n } else {\n setTheme(\"auto\");\n }\n } else {\n // Auto (light) -> Dark -> Light\n if (currentTheme === \"auto\") {\n setTheme(\"dark\");\n } else if (currentTheme == \"dark\") {\n setTheme(\"light\");\n } else {\n setTheme(\"auto\");\n }\n }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n let last_known_scroll_position = 0;\n let ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n offset: () => {\n let rem = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return header.getBoundingClientRect().height + 0.5 * rem + 1;\n },\n });\n}\n\nfunction setupTheme() {\n // Attach event handlers for toggling themes\n const buttons = document.getElementsByClassName(\"theme-toggle\");\n Array.from(buttons).forEach((btn) => {\n btn.addEventListener(\"click\", cycleThemeOnce);\n });\n}\n\nfunction setup() {\n setupTheme();\n setupScrollHandler();\n setupScrollSpy();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Main entrypoint\n////////////////////////////////////////////////////////////////////////////////\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"],"names":["root","g","window","this","defaults","navClass","contentClass","nested","nestedClass","offset","reflow","events","emitEvent","type","elem","detail","settings","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","parseFloat","getOffset","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","last","length","item","useLastItem","i","deactivateNested","nav","parentNode","li","closest","classList","remove","deactivate","items","link","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","active","activate","scrollHandler","cancelAnimationFrame","requestAnimationFrame","detect","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","setup","addEventListener","factory","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","n","getter","__esModule","d","a","definition","o","Object","defineProperty","enumerable","get","globalThis","Function","e","prop","tocScroll","header","lastScrollTop","scrollTop","GO_TO_TOP_OFFSET","cycleThemeOnce","currentTheme","localStorage","getItem","mode","matchMedia","matches","console","error","dataset","theme","setItem","log","buttons","getElementsByClassName","from","btn","setupTheme","last_known_scroll_position","ticking","scrollY","positionY","floor","scrollHandlerForBackToTop","scrollTo","querySelector","scrollHandlerForTOC","scroll","setupScrollHandler","recursive","rem","getComputedStyle","fontSize","height"],"sourceRoot":""} \ No newline at end of file diff --git a/docs_using_sphinx/_build/html/_static/styles/furo.css.map b/docs_using_sphinx/_build/html/_static/styles/furo.css.map index d1dfb109..1924b333 100644 --- a/docs_using_sphinx/_build/html/_static/styles/furo.css.map +++ b/docs_using_sphinx/_build/html/_static/styles/furo.css.map @@ -1 +1 @@ -{"version":3,"file":"styles/furo.css","mappings":"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0CACE,CAFF,kBACA,CACE,wEACA,CARA,YACA,CAKF,mBAFF,OAII,eACA,CAJF,iCAJE,cAGJ,CANI,oBAEA,CAKF,SAIE,2BADA,UACA,kBAGF,sCACA,CAFF,WACE,WACA,qCACE,gCACA,2EACA,sDAKJ,aACE,mDAII,CAJJ,6CAII,kEACA,iBACE,iDACA,+CACE,aACA,WADA,+BACA,uEANN,YACE,mDAEE,mBADF,0CACE,CADF,qBACE,0DACA,YACE,4DACA,sEANN,YACE,8CACA,kBADA,UACA,2CACE,2EACA,cACE,kEACA,mEANN,yBACE,4DACA,sBACE,+EAEE,iEACA,qEANN,sCACE,CAGE,iBAHF,gBAGE,qBACE,CAJJ,uBACA,gDACE,wDACA,6DAHF,2CACA,CADA,gBACA,eACE,CAGE,sBANN,8BACE,CAII,iBAFF,4DACA,WACE,YADF,uCACE,6EACA,2BANN,8CACE,kDACA,0CACE,8BACA,yFACE,sBACA,sFALJ,mEACA,sBACE,kEACA,6EACE,uCACA,kEALJ,qGAEE,kEACA,6EACE,uCACA,kEALJ,8CACA,uDACE,sEACA,2EACE,sCACA,iEALJ,mGACA,qCACE,oDACA,0DACE,6GACA,gDAGR,yDCrEA,sEACE,CACA,6GACE,gEACF,iGAIF,wFACE,qDAGA,mGAEE,2CAEF,4FACE,gCACF,wGACE,8DAEE,6FAIA,iJAKN,6GACE,gDAKF,yDACA,qCAGA,6BACA,kBACA,qDAKA,oCAEA,+DAGA,2CAGE,oDAIA,oEAEE,qBAGJ,wDAEE,uCAEF,kEAGA,8CAEA,uDAKA,oCAEA,yDAEE,gEAKF,+CC5FA,0EAGE,CACA,qDCLJ,+DAIE,sCAIA,kEACE,yBACA,2FAMA,gBACA,yGCbF,mBAOA,2MAIA,4HAYA,0DACE,8GAYF,8HAQE,mBAEA,6HAOF,YAGA,mIAME,eACA,CAFF,YAEE,4FAMJ,8BAEE,uBAYA,sCAEE,CAJF,oBAEA,CARA,wCAEA,CAHA,8BACA,CAFA,eACA,CAGA,wCAEA,CAEA,mDAIE,kCACE,6BACA,4CAKJ,kDAIA,eACE,aAGF,8BACE,uDACA,sCACA,cAEA,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","sources":["webpack:///./node_modules/normalize.css/normalize.css","webpack:///./src/furo/assets/styles/base/_print.sass","webpack:///./src/furo/assets/styles/base/_screen-readers.sass","webpack:///./src/furo/assets/styles/base/_theme.sass","webpack:///./src/furo/assets/styles/variables/_fonts.scss","webpack:///./src/furo/assets/styles/variables/_spacing.scss","webpack:///./src/furo/assets/styles/variables/_icons.scss","webpack:///./src/furo/assets/styles/variables/_admonitions.scss","webpack:///./src/furo/assets/styles/variables/_colors.scss","webpack:///./src/furo/assets/styles/base/_typography.sass","webpack:///./src/furo/assets/styles/_scaffold.sass","webpack:///./src/furo/assets/styles/content/_admonitions.sass","webpack:///./src/furo/assets/styles/content/_api.sass","webpack:///./src/furo/assets/styles/content/_blocks.sass","webpack:///./src/furo/assets/styles/content/_captions.sass","webpack:///./src/furo/assets/styles/content/_code.sass","webpack:///./src/furo/assets/styles/content/_footnotes.sass","webpack:///./src/furo/assets/styles/content/_images.sass","webpack:///./src/furo/assets/styles/content/_indexes.sass","webpack:///./src/furo/assets/styles/content/_lists.sass","webpack:///./src/furo/assets/styles/content/_math.sass","webpack:///./src/furo/assets/styles/content/_misc.sass","webpack:///./src/furo/assets/styles/content/_rubrics.sass","webpack:///./src/furo/assets/styles/content/_sidebar.sass","webpack:///./src/furo/assets/styles/content/_tables.sass","webpack:///./src/furo/assets/styles/content/_target.sass","webpack:///./src/furo/assets/styles/content/_gui-labels.sass","webpack:///./src/furo/assets/styles/components/_footer.sass","webpack:///./src/furo/assets/styles/components/_sidebar.sass","webpack:///./src/furo/assets/styles/components/_table_of_contents.sass","webpack:///./src/furo/assets/styles/_shame.sass"],"sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n","// This file contains styles for managing print media.\n\n////////////////////////////////////////////////////////////////////////////////\n// Hide elements not relevant to print media.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Hide icon container.\n .content-icon-container\n display: none !important\n\n // Hide showing header links if hovering over when printing.\n .headerlink\n display: none !important\n\n // Hide mobile header.\n .mobile-header\n display: none !important\n\n // Hide navigation links.\n .related-pages\n display: none !important\n\n////////////////////////////////////////////////////////////////////////////////\n// Tweaks related to decolorization.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Apply a border around code which no longer have a color background.\n .highlight\n border: 0.1pt solid var(--color-foreground-border)\n\n////////////////////////////////////////////////////////////////////////////////\n// Avoid page break in some relevant cases.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n ul, ol, dl, a, table, pre, blockquote\n page-break-inside: avoid\n\n h1, h2, h3, h4, h5, h6, img, figure, caption\n page-break-inside: avoid\n page-break-after: avoid\n\n ul, ol, dl\n page-break-before: avoid\n",".visually-hidden\n position: absolute !important\n width: 1px !important\n height: 1px !important\n padding: 0 !important\n margin: -1px !important\n overflow: hidden !important\n clip: rect(0,0,0,0) !important\n white-space: nowrap !important\n border: 0 !important\n\n:-moz-focusring\n outline: auto\n","// This file serves as the \"skeleton\" of the theming logic.\n//\n// This contains the bulk of the logic for handling dark mode, color scheme\n// toggling and the handling of color-scheme-specific hiding of elements.\n\nbody\n @include fonts\n @include spacing\n @include icons\n @include admonitions\n @include default-admonition(#651fff, \"abstract\")\n @include default-topic(#14B8A6, \"pencil\")\n\n @include colors\n\n.only-light\n display: block !important\nhtml body .only-dark\n display: none !important\n\n// Ignore dark-mode hints if print media.\n@media not print\n // Enable dark-mode, if requested.\n body[data-theme=\"dark\"]\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n // Enable dark mode, unless explicitly told to avoid.\n @media (prefers-color-scheme: dark)\n body:not([data-theme=\"light\"])\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n//\n// Theme toggle presentation\n//\nbody[data-theme=\"auto\"]\n .theme-toggle svg.theme-icon-when-auto\n display: block\n\nbody[data-theme=\"dark\"]\n .theme-toggle svg.theme-icon-when-dark\n display: block\n\nbody[data-theme=\"light\"]\n .theme-toggle svg.theme-icon-when-light\n display: block\n","// Fonts used by this theme.\n//\n// There are basically two things here -- using the system font stack and\n// defining sizes for various elements in %ages. We could have also used `em`\n// but %age is easier to reason about for me.\n\n@mixin fonts {\n // These are adapted from https://systemfontstack.com/\n --font-stack: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji;\n --font-stack--monospace: \"SFMono-Regular\", Menlo, Consolas, Monaco,\n Liberation Mono, Lucida Console, monospace;\n\n --font-size--normal: 100%;\n --font-size--small: 87.5%;\n --font-size--small--2: 81.25%;\n --font-size--small--3: 75%;\n --font-size--small--4: 62.5%;\n\n // Sidebar\n --sidebar-caption-font-size: var(--font-size--small--2);\n --sidebar-item-font-size: var(--font-size--small);\n --sidebar-search-input-font-size: var(--font-size--small);\n\n // Table of Contents\n --toc-font-size: var(--font-size--small--3);\n --toc-font-size--mobile: var(--font-size--normal);\n --toc-title-font-size: var(--font-size--small--4);\n\n // Admonitions\n //\n // These aren't defined in terms of %ages, since nesting these is permitted.\n --admonition-font-size: 0.8125rem;\n --admonition-title-font-size: 0.8125rem;\n\n // Code\n --code-font-size: var(--font-size--small--2);\n\n // API\n --api-font-size: var(--font-size--small);\n}\n","// Spacing for various elements on the page\n//\n// If the user wants to tweak things in a certain way, they are permitted to.\n// They also have to deal with the consequences though!\n\n@mixin spacing {\n // Header!\n --header-height: calc(\n var(--sidebar-item-line-height) + 4 * #{var(--sidebar-item-spacing-vertical)}\n );\n --header-padding: 0.5rem;\n\n // Sidebar\n --sidebar-tree-space-above: 1.5rem;\n --sidebar-caption-space-above: 1rem;\n\n --sidebar-item-line-height: 1rem;\n --sidebar-item-spacing-vertical: 0.5rem;\n --sidebar-item-spacing-horizontal: 1rem;\n --sidebar-item-height: calc(\n var(--sidebar-item-line-height) + 2 *#{var(--sidebar-item-spacing-vertical)}\n );\n\n --sidebar-expander-width: var(--sidebar-item-height); // be square\n\n --sidebar-search-space-above: 0.5rem;\n --sidebar-search-input-spacing-vertical: 0.5rem;\n --sidebar-search-input-spacing-horizontal: 0.5rem;\n --sidebar-search-input-height: 1rem;\n --sidebar-search-icon-size: var(--sidebar-search-input-height);\n\n // Table of Contents\n --toc-title-padding: 0.25rem 0;\n --toc-spacing-vertical: 1.5rem;\n --toc-spacing-horizontal: 1.5rem;\n --toc-item-spacing-vertical: 0.4rem;\n --toc-item-spacing-horizontal: 1rem;\n}\n","// Expose theme icons as CSS variables.\n\n$icons: (\n // Adapted from tabler-icons\n // url: https://tablericons.com/\n \"search\":\n url('data:image/svg+xml;charset=utf-8,'),\n // Factored out from mkdocs-material on 24-Aug-2020.\n // url: https://squidfunk.github.io/mkdocs-material/reference/admonitions/\n \"pencil\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"abstract\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"info\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"flame\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"question\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"warning\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"failure\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"spark\":\n url('data:image/svg+xml;charset=utf-8,')\n);\n\n@mixin icons {\n @each $name, $glyph in $icons {\n --icon-#{$name}: #{$glyph};\n }\n}\n","// Admonitions\n\n// Structure of these is:\n// admonition-class: color \"icon-name\";\n//\n// The colors are translated into CSS variables below. The icons are\n// used directly in the main declarations to set the `mask-image` in\n// the title.\n\n// prettier-ignore\n$admonitions: (\n // Each of these has an reST directives for it.\n \"caution\": #ff9100 \"spark\",\n \"warning\": #ff9100 \"warning\",\n \"danger\": #ff5252 \"spark\",\n \"attention\": #ff5252 \"warning\",\n \"error\": #ff5252 \"failure\",\n \"hint\": #00c852 \"question\",\n \"tip\": #00c852 \"info\",\n \"important\": #00bfa5 \"flame\",\n \"note\": #00b0ff \"pencil\",\n \"seealso\": #448aff \"info\",\n \"admonition-todo\": #808080 \"pencil\"\n);\n\n@mixin default-admonition($color, $icon-name) {\n --color-admonition-title: #{$color};\n --color-admonition-title-background: #{rgba($color, 0.2)};\n\n --icon-admonition-default: var(--icon-#{$icon-name});\n}\n\n@mixin default-topic($color, $icon-name) {\n --color-topic-title: #{$color};\n --color-topic-title-background: #{rgba($color, 0.2)};\n\n --icon-topic-default: var(--icon-#{$icon-name});\n}\n\n@mixin admonitions {\n @each $name, $values in $admonitions {\n --color-admonition-title--#{$name}: #{nth($values, 1)};\n --color-admonition-title-background--#{$name}: #{rgba(\n nth($values, 1),\n 0.2\n )};\n }\n}\n","// Colors used throughout this theme.\n//\n// The aim is to give the user more control. Thus, instead of hard-coding colors\n// in various parts of the stylesheet, the approach taken is to define all\n// colors as CSS variables and reusing them in all the places.\n//\n// `colors-dark` depends on `colors` being included at a lower specificity.\n\n@mixin colors {\n --color-problematic: #b30000;\n\n // Base Colors\n --color-foreground-primary: black; // for main text and headings\n --color-foreground-secondary: #5a5c63; // for secondary text\n --color-foreground-muted: #646776; // for muted text\n --color-foreground-border: #878787; // for content borders\n\n --color-background-primary: white; // for content\n --color-background-secondary: #f8f9fb; // for navigation + ToC\n --color-background-hover: #efeff4ff; // for navigation-item hover\n --color-background-hover--transparent: #efeff400;\n --color-background-border: #eeebee; // for UI borders\n --color-background-item: #ccc; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #2962ff;\n --color-brand-content: #2a5adf;\n\n // API documentation\n --color-api-background: var(--color-background-hover--transparent);\n --color-api-background-hover: var(--color-background-hover);\n --color-api-overall: var(--color-foreground-secondary);\n --color-api-name: var(--color-problematic);\n --color-api-pre-name: var(--color-problematic);\n --color-api-paren: var(--color-foreground-secondary);\n --color-api-keyword: var(--color-foreground-primary);\n --color-highlight-on-target: #ffffcc;\n\n // Inline code background\n --color-inline-code-background: var(--color-background-secondary);\n\n // Highlighted text (search)\n --color-highlighted-background: #ddeeff;\n --color-highlighted-text: var(--color-foreground-primary);\n\n // GUI Labels\n --color-guilabel-background: #ddeeff80;\n --color-guilabel-border: #bedaf580;\n --color-guilabel-text: var(--color-foreground-primary);\n\n // Admonitions!\n --color-admonition-background: transparent;\n\n //////////////////////////////////////////////////////////////////////////////\n // Everything below this should be one of:\n // - var(...)\n // - *-gradient(...)\n // - special literal values (eg: transparent, none)\n //////////////////////////////////////////////////////////////////////////////\n\n // Tables\n --color-table-header-background: var(--color-background-secondary);\n --color-table-border: var(--color-background-border);\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: transparent;\n --color-card-marginals-background: var(--color-background-secondary);\n\n // Header\n --color-header-background: var(--color-background-primary);\n --color-header-border: var(--color-background-border);\n --color-header-text: var(--color-foreground-primary);\n\n // Sidebar (left)\n --color-sidebar-background: var(--color-background-secondary);\n --color-sidebar-background-border: var(--color-background-border);\n\n --color-sidebar-brand-text: var(--color-foreground-primary);\n --color-sidebar-caption-text: var(--color-foreground-muted);\n --color-sidebar-link-text: var(--color-foreground-secondary);\n --color-sidebar-link-text--top-level: var(--color-brand-primary);\n\n --color-sidebar-item-background: var(--color-sidebar-background);\n --color-sidebar-item-background--current: var(\n --color-sidebar-item-background\n );\n --color-sidebar-item-background--hover: linear-gradient(\n 90deg,\n var(--color-background-hover--transparent) 0%,\n var(--color-background-hover) var(--sidebar-item-spacing-horizontal),\n var(--color-background-hover) 100%\n );\n\n --color-sidebar-item-expander-background: transparent;\n --color-sidebar-item-expander-background--hover: var(\n --color-background-hover\n );\n\n --color-sidebar-search-text: var(--color-foreground-primary);\n --color-sidebar-search-background: var(--color-background-secondary);\n --color-sidebar-search-background--focus: var(--color-background-primary);\n --color-sidebar-search-border: var(--color-background-border);\n --color-sidebar-search-icon: var(--color-foreground-muted);\n\n // Table of Contents (right)\n --color-toc-background: var(--color-background-primary);\n --color-toc-title-text: var(--color-foreground-muted);\n --color-toc-item-text: var(--color-foreground-secondary);\n --color-toc-item-text--hover: var(--color-foreground-primary);\n --color-toc-item-text--active: var(--color-brand-primary);\n\n // Actual page contents\n --color-content-foreground: var(--color-foreground-primary);\n --color-content-background: transparent;\n\n // Links\n --color-link: var(--color-brand-content);\n --color-link--hover: var(--color-brand-content);\n --color-link-underline: var(--color-background-border);\n --color-link-underline--hover: var(--color-foreground-border);\n}\n\n@mixin colors-dark {\n --color-problematic: #ee5151;\n\n // Base Colors\n --color-foreground-primary: #ffffffcc; // for main text and headings\n --color-foreground-secondary: #9ca0a5; // for secondary text\n --color-foreground-muted: #81868d; // for muted text\n --color-foreground-border: #666666; // for content borders\n\n --color-background-primary: #131416; // for content\n --color-background-secondary: #1a1c1e; // for navigation + ToC\n --color-background-hover: #1e2124ff; // for navigation-item hover\n --color-background-hover--transparent: #1e212400;\n --color-background-border: #303335; // for UI borders\n --color-background-item: #444; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #2b8cee;\n --color-brand-content: #368ce2;\n\n // Highlighted text (search)\n --color-highlighted-background: #083563;\n\n // GUI Labels\n --color-guilabel-background: #08356380;\n --color-guilabel-border: #13395f80;\n\n // API documentation\n --color-api-keyword: var(--color-foreground-secondary);\n --color-highlight-on-target: #333300;\n\n // Admonitions\n --color-admonition-background: #18181a;\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: #18181a;\n --color-card-marginals-background: var(--color-background-hover);\n}\n","// This file contains the styling for making the content throughout the page,\n// including fonts, paragraphs, headings and spacing among these elements.\n\nbody\n font-family: var(--font-stack)\npre,\ncode,\nkbd,\nsamp\n font-family: var(--font-stack--monospace)\n\n// Make fonts look slightly nicer.\nbody\n -webkit-font-smoothing: antialiased\n -moz-osx-font-smoothing: grayscale\n\n// Line height from Bootstrap 4.1\narticle\n line-height: 1.5\n\n//\n// Headings\n//\nh1,\nh2,\nh3,\nh4,\nh5,\nh6\n line-height: 1.25\n font-weight: bold\n\n border-radius: 0.5rem\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n margin-left: -0.5rem\n margin-right: -0.5rem\n padding-left: 0.5rem\n padding-right: 0.5rem\n\n + p\n margin-top: 0\n\nh1\n font-size: 2.5em\n margin-top: 1.75rem\n margin-bottom: 1rem\nh2\n font-size: 2em\n margin-top: 1.75rem\nh3\n font-size: 1.5em\nh4\n font-size: 1.25em\nh5\n font-size: 1.125em\nh6\n font-size: 1em\n\nsmall\n opacity: 75%\n font-size: 80%\n\n// Paragraph\np\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n\n// Horizontal rules\nhr.docutils\n height: 1px\n padding: 0\n margin: 2rem 0\n background-color: var(--color-background-border)\n border: 0\n\n.centered\n text-align: center\n\n// Links\na\n text-decoration: underline\n\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &.muted-link\n color: inherit\n &:hover\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline--hover)\n","// This file contains the styles for the overall layouting of the documentation\n// skeleton, including the responsive changes as well as sidebar toggles.\n//\n// This is implemented as a mobile-last design, which isn't ideal, but it is\n// reasonably good-enough and I got pretty tired by the time I'd finished this\n// to move the rules around to fix this. Shouldn't take more than 3-4 hours,\n// if you know what you're doing tho.\n\n// HACK: Not all browsers account for the scrollbar width in media queries.\n// This results in horizontal scrollbars in the breakpoint where we go\n// from displaying everything to hiding the ToC. We accomodate for this by\n// adding a bit of padding to the TOC drawer, disabling the horizontal\n// scrollbar and allowing the scrollbars to cover the padding.\n// https://www.456bereastreet.com/archive/201301/media_query_width_and_vertical_scrollbars/\n\n// HACK: Always having the scrollbar visible, prevents certain browsers from\n// causing the content to stutter horizontally between taller-than-viewport and\n// not-taller-than-viewport pages.\n\nhtml\n overflow-x: hidden\n overflow-y: scroll\n scroll-behavior: smooth\n\n.sidebar-scroll, .toc-scroll, article[role=main] *\n // Override Firefox scrollbar style\n scrollbar-width: thin\n scrollbar-color: var(--color-foreground-border) transparent\n\n // Override Chrome scrollbar styles\n &::-webkit-scrollbar\n width: 0.25rem\n height: 0.25rem\n &::-webkit-scrollbar-thumb\n background-color: var(--color-foreground-border)\n border-radius: 0.125rem\n\n//\n// Overalls\n//\nhtml,\nbody\n height: 100%\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\narticle\n color: var(--color-content-foreground)\n background: var(--color-content-background)\n overflow-wrap: break-word\n\n.page\n display: flex\n // fill the viewport for pages with little content.\n min-height: 100%\n\n.mobile-header\n width: 100%\n height: var(--header-height)\n background-color: var(--color-header-background)\n color: var(--color-header-text)\n border-bottom: 1px solid var(--color-header-border)\n\n // Looks like sub-script/super-script have this, and we need this to\n // be \"on top\" of those.\n z-index: 10\n\n // We don't show the header on large screens.\n display: none\n\n // Add shadow when scrolled\n &.scrolled\n border-bottom: none\n box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.4rem rgba(0, 0, 0, 0.2)\n\n .header-center\n a\n color: var(--color-header-text)\n text-decoration: none\n\n.main\n display: flex\n flex: 1\n\n// Sidebar (left) also covers the entire left portion of screen.\n.sidebar-drawer\n box-sizing: border-box\n\n border-right: 1px solid var(--color-sidebar-background-border)\n background: var(--color-sidebar-background)\n\n display: flex\n justify-content: flex-end\n // These next two lines took me two days to figure out.\n width: calc((100% - #{$full-width}) / 2 + #{$sidebar-width})\n min-width: $sidebar-width\n\n// Scroll-along sidebars\n.sidebar-container,\n.toc-drawer\n box-sizing: border-box\n width: $sidebar-width\n\n.toc-drawer\n background: var(--color-toc-background)\n // See HACK described on top of this document\n padding-right: 1rem\n\n.sidebar-sticky,\n.toc-sticky\n position: sticky\n top: 0\n height: min(100%, 100vh)\n height: 100vh\n\n display: flex\n flex-direction: column\n\n.sidebar-scroll,\n.toc-scroll\n flex-grow: 1\n flex-shrink: 1\n\n overflow: auto\n scroll-behavior: smooth\n\n// Central items.\n.content\n padding: 0 $content-padding\n width: $content-width\n\n display: flex\n flex-direction: column\n justify-content: space-between\n\n.icon\n display: inline-block\n height: 1rem\n width: 1rem\n svg\n width: 100%\n height: 100%\n\n//\n// Accommodate announcement banner\n//\n.announcement\n background-color: var(--color-announcement-background)\n color: var(--color-announcement-text)\n\n height: var(--header-height)\n display: flex\n align-items: center\n overflow-x: auto\n & + .page\n min-height: calc(100% - var(--header-height))\n\n.announcement-content\n box-sizing: border-box\n padding: 0.5rem\n min-width: 100%\n white-space: nowrap\n text-align: center\n\n a\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-announcement-text)\n\n &:hover\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-link--hover)\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for theme\n////////////////////////////////////////////////////////////////////////////////\n.no-js .theme-toggle-container // don't show theme toggle if there's no JS\n display: none\n\n.theme-toggle-container\n vertical-align: middle\n\n.theme-toggle\n cursor: pointer\n border: none\n padding: 0\n background: transparent\n\n.theme-toggle svg\n vertical-align: middle\n height: 1rem\n width: 1rem\n color: var(--color-foreground-primary)\n display: none\n\n.theme-toggle-header\n float: left\n padding: 1rem 0.5rem\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for elements\n////////////////////////////////////////////////////////////////////////////////\n.toc-overlay-icon, .nav-overlay-icon\n display: none\n cursor: pointer\n\n .icon\n color: var(--color-foreground-secondary)\n height: 1rem\n width: 1rem\n\n.toc-header-icon, .nav-overlay-icon\n // for when we set display: flex\n justify-content: center\n align-items: center\n\n.toc-content-icon\n height: 1.5rem\n width: 1.5rem\n\n.content-icon-container\n float: right\n display: flex\n margin-top: 1.5rem\n margin-left: 1rem\n margin-bottom: 1rem\n gap: 0.5rem\n\n .edit-this-page svg\n color: inherit\n height: 1rem\n width: 1rem\n\n.sidebar-toggle\n position: absolute\n display: none\n// \n.sidebar-toggle[name=\"__toc\"]\n left: 20px\n.sidebar-toggle:checked\n left: 40px\n// \n\n.overlay\n position: fixed\n top: 0\n width: 0\n height: 0\n\n transition: width 0ms, height 0ms, opacity 250ms ease-out\n\n opacity: 0\n background-color: rgba(0, 0, 0, 0.54)\n.sidebar-overlay\n z-index: 20\n.toc-overlay\n z-index: 40\n\n// Keep things on top and smooth.\n.sidebar-drawer\n z-index: 30\n transition: left 250ms ease-in-out\n.toc-drawer\n z-index: 50\n transition: right 250ms ease-in-out\n\n// Show the Sidebar\n#__navigation:checked\n & ~ .sidebar-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .sidebar-drawer\n top: 0\n left: 0\n // Show the toc sidebar\n#__toc:checked\n & ~ .toc-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .toc-drawer\n top: 0\n right: 0\n\n////////////////////////////////////////////////////////////////////////////////\n// Back to top\n////////////////////////////////////////////////////////////////////////////////\n.back-to-top\n text-decoration: none\n\n display: none\n position: fixed\n left: 0\n top: 1rem\n padding: 0.5rem\n padding-right: 0.75rem\n border-radius: 1rem\n font-size: 0.8125rem\n\n background: var(--color-background-primary)\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), #6b728080 0px 0px 1px 0px\n\n z-index: 10\n\n margin-left: 50%\n transform: translateX(-50%)\n svg\n height: 1rem\n width: 1rem\n fill: currentColor\n display: inline-block\n\n span\n margin-left: 0.25rem\n\n .show-back-to-top &\n display: flex\n align-items: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Responsive layouting\n////////////////////////////////////////////////////////////////////////////////\n// Make things a bit bigger on bigger screens.\n@media (min-width: $full-width + $sidebar-width)\n html\n font-size: 110%\n\n@media (max-width: $full-width)\n // Collapse \"toc\" into the icon.\n .toc-content-icon\n display: flex\n .toc-drawer\n position: fixed\n height: 100vh\n top: 0\n right: -$sidebar-width\n border-left: 1px solid var(--color-background-muted)\n .toc-tree\n border-left: none\n font-size: var(--toc-font-size--mobile)\n\n // Accomodate for a changed content width.\n .sidebar-drawer\n width: calc((100% - #{$full-width - $sidebar-width}) / 2 + #{$sidebar-width})\n\n@media (max-width: $full-width - $sidebar-width)\n // Collapse \"navigation\".\n .nav-overlay-icon\n display: flex\n .sidebar-drawer\n position: fixed\n height: 100vh\n width: $sidebar-width\n\n top: 0\n left: -$sidebar-width\n\n // Swap which icon is visible.\n .toc-header-icon\n display: flex\n .toc-content-icon, .theme-toggle-content\n display: none\n .theme-toggle-header\n display: block\n\n // Show the header.\n .mobile-header\n position: sticky\n top: 0\n display: flex\n justify-content: space-between\n align-items: center\n\n .header-left,\n .header-right\n display: flex\n height: var(--header-height)\n padding: 0 var(--header-padding)\n label\n height: 100%\n width: 100%\n user-select: none\n\n .nav-overlay-icon .icon,\n .theme-toggle svg\n height: 1.25rem\n width: 1.25rem\n\n // Add a scroll margin for the content\n :target\n scroll-margin-top: var(--header-height)\n\n // Show back-to-top below the header\n .back-to-top\n top: calc(var(--header-height) + 0.5rem)\n\n // Center the page, and accommodate for the header.\n .page\n flex-direction: column\n justify-content: center\n .content\n margin-left: auto\n margin-right: auto\n\n@media (max-width: $content-width + 2* $content-padding)\n // Content should respect window limits.\n .content\n width: 100%\n overflow-x: auto\n\n@media (max-width: $content-width)\n .content\n padding: 0 $content-padding--small\n // Don't float sidebars to the right.\n article aside.sidebar\n float: none\n width: 100%\n margin: 1rem 0\n","//\n// The design here is strongly inspired by mkdocs-material.\n.admonition, .topic\n margin: 1rem auto\n padding: 0 0.5rem 0.5rem 0.5rem\n\n background: var(--color-admonition-background)\n\n border-radius: 0.2rem\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n font-size: var(--admonition-font-size)\n\n overflow: hidden\n page-break-inside: avoid\n\n // First element should have no margin, since the title has it.\n > :nth-child(2)\n margin-top: 0\n\n // Last item should have no margin, since we'll control that w/ padding\n > :last-child\n margin-bottom: 0\n\n.admonition p.admonition-title,\np.topic-title\n position: relative\n margin: 0 -0.5rem 0.5rem\n padding-left: 2rem\n padding-right: .5rem\n padding-top: .4rem\n padding-bottom: .4rem\n\n font-weight: 500\n font-size: var(--admonition-title-font-size)\n line-height: 1.3\n\n // Our fancy icon\n &::before\n content: \"\"\n position: absolute\n left: 0.5rem\n width: 1rem\n height: 1rem\n\n// Default styles\np.admonition-title\n background-color: var(--color-admonition-title-background)\n &::before\n background-color: var(--color-admonition-title)\n mask-image: var(--icon-admonition-default)\n mask-repeat: no-repeat\n\np.topic-title\n background-color: var(--color-topic-title-background)\n &::before\n background-color: var(--color-topic-title)\n mask-image: var(--icon-topic-default)\n mask-repeat: no-repeat\n\n//\n// Variants\n//\n.admonition\n border-left: 0.2rem solid var(--color-admonition-title)\n\n @each $type, $value in $admonitions\n &.#{$type}\n border-left-color: var(--color-admonition-title--#{$type})\n > .admonition-title\n background-color: var(--color-admonition-title-background--#{$type})\n &::before\n background-color: var(--color-admonition-title--#{$type})\n mask-image: var(--icon-#{nth($value, 2)})\n\n.admonition-todo > .admonition-title\n text-transform: uppercase\n","// This file stylizes the API documentation (stuff generated by autodoc). It's\n// deeply nested due to how autodoc structures the HTML without enough classes\n// to select the relevant items.\n\n// API docs!\ndl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)\n // Tweak the spacing of all the things!\n dd\n margin-left: 2rem\n > :first-child\n margin-top: 0.125rem\n > :last-child\n margin-bottom: 0.75rem\n\n // This is used for the arguments\n .field-list\n margin-bottom: 0.75rem\n\n // \"Headings\" (like \"Parameters\" and \"Return\")\n > dt\n text-transform: uppercase\n font-size: var(--font-size--small)\n\n dd:empty\n margin-bottom: 0.5rem\n dd > ul\n margin-left: -1.2rem\n > li\n > p:nth-child(2)\n margin-top: 0\n // When the last-empty-paragraph follows a paragraph, it doesn't need\n // to augument the existing spacing.\n > p + p:last-child:empty\n margin-top: 0\n margin-bottom: 0\n\n // Colorize the elements\n > dt\n color: var(--color-api-overall)\n\n.sig:not(.sig-inline)\n font-weight: bold\n\n font-size: var(--api-font-size)\n font-family: var(--font-stack--monospace)\n\n margin-left: -0.25rem\n margin-right: -0.25rem\n padding-top: 0.25rem\n padding-bottom: 0.25rem\n padding-right: 0.5rem\n\n // These are intentionally em, to properly match the font size.\n padding-left: 3em\n text-indent: -2.5em\n\n border-radius: 0.25rem\n\n background: var(--color-api-background)\n transition: background 100ms ease-out\n\n &:hover\n background: var(--color-api-background-hover)\n\n // adjust the size of the [source] link on the right.\n a.reference\n .viewcode-link\n font-weight: normal\n width: 3.5rem\n\nem.property\n font-style: normal\n &:first-child\n color: var(--color-api-keyword)\n.sig-name\n color: var(--color-api-name)\n.sig-prename\n font-weight: normal\n color: var(--color-api-pre-name)\n.sig-paren\n color: var(--color-api-paren)\n.sig-param\n font-style: normal\n\n.versionmodified\n font-style: italic\ndiv.versionadded, div.versionchanged, div.deprecated\n p\n margin-top: 0.125rem\n margin-bottom: 0.125rem\n\n// Align the [docs] and [source] to the right.\n.viewcode-link, .viewcode-back\n float: right\n text-align: right\n",".line-block\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n .line-block\n margin-top: 0rem\n margin-bottom: 0rem\n padding-left: 1rem\n","// Captions\narticle p.caption,\ntable > caption,\n.code-block-caption\n font-size: var(--font-size--small)\n text-align: center\n\n// Caption above a TOCTree\n.toctree-wrapper.compound\n .caption, :not(.caption) > .caption-text\n font-size: var(--font-size--small)\n text-transform: uppercase\n\n text-align: initial\n margin-bottom: 0\n\n > ul\n margin-top: 0\n margin-bottom: 0\n","// Inline code\ncode.literal, .sig-inline\n background: var(--color-inline-code-background)\n border-radius: 0.2em\n // Make the font smaller, and use padding to recover.\n font-size: var(--font-size--small--2)\n padding: 0.1em 0.2em\n\n pre.literal-block &\n font-size: inherit\n padding: 0\n\n p &\n border: 1px solid var(--color-background-border)\n\n.sig-inline\n font-family: var(--font-stack--monospace)\n\n// Code and Literal Blocks\n$code-spacing-vertical: 0.625rem\n$code-spacing-horizontal: 0.875rem\n\n// Wraps every literal block + line numbers.\ndiv[class*=\" highlight-\"],\ndiv[class^=\"highlight-\"]\n margin: 1em 0\n display: flex\n\n .table-wrapper\n margin: 0\n padding: 0\n\npre\n margin: 0\n padding: 0\n overflow: auto\n\n // Needed to have more specificity than pygments' \"pre\" selector. :(\n article[role=\"main\"] .highlight &\n line-height: 1.5\n\n &.literal-block,\n .highlight &\n font-size: var(--code-font-size)\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n // Make it look like all the other blocks.\n &.literal-block\n margin-top: 1rem\n margin-bottom: 1rem\n\n border-radius: 0.2rem\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n\n// All code is always contained in this.\n.highlight\n width: 100%\n border-radius: 0.2rem\n\n // Make line numbers and prompts un-selectable.\n .gp, span.linenos\n user-select: none\n pointer-events: none\n\n // Expand the line-highlighting.\n .hll\n display: block\n margin-left: -$code-spacing-horizontal\n margin-right: -$code-spacing-horizontal\n padding-left: $code-spacing-horizontal\n padding-right: $code-spacing-horizontal\n\n/* Make code block captions be nicely integrated */\n.code-block-caption\n display: flex\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n border-radius: 0.25rem\n border-bottom-left-radius: 0\n border-bottom-right-radius: 0\n font-weight: 300\n border-bottom: 1px solid\n\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n border-color: var(--color-background-border)\n\n + div[class]\n margin-top: 0\n pre\n border-top-left-radius: 0\n border-top-right-radius: 0\n\n// When `html_codeblock_linenos_style` is table.\n.highlighttable\n width: 100%\n display: block\n tbody\n display: block\n\n tr\n display: flex\n\n // Line numbers\n td.linenos\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n padding: $code-spacing-vertical $code-spacing-horizontal\n padding-right: 0\n border-top-left-radius: 0.2rem\n border-bottom-left-radius: 0.2rem\n\n .linenodiv\n padding-right: $code-spacing-horizontal\n font-size: var(--code-font-size)\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n\n // Actual code\n td.code\n padding: 0\n display: block\n flex: 1\n overflow: hidden\n\n .highlight\n border-top-left-radius: 0\n border-bottom-left-radius: 0\n\n// When `html_codeblock_linenos_style` is inline.\n.highlight\n span.linenos\n display: inline-block\n padding-left: 0\n padding-right: $code-spacing-horizontal\n margin-right: $code-spacing-horizontal\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n","// Inline Footnote Reference\n.footnote-reference\n font-size: var(--font-size--small--4)\n vertical-align: super\n\n// Definition list, listing the content of each note.\n// docutils <= 0.17\ndl.footnote.brackets\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\n display: grid\n grid-template-columns: max-content auto\n dt\n margin: 0\n > .fn-backref\n margin-left: 0.25rem\n\n &:after\n content: \":\"\n\n .brackets\n &:before\n content: \"[\"\n &:after\n content: \"]\"\n\n dd\n margin: 0\n padding: 0 1rem\n\n// docutils >= 0.18\naside.footnote\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\naside.footnote > span,\ndiv.citation > span\n float: left\n font-weight: 500\n padding-right: 0.25rem\n\naside.footnote > p,\ndiv.citation > p\n margin-left: 2rem\n","//\n// Figures\n//\nimg\n box-sizing: border-box\n max-width: 100%\n height: auto\n\narticle\n figure, .figure\n border-radius: 0.2rem\n\n margin: 0\n :last-child\n margin-bottom: 0\n\n .align-left\n float: left\n clear: left\n margin: 0 1rem 1rem\n\n .align-right\n float: right\n clear: right\n margin: 0 1rem 1rem\n\n .align-default,\n .align-center\n display: block\n text-align: center\n margin-left: auto\n margin-right: auto\n\n // WELL, table needs to be stylised like a table.\n table.align-default\n display: table\n text-align: initial\n",".genindex-jumpbox, .domainindex-jumpbox\n border-top: 1px solid var(--color-background-border)\n border-bottom: 1px solid var(--color-background-border)\n padding: 0.25rem\n\n.genindex-section, .domainindex-section\n h2\n margin-top: 0.75rem\n margin-bottom: 0.5rem\n ul\n margin-top: 0\n margin-bottom: 0\n","ul,\nol\n padding-left: 1.2rem\n\n // Space lists out like paragraphs\n margin-top: 1rem\n margin-bottom: 1rem\n // reduce margins within li.\n li\n > p:first-child\n margin-top: 0.25rem\n margin-bottom: 0.25rem\n\n > p:last-child\n margin-top: 0.25rem\n\n > ul,\n > ol\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n\nol\n &.arabic\n list-style: decimal\n &.loweralpha\n list-style: lower-alpha\n &.upperalpha\n list-style: upper-alpha\n &.lowerroman\n list-style: lower-roman\n &.upperroman\n list-style: upper-roman\n\n// Don't space lists out when they're \"simple\" or in a `.. toctree::`\n.simple,\n.toctree-wrapper\n li\n > ul,\n > ol\n margin-top: 0\n margin-bottom: 0\n\n// Definition Lists\n.field-list,\n.option-list,\ndl:not([class]),\ndl.simple,\ndl.footnote,\ndl.glossary\n dt\n font-weight: 500\n margin-top: 0.25rem\n + dt\n margin-top: 0\n\n .classifier::before\n content: \":\"\n margin-left: 0.2rem\n margin-right: 0.2rem\n\n dd\n > p:first-child,\n ul\n margin-top: 0.125rem\n\n ul\n margin-bottom: 0.125rem\n",".math-wrapper\n width: 100%\n overflow-x: auto\n\ndiv.math\n position: relative\n text-align: center\n\n .headerlink,\n &:focus .headerlink\n display: none\n\n &:hover .headerlink\n display: inline-block\n\n span.eqno\n position: absolute\n right: 0.5rem\n top: 50%\n transform: translate(0, -50%)\n z-index: 1\n","// Abbreviations\nabbr[title]\n cursor: help\n\n// \"Problematic\" content, as identified by Sphinx\n.problematic\n color: var(--color-problematic)\n\n// Keyboard / Mouse \"instructions\"\nkbd:not(.compound)\n margin: 0 0.2rem\n padding: 0 0.2rem\n border-radius: 0.2rem\n border: 1px solid var(--color-foreground-border)\n color: var(--color-foreground-primary)\n vertical-align: text-bottom\n\n font-size: var(--font-size--small--3)\n display: inline-block\n\n box-shadow: 0 0.0625rem 0 rgba(0, 0, 0, 0.2), inset 0 0 0 0.125rem var(--color-background-primary)\n\n background-color: var(--color-background-secondary)\n\n// Blockquote\nblockquote\n border-left: 4px solid var(--color-background-border)\n background: var(--color-background-secondary)\n\n margin-left: 0\n margin-right: 0\n padding: 0.5rem 1rem\n\n .attribution\n font-weight: 600\n text-align: right\n\n &.pull-quote,\n &.highlights\n font-size: 1.25em\n\n &.epigraph,\n &.pull-quote\n border-left-width: 0\n border-radius: 0.5rem\n\n &.highlights\n border-left-width: 0\n background: transparent\n\n// Center align embedded-in-text images\np .reference img\n vertical-align: middle\n","p.rubric\n line-height: 1.25\n font-weight: bold\n font-size: 1.125em\n\n // For Numpy-style documentation that's got rubrics within it.\n // https://github.com/pradyunsg/furo/discussions/505\n dd &\n line-height: inherit\n font-weight: inherit\n\n font-size: var(--font-size--small)\n text-transform: uppercase\n","article .sidebar\n float: right\n clear: right\n width: 30%\n\n margin-left: 1rem\n margin-right: 0\n\n border-radius: 0.2rem\n background-color: var(--color-background-secondary)\n border: var(--color-background-border) 1px solid\n\n > *\n padding-left: 1rem\n padding-right: 1rem\n\n > ul, > ol // lists need additional padding, because bullets.\n padding-left: 2.2rem\n\n .sidebar-title\n margin: 0\n padding: 0.5rem 1rem\n border-bottom: var(--color-background-border) 1px solid\n\n font-weight: 500\n\n// TODO: subtitle\n// TODO: dedicated variables?\n",".table-wrapper\n width: 100%\n overflow-x: auto\n margin-top: 1rem\n margin-bottom: 0.5rem\n padding: 0.2rem 0.2rem 0.75rem\n\ntable.docutils\n border-radius: 0.2rem\n border-spacing: 0\n border-collapse: collapse\n\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n th\n background: var(--color-table-header-background)\n\n td,\n th\n // Space things out properly\n padding: 0 0.25rem\n\n // Get the borders looking just-right.\n border-left: 1px solid var(--color-table-border)\n border-right: 1px solid var(--color-table-border)\n border-bottom: 1px solid var(--color-table-border)\n\n p\n margin: 0.25rem\n\n &:first-child\n border-left: none\n &:last-child\n border-right: none\n\n // MyST-parser tables set these classes for control of column alignment\n &.text-left\n text-align: left\n &.text-right\n text-align: right\n &.text-center\n text-align: center\n",":target\n scroll-margin-top: 0.5rem\n\n@media (max-width: $full-width - $sidebar-width)\n :target\n scroll-margin-top: calc(0.5rem + var(--header-height))\n\n // When a heading is selected\n section > span:target\n scroll-margin-top: calc(0.8rem + var(--header-height))\n\n// Permalinks\n.headerlink\n font-weight: 100\n user-select: none\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\ndl dt,\np.caption,\nfigcaption p,\ntable > caption,\n.code-block-caption\n > .headerlink\n margin-left: 0.5rem\n visibility: hidden\n &:hover > .headerlink\n visibility: visible\n\n // Don't change to link-like, if someone adds the contents directive.\n > .toc-backref\n color: inherit\n text-decoration-line: none\n\n// Figure and table captions are special.\nfigure:hover > figcaption > p > .headerlink,\ntable:hover > caption > .headerlink\n visibility: visible\n\n:target >, // Regular section[id] style anchors\nspan:target ~ // Non-regular span[id] style \"extra\" anchors\n h1,\n h2,\n h3,\n h4,\n h5,\n h6\n &:nth-of-type(1)\n background-color: var(--color-highlight-on-target)\n // .headerlink\n // visibility: visible\n code.literal\n background-color: transparent\n\ntable:target > caption,\nfigure:target\n background-color: var(--color-highlight-on-target)\n\n// Inline page contents\n.this-will-duplicate-information-and-it-is-still-useful-here li :target\n background-color: var(--color-highlight-on-target)\n\n// Code block permalinks\n.literal-block-wrapper:target .code-block-caption\n background-color: var(--color-highlight-on-target)\n\n// When a definition list item is selected\n//\n// There isn't really an alternative to !important here, due to the\n// high-specificity of API documentation's selector.\ndt:target\n background-color: var(--color-highlight-on-target) !important\n\n// When a footnote reference is selected\n.footnote > dt:target + dd,\n.footnote-reference:target\n background-color: var(--color-highlight-on-target)\n",".guilabel\n background-color: var(--color-guilabel-background)\n border: 1px solid var(--color-guilabel-border)\n color: var(--color-guilabel-text)\n\n padding: 0 0.3em\n border-radius: 0.5em\n font-size: 0.9em\n","// This file contains the styles used for stylizing the footer that's shown\n// below the content.\n\nfooter\n font-size: var(--font-size--small)\n display: flex\n flex-direction: column\n\n margin-top: 2rem\n\n// Bottom of page information\n.bottom-of-page\n display: flex\n align-items: center\n justify-content: space-between\n\n margin-top: 1rem\n padding-top: 1rem\n padding-bottom: 1rem\n\n color: var(--color-foreground-secondary)\n border-top: 1px solid var(--color-background-border)\n\n line-height: 1.5\n\n @media (max-width: $content-width)\n text-align: center\n flex-direction: column-reverse\n gap: 0.25rem\n\n .left-details\n font-size: var(--font-size--small)\n\n .right-details\n display: flex\n flex-direction: column\n gap: 0.25rem\n text-align: right\n\n .icons\n display: flex\n justify-content: flex-end\n gap: 0.25rem\n font-size: 1rem\n\n a\n text-decoration: none\n\n svg,\n img\n font-size: 1.125rem\n height: 1em\n width: 1em\n\n// Next/Prev page information\n.related-pages\n a\n display: flex\n align-items: center\n\n text-decoration: none\n &:hover .page-info .title\n text-decoration: underline\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n svg.furo-related-icon,\n svg.furo-related-icon > use\n flex-shrink: 0\n\n color: var(--color-foreground-border)\n\n width: 0.75rem\n height: 0.75rem\n margin: 0 0.5rem\n\n &.next-page\n max-width: 50%\n\n float: right\n clear: right\n text-align: right\n\n &.prev-page\n max-width: 50%\n\n float: left\n clear: left\n\n svg\n transform: rotate(180deg)\n\n.page-info\n display: flex\n flex-direction: column\n overflow-wrap: anywhere\n\n .next-page &\n align-items: flex-end\n\n .context\n display: flex\n align-items: center\n\n padding-bottom: 0.1rem\n\n color: var(--color-foreground-muted)\n font-size: var(--font-size--small)\n text-decoration: none\n","// This file contains the styles for the contents of the left sidebar, which\n// contains the navigation tree, logo, search etc.\n\n////////////////////////////////////////////////////////////////////////////////\n// Brand on top of the scrollable tree.\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-brand\n display: flex\n flex-direction: column\n flex-shrink: 0\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n text-decoration: none\n\n.sidebar-brand-text\n color: var(--color-sidebar-brand-text)\n overflow-wrap: break-word\n margin: var(--sidebar-item-spacing-vertical) 0\n font-size: 1.5rem\n\n.sidebar-logo-container\n margin: var(--sidebar-item-spacing-vertical) 0\n\n.sidebar-logo\n margin: 0 auto\n display: block\n max-width: 100%\n\n////////////////////////////////////////////////////////////////////////////////\n// Search\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-search-container\n display: flex\n align-items: center\n margin-top: var(--sidebar-search-space-above)\n\n position: relative\n\n background: var(--color-sidebar-search-background)\n &:hover,\n &:focus-within\n background: var(--color-sidebar-search-background--focus)\n\n &::before\n content: \"\"\n position: absolute\n left: var(--sidebar-item-spacing-horizontal)\n width: var(--sidebar-search-icon-size)\n height: var(--sidebar-search-icon-size)\n\n background-color: var(--color-sidebar-search-icon)\n mask-image: var(--icon-search)\n\n.sidebar-search\n box-sizing: border-box\n\n border: none\n border-top: 1px solid var(--color-sidebar-search-border)\n border-bottom: 1px solid var(--color-sidebar-search-border)\n\n padding-top: var(--sidebar-search-input-spacing-vertical)\n padding-bottom: var(--sidebar-search-input-spacing-vertical)\n padding-right: var(--sidebar-search-input-spacing-horizontal)\n padding-left: calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size))\n\n width: 100%\n\n color: var(--color-sidebar-search-foreground)\n background: transparent\n z-index: 10\n\n &:focus\n outline: none\n\n &::placeholder\n font-size: var(--sidebar-search-input-font-size)\n\n//\n// Hide Search Matches link\n//\n#searchbox .highlight-link\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0\n margin: 0\n text-align: center\n\n a\n color: var(--color-sidebar-search-icon)\n font-size: var(--font-size--small--2)\n\n////////////////////////////////////////////////////////////////////////////////\n// Structure/Skeleton of the navigation tree (left)\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-tree\n font-size: var(--sidebar-item-font-size)\n margin-top: var(--sidebar-tree-space-above)\n margin-bottom: var(--sidebar-item-spacing-vertical)\n\n ul\n padding: 0\n margin-top: 0\n margin-bottom: 0\n\n display: flex\n flex-direction: column\n\n list-style: none\n\n li\n position: relative\n margin: 0\n\n > ul\n margin-left: var(--sidebar-item-spacing-horizontal)\n\n .icon\n color: var(--color-sidebar-link-text)\n\n .reference\n box-sizing: border-box\n color: var(--color-sidebar-link-text)\n\n // Fill the parent.\n display: inline-block\n line-height: var(--sidebar-item-line-height)\n text-decoration: none\n\n // Don't allow long words to cause wrapping.\n overflow-wrap: anywhere\n\n height: 100%\n width: 100%\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n &:hover\n background: var(--color-sidebar-item-background--hover)\n\n // Add a nice little \"external-link\" arrow here.\n &.external::after\n content: url('data:image/svg+xml,')\n margin: 0 0.25rem\n vertical-align: middle\n color: var(--color-sidebar-link-text)\n\n // Make the current page reference bold.\n .current-page > .reference\n font-weight: bold\n\n label\n position: absolute\n top: 0\n right: 0\n height: var(--sidebar-item-height)\n width: var(--sidebar-expander-width)\n\n cursor: pointer\n user-select: none\n\n display: flex\n justify-content: center\n align-items: center\n\n .caption, :not(.caption) > .caption-text\n font-size: var(--sidebar-caption-font-size)\n color: var(--color-sidebar-caption-text)\n\n font-weight: bold\n text-transform: uppercase\n\n margin: var(--sidebar-caption-space-above) 0 0 0\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n // If it has children, add a bit more padding to wrap the content to avoid\n // overlapping with the