plebeiangraphlibrary 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ # Code of Conduct for Plebeian Graph Library (PGL)
2
+
3
+ ## My Pledge
4
+ In the interest of fostering an open and welcoming environment, I, as the maintainer and primary contributor of the Plebeian Graph Library (PGL), pledge to make participation in this project a harassment-free experience for everyone, regardless of individual differences.
5
+
6
+ ## Standards
7
+
8
+ Behavior that contributes to a positive environment includes:
9
+
10
+ - Using welcoming and inclusive language
11
+ - Showing respect for differing viewpoints and experiences
12
+ - Gracefully accepting constructive criticism
13
+ - Focusing on what is best for the community
14
+ - Demonstrating empathy towards other community members
15
+
16
+ Unacceptable behavior includes:
17
+
18
+ - Use of sexualized language or imagery, unwelcome sexual attention or advances
19
+ - Trolling, insulting or derogatory comments, and personal or political attacks
20
+ - Public or private harassment
21
+ - Publishing others' private information without explicit permission
22
+ - Other conduct deemed inappropriate in a professional setting
23
+
24
+ ## Responsibilities
25
+
26
+ As the project maintainer, I am responsible for clarifying the standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior.
27
+
28
+ I have the right to remove, edit, or reject comments, commits, code, and other contributions that do not align with this Code of Conduct.
29
+
30
+ ## Scope
31
+
32
+ This Code of Conduct applies within all project spaces, as well as in public spaces when an individual is representing the project or its community. Representation of the project may include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at online or offline events.
33
+
34
+ ## Enforcement
35
+
36
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting me [at](indrajeet.haldar08@gmail.com). All complaints will be reviewed and investigated and will result in a response that is necessary and appropriate to the circumstances. Confidentiality will be maintained for the reporter of an incident.
37
+
38
+ ## Attribution
39
+
40
+ This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
@@ -0,0 +1,52 @@
1
+ # Contributing to Plebeian Graph Library (PGL)
2
+
3
+ First off, thank you for considering contributing to PGL! It's people like you that make the open source community such a great place. Here are some guidelines to help you get started.
4
+
5
+ ## How to Contribute
6
+ ### Reporting Issues
7
+
8
+ If you find a bug or have a suggestion for a new feature or enhancement, I would love to hear about it! Before you submit an issue, please check to make sure it hasn't already been reported. Here's how you can report an issue:
9
+
10
+ - Go to the Issues section of our GitHub repository.
11
+ - Click on 'New Issue'.
12
+ - Write a clear title and a detailed description. For bugs, it's helpful to include:
13
+ * Steps to reproduce
14
+ * Expected and actual behavior
15
+ * Screenshots or error messages
16
+ * Your environment (browser, OS, etc.)
17
+
18
+ ### Submitting Changes
19
+
20
+ Changes are accepted via Pull Requests (PRs) on GitHub. Here’s how you make a PR:
21
+
22
+ 1. Fork the PGL repository.
23
+ 1. Clone your fork to your local machine.
24
+ 1. Create a new branch.
25
+ 1. Make your changes. Please keep your code as clean and well-organized as possible.
26
+ 1. Test your changes.
27
+ 1. Commit your changes. Write a clear, descriptive commit message.
28
+ 1. Push your changes to your fork on GitHub.
29
+ 1. From your fork, make a Pull Request to the PGL main branch.
30
+ 1. In your pull request, describe what your changes do and mention any relevant issue numbers.
31
+
32
+ Please adhere to the coding conventions used throughout the project (indentation, accurate comments, etc.).
33
+
34
+ ### Seeking Support
35
+
36
+ If you need help or have any questions about contributing, please open an issue in the GitHub Issues. I'd be happy to help!
37
+
38
+ ### Improving Documentation
39
+
40
+ Good documentation is as important as the code itself. If you find errors, typos, or areas that need enhancement, feel free to create a pull request.
41
+
42
+ ## Code of Conduct
43
+
44
+ Please follow Code of Conduct in all your interactions with the project.
45
+
46
+ ## Pull Request Process
47
+
48
+ 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.
49
+ 1. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations, and container parameters.
50
+ 1. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme used is SemVer.
51
+ 1. The Pull Request will be merged once it is approved and passes CI checks.
52
+
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <link rel="stylesheet" href="MasterStyle.css">
9
+ <title>ZKC3d - Example</title>
10
+ </head>
11
+
12
+ <body>
13
+ <h4>A simple plot of the ZKC Dataset <a href="https://github.com/range-et/PGL/blob/main/public/1_ZKC_simple.html">Code</a></h4>
14
+ <canvas id="displayCanvas" class="displayCanvas"></canvas>
15
+ <script type="module">
16
+ // import the library
17
+ import * as PGL from "../Build/pgl_module.js";
18
+
19
+ // construct a simple ZKC graph
20
+ // this graph is pre initialized (Since it is simulated in this case)
21
+ const zkcSimulated = await PGL.SampleData.LoadZKCSimulated();
22
+ // console log this to see how this data is stored
23
+ console.log(zkcSimulated);
24
+ // also as a reference just see how this data is stored
25
+ zkcSimulated.printData();
26
+
27
+ // set the width and height
28
+ const width = 800;
29
+ const heigth = 700;
30
+
31
+ // pass in the graph and the canvas into the drawing object to draw it
32
+ // first get the canvas element
33
+ const canvas = document.getElementById("displayCanvas");
34
+ // then create a graph drawer object
35
+ // to do that first make a options object
36
+ const graphDrawerOptions = {
37
+ graph: zkcSimulated,
38
+ width: width,
39
+ height: heigth,
40
+ canvas: canvas
41
+ };
42
+ // then create the visualization window
43
+ // with those settings
44
+ const graph3d = new PGL.GraphDrawer.GraphDrawer3d(graphDrawerOptions);
45
+ // initialize this object before adding things to it
46
+ await graph3d.init();
47
+
48
+ // Create the 3d elements for the graph
49
+ // first describe a global scaling factor
50
+ const bounds = 1
51
+ // first create all the node elements
52
+ const nodeVisualElements = PGL.ThreeWrapper.DrawTHREEBoxBasedVertices(zkcSimulated, bounds, 0xffffff, 5);
53
+ // add the node elements to the scene
54
+ graph3d.addVisElement(nodeVisualElements);
55
+ // then create the edge elements
56
+ const edgeVisualElements = PGL.ThreeWrapper.DrawTHREEGraphEdgesThick(zkcSimulated, bounds, 0xffafcc, 0.02);
57
+ graph3d.addVisElement(edgeVisualElements);
58
+
59
+ // then there are two last steps for a 3d graph
60
+ // this is done so that other 3d objects can be added in later
61
+ // since the base library is three.js all standard three js things are possible
62
+ // now moving on to the two steps :
63
+ // make an animation function
64
+ function animate() {
65
+ requestAnimationFrame(animate);
66
+ graph3d.rendercall();
67
+ }
68
+
69
+ // append the graph renderer to the container
70
+ // and then drawing render calls
71
+ animate();
72
+
73
+ </script>
74
+ </body>
75
+
76
+ </html>
@@ -0,0 +1,82 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <link rel="stylesheet" href="MasterStyle.css">
9
+ <title>ZKC3d - Example</title>
10
+ </head>
11
+
12
+ <body>
13
+ <h4>A simple plot of the ZKC Dataset <a href="https://github.com/range-et/PGL/blob/main/public/2_ZKC_edge_bundling.html">Code</a></h4>
14
+ <canvas id="displayCanvas" class="displayCanvas"></canvas>
15
+ <script type="module">
16
+ // import the library
17
+ import * as PGL from "../Build/pgl_module.js";
18
+
19
+ // construct a simple ZKC graph
20
+ // this graph is pre initialized (Since it is simulated in this case)
21
+ const zkcSimulated = await PGL.SampleData.LoadZKCSimulated();
22
+ // console log this to see how this data is stored
23
+ zkcSimulated.printData();
24
+
25
+ // set the width and height
26
+ const width = 800;
27
+ const heigth = 700;
28
+
29
+ // pass in the graph and the canvas into the drawing object to draw it
30
+ // first get the canvas element
31
+ const canvas = document.getElementById("displayCanvas");
32
+ // then create a graph drawer object
33
+ // to do that first make a options object
34
+ const graphDrawerOptions = {
35
+ graph: zkcSimulated,
36
+ width: width,
37
+ height: heigth,
38
+ canvas: canvas
39
+ };
40
+ // then create the visualization window
41
+ // with those settings
42
+ const graph3d = new PGL.GraphDrawer.GraphDrawer3d(graphDrawerOptions);
43
+ // initialize this object before adding things to it
44
+ await graph3d.init();
45
+
46
+ // Create the 3d elements for the graph
47
+ // first describe a global scaling factor
48
+ const bounds = 1
49
+ // first create all the node elements
50
+ const nodeVisualElements = PGL.ThreeWrapper.DrawTHREEBoxBasedVertices(zkcSimulated, bounds, 0xffffff, 3);
51
+ // add the node elements to the scene
52
+ graph3d.addVisElement(nodeVisualElements);
53
+
54
+ const EdgeMap = zkcSimulated.get_edge_map();
55
+ const EdgeMap_copy = PGL.Drawing.DisplaceEdgeInY(EdgeMap, 20);
56
+ const newEdgeMap = await PGL.Drawing.DrawEdgeBundling(EdgeMap_copy, 50, 10);
57
+ // then create the edge elements
58
+ // these are the reuglar edges
59
+ const edgeVisualElements = PGL.ThreeWrapper.DrawThinEdgesFromEdgeMap(EdgeMap, bounds, 0x62b6cb, 0.01);
60
+ graph3d.addVisElement(edgeVisualElements);
61
+ // these are the bundled edges
62
+ const edgeVisualElements_Bundled = PGL.ThreeWrapper.DrawThickEdgesFromEdgeMap(newEdgeMap, bounds, 0x5fa8d3, 0.01);
63
+ graph3d.addVisElement(edgeVisualElements_Bundled);
64
+
65
+ // then there are two last steps for a 3d graph
66
+ // this is done so that other 3d objects can be added in later
67
+ // since the base library is three.js all standard three js things are possible
68
+ // now moving on to the two steps :
69
+ // make an animation function
70
+ function animate() {
71
+ requestAnimationFrame(animate);
72
+ graph3d.rendercall();
73
+ }
74
+
75
+ // append the graph renderer to the container
76
+ // and then drawing render calls
77
+ animate();
78
+
79
+ </script>
80
+ </body>
81
+
82
+ </html>
@@ -0,0 +1,82 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <link rel="stylesheet" href="MasterStyle.css" />
9
+ <title>Large Graph - Example</title>
10
+ </head>
11
+
12
+ <body>
13
+ <h4>A large plot using PGL - 5000 points <a href="https://github.com/range-et/PGL/blob/main/public/3_LargePointCloud.html">Code</a></h4>
14
+ <canvas id="displayCanvas" class="displayCanvas"></canvas>
15
+ <script type="module">
16
+ // import the library
17
+ import * as PGL from "../Build/pgl_module.js";
18
+
19
+ // create an Erdos Reyni graph. Lets do 1000 Points for this example
20
+ const G = await PGL.Models.GenerateErdosReyni_n_p(5000, 0.0001);
21
+ // since these graphs can be really large - they are not initialized
22
+ // so you must initialize them
23
+ G.initialize();
24
+ G.printData();
25
+
26
+ // now in this case we shall use the Kamada Kawai algorithm to initilaize all the positions
27
+ const simulatedPosMap = await PGL.Drawing.SimulateKamadaKawai(G, 2);
28
+ G.apply_position_map(simulatedPosMap);
29
+ // get the line map associated
30
+ const lmap = PGL.Drawing.DrawEdgeLinesDivisions(G, 1);
31
+ G.apply_edge_pos_maps(lmap)
32
+
33
+ // set the width and height
34
+ const width = 800;
35
+ const heigth = 700;
36
+
37
+ // pass in the graph and the canvas into the drawing object to draw it
38
+ // first get the canvas element
39
+ const canvas = document.getElementById("displayCanvas");
40
+ // then create a graph drawer object
41
+ // to do that first make a options object
42
+ const graphDrawerOptions = {
43
+ graph: G,
44
+ width: width,
45
+ height: heigth,
46
+ canvas: canvas
47
+ };
48
+
49
+ // then create the visualization window
50
+ // with those settings
51
+ const graph3d = new PGL.GraphDrawer.GraphDrawer3d(graphDrawerOptions);
52
+ // initialize this object before adding things to it
53
+ await graph3d.init();
54
+
55
+ // Create the 3d elements for the graph
56
+ // first describe a global scaling factor
57
+ const bounds = 0.1
58
+ // first create all the node elements
59
+ const nodeVisualElements = PGL.ThreeWrapper.DrawTHREEGraphVertices(G, bounds, 1, 0xffffff, 1);
60
+ // add the node elements to the scene
61
+ graph3d.addVisElement(nodeVisualElements);
62
+ // then create the edge elements
63
+ const edgeVisualElements = PGL.ThreeWrapper.DrawTHREEGraphEdgesThin(G, bounds, 0xffafcc, 0.01);
64
+ graph3d.addVisElement(edgeVisualElements);
65
+
66
+ // then there are two last steps for a 3d graph
67
+ // this is done so that other 3d objects can be added in later
68
+ // since the base library is three.js all standard three js things are possible
69
+ // now moving on to the two steps :
70
+ // make an animation function
71
+ function animate() {
72
+ requestAnimationFrame(animate);
73
+ graph3d.rendercall();
74
+ }
75
+
76
+ // append the graph renderer to the container
77
+ // and then drawing render calls
78
+ animate();
79
+ </script>
80
+ </body>
81
+
82
+ </html>
@@ -0,0 +1,106 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
+ <link rel="stylesheet" href="MasterStyle.css" />
9
+ <title>Large Graph Toggle - Example</title>
10
+ </head>
11
+
12
+ <body>
13
+ <h4>Toggle and activate some nodes <a href="https://github.com/range-et/PGL/blob/main/public/4_ToggleActivation.html">Code</a></h4>
14
+ <div id="toggle">Toggle Activation</div>
15
+ <canvas id="displayCanvas" class="displayCanvas"></canvas>
16
+ <script type="module">
17
+ // import the library
18
+ import * as PGL from "../Build/pgl_module.js";
19
+
20
+ // create an Erdos Reyni graph. Lets do 1000 Points for this example
21
+ const G = await PGL.Models.GenerateErdosReyni_n_p(1000, 0.02);
22
+ // since these graphs can be really large - they are not initialized
23
+ // so you must initialize them
24
+ G.initialize();
25
+ G.printData();
26
+
27
+ // now in this case we shall use the Kamada Kawai algorithm to initilaize all the positions
28
+ // this essentially spreads them out a little
29
+ const simulatedPosMap = await PGL.Drawing.SimulateKamadaKawai(G, 3, 500, 1, 1.5);
30
+ G.apply_position_map(simulatedPosMap);
31
+ // get the line map associated
32
+ const lmap = PGL.Drawing.DrawEdgeLinesDivisions(G, 1);
33
+ G.apply_edge_pos_maps(lmap)
34
+
35
+ // set the width and height
36
+ const width = 800;
37
+ const heigth = 700;
38
+
39
+ // pass in the graph and the canvas into the drawing object to draw it
40
+ // first get the canvas element
41
+ const canvas = document.getElementById("displayCanvas");
42
+ // then create a graph drawer object
43
+ // to do that first make a options object
44
+ const graphDrawerOptions = {
45
+ graph: G,
46
+ width: width,
47
+ height: heigth,
48
+ canvas: canvas
49
+ };
50
+
51
+ // then create the visualization window
52
+ // with those settings
53
+ const graph3d = new PGL.GraphDrawer.GraphDrawer3d(graphDrawerOptions);
54
+ // initialize this object before adding things to it
55
+ await graph3d.init();
56
+
57
+ // Create the 3d elements for the graph
58
+ // first describe a global scaling factor
59
+ const bounds = 0.1
60
+ // first create all the node elements
61
+ const nodeVisualElements = PGL.ThreeWrapper.DrawTHREEGraphVertices(G, bounds, 3, 0xffffff, 1);
62
+ // now in cases of edges - this is really what slows down the whole process
63
+ // A trick I use is to render sample about 10% of the lines and then draw them
64
+ // To do that collect all the edges (as an lmap)
65
+ const Edges = G.get_edge_map()
66
+ const EdgesToDraw = PGL.Utilities.getRandomSubset_map(Edges, 0.1);
67
+ const edgeVisualElements = PGL.ThreeWrapper.DrawThinEdgesFromEdgeMap(EdgesToDraw, bounds, 0x5fa8d3)
68
+
69
+ // add the node elements to the scene
70
+ graph3d.addVisElement(nodeVisualElements);
71
+ graph3d.addVisElement(edgeVisualElements);
72
+ // then there are two last steps for a 3d graph
73
+ // this is done so that other 3d objects can be added in later
74
+ // since the base library is three.js all standard three js things are possible
75
+ // now moving on to the two steps :
76
+ // make an animation function
77
+ function animate() {
78
+ requestAnimationFrame(animate);
79
+ graph3d.rendercall();
80
+ }
81
+
82
+ // append the graph renderer to the container
83
+ // and then drawing render calls
84
+ animate();
85
+
86
+ // lastly add a method so that everytime toggle activation is clicked the colors are randomized
87
+ function toggle_randomizer(){
88
+ // this need the child element - this probably would get fixed in a future update
89
+ PGL.ThreeWrapper.ResetVertexColors(nodeVisualElements.children[0]);
90
+ // in this case just randomly activate like 30% of the nodes
91
+ const activated = [];
92
+ for (let i = 0; i < G.nodes.size; i++) {
93
+ if(Math.random()<0.3){
94
+ activated.push(i)
95
+ }
96
+ }
97
+ // use this to change the activation thingy
98
+ PGL.ThreeWrapper.ChangeTheVertexColours(nodeVisualElements.children[0], activated, 0xff0000);
99
+ }
100
+ // assign this function to the toggle button
101
+ document.getElementById("toggle").onclick = toggle_randomizer;
102
+
103
+ </script>
104
+ </body>
105
+
106
+ </html>
@@ -0,0 +1,53 @@
1
+ :root {
2
+ --skyBlue: #bee9e8;
3
+ --teal: #62b6cb;
4
+ --navy: #1b4965;
5
+ --lavender: #cae9ff;
6
+ --electricBlue: #5fa8d3;
7
+ --charcoal: #333533;
8
+ --black: #242423;
9
+ --yellow: #f5cb5c;
10
+ --cream: #e8eddf;
11
+ --grey: #cfdbd5;
12
+ }
13
+
14
+ * {
15
+ font-family: "Courier New", Courier, monospace;
16
+ color: var(--cream);
17
+ }
18
+
19
+ body {
20
+ background-color: var(--charcoal);
21
+ text-align: center;
22
+ }
23
+
24
+ h4 {
25
+ z-index: 10;
26
+ text-align: center;
27
+ }
28
+
29
+ main{
30
+ max-width: 1000px;
31
+ padding: 10px;
32
+ margin: auto;
33
+ }
34
+
35
+ .displayCanvas {
36
+ margin-left: auto;
37
+ margin-right: auto;
38
+ outline: var(--black) 3px solid;
39
+ }
40
+
41
+ #toggle{
42
+ padding: 10;
43
+ background-color: var(--navy);
44
+ max-width: 200px;
45
+ margin: 10px;
46
+ margin-left: auto;
47
+ margin-right: auto;
48
+ cursor: pointer;
49
+ }
50
+
51
+ #toggle:hover{
52
+ background-color: var(--teal);
53
+ }
Binary file
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <link rel="stylesheet" href="MasterStyle.css" />
8
+ <title>PGL Examples</title>
9
+ </head>
10
+
11
+ <body>
12
+ <main>
13
+ <h1>Here are the examples for the Plebian Graph Library:</h1>
14
+ <hr>
15
+ <h3>Example 1:</h3>
16
+ <p>A simple example of a simple graph - this is the ZKC dataset, this come with the library to familiarize
17
+ yourself with the library</p>
18
+ <a href="1_ZKC_simple.html">Example 1</iframe></a>
19
+ <hr>
20
+ <h3>Example 2:</h3>
21
+ <p>The same example but with the edge bundling, edge displacement functionalities being demonstrated</p>
22
+ <a href="2_ZKC_edge_bundling.html">Example 2</iframe></a>
23
+ <hr>
24
+ <h3>Example 3:</h3>
25
+ <p>A key feature of the library is to render really large graphs, this is an example with 5000 points. It also has some of the other features like the kamada kawai layout feature being demonstrated here. The Erdos-Reyni model is also whats used here to generate the really large graph</p>
26
+ <a href="3_LargePointCloud.html">Example 3</iframe></a>
27
+ <hr>
28
+ <h3>Example 4:</h3>
29
+ <p>Lastly, edges really slow down the rendering time associated with the visualisation, in most cases I render in batches and draw some of the edges, this example shows the edge sampling operation. Also one of the key features of the library, dynamically changing properties of the graph, for example in this case it randomly activates some of the nodes, this feature is what helps in simulating diffusion cascades on networks</p>
30
+ <a href="4_ToggleActivation.html">Example 4</a>
31
+ </main>
32
+ </body>
33
+
34
+ </html>
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Indrajeet Haldar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.