Creating your own visualizations#

This tutorial describes how to build custom visualizations (BaseVisualizations) in OCE.

We have a unique way of building visualizations in OCE to make them interactive, shareable, and customizable.

The BaseVisualization class#

Basic flow#

Fundamentally BaseVisualizations are rendered via render_X() (the function render_ipynb() returns an output renderable in Jupyter notebooks and the function render_data_url() returns a dataURL which can be pasted in any web browser and rendered).

Each BaseVisualization is drawn onto a blank div via a JavaScript template defined by the file specified by the property JS_NAME. The render_X() functions compile the HTML/JavaScript code and populates the visualization tempalte with the visualization data returned by get_data(). save_html saves the visulalization to a standalone HTML file.

Notes on use#

Visualizations often require external JavaScript packages to load this can be specified in self.packages and a dictionary of such available packages is in package_urls.

from olorenchemengine import BaseVisualization, log_arguments

class CustomVis(BaseVisualization):

    package_urls = {...}

    @log_arguments
    def __init__(self, log=True, **kwargs):
        self.packages = []

    def get_data() -> dict:
        """Get data for visualization in JSON-like dictionary.
        """
        return {}

    @property
    def JS_NAME(self) -> str:
        pass

    def render(self, data: dict = None, print_html_js=False) -> str:
        pass

    def save_html(self, path):
        pass

    def render_ipynb(self, data: dict = None, print_html_js=False) -> str:
       pass

    def render_data_url(self, data: dict = None, print_html_js=False) -> str:
        pass

Notes on attributes class#

You’ll notice two methods in the visualizations, get_attributes() and from_attributes. These two methods are used to systematize the arguments used for visualizations, especially the aesthetic and BaseClass subclasses. These attributes are optional, but highly reccomended for contributed code.

@staticmethod
def get_attributes() -> list:
    pass

@classmethod
def from_attributes(cls, attributes: dict) -> "BaseVisualization":
    pass

Creating by example#

We will go through an example chemical space plot to show the components of a visualization. We’ll do two run-throughs. The first will show the basic funtional components of the Python class. The second will show the integration with JavaScript.

First run-through#

# This is what the visualization looks like

from olorenchemengine import ChemicalSpacePlot, BACEDataset, MorganVecRepresentation
vis = ChemicalSpacePlot(BACEDataset(), MorganVecRepresentation())
vis.render_ipynb()

Second run-through#

First we’ll show the data that is passed to the HTML/JavaScript created by get_data() and then we will show the final combined HTML/JavaScript + data file.

# This is what the visualization data looks like
vis.get_data()
{'title': 'Chemical Space Plot',
 'xaxis_title': 'Component 1',
 'yaxis_title': 'Component 2',
 'hover_size': 0.4,
 'xaxis_type': 'linear',
 'yaxis_type': 'linear',
 'width': 800,
 'height': 600,
 'opacity': 1,
 'X': [43.61760330200195,
  -17.472150802612305,
  41.86582946777344,
  158.97496032714844,
  -24.860200881958008,
  -2.232616424560547,
  -35.85402297973633,
  -67.47518157958984,
  55.304420471191406,
  -13.724129676818848,
  -3.4850451946258545,
  -134.3723602294922,
  -62.69178771972656,
  30.23807716369629,
  -5.901937961578369,
  10.940505981445312,
  -4.623172283172607,
  -43.74485778808594,
  8.369648933410645,
  68.97262573242188,
  -22.280351638793945,
  -30.012405395507812,
  75.25151062011719,
  64.52973937988281,
  -3.1073720455169678,
  -26.3098087310791,
  -29.127517700195312,
  14.045056343078613,
  27.511388778686523,
  62.6290168762207,
  46.29264831542969,
  18.152881622314453,
  49.81310272216797,
  -81.98030853271484,
  41.48120880126953,
  89.24085998535156,
  27.849729537963867,
  -41.686649322509766,
  26.67981719970703,
  -6.256188869476318,
  -26.8016300201416,
  8.647194862365723,
  -49.416343688964844,
  -42.954734802246094,
  48.0875129699707,
  -25.647356033325195,
  23.574270248413086,
  -62.410926818847656,
  12.529644966125488],
 'Y': [-37.546878814697266,
  -26.210065841674805,
  -12.783864974975586,
  27.13193702697754,
  87.86702728271484,
  -81.90585327148438,
  -47.80723571777344,
  36.506431579589844,
  -61.465553283691406,
  -56.813961029052734,
  -39.14337921142578,
  76.40354919433594,
  -47.68071746826172,
  6.304887294769287,
  61.944801330566406,
  44.215999603271484,
  -10.914501190185547,
  59.72188949584961,
  -62.289512634277344,
  21.70496940612793,
  30.97284507751465,
  -73.79450225830078,
  -1.874199628829956,
  44.48176956176758,
  31.48701286315918,
  50.19774627685547,
  149.90878295898438,
  -6.158529281616211,
  32.54773712158203,
  -22.430017471313477,
  33.658206939697266,
  67.7158432006836,
  6.881969451904297,
  1.560334324836731,
  59.63355255126953,
  -42.17106246948242,
  -72.33515930175781,
  -26.811941146850586,
  -24.993431091308594,
  10.065010070800781,
  -9.101613998413086,
  -25.244958877563477,
  1.6200640201568604,
  22.73969841003418,
  -87.27729034423828,
  9.062121391296387,
  -48.46100997924805,
  -18.139448165893555,
  14.488275527954102],
 'SMILES': ['CC(C)CC(c1nnnn1C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1',
  'Cc1c(NS(C)(=O)=O)cccc1N(Cc1ccccc1)Cc1ccc(Oc2ccc(OCC(=O)O)cc2)cc1',
  'C=C(C)[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(SC)cc3)OC[C@@]21C',
  'CC(C)N1C(=O)OC(C)(C)c2cc(Nc3ccc(Br)cc3)ccc21',
  'CS(=O)(=O)Nc1ccc2c(c1)C(c1ccccc1)Oc1cccc(OC(F)F)c1-2',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCC(=O)O)cc3)C[C@@]21C',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(NC)cc3)C[C@@]21C',
  'CCn1nnnc1C(C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1',
  'CC1(C)OC(=O)Nc2ccc(-c3ccc(F)c(C#N)c3)cc21',
  'CN1C(=O)OC(C)(C)c2cc(Nc3cccc(Cl)c3Cl)ccc21',
  'CCOc1cccc2c1-c1ccc(NS(C)(=O)=O)cc1C(c1ccccc1)O2',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCC)cc3)C[C@@]21C',
  'Cn1nnnc1CN(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1',
  'C=C1C=C(C)CC(C)(C)C1Cc1ccc([N+](=O)[O-])cc1',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)C[C@@]21C',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)C[C@@]21C',
  'CC1(C)OC(=O)N(Cc2ccccc2)c2ccc(Nc3ccc(Br)cc3)cc21',
  'C[C@@H]1C[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(-c4ccccn4)cc3)C[C@]2(C)[C@H]1C(=O)C1CC1',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C(=O)NCCCCCC(=O)N[C@@H](CC(C)C)C(=O)OC(C)(C)C)cc3)C[C@@]21C',
  'CN(C)c1ccc([C@H]2OC[C@]3(C)[C@@H](O)CC[C@H]3[C@@H]3CCC4=CC(=O)CCC4=C32)cc1',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCC(=O)Nc4ccc(C(N)=O)c(O)c4)cc3)C[C@@]21C',
  'CC1=CC(C)(C)Nc2ccc3c(c21)COc1c(Cl)cccc1-3',
  'C=C1CCO[C@]12CC[C@H]1[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)OC[C@@]12C',
  'CC(c1nnnn1C(C)C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1',
  'C=C1C(C)=CCC(C)(C)[C@@H]1Cc1cc(OC)c(Br)cc1OC(C)=O',
  'CC1=CC(C)(C)Nc2ccc3c(c21)/C(=C/C=O)Oc1ccc(F)cc1-3',
  'C=C1C=C(C)CC(C)(C)C1Sc1ccc([N+](=O)[O-])cc1',
  'CCCCn1c2ccccc2c2ccc3c(c21)C(C)=CC(C)(C)N3',
  'CC(C)CC(c1nnnn1C)N(CC(C)C)c1ccc(C#N)c(Cl)c1',
  'C=C1CCCC(C)(C)C1Cc1cc(OC)c(Br)cc1O',
  'COc1ccc(-c2ccc([C@H]3C[C@]4(C)[C@@H](C(=O)C5CC5)CC[C@H]4[C@@H]4CCC5=CC(=O)CCC5=C43)cc2)cn1',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCC=O)cc3)C[C@@]21C',
  'CCC1(CC)OC(=O)N(C)c2ccc(Nc3cccc(Cl)c3)cc21',
  'CN(C)c1ccc([C@H]2C[C@]3(C)[C@@H](CC[C@]3(O)CCCO)[C@@H]3CCC4=CC(=O)CCC4=C32)cc1',
  'COc1ccccc1-c1ccc2c(c1)C(C(C)OCCc1cccc(Cl)c1)=CC(C)(C)N2',
  'CC1(C)[C@H](O)CC[C@]2(C)[C@@]3(C)c4[nH]c5ccccc5c4C[C@@H]3CC[C@@]12O',
  'CC(c1cn(C)nn1)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1',
  'CC1(C)OC(C(C)(C)C)Nc2ccc(-c3cc(F)cc(C#N)c3)cc21',
  'CC1=CC(C)(C)Nc2cc3oc4ccccc4c3cc21',
  'O=[N+]([O-])c1cccc(-c2ccc3nc(S)n(Cc4ccccc4)c3c2)c1',
  'O=C(c1ccc([N+](=O)[O-])cc1)N1CCCC(c2ccc(Cl)c(Cl)c2)=N1',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C(=O)NCCCC)cc3)C[C@@]21C',
  'C=C1C(C)=CCC(C)(C)[C@@H]1Cc1cc(OC)c(Br)cc1OC(C)=O',
  'CN(C)c1ccc([C@H]2C[C@]3(C)[C@@H](CC[C@]3(O)CCCO)[C@@H]3CCC4=CC(=O)CCC4=C32)cc1',
  'CC1=CC(C)(C)Nc2ccc(-c3ccsc3C#N)cc21',
  'CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCCCC(=O)OC)cc3)C[C@@]21C',
  'CCC1(CC)OC(=O)N(C)c2ccc(Nc3cccc(Cl)c3Cl)cc21',
  'CC1(C)C(=O)Nc2ccc(-c3cc(F)cc(Cl)c3)cc21',
  'C[C@@H]1c2c(ccc3c2[C@H](c2ccc(Cl)cc2)Oc2ccccc2-3)NC(C)(C)[C@H]1O'],
 'colorscale': 'Portland'}

This is what the combined vis HTML/JavaScript/Data looks like Notice the first section has a header, then package imports, then a div with id ‘basevis-entry’ which is where the visualization is rendered. The div has the tag data-visdata which has the JSON-ified data returned by get_data(). Then the visualization is rendered with Plotly with the compounds rendered on hover with smilesDrawer.

Note that the bulk of the visualization is performed in the JavaScript file pointed to by JS_NAME and the bulk of the processing is done in Python and returned by get_data. As a general principle, time-intensive procedures should be performed in the __init__() of the visualization with less time-intensive procedures like data filtering performed in get_data()

After the printed HTML/JavaScript is the dataURL which can be copy pasted without the quotation marks to be rendered in any browser.

vis.render_data_url(print_html_js=True)
        <!DOCTYPE html>
        <head>
        <meta charset="utf-8">
        </head>

        <html style="height: 100%;">

        <!-- Load packages -->
        <script src="https://cdn.plot.ly/plotly-2.12.1.min.js"></script><script src="https://unpkg.com/smiles-drawer@1.0.10/dist/smiles-drawer.min.js"></script>
        <body style="background-color:#FFFFFF; height: 100%;">
        <!-- Create a div where the graph will take place -->
        <div id="basevis-entry" data-visdata="{&quot;title&quot;: &quot;Chemical Space Plot&quot;, &quot;xaxis_title&quot;: &quot;Component 1&quot;, &quot;yaxis_title&quot;: &quot;Component 2&quot;, &quot;hover_size&quot;: 0.4, &quot;xaxis_type&quot;: &quot;linear&quot;, &quot;yaxis_type&quot;: &quot;linear&quot;, &quot;width&quot;: 800, &quot;height&quot;: 600, &quot;opacity&quot;: 1, &quot;X&quot;: [43.61760330200195, -17.472150802612305, 41.86582946777344, 158.97496032714844, -24.860200881958008, -2.232616424560547, -35.85402297973633, -67.47518157958984, 55.304420471191406, -13.724129676818848, -3.4850451946258545, -134.3723602294922, -62.69178771972656, 30.23807716369629, -5.901937961578369, 10.940505981445312, -4.623172283172607, -43.74485778808594, 8.369648933410645, 68.97262573242188, -22.280351638793945, -30.012405395507812, 75.25151062011719, 64.52973937988281, -3.1073720455169678, -26.3098087310791, -29.127517700195312, 14.045056343078613, 27.511388778686523, 62.6290168762207, 46.29264831542969, 18.152881622314453, 49.81310272216797, -81.98030853271484, 41.48120880126953, 89.24085998535156, 27.849729537963867, -41.686649322509766, 26.67981719970703, -6.256188869476318, -26.8016300201416, 8.647194862365723, -49.416343688964844, -42.954734802246094, 48.0875129699707, -25.647356033325195, 23.574270248413086, -62.410926818847656, 12.529644966125488], &quot;Y&quot;: [-37.546878814697266, -26.210065841674805, -12.783864974975586, 27.13193702697754, 87.86702728271484, -81.90585327148438, -47.80723571777344, 36.506431579589844, -61.465553283691406, -56.813961029052734, -39.14337921142578, 76.40354919433594, -47.68071746826172, 6.304887294769287, 61.944801330566406, 44.215999603271484, -10.914501190185547, 59.72188949584961, -62.289512634277344, 21.70496940612793, 30.97284507751465, -73.79450225830078, -1.874199628829956, 44.48176956176758, 31.48701286315918, 50.19774627685547, 149.90878295898438, -6.158529281616211, 32.54773712158203, -22.430017471313477, 33.658206939697266, 67.7158432006836, 6.881969451904297, 1.560334324836731, 59.63355255126953, -42.17106246948242, -72.33515930175781, -26.811941146850586, -24.993431091308594, 10.065010070800781, -9.101613998413086, -25.244958877563477, 1.6200640201568604, 22.73969841003418, -87.27729034423828, 9.062121391296387, -48.46100997924805, -18.139448165893555, 14.488275527954102], &quot;SMILES&quot;: [&quot;CC(C)CC(c1nnnn1C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1&quot;, &quot;Cc1c(NS(C)(=O)=O)cccc1N(Cc1ccccc1)Cc1ccc(Oc2ccc(OCC(=O)O)cc2)cc1&quot;, &quot;C=C(C)[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(SC)cc3)OC[C@@]21C&quot;, &quot;CC(C)N1C(=O)OC(C)(C)c2cc(Nc3ccc(Br)cc3)ccc21&quot;, &quot;CS(=O)(=O)Nc1ccc2c(c1)C(c1ccccc1)Oc1cccc(OC(F)F)c1-2&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCC(=O)O)cc3)C[C@@]21C&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(NC)cc3)C[C@@]21C&quot;, &quot;CCn1nnnc1C(C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1&quot;, &quot;CC1(C)OC(=O)Nc2ccc(-c3ccc(F)c(C#N)c3)cc21&quot;, &quot;CN1C(=O)OC(C)(C)c2cc(Nc3cccc(Cl)c3Cl)ccc21&quot;, &quot;CCOc1cccc2c1-c1ccc(NS(C)(=O)=O)cc1C(c1ccccc1)O2&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCC)cc3)C[C@@]21C&quot;, &quot;Cn1nnnc1CN(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1&quot;, &quot;C=C1C=C(C)CC(C)(C)C1Cc1ccc([N+](=O)[O-])cc1&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)C[C@@]21C&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)C[C@@]21C&quot;, &quot;CC1(C)OC(=O)N(Cc2ccccc2)c2ccc(Nc3ccc(Br)cc3)cc21&quot;, &quot;C[C@@H]1C[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(-c4ccccn4)cc3)C[C@]2(C)[C@H]1C(=O)C1CC1&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C(=O)NCCCCCC(=O)N[C@@H](CC(C)C)C(=O)OC(C)(C)C)cc3)C[C@@]21C&quot;, &quot;CN(C)c1ccc([C@H]2OC[C@]3(C)[C@@H](O)CC[C@H]3[C@@H]3CCC4=CC(=O)CCC4=C32)cc1&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCC(=O)Nc4ccc(C(N)=O)c(O)c4)cc3)C[C@@]21C&quot;, &quot;CC1=CC(C)(C)Nc2ccc3c(c21)COc1c(Cl)cccc1-3&quot;, &quot;C=C1CCO[C@]12CC[C@H]1[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C)cc3)OC[C@@]12C&quot;, &quot;CC(c1nnnn1C(C)C)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1&quot;, &quot;C=C1C(C)=CCC(C)(C)[C@@H]1Cc1cc(OC)c(Br)cc1OC(C)=O&quot;, &quot;CC1=CC(C)(C)Nc2ccc3c(c21)/C(=C/C=O)Oc1ccc(F)cc1-3&quot;, &quot;C=C1C=C(C)CC(C)(C)C1Sc1ccc([N+](=O)[O-])cc1&quot;, &quot;CCCCn1c2ccccc2c2ccc3c(c21)C(C)=CC(C)(C)N3&quot;, &quot;CC(C)CC(c1nnnn1C)N(CC(C)C)c1ccc(C#N)c(Cl)c1&quot;, &quot;C=C1CCCC(C)(C)C1Cc1cc(OC)c(Br)cc1O&quot;, &quot;COc1ccc(-c2ccc([C@H]3C[C@]4(C)[C@@H](C(=O)C5CC5)CC[C@H]4[C@@H]4CCC5=CC(=O)CCC5=C43)cc2)cn1&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCC=O)cc3)C[C@@]21C&quot;, &quot;CCC1(CC)OC(=O)N(C)c2ccc(Nc3cccc(Cl)c3)cc21&quot;, &quot;CN(C)c1ccc([C@H]2C[C@]3(C)[C@@H](CC[C@]3(O)CCCO)[C@@H]3CCC4=CC(=O)CCC4=C32)cc1&quot;, &quot;COc1ccccc1-c1ccc2c(c1)C(C(C)OCCc1cccc(Cl)c1)=CC(C)(C)N2&quot;, &quot;CC1(C)[C@H](O)CC[C@]2(C)[C@@]3(C)c4[nH]c5ccccc5c4C[C@@H]3CC[C@@]12O&quot;, &quot;CC(c1cn(C)nn1)N(Cc1ccccc1Cl)c1ccc(C#N)c(Cl)c1&quot;, &quot;CC1(C)OC(C(C)(C)C)Nc2ccc(-c3cc(F)cc(C#N)c3)cc21&quot;, &quot;CC1=CC(C)(C)Nc2cc3oc4ccccc4c3cc21&quot;, &quot;O=[N+]([O-])c1cccc(-c2ccc3nc(S)n(Cc4ccccc4)c3c2)c1&quot;, &quot;O=C(c1ccc([N+](=O)[O-])cc1)N1CCCC(c2ccc(Cl)c(Cl)c2)=N1&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)C(=O)NCCCC)cc3)C[C@@]21C&quot;, &quot;C=C1C(C)=CCC(C)(C)[C@@H]1Cc1cc(OC)c(Br)cc1OC(C)=O&quot;, &quot;CN(C)c1ccc([C@H]2C[C@]3(C)[C@@H](CC[C@]3(O)CCCO)[C@@H]3CCC4=CC(=O)CCC4=C32)cc1&quot;, &quot;CC1=CC(C)(C)Nc2ccc(-c3ccsc3C#N)cc21&quot;, &quot;CC#C[C@]1(O)CC[C@H]2[C@@H]3CCC4=CC(=O)CCC4=C3[C@@H](c3ccc(N(C)CCCCCCCC(=O)OC)cc3)C[C@@]21C&quot;, &quot;CCC1(CC)OC(=O)N(C)c2ccc(Nc3cccc(Cl)c3Cl)cc21&quot;, &quot;CC1(C)C(=O)Nc2ccc(-c3cc(F)cc(Cl)c3)cc21&quot;, &quot;C[C@@H]1c2c(ccc3c2[C@H](c2ccc(Cl)cc2)Oc2ccccc2-3)NC(C)(C)[C@H]1O&quot;], &quot;colorscale&quot;: &quot;Portland&quot;}" style="width: 100%; height: 100%; display:inline-block;"></div>
        </body>
        </meta>

<script>var plot = document.getElementById("basevis-entry");
var hoverInfo = document.getElementById("basevis-entry2");

var data = JSON.parse(document.getElementById("basevis-entry").dataset.visdata);

let options = {};
let smilesDrawer = new SmilesDrawer.Drawer(options);

var trace = {
  x: data.X,
  y: data.Y,
  text: data.SMILES,
  mode: "markers",
  type: "scatter",
  hoverinfo: "none",
  marker: {},
};

if ("hovertext" in data) {
  trace.hovertext = data.hovertext;
  trace.hoverinfo = "text";
}

if ("group" in data) {
  trace.transforms = [{ type: "groupby", groups: data.group }];
}

if ("hovertemplate" in data) {
  trace.hovertemplate = data.hovertemplate;
}

if ("color" in data) {
  trace.marker.color = data.color;
}

if ("size" in data) {
  trace.marker.size = data.size;
} else {
  trace.marker.size = 12;
}

// if ("outline" in data) {
//   trace.marker.line = {
//     color: data.outline,
//     width: 4,
//   };
// }

if ("opacity" in data) {
  trace.marker.opacity = data.opacity;
}

var plot_data = [trace];

var layout = {
  title: "Plot Title",
  xaxis: {
    title: "x Axis",
  },
  yaxis: {
    title: "y Axis",
  },
  width: data.width,
  height: data.height,
  autosize: true,
};

if ("title" in data) {
  layout.title = data.title;
}

if ("xaxis_title" in data) {
  layout.xaxis.title = data.xaxis_title;
}

if ("yaxis_title" in data) {
  layout.yaxis.title = data.yaxis_title;
}

layout.xaxis.type = data["xaxis_type"];
layout.yaxis.type = data["yaxis_type"];

if ("ydomain" in data){
  layout.yaxis.domain = data.ydomain;
}
if ("xdomain" in data){
  layout.xaxis.domain = data.xdomain;
}

if ("yrange" in data){
  layout.yaxis.range = data.yrange;
}
if ("xrange" in data){
  layout.xaxis.range = data.xrange;
}

if ("axesratio" in data){
  layout.yaxis.scaleanchor = "x";
  layout.yaxis.scaleratio = data.axesratio;
}

if ("xdtick" in data){
  layout.xaxis.dtick = data.xdtick;
}

if ("ydtick" in data){
  layout.yaxis.dtick = data.ydtick;
}

if ("color" in data) {
  if ("colorscale" in data) {
    trace.colorscale = data.colorscale;
    trace.marker.colorscale = data.colorscale;
    trace.marker.colorbar = {
      title: "",
      titleside: "top",
    };
  }
}

Plotly.newPlot(
  "basevis-entry",
  plot_data,
  layout,
  (config = {
    displaylogo: false,
    modeBarButtonsToRemove: ["zoom2d", "pan2d", "select2d", "lasso2d"],
  })
);

if ("layout_update" in data){
  Plotly.update("basevis-entry", {}, data.layout_update);
}

if ("trace_update" in data){
  Plotly.addTraces("basevis-entry", data.trace_update);
}

const hoverCanvas = document.createElement("canvas");
hoverCanvas.id = "hoverCanvas";

const hoverBackground = document.createElement("canvas");
hoverBackground.id = "hoverBackground";

var hoverSize = parseFloat(data.hover_size);

plot.appendChild(hoverCanvas);
plot.appendChild(hoverBackground);

plot
  .on("plotly_hover", function (data) {
    var xaxis = data.points[0].xaxis,
      yaxis = data.points[0].yaxis;

    data.points.map(function (d) {
      hoverCanvas.hidden = false;
      hoverBackground.hidden = false;

      ctx = hoverCanvas.getContext("2d");

      SmilesDrawer.parse(d.text, function (smiles) {
        smilesDrawer.draw(smiles, "hoverCanvas", "light", false);
      });

      ctx.fillStyle = "black";
      ctx.shadowColor = "black";
      ctx.shadowBlur = 20;
      ctx.lineJoin = "bevel";
      ctx.lineWidth = 15;
      ctx.strokeRect(0, 0, hoverCanvas.width, hoverCanvas.height, "light");

      hoverBackground.width = hoverCanvas.width;
      hoverBackground.height = hoverCanvas.height;
      ctx = hoverBackground.getContext("2d");
      ctx.fillStyle = "white";
      ctx.fillRect(0, 0, hoverBackground.width, hoverBackground.height);

      Plotly.update(
        "basevis-entry",
        {},
        {
          // margin: { t: 100, b: 100, l: 50, r: 50 },
          annotations: [
            {
              x: d.x,
              y: d.y,
              xref: "x",
              yref: "y",
              text: "",
              showarrow: true,
              arrowhead: 7,
              ax: 0,
              ay: 0,
            },
          ],
          images: [
            {
              x: (d.x - xaxis.range[0]) / (xaxis.range[1] - xaxis.range[0]),
              y: (d.y - yaxis.range[0]) / (yaxis.range[1] - yaxis.range[0]),
              sizex: hoverSize,
              sizey: hoverSize,
              xref: "paper",
              yref: "paper",
              source: document.getElementById("hoverBackground").toDataURL(),
              xanchor: "left",
              yanchor: "top",
              layer: "above",
            },
            {
              x: (d.x - xaxis.range[0]) / (xaxis.range[1] - xaxis.range[0]),
              y: (d.y - yaxis.range[0]) / (yaxis.range[1] - yaxis.range[0]),
              sizex: hoverSize,
              sizey: hoverSize,
              xref: "paper",
              yref: "paper",
              source: document.getElementById("hoverCanvas").toDataURL(),
              xanchor: "left",
              yanchor: "top",
              layer: "above",
            },
          ],
        }
      );
      hoverCanvas.hidden = true;
      hoverBackground.hidden = true;
    });
  })
  .on("plotly_unhover", function (data) {
    Plotly.update("basevis-entry", {}, { annotations: [], images: [] });
  });
</script><script> window.addEventListener("resize", function(){if (document.getElementById("basevis-entry")) {Plotly.Plots.resize(document.getElementById("basevis-entry"));};}) </script>
'data:text/html,%0A%20%20%20%20%20%20%20%20%3C%21DOCTYPE%20html%3E%0A%20%20%20%20%20%20%20%20%3Chead%3E%0A%20%20%20%20%20%20%20%20%3Cmeta%20charset%3D%22utf-8%22%3E%0A%20%20%20%20%20%20%20%20%3C%2Fhead%3E%0A%0A%20%20%20%20%20%20%20%20%3Chtml%20style%3D%22height%3A%20100%25%3B%22%3E%0A%0A%20%20%20%20%20%20%20%20%3C%21--%20Load%20packages%20--%3E%0A%20%20%20%20%20%20%20%20%3Cscript%20src%3D%22https%3A%2F%2Fcdn.plot.ly%2Fplotly-2.12.1.min.js%22%3E%3C%2Fscript%3E%3Cscript%20src%3D%22https%3A%2F%2Funpkg.com%2Fsmiles-drawer%401.0.10%2Fdist%2Fsmiles-drawer.min.js%22%3E%3C%2Fscript%3E%0A%20%20%20%20%20%20%20%20%3Cbody%20style%3D%22background-color%3A%23FFFFFF%3B%20height%3A%20100%25%3B%22%3E%0A%20%20%20%20%20%20%20%20%3C%21--%20Create%20a%20div%20where%20the%20graph%20will%20take%20place%20--%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20id%3D%22basevis-entry%22%20data-visdata%3D%22%7B%26quot%3Btitle%26quot%3B%3A%20%26quot%3BChemical%20Space%20Plot%26quot%3B%2C%20%26quot%3Bxaxis_title%26quot%3B%3A%20%26quot%3BComponent%201%26quot%3B%2C%20%26quot%3Byaxis_title%26quot%3B%3A%20%26quot%3BComponent%202%26quot%3B%2C%20%26quot%3Bhover_size%26quot%3B%3A%200.4%2C%20%26quot%3Bxaxis_type%26quot%3B%3A%20%26quot%3Blinear%26quot%3B%2C%20%26quot%3Byaxis_type%26quot%3B%3A%20%26quot%3Blinear%26quot%3B%2C%20%26quot%3Bwidth%26quot%3B%3A%20800%2C%20%26quot%3Bheight%26quot%3B%3A%20600%2C%20%26quot%3Bopacity%26quot%3B%3A%201%2C%20%26quot%3BX%26quot%3B%3A%20%5B43.61760330200195%2C%20-17.472150802612305%2C%2041.86582946777344%2C%20158.97496032714844%2C%20-24.860200881958008%2C%20-2.232616424560547%2C%20-35.85402297973633%2C%20-67.47518157958984%2C%2055.304420471191406%2C%20-13.724129676818848%2C%20-3.4850451946258545%2C%20-134.3723602294922%2C%20-62.69178771972656%2C%2030.23807716369629%2C%20-5.901937961578369%2C%2010.940505981445312%2C%20-4.623172283172607%2C%20-43.74485778808594%2C%208.369648933410645%2C%2068.97262573242188%2C%20-22.280351638793945%2C%20-30.012405395507812%2C%2075.25151062011719%2C%2064.52973937988281%2C%20-3.1073720455169678%2C%20-26.3098087310791%2C%20-29.127517700195312%2C%2014.045056343078613%2C%2027.511388778686523%2C%2062.6290168762207%2C%2046.29264831542969%2C%2018.152881622314453%2C%2049.81310272216797%2C%20-81.98030853271484%2C%2041.48120880126953%2C%2089.24085998535156%2C%2027.849729537963867%2C%20-41.686649322509766%2C%2026.67981719970703%2C%20-6.256188869476318%2C%20-26.8016300201416%2C%208.647194862365723%2C%20-49.416343688964844%2C%20-42.954734802246094%2C%2048.0875129699707%2C%20-25.647356033325195%2C%2023.574270248413086%2C%20-62.410926818847656%2C%2012.529644966125488%5D%2C%20%26quot%3BY%26quot%3B%3A%20%5B-37.546878814697266%2C%20-26.210065841674805%2C%20-12.783864974975586%2C%2027.13193702697754%2C%2087.86702728271484%2C%20-81.90585327148438%2C%20-47.80723571777344%2C%2036.506431579589844%2C%20-61.465553283691406%2C%20-56.813961029052734%2C%20-39.14337921142578%2C%2076.40354919433594%2C%20-47.68071746826172%2C%206.304887294769287%2C%2061.944801330566406%2C%2044.215999603271484%2C%20-10.914501190185547%2C%2059.72188949584961%2C%20-62.289512634277344%2C%2021.70496940612793%2C%2030.97284507751465%2C%20-73.79450225830078%2C%20-1.874199628829956%2C%2044.48176956176758%2C%2031.48701286315918%2C%2050.19774627685547%2C%20149.90878295898438%2C%20-6.158529281616211%2C%2032.54773712158203%2C%20-22.430017471313477%2C%2033.658206939697266%2C%2067.7158432006836%2C%206.881969451904297%2C%201.560334324836731%2C%2059.63355255126953%2C%20-42.17106246948242%2C%20-72.33515930175781%2C%20-26.811941146850586%2C%20-24.993431091308594%2C%2010.065010070800781%2C%20-9.101613998413086%2C%20-25.244958877563477%2C%201.6200640201568604%2C%2022.73969841003418%2C%20-87.27729034423828%2C%209.062121391296387%2C%20-48.46100997924805%2C%20-18.139448165893555%2C%2014.488275527954102%5D%2C%20%26quot%3BSMILES%26quot%3B%3A%20%5B%26quot%3BCC%28C%29CC%28c1nnnn1C%29N%28Cc1ccccc1Cl%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BCc1c%28NS%28C%29%28%3DO%29%3DO%29cccc1N%28Cc1ccccc1%29Cc1ccc%28Oc2ccc%28OCC%28%3DO%29O%29cc2%29cc1%26quot%3B%2C%20%26quot%3BC%3DC%28C%29%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28SC%29cc3%29OC%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCC%28C%29N1C%28%3DO%29OC%28C%29%28C%29c2cc%28Nc3ccc%28Br%29cc3%29ccc21%26quot%3B%2C%20%26quot%3BCS%28%3DO%29%28%3DO%29Nc1ccc2c%28c1%29C%28c1ccccc1%29Oc1cccc%28OC%28F%29F%29c1-2%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29CCC%28%3DO%29O%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28NC%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCCn1nnnc1C%28C%29N%28Cc1ccccc1Cl%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BCC1%28C%29OC%28%3DO%29Nc2ccc%28-c3ccc%28F%29c%28C%23N%29c3%29cc21%26quot%3B%2C%20%26quot%3BCN1C%28%3DO%29OC%28C%29%28C%29c2cc%28Nc3cccc%28Cl%29c3Cl%29ccc21%26quot%3B%2C%20%26quot%3BCCOc1cccc2c1-c1ccc%28NS%28C%29%28%3DO%29%3DO%29cc1C%28c1ccccc1%29O2%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29CCCCCC%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCn1nnnc1CN%28Cc1ccccc1Cl%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BC%3DC1C%3DC%28C%29CC%28C%29%28C%29C1Cc1ccc%28%5BN%2B%5D%28%3DO%29%5BO-%5D%29cc1%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29C%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29C%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCC1%28C%29OC%28%3DO%29N%28Cc2ccccc2%29c2ccc%28Nc3ccc%28Br%29cc3%29cc21%26quot%3B%2C%20%26quot%3BC%5BC%40%40H%5D1C%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28-c4ccccn4%29cc3%29C%5BC%40%5D2%28C%29%5BC%40H%5D1C%28%3DO%29C1CC1%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29C%28%3DO%29NCCCCCC%28%3DO%29N%5BC%40%40H%5D%28CC%28C%29C%29C%28%3DO%29OC%28C%29%28C%29C%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCN%28C%29c1ccc%28%5BC%40H%5D2OC%5BC%40%5D3%28C%29%5BC%40%40H%5D%28O%29CC%5BC%40H%5D3%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC32%29cc1%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29CCC%28%3DO%29Nc4ccc%28C%28N%29%3DO%29c%28O%29c4%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCC1%3DCC%28C%29%28C%29Nc2ccc3c%28c21%29COc1c%28Cl%29cccc1-3%26quot%3B%2C%20%26quot%3BC%3DC1CCO%5BC%40%5D12CC%5BC%40H%5D1%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29C%29cc3%29OC%5BC%40%40%5D12C%26quot%3B%2C%20%26quot%3BCC%28c1nnnn1C%28C%29C%29N%28Cc1ccccc1Cl%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BC%3DC1C%28C%29%3DCCC%28C%29%28C%29%5BC%40%40H%5D1Cc1cc%28OC%29c%28Br%29cc1OC%28C%29%3DO%26quot%3B%2C%20%26quot%3BCC1%3DCC%28C%29%28C%29Nc2ccc3c%28c21%29%2FC%28%3DC%2FC%3DO%29Oc1ccc%28F%29cc1-3%26quot%3B%2C%20%26quot%3BC%3DC1C%3DC%28C%29CC%28C%29%28C%29C1Sc1ccc%28%5BN%2B%5D%28%3DO%29%5BO-%5D%29cc1%26quot%3B%2C%20%26quot%3BCCCCn1c2ccccc2c2ccc3c%28c21%29C%28C%29%3DCC%28C%29%28C%29N3%26quot%3B%2C%20%26quot%3BCC%28C%29CC%28c1nnnn1C%29N%28CC%28C%29C%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BC%3DC1CCCC%28C%29%28C%29C1Cc1cc%28OC%29c%28Br%29cc1O%26quot%3B%2C%20%26quot%3BCOc1ccc%28-c2ccc%28%5BC%40H%5D3C%5BC%40%5D4%28C%29%5BC%40%40H%5D%28C%28%3DO%29C5CC5%29CC%5BC%40H%5D4%5BC%40%40H%5D4CCC5%3DCC%28%3DO%29CCC5%3DC43%29cc2%29cn1%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29CCCCCC%3DO%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCCC1%28CC%29OC%28%3DO%29N%28C%29c2ccc%28Nc3cccc%28Cl%29c3%29cc21%26quot%3B%2C%20%26quot%3BCN%28C%29c1ccc%28%5BC%40H%5D2C%5BC%40%5D3%28C%29%5BC%40%40H%5D%28CC%5BC%40%5D3%28O%29CCCO%29%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC32%29cc1%26quot%3B%2C%20%26quot%3BCOc1ccccc1-c1ccc2c%28c1%29C%28C%28C%29OCCc1cccc%28Cl%29c1%29%3DCC%28C%29%28C%29N2%26quot%3B%2C%20%26quot%3BCC1%28C%29%5BC%40H%5D%28O%29CC%5BC%40%5D2%28C%29%5BC%40%40%5D3%28C%29c4%5BnH%5Dc5ccccc5c4C%5BC%40%40H%5D3CC%5BC%40%40%5D12O%26quot%3B%2C%20%26quot%3BCC%28c1cn%28C%29nn1%29N%28Cc1ccccc1Cl%29c1ccc%28C%23N%29c%28Cl%29c1%26quot%3B%2C%20%26quot%3BCC1%28C%29OC%28C%28C%29%28C%29C%29Nc2ccc%28-c3cc%28F%29cc%28C%23N%29c3%29cc21%26quot%3B%2C%20%26quot%3BCC1%3DCC%28C%29%28C%29Nc2cc3oc4ccccc4c3cc21%26quot%3B%2C%20%26quot%3BO%3D%5BN%2B%5D%28%5BO-%5D%29c1cccc%28-c2ccc3nc%28S%29n%28Cc4ccccc4%29c3c2%29c1%26quot%3B%2C%20%26quot%3BO%3DC%28c1ccc%28%5BN%2B%5D%28%3DO%29%5BO-%5D%29cc1%29N1CCCC%28c2ccc%28Cl%29c%28Cl%29c2%29%3DN1%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29C%28%3DO%29NCCCC%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BC%3DC1C%28C%29%3DCCC%28C%29%28C%29%5BC%40%40H%5D1Cc1cc%28OC%29c%28Br%29cc1OC%28C%29%3DO%26quot%3B%2C%20%26quot%3BCN%28C%29c1ccc%28%5BC%40H%5D2C%5BC%40%5D3%28C%29%5BC%40%40H%5D%28CC%5BC%40%5D3%28O%29CCCO%29%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC32%29cc1%26quot%3B%2C%20%26quot%3BCC1%3DCC%28C%29%28C%29Nc2ccc%28-c3ccsc3C%23N%29cc21%26quot%3B%2C%20%26quot%3BCC%23C%5BC%40%5D1%28O%29CC%5BC%40H%5D2%5BC%40%40H%5D3CCC4%3DCC%28%3DO%29CCC4%3DC3%5BC%40%40H%5D%28c3ccc%28N%28C%29CCCCCCCC%28%3DO%29OC%29cc3%29C%5BC%40%40%5D21C%26quot%3B%2C%20%26quot%3BCCC1%28CC%29OC%28%3DO%29N%28C%29c2ccc%28Nc3cccc%28Cl%29c3Cl%29cc21%26quot%3B%2C%20%26quot%3BCC1%28C%29C%28%3DO%29Nc2ccc%28-c3cc%28F%29cc%28Cl%29c3%29cc21%26quot%3B%2C%20%26quot%3BC%5BC%40%40H%5D1c2c%28ccc3c2%5BC%40H%5D%28c2ccc%28Cl%29cc2%29Oc2ccccc2-3%29NC%28C%29%28C%29%5BC%40H%5D1O%26quot%3B%5D%2C%20%26quot%3Bcolorscale%26quot%3B%3A%20%26quot%3BPortland%26quot%3B%7D%22%20style%3D%22width%3A%20100%25%3B%20height%3A%20100%25%3B%20display%3Ainline-block%3B%22%3E%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3C%2Fbody%3E%0A%20%20%20%20%20%20%20%20%3C%2Fmeta%3E%0A%20%20%20%20%20%20%20%20%3Cscript%3Evar%20plot%20%3D%20document.getElementById%28%22basevis-entry%22%29%3B%0Avar%20hoverInfo%20%3D%20document.getElementById%28%22basevis-entry2%22%29%3B%0A%0Avar%20data%20%3D%20JSON.parse%28document.getElementById%28%22basevis-entry%22%29.dataset.visdata%29%3B%0A%0Alet%20options%20%3D%20%7B%7D%3B%0Alet%20smilesDrawer%20%3D%20new%20SmilesDrawer.Drawer%28options%29%3B%0A%0Avar%20trace%20%3D%20%7B%0A%20%20x%3A%20data.X%2C%0A%20%20y%3A%20data.Y%2C%0A%20%20text%3A%20data.SMILES%2C%0A%20%20mode%3A%20%22markers%22%2C%0A%20%20type%3A%20%22scatter%22%2C%0A%20%20hoverinfo%3A%20%22none%22%2C%0A%20%20marker%3A%20%7B%7D%2C%0A%7D%3B%0A%0Aif%20%28%22hovertext%22%20in%20data%29%20%7B%0A%20%20trace.hovertext%20%3D%20data.hovertext%3B%0A%20%20trace.hoverinfo%20%3D%20%22text%22%3B%0A%7D%0A%0Aif%20%28%22group%22%20in%20data%29%20%7B%0A%20%20trace.transforms%20%3D%20%5B%7B%20type%3A%20%22groupby%22%2C%20groups%3A%20data.group%20%7D%5D%3B%0A%7D%0A%0Aif%20%28%22hovertemplate%22%20in%20data%29%20%7B%0A%20%20trace.hovertemplate%20%3D%20data.hovertemplate%3B%0A%7D%0A%0Aif%20%28%22color%22%20in%20data%29%20%7B%0A%20%20trace.marker.color%20%3D%20data.color%3B%0A%7D%0A%0Aif%20%28%22size%22%20in%20data%29%20%7B%0A%20%20trace.marker.size%20%3D%20data.size%3B%0A%7D%20else%20%7B%0A%20%20trace.marker.size%20%3D%2012%3B%0A%7D%0A%0A%2F%2F%20if%20%28%22outline%22%20in%20data%29%20%7B%0A%2F%2F%20%20%20trace.marker.line%20%3D%20%7B%0A%2F%2F%20%20%20%20%20color%3A%20data.outline%2C%0A%2F%2F%20%20%20%20%20width%3A%204%2C%0A%2F%2F%20%20%20%7D%3B%0A%2F%2F%20%7D%0A%0Aif%20%28%22opacity%22%20in%20data%29%20%7B%0A%20%20trace.marker.opacity%20%3D%20data.opacity%3B%0A%7D%0A%0Avar%20plot_data%20%3D%20%5Btrace%5D%3B%0A%0Avar%20layout%20%3D%20%7B%0A%20%20title%3A%20%22Plot%20Title%22%2C%0A%20%20xaxis%3A%20%7B%0A%20%20%20%20title%3A%20%22x%20Axis%22%2C%0A%20%20%7D%2C%0A%20%20yaxis%3A%20%7B%0A%20%20%20%20title%3A%20%22y%20Axis%22%2C%0A%20%20%7D%2C%0A%20%20width%3A%20data.width%2C%0A%20%20height%3A%20data.height%2C%0A%20%20autosize%3A%20true%2C%0A%7D%3B%0A%0Aif%20%28%22title%22%20in%20data%29%20%7B%0A%20%20layout.title%20%3D%20data.title%3B%0A%7D%0A%0Aif%20%28%22xaxis_title%22%20in%20data%29%20%7B%0A%20%20layout.xaxis.title%20%3D%20data.xaxis_title%3B%0A%7D%0A%0Aif%20%28%22yaxis_title%22%20in%20data%29%20%7B%0A%20%20layout.yaxis.title%20%3D%20data.yaxis_title%3B%0A%7D%0A%0Alayout.xaxis.type%20%3D%20data%5B%22xaxis_type%22%5D%3B%0Alayout.yaxis.type%20%3D%20data%5B%22yaxis_type%22%5D%3B%0A%0Aif%20%28%22ydomain%22%20in%20data%29%7B%0A%20%20layout.yaxis.domain%20%3D%20data.ydomain%3B%0A%7D%0Aif%20%28%22xdomain%22%20in%20data%29%7B%0A%20%20layout.xaxis.domain%20%3D%20data.xdomain%3B%0A%7D%0A%0Aif%20%28%22yrange%22%20in%20data%29%7B%0A%20%20layout.yaxis.range%20%3D%20data.yrange%3B%0A%7D%0Aif%20%28%22xrange%22%20in%20data%29%7B%0A%20%20layout.xaxis.range%20%3D%20data.xrange%3B%0A%7D%0A%0Aif%20%28%22axesratio%22%20in%20data%29%7B%0A%20%20layout.yaxis.scaleanchor%20%3D%20%22x%22%3B%0A%20%20layout.yaxis.scaleratio%20%3D%20data.axesratio%3B%0A%7D%0A%0Aif%20%28%22xdtick%22%20in%20data%29%7B%0A%20%20layout.xaxis.dtick%20%3D%20data.xdtick%3B%0A%7D%0A%0Aif%20%28%22ydtick%22%20in%20data%29%7B%0A%20%20layout.yaxis.dtick%20%3D%20data.ydtick%3B%0A%7D%0A%0Aif%20%28%22color%22%20in%20data%29%20%7B%0A%20%20if%20%28%22colorscale%22%20in%20data%29%20%7B%0A%20%20%20%20trace.colorscale%20%3D%20data.colorscale%3B%0A%20%20%20%20trace.marker.colorscale%20%3D%20data.colorscale%3B%0A%20%20%20%20trace.marker.colorbar%20%3D%20%7B%0A%20%20%20%20%20%20title%3A%20%22%22%2C%0A%20%20%20%20%20%20titleside%3A%20%22top%22%2C%0A%20%20%20%20%7D%3B%0A%20%20%7D%0A%7D%0A%0APlotly.newPlot%28%0A%20%20%22basevis-entry%22%2C%0A%20%20plot_data%2C%0A%20%20layout%2C%0A%20%20%28config%20%3D%20%7B%0A%20%20%20%20displaylogo%3A%20false%2C%0A%20%20%20%20modeBarButtonsToRemove%3A%20%5B%22zoom2d%22%2C%20%22pan2d%22%2C%20%22select2d%22%2C%20%22lasso2d%22%5D%2C%0A%20%20%7D%29%0A%29%3B%0A%0Aif%20%28%22layout_update%22%20in%20data%29%7B%0A%20%20Plotly.update%28%22basevis-entry%22%2C%20%7B%7D%2C%20data.layout_update%29%3B%0A%7D%0A%0Aif%20%28%22trace_update%22%20in%20data%29%7B%0A%20%20Plotly.addTraces%28%22basevis-entry%22%2C%20data.trace_update%29%3B%0A%7D%0A%0Aconst%20hoverCanvas%20%3D%20document.createElement%28%22canvas%22%29%3B%0AhoverCanvas.id%20%3D%20%22hoverCanvas%22%3B%0A%0Aconst%20hoverBackground%20%3D%20document.createElement%28%22canvas%22%29%3B%0AhoverBackground.id%20%3D%20%22hoverBackground%22%3B%0A%0Avar%20hoverSize%20%3D%20parseFloat%28data.hover_size%29%3B%0A%0Aplot.appendChild%28hoverCanvas%29%3B%0Aplot.appendChild%28hoverBackground%29%3B%0A%0Aplot%0A%20%20.on%28%22plotly_hover%22%2C%20function%20%28data%29%20%7B%0A%20%20%20%20var%20xaxis%20%3D%20data.points%5B0%5D.xaxis%2C%0A%20%20%20%20%20%20yaxis%20%3D%20data.points%5B0%5D.yaxis%3B%0A%0A%20%20%20%20data.points.map%28function%20%28d%29%20%7B%0A%20%20%20%20%20%20hoverCanvas.hidden%20%3D%20false%3B%0A%20%20%20%20%20%20hoverBackground.hidden%20%3D%20false%3B%0A%0A%20%20%20%20%20%20ctx%20%3D%20hoverCanvas.getContext%28%222d%22%29%3B%0A%0A%20%20%20%20%20%20SmilesDrawer.parse%28d.text%2C%20function%20%28smiles%29%20%7B%0A%20%20%20%20%20%20%20%20smilesDrawer.draw%28smiles%2C%20%22hoverCanvas%22%2C%20%22light%22%2C%20false%29%3B%0A%20%20%20%20%20%20%7D%29%3B%0A%0A%20%20%20%20%20%20ctx.fillStyle%20%3D%20%22black%22%3B%0A%20%20%20%20%20%20ctx.shadowColor%20%3D%20%22black%22%3B%0A%20%20%20%20%20%20ctx.shadowBlur%20%3D%2020%3B%0A%20%20%20%20%20%20ctx.lineJoin%20%3D%20%22bevel%22%3B%0A%20%20%20%20%20%20ctx.lineWidth%20%3D%2015%3B%0A%20%20%20%20%20%20ctx.strokeRect%280%2C%200%2C%20hoverCanvas.width%2C%20hoverCanvas.height%2C%20%22light%22%29%3B%0A%0A%20%20%20%20%20%20hoverBackground.width%20%3D%20hoverCanvas.width%3B%0A%20%20%20%20%20%20hoverBackground.height%20%3D%20hoverCanvas.height%3B%0A%20%20%20%20%20%20ctx%20%3D%20hoverBackground.getContext%28%222d%22%29%3B%0A%20%20%20%20%20%20ctx.fillStyle%20%3D%20%22white%22%3B%0A%20%20%20%20%20%20ctx.fillRect%280%2C%200%2C%20hoverBackground.width%2C%20hoverBackground.height%29%3B%0A%0A%20%20%20%20%20%20Plotly.update%28%0A%20%20%20%20%20%20%20%20%22basevis-entry%22%2C%0A%20%20%20%20%20%20%20%20%7B%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20margin%3A%20%7B%20t%3A%20100%2C%20b%3A%20100%2C%20l%3A%2050%2C%20r%3A%2050%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20annotations%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3A%20d.x%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3A%20d.y%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20xref%3A%20%22x%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20yref%3A%20%22y%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20text%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20showarrow%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20arrowhead%3A%207%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20ax%3A%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20ay%3A%200%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%20%20images%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3A%20%28d.x%20-%20xaxis.range%5B0%5D%29%20%2F%20%28xaxis.range%5B1%5D%20-%20xaxis.range%5B0%5D%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3A%20%28d.y%20-%20yaxis.range%5B0%5D%29%20%2F%20%28yaxis.range%5B1%5D%20-%20yaxis.range%5B0%5D%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20sizex%3A%20hoverSize%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20sizey%3A%20hoverSize%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20xref%3A%20%22paper%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20yref%3A%20%22paper%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20source%3A%20document.getElementById%28%22hoverBackground%22%29.toDataURL%28%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20xanchor%3A%20%22left%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20yanchor%3A%20%22top%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20layer%3A%20%22above%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20x%3A%20%28d.x%20-%20xaxis.range%5B0%5D%29%20%2F%20%28xaxis.range%5B1%5D%20-%20xaxis.range%5B0%5D%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20y%3A%20%28d.y%20-%20yaxis.range%5B0%5D%29%20%2F%20%28yaxis.range%5B1%5D%20-%20yaxis.range%5B0%5D%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20sizex%3A%20hoverSize%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20sizey%3A%20hoverSize%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20xref%3A%20%22paper%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20yref%3A%20%22paper%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20source%3A%20document.getElementById%28%22hoverCanvas%22%29.toDataURL%28%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20xanchor%3A%20%22left%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20yanchor%3A%20%22top%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20layer%3A%20%22above%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%29%3B%0A%20%20%20%20%20%20hoverCanvas.hidden%20%3D%20true%3B%0A%20%20%20%20%20%20hoverBackground.hidden%20%3D%20true%3B%0A%20%20%20%20%7D%29%3B%0A%20%20%7D%29%0A%20%20.on%28%22plotly_unhover%22%2C%20function%20%28data%29%20%7B%0A%20%20%20%20Plotly.update%28%22basevis-entry%22%2C%20%7B%7D%2C%20%7B%20annotations%3A%20%5B%5D%2C%20images%3A%20%5B%5D%20%7D%29%3B%0A%20%20%7D%29%3B%0A%3C%2Fscript%3E%3Cscript%3E%20window.addEventListener%28%22resize%22%2C%20function%28%29%7Bif%20%28document.getElementById%28%22basevis-entry%22%29%29%20%7BPlotly.Plots.resize%28document.getElementById%28%22basevis-entry%22%29%29%3B%7D%3B%7D%29%20%3C%2Fscript%3E'