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
E3r2MPOaK4?
literal 0
HcmV?d00001
diff --git a/src/mock_data/explainer.html b/src/mock_data/explainer.html
new file mode 100644
index 00000000..5a0c5557
--- /dev/null
+++ b/src/mock_data/explainer.html
@@ -0,0 +1,32 @@
+
+
+
+
+ Visualization omitted, Javascript library not loaded!
+ Have you run `initjs()` in this notebook? If this notebook was from another
+ user you must also trust this notebook (File -> Trust notebook). If you are viewing
+ this notebook on github the Javascript has been stripped for security. If you are using
+ JupyterLab this error is because a JupyterLab extension has not yet been written.
+
+
diff --git a/src/mock_data/scratch.png b/src/mock_data/scratch.png
new file mode 100644
index 0000000000000000000000000000000000000000..06a73538b28df2a5ad28cce7bebda162ea8b687c
GIT binary patch
literal 18776
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
D_DB1f
literal 0
HcmV?d00001
diff --git a/src/mock_data/test.txt b/src/mock_data/test.txt
new file mode 100644
index 00000000..f8deee10
--- /dev/null
+++ b/src/mock_data/test.txt
@@ -0,0 +1,1128 @@
+ "\n",
+ "\n",
+ "G \n",
+ " \n",
+ "\n",
+ "cluster_legend \n",
+ " \n",
+ "\n",
+ "\n",
+ "node2 \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "leaf3 \n",
+ " \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "node2->leaf3 \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "leaf4 \n",
+ " \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "node2->leaf4 \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "leaf5 \n",
+ " \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "\n",
+ "node1 \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "node1->node2 \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "node1->leaf5 \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "leaf6 \n",
+ " \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "\n",
+ "node0 \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "\n",
+ "node0->node1 \n",
+ " \n",
+ " \n",
+ "< \n",
+ " \n",
+ "\n",
+ "\n",
+ "node0->leaf6 \n",
+ " \n",
+ " \n",
+ "≥ \n",
+ " \n",
+ "\n",
+ "\n",
+ "\n",
+ "legend \n",
+ " \n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " "
\ No newline at end of file
diff --git a/src/mock_data/viz.svg b/src/mock_data/viz.svg
new file mode 100644
index 00000000..f906151f
--- /dev/null
+++ b/src/mock_data/viz.svg
@@ -0,0 +1 @@
+\n\nG \n \n\ncluster_legend \n \n\n\nnode2 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nleaf3 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode2->leaf3 \n \n \n \n\n\nleaf4 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode2->leaf4 \n \n \n \n\n\nleaf5 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\nnode1 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode1->node2 \n \n \n \n\n\nnode1->leaf5 \n \n \n \n\n\nleaf6 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\nnode0 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode0->node1 \n \n \n< \n \n\n\nnode0->leaf6 \n \n \n≥ \n \n\n\n\nlegend \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\ No newline at end of file
diff --git a/src/reducers/Explanation.js b/src/reducers/Explanation.js
new file mode 100644
index 00000000..e69de29b
diff --git a/src/util/dataReducers.js b/src/util/dataReducers.js
index e5bf6082..670cc282 100644
--- a/src/util/dataReducers.js
+++ b/src/util/dataReducers.js
@@ -288,8 +288,20 @@ export const parseICEResult = (iceResult) => {
let values = [];
let count = [];
for (let j = 0; j < iceResult.length; j++) {
- labels.push(iceResult[j].value);
- values.push(iceResult[j].label - 1).toFixed(2);
+ labels.push(iceResult[j].label);
+ values.push(iceResult[j].value - 1).toFixed(2);
+ count.push(iceResult[j].count | 0);
+ }
+ return ({labels: labels, values: values, count: count});
+};
+
+export const parseFairMLResult = (iceResult) => {
+ let labels = [];
+ let values = [];
+ let count = [];
+ for (let j = 0; j < iceResult.length; j++) {
+ labels.push(iceResult[j].label);
+ values.push(iceResult[j].value).toFixed(2);
count.push(iceResult[j].count | 0);
}
return ({labels: labels, values: values, count: count});
diff --git a/src/views/Explanation/Explanation.js b/src/views/Explanation/Explanation.js
index f3f79c6c..be02ac54 100644
--- a/src/views/Explanation/Explanation.js
+++ b/src/views/Explanation/Explanation.js
@@ -29,9 +29,12 @@ import {getTraceIdsFromLogs, parseLimeResult, parseICEResult} from '../../util/d
import JobModelsTable from '../../components/explanation/JobModelsTable';
import TemporalStability from '../../components/explanation/TemporalStability';
import {temporalPredictionListRequested, temporalLimePredictionListRequested} from '../../actions/PredictionAction';
-import VerticalBarChartCard from '../../components/chart/VerticalBarChartCard';
-import viz from '../../viz.svg';
-import AspectRatio from 'react-aspect-ratio';
+import ShapResult from '../../components/explanation/ShapResult';
+import ICEResult from '../../components/explanation/ICEResult';
+import SkaterResult from '../../components/explanation/SkaterResult';
+import FairMLResult from '../../components/explanation/FairMLResult';
+import {Row} from 'react-grid-system';
+import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
class Explanation extends Component {
constructor(props) {
@@ -108,7 +111,7 @@ class Explanation extends Component {
render() {
// eslint-disable-next-line max-len
- const iceResult = parseICEResult([{'value': 'First outpatient consultation', 'label': 1.25, 'count': 48}, {'value': 'aspiration cytology behalf by p', 'label': 1.6666666666666667, 'count': 3}, {'value': 'assumption laboratory', 'label': 1.6923076923076923, 'count': 130}, {'value': 'compartment for inspection', 'label': 1.6666666666666667, 'count': 12}, {'value': 'ct abdomen', 'label': 2.0, 'count': 2}, {'value': 'cytology - abdominal tumor puncture', 'label': 1.0, 'count': 1}, {'value': 'cytology - ectocervix -', 'label': 1.32, 'count': 25}, {'value': 'cytology - vagina -', 'label': 1.2222222222222223, 'count': 9}, {'value': 'day care - all spec.beh.kind.-rev.', 'label': 1.0, 'count': 2}, {'value': 'demurrage - all spec.beh.kinderg.-Reval.', 'label': 1.7142857142857142, 'count': 28}, {'value': 'e.c.g. - Electrocardiography', 'label': 1.5, 'count': 22}, {'value': 'histological examination - biopsies nno', 'label': 1.3076923076923077, 'count': 13}, {'value': 'immuno-pathology', 'label': 1.25, 'count': 4}, {'value': 'inwend.geneesk. Out-year card costs', 'label': 2.0, 'count': 1}, {'value': 'inwend.geneesk. short-out card cost', 'label': 1.375, 'count': 8}, {'value': 'mammography chest wall', 'label': 1.3333333333333333, 'count': 3}, {'value': 'outpatient follow-up consultation', 'label': 1.087719298245614, 'count': 228}, {'value': 'telephone consultation', 'label': 1.0769230769230769, 'count': 13}, {'value': 'thorax', 'label': 1.375, 'count': 8}, {'value': 'treatment time - Unit t2 - megavolt', 'label': 1.0, 'count': 1}, {'value': 'treatment time - Unit t3 - megavolt', 'label': 1.0, 'count': 1}, {'value': 'ultrasound - internal genitals', 'label': 1.6333333333333333, 'count': 30}]
+ const iceResult = parseICEResult([{'label': 'First outpatient consultation', 'value': 1.25, 'count': 48}, {'label': 'aspiration cytology behalf by p', 'value': 1.6666666666666667, 'count': 3}, {'label': 'assumption laboratory', 'value': 1.6923076923076923, 'count': 130}, {'label': 'compartment for inspection', 'value': 1.6666666666666667, 'count': 12}, {'label': 'ct abdomen', 'value': 2.0, 'count': 2}, {'label': 'cytology - abdominal tumor puncture', 'value': 1.0, 'count': 1}, {'label': 'cytology - ectocervix -', 'value': 1.32, 'count': 25}, {'label': 'cytology - vagina -', 'value': 1.2222222222222223, 'count': 9}, {'label': 'day care - all spec.beh.kind.-rev.', 'value': 1.0, 'count': 2}, {'label': 'demurrage - all spec.beh.kinderg.-Reval.', 'value': 1.7142857142857142, 'count': 28}, {'label': 'e.c.g. - Electrocardiography', 'value': 1.5, 'count': 22}, {'label': 'histological examination - biopsies nno', 'value': 1.3076923076923077, 'count': 13}, {'label': 'immuno-pathology', 'value': 1.25, 'count': 4}, {'label': 'inwend.geneesk. Out-year card costs', 'value': 2.0, 'count': 1}, {'label': 'inwend.geneesk. short-out card cost', 'value': 1.375, 'count': 8}, {'label': 'mammography chest wall', 'value': 1.3333333333333333, 'count': 3}, {'label': 'outpatient follow-up consultation', 'value': 1.087719298245614, 'count': 228}, {'label': 'telephone consultation', 'value': 1.0769230769230769, 'count': 13}, {'label': 'thorax', 'value': 1.375, 'count': 8}, {'label': 'treatment time - Unit t2 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'treatment time - Unit t3 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'ultrasound - internal genitals', 'value': 1.6333333333333333, 'count': 30}]
);
return (
@@ -127,22 +130,7 @@ class Explanation extends Component {
{/*
*/}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/src/viz.svg b/src/viz.svg
deleted file mode 100644
index 297d5336..00000000
--- a/src/viz.svg
+++ /dev/null
@@ -1,39004 +0,0 @@
-
-
-G
-
-
-cluster_legend
-
-
-
-node8
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf9
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node8->leaf9
-
-
-
-
-
-leaf20
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node8->leaf20
-
-
-
-
-
-node2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node2->node8
-
-
-
-
-
-node29
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf3
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node2->leaf3
-
-
-
-
-
-node39
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf40
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node39->leaf40
-
-
-
-
-
-leaf41
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node39->leaf41
-
-
-
-
-
-leaf42
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node38
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node38->node39
-
-
-
-
-
-node38->leaf42
-
-
-
-
-
-node36
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node36->node38
-
-
-
-
-
-leaf37
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node36->leaf37
-
-
-
-
-
-node34
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node34->node36
-
-
-
-
-
-leaf35
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node34->leaf35
-
-
-
-
-
-node32
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node32->node34
-
-
-
-
-
-leaf33
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node32->leaf33
-
-
-
-
-
-leaf43
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node31
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node31->node32
-
-
-
-
-
-node44
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node31->leaf43
-
-
-
-
-
-node48
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node51
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf49
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node48->leaf49
-
-
-
-
-
-leaf50
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node48->leaf50
-
-
-
-
-
-node52
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf53
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node52->leaf53
-
-
-
-
-
-leaf54
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node52->leaf54
-
-
-
-
-
-leaf55
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node51->node52
-
-
-
-
-
-node51->leaf55
-
-
-
-
-
-node47
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node47->node48
-
-
-
-
-
-node47->node51
-
-
-
-
-
-leaf56
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node46
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node46->node47
-
-
-
-
-
-node46->leaf56
-
-
-
-
-
-node44->node46
-
-
-
-
-
-leaf45
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node44->leaf45
-
-
-
-
-
-node30
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node30->node31
-
-
-
-
-
-node30->node44
-
-
-
-
-
-leaf57
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node29->node30
-
-
-
-
-
-node29->leaf57
-
-
-
-
-
-node1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node1->node2
-
-
-
-
-
-node1->node29
-
-
-
-
-
-node58
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node62
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node65
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf63
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node62->leaf63
-
-
-
-
-
-leaf64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node62->leaf64
-
-
-
-
-
-leaf66
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node65->leaf66
-
-
-
-
-
-leaf67
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node65->leaf67
-
-
-
-
-
-node61
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node61->node62
-
-
-
-
-
-node61->node65
-
-
-
-
-
-node68
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node71
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf72
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node71->leaf72
-
-
-
-
-
-leaf73
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node71->leaf73
-
-
-
-
-
-node69
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node69->node71
-
-
-
-
-
-node74
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf70
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node69->leaf70
-
-
-
-
-
-node80
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf81
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node80->leaf81
-
-
-
-
-
-leaf82
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node80->leaf82
-
-
-
-
-
-node78
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node78->node80
-
-
-
-
-
-node83
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf79
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node78->leaf79
-
-
-
-
-
-node85
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf86
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node85->leaf86
-
-
-
-
-
-leaf87
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node85->leaf87
-
-
-
-
-
-node83->node85
-
-
-
-
-
-leaf84
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node83->leaf84
-
-
-
-
-
-node77
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node77->node78
-
-
-
-
-
-node77->node83
-
-
-
-
-
-leaf88
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node76
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node76->node77
-
-
-
-
-
-node89
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node76->leaf88
-
-
-
-
-
-node90
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node93
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf91
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node90->leaf91
-
-
-
-
-
-leaf92
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node90->leaf92
-
-
-
-
-
-node96
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf97
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node96->leaf97
-
-
-
-
-
-leaf98
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node96->leaf98
-
-
-
-
-
-node94
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node94->node96
-
-
-
-
-
-leaf95
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node94->leaf95
-
-
-
-
-
-leaf99
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node93->node94
-
-
-
-
-
-node93->leaf99
-
-
-
-
-
-node89->node90
-
-
-
-
-
-node89->node93
-
-
-
-
-
-node75
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node75->node76
-
-
-
-
-
-node75->node89
-
-
-
-
-
-leaf100
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node74->node75
-
-
-
-
-
-node74->leaf100
-
-
-
-
-
-node68->node69
-
-
-
-
-
-node68->node74
-
-
-
-
-
-node60
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node60->node61
-
-
-
-
-
-node60->node68
-
-
-
-
-
-node101
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node107
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf108
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node107->leaf108
-
-
-
-
-
-leaf109
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node107->leaf109
-
-
-
-
-
-node105
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node105->node107
-
-
-
-
-
-node110
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf106
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node105->leaf106
-
-
-
-
-
-node112
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf113
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node112->leaf113
-
-
-
-
-
-leaf114
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node112->leaf114
-
-
-
-
-
-node110->node112
-
-
-
-
-
-leaf111
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node110->leaf111
-
-
-
-
-
-node104
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node104->node105
-
-
-
-
-
-node104->node110
-
-
-
-
-
-node115
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node119
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf120
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node119->leaf120
-
-
-
-
-
-leaf121
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node119->leaf121
-
-
-
-
-
-leaf122
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node118
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node118->node119
-
-
-
-
-
-node118->leaf122
-
-
-
-
-
-node116
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node116->node118
-
-
-
-
-
-node123
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf117
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node116->leaf117
-
-
-
-
-
-leaf124
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node123->leaf124
-
-
-
-
-
-leaf125
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node123->leaf125
-
-
-
-
-
-node115->node116
-
-
-
-
-
-node115->node123
-
-
-
-
-
-node103
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node103->node104
-
-
-
-
-
-node103->node115
-
-
-
-
-
-node126
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node130
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node133
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf131
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node130->leaf131
-
-
-
-
-
-leaf132
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node130->leaf132
-
-
-
-
-
-node134
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf135
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node134->leaf135
-
-
-
-
-
-leaf136
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node134->leaf136
-
-
-
-
-
-leaf137
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node133->node134
-
-
-
-
-
-node133->leaf137
-
-
-
-
-
-node129
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node129->node130
-
-
-
-
-
-node129->node133
-
-
-
-
-
-node127
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node127->node129
-
-
-
-
-
-node138
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf128
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node127->leaf128
-
-
-
-
-
-node139
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node142
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf140
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node139->leaf140
-
-
-
-
-
-leaf141
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node139->leaf141
-
-
-
-
-
-node145
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf146
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node145->leaf146
-
-
-
-
-
-leaf147
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node145->leaf147
-
-
-
-
-
-node143
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node143->node145
-
-
-
-
-
-leaf144
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node143->leaf144
-
-
-
-
-
-leaf148
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node142->node143
-
-
-
-
-
-node142->leaf148
-
-
-
-
-
-node138->node139
-
-
-
-
-
-node138->node142
-
-
-
-
-
-node126->node127
-
-
-
-
-
-node126->node138
-
-
-
-
-
-node102
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node102->node103
-
-
-
-
-
-node102->node126
-
-
-
-
-
-node149
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node152
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf153
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node152->leaf153
-
-
-
-
-
-leaf154
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node152->leaf154
-
-
-
-
-
-node150
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node150->node152
-
-
-
-
-
-leaf151
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node150->leaf151
-
-
-
-
-
-leaf155
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node149->node150
-
-
-
-
-
-node149->leaf155
-
-
-
-
-
-node101->node102
-
-
-
-
-
-node101->node149
-
-
-
-
-
-node59
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node59->node60
-
-
-
-
-
-node59->node101
-
-
-
-
-
-node156
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node158
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node161
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf159
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node158->leaf159
-
-
-
-
-
-leaf160
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node158->leaf160
-
-
-
-
-
-node165
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf166
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node165->leaf166
-
-
-
-
-
-leaf167
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node165->leaf167
-
-
-
-
-
-node163
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node163->node165
-
-
-
-
-
-leaf164
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node163->leaf164
-
-
-
-
-
-leaf168
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node162
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node162->node163
-
-
-
-
-
-node169
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node162->leaf168
-
-
-
-
-
-leaf170
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node169->leaf170
-
-
-
-
-
-leaf171
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node169->leaf171
-
-
-
-
-
-node161->node162
-
-
-
-
-
-node161->node169
-
-
-
-
-
-node157
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node157->node158
-
-
-
-
-
-node157->node161
-
-
-
-
-
-node172
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node176
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf177
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node176->leaf177
-
-
-
-
-
-leaf178
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node176->leaf178
-
-
-
-
-
-leaf179
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node175
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node175->node176
-
-
-
-
-
-node180
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node175->leaf179
-
-
-
-
-
-node182
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf183
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node182->leaf183
-
-
-
-
-
-leaf184
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node182->leaf184
-
-
-
-
-
-node180->node182
-
-
-
-
-
-leaf181
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node180->leaf181
-
-
-
-
-
-node174
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node174->node175
-
-
-
-
-
-node174->node180
-
-
-
-
-
-node185
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node195
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node198
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf196
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node195->leaf196
-
-
-
-
-
-leaf197
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node195->leaf197
-
-
-
-
-
-node205
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf206
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node205->leaf206
-
-
-
-
-
-leaf207
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node205->leaf207
-
-
-
-
-
-node203
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node203->node205
-
-
-
-
-
-leaf204
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node203->leaf204
-
-
-
-
-
-leaf208
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node202
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node202->node203
-
-
-
-
-
-node202->leaf208
-
-
-
-
-
-node200
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node200->node202
-
-
-
-
-
-leaf201
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node200->leaf201
-
-
-
-
-
-node198->node200
-
-
-
-
-
-leaf199
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node198->leaf199
-
-
-
-
-
-node194
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node194->node195
-
-
-
-
-
-node194->node198
-
-
-
-
-
-leaf209
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node193
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node193->node194
-
-
-
-
-
-node193->leaf209
-
-
-
-
-
-node191
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node191->node193
-
-
-
-
-
-leaf192
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node191->leaf192
-
-
-
-
-
-leaf210
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node190
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node190->node191
-
-
-
-
-
-node190->leaf210
-
-
-
-
-
-node188
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node188->node190
-
-
-
-
-
-leaf189
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node188->leaf189
-
-
-
-
-
-node186
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node186->node188
-
-
-
-
-
-node211
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf187
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node186->leaf187
-
-
-
-
-
-leaf212
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node211->leaf212
-
-
-
-
-
-leaf213
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node211->leaf213
-
-
-
-
-
-node185->node186
-
-
-
-
-
-node185->node211
-
-
-
-
-
-node173
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node173->node174
-
-
-
-
-
-node173->node185
-
-
-
-
-
-node214
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node222
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf223
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node222->leaf223
-
-
-
-
-
-leaf224
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node222->leaf224
-
-
-
-
-
-node220
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node220->node222
-
-
-
-
-
-leaf221
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node220->leaf221
-
-
-
-
-
-leaf225
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node219
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node219->node220
-
-
-
-
-
-node219->leaf225
-
-
-
-
-
-node217
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node217->node219
-
-
-
-
-
-node226
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf218
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node217->leaf218
-
-
-
-
-
-node230
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf231
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node230->leaf231
-
-
-
-
-
-leaf232
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node230->leaf232
-
-
-
-
-
-node228
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node228->node230
-
-
-
-
-
-leaf229
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node228->leaf229
-
-
-
-
-
-node226->node228
-
-
-
-
-
-leaf227
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node226->leaf227
-
-
-
-
-
-node216
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node216->node217
-
-
-
-
-
-node216->node226
-
-
-
-
-
-node233
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node238
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf239
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node238->leaf239
-
-
-
-
-
-leaf240
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node238->leaf240
-
-
-
-
-
-leaf241
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node237
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node237->node238
-
-
-
-
-
-node237->leaf241
-
-
-
-
-
-node235
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node235->node237
-
-
-
-
-
-leaf236
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node235->leaf236
-
-
-
-
-
-leaf242
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node234
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node234->node235
-
-
-
-
-
-node243
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node234->leaf242
-
-
-
-
-
-node244
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf245
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node244->leaf245
-
-
-
-
-
-leaf246
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node244->leaf246
-
-
-
-
-
-leaf247
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node243->node244
-
-
-
-
-
-node243->leaf247
-
-
-
-
-
-node233->node234
-
-
-
-
-
-node233->node243
-
-
-
-
-
-node215
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node215->node216
-
-
-
-
-
-node215->node233
-
-
-
-
-
-node248
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node250
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-leaf251
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node250->leaf251
-
-
-
-
-
-leaf252
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node250->leaf252
-
-
-
-
-
-node248->node250
-
-
-
-
-
-leaf249
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node248->leaf249
-
-
-
-
-
-node214->node215
-
-
-
-
-
-node214->node248
-
-
-
-
-
-node172->node173
-
-
-
-
-
-node172->node214
-
-
-
-
-
-node156->node157
-
-
-
-
-
-node156->node172
-
-
-
-
-
-node58->node59
-
-
-
-
-
-node58->node156
-
-
-
-
-
-node0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-node0->node1
-
-
-<
-
-
-
-node0->node58
-
-
-≥
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-legend
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From c5807775e21abc7d3463d68e1b930cefbe03e4af Mon Sep 17 00:00:00 2001
From: Musacca
Date: Thu, 19 Mar 2020 16:29:22 +0200
Subject: [PATCH 11/29] ICE and Decoded dataframe table is ready
---
src/actions/JobActions.js | 8 +
src/actions/ServerActions.js | 41 ++--
src/components/chart/VerticalBarChartCard.js | 2 +-
src/components/explanation/DecodedDFTable.js | 94 +++++++++
src/components/explanation/ICEResult.js | 52 +++--
src/components/explanation/IceResultTable.js | 81 ++++++++
src/components/explanation/JobModelsTable.js | 2 +-
src/components/explanation/ShapResult.js | 62 +++---
src/components/explanation/SkaterResult.js | 41 ++--
src/components/explanation/post_hoc.js | 8 +-
src/middlewares/ServerMiddleware.js | 10 +-
src/reducers/Explanation.js | 155 +++++++++++++++
src/reducers/Jobs.js | 35 +++-
src/reducers/index.js | 4 +-
src/util/dataReducers.js | 48 ++++-
src/views/Explanation/Explanation.js | 197 +++++++++++++------
16 files changed, 681 insertions(+), 159 deletions(-)
create mode 100644 src/components/explanation/DecodedDFTable.js
create mode 100644 src/components/explanation/IceResultTable.js
diff --git a/src/actions/JobActions.js b/src/actions/JobActions.js
index 0228fde0..2aaa0976 100644
--- a/src/actions/JobActions.js
+++ b/src/actions/JobActions.js
@@ -21,6 +21,14 @@ export const trainingSucceeded = createPayloadForwardingAction(TRAINING_SUCCEEDE
export const TRAINING_FAILED = 'TRAINING_FAILED';
export const trainingFailed = createPayloadForwardingAction(TRAINING_FAILED);
+
+export const DECODING_REQUESTED = 'DECODING_REQUESTED';
+export const decodingRequested = createPayloadForwardingAction(DECODING_REQUESTED);
+export const DECODING_RETRIEVED = 'DECODING_RETRIEVED';
+export const decodingtRetrieved = createPayloadForwardingAction(DECODING_RETRIEVED);
+export const DECODING_FAILED = 'DECODING_FAILED';
+export const decodingFailed = createPayloadForwardingAction(DECODING_FAILED);
+
export const FILTER_SPLIT_CHANGED = 'FILTER_SPLIT_CHANGED';
export const PREDICTION_SPLIT_CHANGED = 'PREDICTION_SPLIT_CHANGED';
export const REPLAY_SPLIT_CHANGED = 'REPLAY_SPLIT_CHANGED';
diff --git a/src/actions/ServerActions.js b/src/actions/ServerActions.js
index e473fec9..3e1b7fea 100644
--- a/src/actions/ServerActions.js
+++ b/src/actions/ServerActions.js
@@ -1,6 +1,6 @@
import {SERVER_URL} from '../constants';
import jsonAjax from '../JSONAjaxRequest';
-import {JOB_DELETED, jobsFailed, jobsRetrieved, trainingFailed, trainingSucceeded} from './JobActions';
+import {JOB_DELETED, jobsFailed, jobsRetrieved, trainingFailed, trainingSucceeded, decodingtRetrieved, decodingFailed} from './JobActions';
import {logInfoFailed, logInfoRetrieved, logListFailed, logListsRetrieved} from './LogActions';
import {traceListFailed, traceListRetrieved} from './TraceActions';
import {limeValueListFailed, limeValueListRetrieved} from './LimeActions';
@@ -9,6 +9,7 @@ import {modelsFailed, modelsRetrieved} from './ModelActions';
import {predictionFailed, predictionSucceeded, replayFailed, replaySucceeded} from './RuntimeActions';
import {temporalLimePredictionListRetrieved, temporalLimePredictionListFailed,
temporalPredictionListRetrieved, temporalPredictionListFailed} from './PredictionAction';
+import { shapValueListRetrieved, shapValueListFailed, skaterValueListRetrieved, skaterValueListFailed, iceValueListRequested, iceValueListFailed, iceValueListRetrieved } from './ExplanationActions';
export const getJobs = () => (dispatch) => {
jsonAjax(
@@ -54,6 +55,18 @@ export const postTraining = (payload) => (dispatch) => {
);
};
+export const getDecodingDf = ({id}) => (dispatch) => {
+ jsonAjax(
+ SERVER_URL + `/jobs/decode/${id}`,
+ 'GET',
+ null,
+ (resultList) => {
+ dispatch(decodingtRetrieved(resultList));
+ },
+ ({error}) => dispatch(decodingFailed(error))
+ );
+};
+
export const getSplits = () => (dispatch) => {
jsonAjax(
SERVER_URL + '/splits/',
@@ -146,34 +159,34 @@ export const getShapValues = ({jobId, traceId}) => (dispatch) => {
SERVER_URL + `/explanation/shap/${jobId}&${traceId}/`,
'GET',
null,
- (limeList) => {
- dispatch(limeValueListRetrieved(limeList));
+ (shapResult) => {
+ dispatch(shapValueListRetrieved(shapResult));
},
- ({error}) => dispatch(limeValueListFailed(error))
+ ({error}) => dispatch(shapValueListFailed(error))
);
};
-export const getSkaterValues = ({jobId, traceId}) => (dispatch) => {
+export const getSkaterValues = ({jobId}) => (dispatch) => {
jsonAjax(
- SERVER_URL + `/explanation/skater/${jobId}&${traceId}/`,
+ SERVER_URL + `/explanation/skater/${jobId}/`,
'GET',
null,
- (limeList) => {
- dispatch(limeValueListRetrieved(limeList));
+ (skaterResult) => {
+ dispatch(skaterValueListRetrieved(skaterResult));
},
- ({error}) => dispatch(limeValueListFailed(error))
+ ({error}) => dispatch(skaterValueListFailed(error))
);
};
-export const getIceValues = ({jobId, traceId}) => (dispatch) => {
+export const getIceValues = ({jobId, attribute}) => (dispatch) => {
jsonAjax(
- SERVER_URL + `/explanation/ice/${jobId}&${traceId}/`,
+ SERVER_URL + `/explanation/ice/${jobId}&${attribute}/`,
'GET',
null,
- (limeList) => {
- dispatch(limeValueListRetrieved(limeList));
+ (iceList) => {
+ dispatch(iceValueListRetrieved(iceList));
},
- ({error}) => dispatch(limeValueListFailed(error))
+ ({error}) => dispatch(iceValueListFailed(error))
);
};
diff --git a/src/components/chart/VerticalBarChartCard.js b/src/components/chart/VerticalBarChartCard.js
index 8fed5d7a..ce28b321 100644
--- a/src/components/chart/VerticalBarChartCard.js
+++ b/src/components/chart/VerticalBarChartCard.js
@@ -21,7 +21,7 @@ class HorizontalBarChartCard extends React.Component {
bar: {
horizontal: false,
distributed: false,
- columnWidth: '30%',
+ columnWidth: '10%',
barHeight: '80%'
}
},
diff --git a/src/components/explanation/DecodedDFTable.js b/src/components/explanation/DecodedDFTable.js
new file mode 100644
index 00000000..cfd8bd7d
--- /dev/null
+++ b/src/components/explanation/DecodedDFTable.js
@@ -0,0 +1,94 @@
+import React, {PureComponent} from 'react';
+import {DataTable, TableBody, TableColumn, TableHeader, TablePagination, TableRow} from 'react-md/lib/DataTables/index';
+import PropTypes from 'prop-types';
+import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+
+class IceResultTable extends PureComponent {
+ constructor(props) {
+ super(props);
+ this.state = {
+ values: this.props.values.slice(0, 10),
+ };
+ }
+
+ handlePagination(start, rowsPerPage) {
+ this.setState({
+ values: this.props.values.slice(start, start + rowsPerPage)
+ });
+ }
+
+ componentDidUpdate(prevProps) {
+ if (prevProps.values.length !== this.props.values.length) {
+ this.setState({values: this.props.values.slice(0, 10)});
+ }
+ }
+
+ getHeaderColumns(headers) {
+ return headers.map(header => {
+ let grow = false;
+ if (header === 'Configuration') {
+ grow = true;
+ }
+ return (
+
+ {' '}
+ {header}
+
+ );
+ });
+ }
+
+ getDecodedDFValuesTable(values) {
+ return (
+
+
+
+ {this.props.jobId != '' ?
+ 'Decoded dataframe result with job id: '+ this.props.jobId: ''}
+
+ {!this.props.isDecodedValueLoaded ? : null}
+
+
+
+
+ {this.getHeaderColumns(this.props.headers)}
+
+
+
+ {values.map(
+ (value, index) => (
+
+ {value.map(
+ (v) => (
+ {v}
+ )
+ )}
+
+ )
+ )}
+
+
+
+
+
+ );
+ }
+ render() {
+ return
+ {this.getDecodedDFValuesTable(this.state.values)}
+
;
+ }
+}
+
+IceResultTable.propTypes = {
+ values: PropTypes.array.isRequired,
+ headers: PropTypes.array.isRequired,
+ isDecodedValueLoaded: PropTypes.bool.isRequired,
+ jobId: PropTypes.any.isRequired,
+};
+
+export default IceResultTable;
diff --git a/src/components/explanation/ICEResult.js b/src/components/explanation/ICEResult.js
index e2b581b0..17c3cb75 100644
--- a/src/components/explanation/ICEResult.js
+++ b/src/components/explanation/ICEResult.js
@@ -3,6 +3,8 @@ import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
import PropTypes from 'prop-types';
import VerticalBarChartCard from '../../components/chart/VerticalBarChartCard';
import SelectField from 'react-md/lib/SelectFields';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+import IceResultTable from './IceResultTable';
class ShapResult extends PureComponent {
constructor(props) {
@@ -10,37 +12,57 @@ class ShapResult extends PureComponent {
this.state = {
};
}
+ onChangeFeature(value, _) {
+ this.props.onChangeFeature(value);
+ }
getTraceSelector() {
return (
);
}
render() {
return (
-
-
ICE result
-
-
Select the prefix
- {this.getTraceSelector()}
-
+
+
+
+ Select the feature
+ {this.getTraceSelector()}
+
+ {!this.props.isIceValuesLoaded ? : null}
+
+ {this.props.iceValueList.count.length != 0 ?
+ this.props.iceValueList.count.length < 70 ?
+ labels = {this.props.iceValueList.values}
+ count = {this.props.iceValueList.count}
+ data = {this.props.iceValueList.labels}>
-
+ :
+
+
+ : null
+ }
+
+
);
}
}
ShapResult.propTypes = {
- iceResult: PropTypes.any,
- jobId: PropTypes.any,
+ iceValueList: PropTypes.any,
+ jobId: PropTypes.any,
+ isIceValuesLoaded: PropTypes.bool,
+ selectedAttribute: PropTypes.any,
+ attributes: PropTypes.any,
+ onChangeFeature: PropTypes.func,
+ originalList: PropTypes.any
};
export default ShapResult;
diff --git a/src/components/explanation/IceResultTable.js b/src/components/explanation/IceResultTable.js
new file mode 100644
index 00000000..ef82ffe1
--- /dev/null
+++ b/src/components/explanation/IceResultTable.js
@@ -0,0 +1,81 @@
+import React, {PureComponent} from 'react';
+import {DataTable, TableBody, TableColumn, TableHeader, TablePagination, TableRow} from 'react-md/lib/DataTables/index';
+import PropTypes from 'prop-types';
+import {getIceResultListTable} from '../../util/dataReducers';
+
+class IceResultTable extends PureComponent {
+ constructor(props) {
+ super(props);
+ this.state = {
+ features: this.props.iceResultList.slice(0, 10),
+ };
+ }
+
+ handlePagination(start, rowsPerPage) {
+ this.setState({
+ features: this.props.iceResultList.slice(start, start + rowsPerPage)
+ });
+ }
+
+ componentDidUpdate(prevProps) {
+ if (prevProps.iceResultList.length !== this.props.iceResultList.length) {
+ this.setState({features: this.props.iceResultList.slice(0, 10)});
+ }
+ }
+
+ getHeaderColumns(headers) {
+ return headers.map(header => {
+ let grow = false;
+ if (header === 'Configuration') {
+ grow = true;
+ }
+ return (
+
+ {' '}
+ {header}
+
+ );
+ });
+ }
+
+ getPrefixValuesTable(values) {
+ return (
+
+
+
+ {this.getHeaderColumns(['label', 'value', 'count'])}
+
+
+
+ {values.map(
+ (value, index) => (
+
+ {value.map(
+ (v) => (
+ {v}
+ )
+ )}
+
+ )
+ )}
+
+
+
+ );
+ }
+ render() {
+ return
+ {this.getPrefixValuesTable(getIceResultListTable(this.state.features))}
+
;
+ }
+}
+
+IceResultTable.propTypes = {
+ iceResultList: PropTypes.array.isRequired,
+};
+
+export default IceResultTable;
diff --git a/src/components/explanation/JobModelsTable.js b/src/components/explanation/JobModelsTable.js
index aca356d9..b2ce77f1 100644
--- a/src/components/explanation/JobModelsTable.js
+++ b/src/components/explanation/JobModelsTable.js
@@ -23,7 +23,7 @@ const JobModelsTable = (props) => {
- );
- }
render() {
return (
-
-
-
-
-
-
-
-
-
- Select the trace composition
- {this.getTraceSelector()}
-
-
-
-
-
+
+
+
+ { this.props.traceId != '' && this.props.jobId != '' ?
+ 'SHAP result with trace id: '+ this.props.traceId
+ +' and job id: '+ this.props.jobId: ''}
+
+
+ {!this.props.isShapValuesLoaded ? : null}
+ {JSON.stringify(this.props.shapValueList) !='{}'?
+ : null}
+
+
);
}
}
ShapResult.propTypes = {
- shapGeneralResult: PropTypes.any.isRequired,
- shapSpecificTraceIdResult: PropTypes.any.isRequired,
- shapSummaryPlotResult: PropTypes.any.isRequired,
- traceId: PropTypes.any,
- jobId: PropTypes.any,
- traceIdList: PropTypes.any.isRequired,
- shapSelectedTrace: PropTypes.string.isRequired
+ shapValueList: PropTypes.any.isRequired,
+ traceId: PropTypes.any,
+ jobId: PropTypes.any,
+ shapSelectedTrace: PropTypes.string.isRequired,
+ isShapValuesLoaded: PropTypes.bool.isRequired,
};
export default ShapResult;
diff --git a/src/components/explanation/SkaterResult.js b/src/components/explanation/SkaterResult.js
index af84b411..4bf28559 100644
--- a/src/components/explanation/SkaterResult.js
+++ b/src/components/explanation/SkaterResult.js
@@ -3,6 +3,7 @@ import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
import PropTypes from 'prop-types';
import viz from '../../mock_data/viz.svg';
import InlineSVG from 'svg-inline-react';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
class ShapResult extends PureComponent {
constructor(props) {
@@ -12,31 +13,35 @@ class ShapResult extends PureComponent {
}
render() {
- const svgSource = `\n\nG \n \n\ncluster_legend \n \n\n\nnode2 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nleaf3 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode2->leaf3 \n \n \n \n\n\nleaf4 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode2->leaf4 \n \n \n \n\n\nleaf5 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\nnode1 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode1->node2 \n \n \n \n\n\nnode1->leaf5 \n \n \n \n\n\nleaf6 \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\n\nnode0 \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n\nnode0->node1 \n \n \n< \n \n\n\nnode0->leaf6 \n \n \n≥ \n \n\n\n\nlegend \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n `;
-
return (
-
-
-
Skater result
-
this.showSvgNewPage(svgSource)} style={{display: 'flex', justifyContent:'center', alignItems:'center'}} href preserveAspectRatio="xMidYMid slice" className="md-cell md-cell--12" alt="svg" src={svgSource} />
-
+
+
+
+
+ {!this.props.isSkaterValuesLoaded ?
+ : null}
+
+ {JSON.stringify(this.props.skaterValueList) !='{}'?
+ this.showSvgNewPage(this.props.skaterValueList)}
+ style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}
+ href preserveAspectRatio="xMidYMid slice"
+ alt="svg" src={this.props.skaterValueList}/>
+ : null}
+
+
-
+
);
}
-
- showSvgNewPage(svg){
- let v = window.open("")
- v.document.write(svg)
+ showSvgNewPage(svg) {
+ let v = window.open('');
+ v.document.write(svg);
}
}
ShapResult.propTypes = {
- shapGeneralResult: PropTypes.any.isRequired,
- shapSpecificTraceIdResult: PropTypes.any.isRequired,
- shapSummaryPlotResult: PropTypes.any.isRequired,
+ skaterValueList: PropTypes.any.isRequired,
traceId: PropTypes.any,
- jobId: PropTypes.any,
- traceIdList: PropTypes.any.isRequired,
- shapSelectedTrace: PropTypes.string.isRequired
+ isSkaterValuesLoaded: PropTypes.bool.isRequired
};
export default ShapResult;
diff --git a/src/components/explanation/post_hoc.js b/src/components/explanation/post_hoc.js
index 586f1634..485d3a87 100644
--- a/src/components/explanation/post_hoc.js
+++ b/src/components/explanation/post_hoc.js
@@ -15,8 +15,9 @@ const PostHocExplanation = (props) => {
return
- {!props.isLimeValuesLoaded ? 'Lime result with trace id: '+ props.traceId +' is loading. Please wait...' :
- 'Lime result with trace id: '+ props.traceId}
+ {props.traceId != '' && props.jobId != '' ?
+ 'Lime result with trace id: '+ props.traceId
+ +' and job id: '+ props.jobId: ''}
{!props.isLimeValuesLoaded ? : null}
@@ -32,7 +33,8 @@ PostHocExplanation.propTypes = {
jobs: PropTypes.arrayOf(jobPropType).isRequired,
limeValueList: PropTypes.any.isRequired,
isLimeValuesLoaded: PropTypes.bool.isRequired,
- traceId: PropTypes.any
+ traceId: PropTypes.any,
+ jobId: PropTypes.any
};
export default PostHocExplanation;
diff --git a/src/middlewares/ServerMiddleware.js b/src/middlewares/ServerMiddleware.js
index 8de4272c..3c27e885 100644
--- a/src/middlewares/ServerMiddleware.js
+++ b/src/middlewares/ServerMiddleware.js
@@ -15,12 +15,14 @@ import {
getPredictionTemporalStabilityValues,
getShapValues,
getIceValues,
- getSkaterValues
+ getSkaterValues,
+ getDecodingDf
} from '../actions/ServerActions';
-import {JOB_DELETE_REQUESTED, JOBS_REQUESTED, TRAINING_SUBMITTED} from '../actions/JobActions';
+import {JOB_DELETE_REQUESTED, JOBS_REQUESTED, TRAINING_SUBMITTED, DECODING_REQUESTED} from '../actions/JobActions';
import {TRACE_LIST_REQUESTED} from '../actions/TraceActions';
import {LOG_INFO_REQUESTED, LOG_LIST_REQUESTED} from '../actions/LogActions';
-import {LIME_VALUE_LIST_REQUESTED, SHAP_VALUE_LIST_REQUESTED, ICE_VALUE_LIST_REQUESTED, SKATER_VALUE_LIST_REQUESTED} from '../actions/ExplanationActions';
+import {LIME_VALUE_LIST_REQUESTED, SHAP_VALUE_LIST_REQUESTED,
+ ICE_VALUE_LIST_REQUESTED, SKATER_VALUE_LIST_REQUESTED} from '../actions/ExplanationActions';
import {SPLIT_SUBMITTED, SPLITS_REQUESTED} from '../actions/SplitActions';
import {MODELS_REQUESTED} from '../actions/ModelActions';
import {PREDICTION_SUBMITTED, REPLAY_SUBMITTED} from '../actions/RuntimeActions';
@@ -45,7 +47,7 @@ const ACTION_TYPE_TO_SERVER_ACTION = {
[SKATER_VALUE_LIST_REQUESTED]: getSkaterValues,
[TEMPORAL_STABILITY_LIME_PREDICTION_LIST_REQUESTED]: getLimeTemporalStabilityValues,
[TEMPORAL_STABILITY_PREDICTION_LIST_REQUESTED]: getPredictionTemporalStabilityValues,
-
+ [DECODING_REQUESTED]: getDecodingDf,
};
const serverMiddleware = (store) => (next) => (action) => {
diff --git a/src/reducers/Explanation.js b/src/reducers/Explanation.js
index e69de29b..6c1d3270 100644
--- a/src/reducers/Explanation.js
+++ b/src/reducers/Explanation.js
@@ -0,0 +1,155 @@
+import {
+ LIME_VALUE_LIST_FAILED,
+ LIME_VALUE_LIST_REQUESTED,
+ LIME_VALUE_LIST_RETRIEVED,
+
+ SHAP_VALUE_LIST_FAILED,
+ SHAP_VALUE_LIST_REQUESTED,
+ SHAP_VALUE_LIST_RETRIEVED,
+
+ SKATER_VALUE_LIST_FAILED,
+ SKATER_VALUE_LIST_REQUESTED,
+ SKATER_VALUE_LIST_RETRIEVED,
+
+ ICE_VALUE_LIST_FAILED,
+ ICE_VALUE_LIST_REQUESTED,
+ ICE_VALUE_LIST_RETRIEVED
+} from '../actions/ExplanationActions';
+
+const initialState = {
+ fetchState: {inFlight: false},
+ limeValueList: {},
+ shapValueList: {},
+ iceValueList: {},
+ skaterValueList: {},
+ isLimeValuesLoaded: true,
+ isShapValuesLoaded: true,
+ isSkaterValuesLoaded: true,
+ isIceValuesLoaded: true,
+};
+
+const explanation = (state = initialState, action) => {
+ switch (action.type) {
+ case LIME_VALUE_LIST_REQUESTED: {
+ return {
+ ...state,
+ fetchState: {inFlight: true},
+ isLimeValuesLoaded: false,
+
+ };
+ }
+
+ case LIME_VALUE_LIST_RETRIEVED: {
+ const limeValueList = action.payload;
+ return {
+ ...state,
+ fetchState: {inFlight: false},
+ limeValueList,
+ isLimeValuesLoaded: true
+ };
+ }
+
+ case LIME_VALUE_LIST_FAILED: {
+ const limeValueList = initialState.limeValueList;
+ return {
+ ...state,
+ fetchState: {inFlight: false, error: action.payload},
+ limeValueList,
+ isLimeValuesLoaded: true
+ };
+ }
+
+ case SHAP_VALUE_LIST_REQUESTED: {
+ return {
+ ...state,
+ fetchState: {inFlight: true},
+ isShapValuesLoaded: false,
+
+ };
+ }
+
+ case SHAP_VALUE_LIST_RETRIEVED: {
+ const shapValueList = action.payload[1];
+ return {
+ ...state,
+ fetchState: {inFlight: false},
+ shapValueList,
+ isShapValuesLoaded: true
+ };
+ }
+
+ case SHAP_VALUE_LIST_FAILED: {
+ const shapValueList = initialState.shapValueList;
+ return {
+ ...state,
+ fetchState: {inFlight: false, error: action.payload},
+ shapValueList,
+ isShapValuesLoaded: true
+ };
+ }
+
+ case SKATER_VALUE_LIST_REQUESTED: {
+ return {
+ ...state,
+ fetchState: {inFlight: true},
+ isSkaterValuesLoaded: false,
+
+ };
+ }
+
+ case SKATER_VALUE_LIST_RETRIEVED: {
+ const skaterValueList = action.payload[1];
+ return {
+ ...state,
+ fetchState: {inFlight: false},
+ skaterValueList,
+ isSkaterValuesLoaded: true
+ };
+ }
+
+ case SKATER_VALUE_LIST_FAILED: {
+ const skaterValueList = initialState.limeValueList;
+ return {
+ ...state,
+ fetchState: {inFlight: false, error: action.payload},
+ skaterValueList,
+ isSkaterValuesLoaded: true
+ };
+ }
+
+ case ICE_VALUE_LIST_REQUESTED: {
+ return {
+ ...state,
+ fetchState: {inFlight: true},
+ isIceValuesLoaded: false,
+
+ };
+ }
+
+ case ICE_VALUE_LIST_RETRIEVED: {
+ const iceValueList = action.payload[1];
+ return {
+ ...state,
+ fetchState: {inFlight: false},
+ iceValueList,
+ isIceValuesLoaded: true
+ };
+ }
+
+ case ICE_VALUE_LIST_FAILED: {
+ const iceValueList = initialState.limeValueList;
+ return {
+ ...state,
+ fetchState: {inFlight: false, error: action.payload},
+ iceValueList,
+ isIceValuesLoaded: true
+ };
+ }
+
+ default:
+ return state;
+ }
+ }
+;
+
+export default explanation;
diff --git a/src/reducers/Jobs.js b/src/reducers/Jobs.js
index 0e6650b6..cc8102bc 100644
--- a/src/reducers/Jobs.js
+++ b/src/reducers/Jobs.js
@@ -15,7 +15,10 @@ import {
JOBS_FAILED,
JOBS_REQUESTED,
JOBS_RETRIEVED,
- TRACE_CHANGED
+ TRACE_CHANGED,
+ DECODING_REQUESTED,
+ DECODING_FAILED,
+ DECODING_RETRIEVED
} from '../actions/JobActions';
import {JOB_RUN_CHANGED} from '../actions/RuntimeActions';
import {
@@ -78,7 +81,11 @@ const initialState = {
attributeNames: [],
splitId: -100,
filteredJobs: [],
- selectedTrace: ''
+ selectedTrace: '',
+ jobsById: {},
+ decodedDf: {},
+ isDecodingLoaded: true
+
};
const initialFilters = {
@@ -318,6 +325,30 @@ const jobs = (state = {...initialState, ...initialFilters}, action) => {
};
}
+ case DECODING_REQUESTED: {
+ return {
+ ...state,
+ isDecodingLoaded: false,
+ decodedDf: {}
+ };
+ }
+
+ case DECODING_FAILED: {
+ return {
+ ...state,
+ isDecodingLoaded: true,
+ decodedDf: initialState.decodedDf
+ };
+ }
+ case DECODING_RETRIEVED: {
+ const resultList = action.payload;
+ return {
+ ...state,
+ isDecodingLoaded: true,
+ decodedDf: resultList
+ };
+ }
+
default:
return state;
}
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 483d7c91..7fd44d6f 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -6,7 +6,7 @@ import training from './Training';
import splits from './Splits';
import models from './Models';
import traces from './Traces';
-import lime from './Lime';
+import explanation from './Explanation';
import predictions from './Predictions';
@@ -18,6 +18,6 @@ export default combineReducers({
training,
splits,
traces,
- lime,
+ explanation,
predictions
});
diff --git a/src/util/dataReducers.js b/src/util/dataReducers.js
index 670cc282..ae8d9060 100644
--- a/src/util/dataReducers.js
+++ b/src/util/dataReducers.js
@@ -275,7 +275,7 @@ export const parseLimeResult = (limeValueList) => {
if (keys != null) {
for (let j = 0; j < keys.length; j++) {
if (limeValueList[keys[j]].length == 2) {
- labels.push(limeValueList[keys[j]][0]);
+ labels.push(keys[j] +' = '+ limeValueList[keys[j]][0]);
values.push(limeValueList[keys[j]][1]);
}
}
@@ -289,7 +289,9 @@ export const parseICEResult = (iceResult) => {
let count = [];
for (let j = 0; j < iceResult.length; j++) {
labels.push(iceResult[j].label);
- values.push(iceResult[j].value - 1).toFixed(2);
+ if (isNaN(parseFloat(iceResult[j].value))) values.push(iceResult[j].value);
+ else values.push(iceResult[j].value).toFixed(2);
+
count.push(iceResult[j].count | 0);
}
return ({labels: labels, values: values, count: count});
@@ -316,10 +318,11 @@ export const parseTemporalStabilityLimeResultList = (predictionList, traceId) =>
data.pop();
for (let j = 0; j < prefixs.length; j++) {
const prefixValues = traceAttr[prefixs[j]];
- for (let k = 1; k <= Object.keys(prefixValues).length; k++) {
- const value = prefixValues['prefix_'+k];
- if (j == 0) data.push({name: 'prefix_'+k, data: []});
- data[k-1]['data'].push(value['importance']);
+ for (let k = 0; k <= Object.keys(prefixValues).length-1; k++) {
+ const value = prefixValues[Object.keys(prefixValues)[k]];
+ console.log(Object.keys(prefixValues)[k])
+ if (j == 0) data.push({name: (Object.keys(prefixValues)[k].concat(' = ', value['value'])), data: []});
+ data[k]['data'].push(value['importance']);
}
}
}
@@ -395,3 +398,36 @@ const getTraceEventsHeader = (traceList) =>{
}
return traceEventsHeaders;
};
+
+
+export const getIceResultListTable = (iceResultList) =>{
+ let i=0;
+ let result = [];
+ for (i = 0; i{
+ let i=0; let j=0;
+ let result = [];
+ let keys = Object.keys(dfResult);
+ if (keys.length>0) {
+ for (j = 0; j < dfResult[keys[0]].length; j++) {
+ let arr = [];
+ arr.push(j+1);
+
+ for (i = 0; i job.id==id)[0];
+ }
render() {
// eslint-disable-next-line max-len
- const iceResult = parseICEResult([{'label': 'First outpatient consultation', 'value': 1.25, 'count': 48}, {'label': 'aspiration cytology behalf by p', 'value': 1.6666666666666667, 'count': 3}, {'label': 'assumption laboratory', 'value': 1.6923076923076923, 'count': 130}, {'label': 'compartment for inspection', 'value': 1.6666666666666667, 'count': 12}, {'label': 'ct abdomen', 'value': 2.0, 'count': 2}, {'label': 'cytology - abdominal tumor puncture', 'value': 1.0, 'count': 1}, {'label': 'cytology - ectocervix -', 'value': 1.32, 'count': 25}, {'label': 'cytology - vagina -', 'value': 1.2222222222222223, 'count': 9}, {'label': 'day care - all spec.beh.kind.-rev.', 'value': 1.0, 'count': 2}, {'label': 'demurrage - all spec.beh.kinderg.-Reval.', 'value': 1.7142857142857142, 'count': 28}, {'label': 'e.c.g. - Electrocardiography', 'value': 1.5, 'count': 22}, {'label': 'histological examination - biopsies nno', 'value': 1.3076923076923077, 'count': 13}, {'label': 'immuno-pathology', 'value': 1.25, 'count': 4}, {'label': 'inwend.geneesk. Out-year card costs', 'value': 2.0, 'count': 1}, {'label': 'inwend.geneesk. short-out card cost', 'value': 1.375, 'count': 8}, {'label': 'mammography chest wall', 'value': 1.3333333333333333, 'count': 3}, {'label': 'outpatient follow-up consultation', 'value': 1.087719298245614, 'count': 228}, {'label': 'telephone consultation', 'value': 1.0769230769230769, 'count': 13}, {'label': 'thorax', 'value': 1.375, 'count': 8}, {'label': 'treatment time - Unit t2 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'treatment time - Unit t3 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'ultrasound - internal genitals', 'value': 1.6333333333333333, 'count': 30}]
- );
+ // const iceResult = parseICEResult([{'label': 'First outpatient consultation', 'value': 1.25, 'count': 48}, {'label': 'aspiration cytology behalf by p', 'value': 1.6666666666666667, 'count': 3}, {'label': 'assumption laboratory', 'value': 1.6923076923076923, 'count': 130}, {'label': 'compartment for inspection', 'value': 1.6666666666666667, 'count': 12}, {'label': 'ct abdomen', 'value': 2.0, 'count': 2}, {'label': 'cytology - abdominal tumor puncture', 'value': 1.0, 'count': 1}, {'label': 'cytology - ectocervix -', 'value': 1.32, 'count': 25}, {'label': 'cytology - vagina -', 'value': 1.2222222222222223, 'count': 9}, {'label': 'day care - all spec.beh.kind.-rev.', 'value': 1.0, 'count': 2}, {'label': 'demurrage - all spec.beh.kinderg.-Reval.', 'value': 1.7142857142857142, 'count': 28}, {'label': 'e.c.g. - Electrocardiography', 'value': 1.5, 'count': 22}, {'label': 'histological examination - biopsies nno', 'value': 1.3076923076923077, 'count': 13}, {'label': 'immuno-pathology', 'value': 1.25, 'count': 4}, {'label': 'inwend.geneesk. Out-year card costs', 'value': 2.0, 'count': 1}, {'label': 'inwend.geneesk. short-out card cost', 'value': 1.375, 'count': 8}, {'label': 'mammography chest wall', 'value': 1.3333333333333333, 'count': 3}, {'label': 'outpatient follow-up consultation', 'value': 1.087719298245614, 'count': 228}, {'label': 'telephone consultation', 'value': 1.0769230769230769, 'count': 13}, {'label': 'thorax', 'value': 1.375, 'count': 8}, {'label': 'treatment time - Unit t2 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'treatment time - Unit t3 - megavolt', 'value': 1.0, 'count': 1}, {'label': 'ultrasound - internal genitals', 'value': 1.6333333333333333, 'count': 30}]
+ // );
+ let decodedDfTableResult = getDecodedDFTable(this.props.decodedDf);
return (
@@ -130,7 +153,30 @@ class Explanation extends Component {
{/*
*/}
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+ jobs = {this.props.jobs}
+ iceValueList = {parseICEResult(this.props.iceValueList)}
+ originalList = {this.props.iceValueList}
+ isIceValuesLoaded = {this.props.isIceValuesLoaded}
+ selectedAttribute={this.props.selectedAttribute}
+ attributes ={this.filterJobsById(this.props.jobId) != undefined ?
+ this.filterJobsById(this.props.jobId).config.encoding.features: []}
+ onChangeFeature = {this.onChangeFeature.bind(this)}
+ >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
);
}
@@ -193,6 +240,7 @@ Explanation.propTypes = {
onRequestLogList: PropTypes.func.isRequired,
onRequestSplitList: PropTypes.func.isRequired,
onRequestJobs: PropTypes.func.isRequired,
+ onRequestDecoding: PropTypes.func.isRequired,
onSplitChange: PropTypes.func.isRequired,
onMethodChange: PropTypes.func.isRequired,
onTraceChange: PropTypes.func.isRequired,
@@ -200,8 +248,17 @@ Explanation.propTypes = {
onRequestTraces: PropTypes.func.isRequired,
onJobChange: PropTypes.func.isRequired,
onRequestLimeValues: PropTypes.func.isRequired,
+ onRequestSkaterValues: PropTypes.func.isRequired,
+ onRequestShapValues: PropTypes.func.isRequired,
+ onRequestIceValues: PropTypes.func.isRequired,
onRequestPredictionTemporalList: PropTypes.func.isRequired,
onRequestLimeTemporalList: PropTypes.func.isRequired,
+ onRequestFailLimeValues: PropTypes.func.isRequired,
+ onRequestFailLimeTemporalList: PropTypes.func.isRequired,
+ onRequestFailPredictionTemporalList: PropTypes.func.isRequired,
+ onRequestFailShapValues: PropTypes.func.isRequired,
+ onRequestFailSkaterValues: PropTypes.func.isRequired,
+ onRequestFailIceValues: PropTypes.func.isRequired,
filterOptionChange: PropTypes.func.isRequired,
labelTypeChange: PropTypes.func.isRequired,
jobs: PropTypes.arrayOf(jobPropType).isRequired,
@@ -222,16 +279,25 @@ Explanation.propTypes = {
}).isRequired,
clickedJobId: PropTypes.number,
limeValueList: PropTypes.any,
+ shapValueList: PropTypes.any,
+ iceValueList: PropTypes.any,
+ skaterValueList: PropTypes.any,
traceList: PropTypes.any,
logs: PropTypes.any,
splits: PropTypes.any,
jobsById: PropTypes.any,
selectedTrace: PropTypes.any,
+ selectedAttribute: PropTypes.any,
filteredJobs: PropTypes.any,
+ decodedDf: PropTypes.any,
jobId: PropTypes.number.isRequired,
isLimeTempStabilityLoaded: PropTypes.bool.isRequired,
isPredictionTempStabilityLoaded: PropTypes.bool.isRequired,
isLimeValuesLoaded: PropTypes.bool.isRequired,
+ isShapValuesLoaded: PropTypes.bool.isRequired,
+ isSkaterValuesLoaded: PropTypes.bool.isRequired,
+ isIceValuesLoaded: PropTypes.bool.isRequired,
+ isDecodedValueLoaded: PropTypes.bool.isRequired,
limeTempStabilityList: PropTypes.any,
predictionTempStabilityList: PropTypes.any
};
@@ -241,11 +307,19 @@ const mapStateToProps = (state) => ({
splitLabels: splitsToLabel(state.logs.byId, state.splits.byId, state.jobs.uniqueSplits),
fetchState: state.jobs.fetchState,
filteredJobs: state.jobs.filteredJobs,
+ decodedDf: state.jobs.decodedDf,
+ isDecodedValueLoaded: state.jobs.isDecodingLoaded,
logs: state.logs.byId,
splits: state.splits.byId,
splitId: state.jobs.splitId,
- limeValueList: state.lime.limeValueList,
- isLimeValuesLoaded: state.lime.isLimeValuesLoaded,
+ limeValueList: state.explanation.limeValueList,
+ isLimeValuesLoaded: state.explanation.isLimeValuesLoaded,
+ shapValueList: state.explanation.shapValueList,
+ isShapValuesLoaded: state.explanation.isShapValuesLoaded,
+ iceValueList: state.explanation.iceValueList,
+ isIceValuesLoaded: state.explanation.isIceValuesLoaded,
+ skaterValueList: state.explanation.skaterValueList,
+ isSkaterValuesLoaded: state.explanation.isSkaterValuesLoaded,
traceList: state.traces.byId,
predictionMethod: state.jobs.predictionMethod,
prefixLengths: state.jobs.prefixLengths.sort((a, b) => (a - b)),
@@ -253,6 +327,7 @@ const mapStateToProps = (state) => ({
jobsById: state.jobs.byId,
jobId: state.jobs.predictionJobId,
selectedTrace: state.jobs.selectedTrace,
+ selectedAttribute: state.explanation.selectedAttribute,
limeTempStabilityList: state.predictions.limeTempStabilityList,
predictionTempStabilityList: state.predictions.predictionTempStabilityList,
isLimeTempStabilityLoaded: state.predictions.isLimeTempStabilityLoaded,
@@ -278,11 +353,23 @@ const mapDispatchToProps = (dispatch) => ({
onRequestSplitList: () => dispatch(splitsRequested()),
onRequestJobs: () => dispatch(jobsRequested()),
onRequestTraces: (id) => dispatch(traceListRequested({id})),
+ onRequestDecoding: (id) => dispatch(decodingRequested({id})),
onRequestLimeValues: (jobId, traceId) => dispatch(limeValueListRequested({jobId, traceId})),
+ onRequestShapValues: (jobId, traceId) => dispatch(shapValueListRequested({jobId, traceId})),
+ onRequestIceValues: (jobId, attribute) => dispatch(iceValueListRequested({jobId, attribute})),
+ onRequestSkaterValues: (jobId) => dispatch(skaterValueListRequested({jobId})),
onRequestPredictionTemporalList: (jobId, traceId) =>
dispatch(temporalPredictionListRequested({jobId, traceId})),
onRequestLimeTemporalList: (jobId, traceId) =>
dispatch(temporalLimePredictionListRequested({jobId, traceId})),
+ onRequestFailLimeValues: () => dispatch(limeValueListFailed(null)),
+ onRequestFailShapValues: () => dispatch(shapValueListFailed(null)),
+ onRequestFailIceValues: () => dispatch(iceValueListFailed(null)),
+ onRequestFailSkaterValues: () => dispatch(skaterValueListFailed(null)),
+ onRequestFailPredictionTemporalList: ()=>
+ dispatch(temporalPredictionListFailed(null)),
+ onRequestFailLimeTemporalList: () =>
+ dispatch(temporalLimePredictionListFailed(null)),
filterOptionChange: (_, event) => dispatch({
type: FILTER_OPTION_CHANGED,
payload: {name: event.target.name, value: event.target.value}
From 54a0994dcc293bc1b77f193bfb4f1cd2979a8e79 Mon Sep 17 00:00:00 2001
From: Musacca
Date: Mon, 23 Mar 2020 17:53:53 +0200
Subject: [PATCH 12/29] Tests SHAP, ICE and Skater developed
---
.../components/chart/ScatterChart.test.js | 24 +
.../chart/VerticalBarChartCard.test.js | 40 +
.../explanation/DecodedDFTable.test.js | 42 +
.../components/explanation/ICEResult.test.js | 48 +
.../explanation/ICEResultTable.test.js | 24 +
.../components/explanation/ShapResult.test.js | 32 +
.../explanation/SkaterResult.test.js | 28 +
.../explanation/TemporalStability.test.js | 38 +
.../components/explanation/post_hoc.test.js | 2 +-
src/actions/ServerActions.js | 6 +-
src/components/chart/DecisionTree.js | 98 --
src/components/chart/PredictionLineChart.js | 13 +-
src/components/chart/R3DecisionTree.js | 72 --
src/components/explanation/DecodedDFTable.js | 10 +-
src/components/explanation/FairMLResult.js | 55 -
src/components/explanation/ShapResult.js | 1 -
src/components/explanation/SkaterResult.js | 1 -
.../explanation/TemporalStability.js | 3 +-
src/components/explanation/ante_hoc.js | 50 -
src/mock_data/Template.js | 7 -
src/mock_data/dependence_plot.png | Bin 26054 -> 0 bytes
src/mock_data/explainer.html | 32 -
src/mock_data/scratch.png | Bin 18776 -> 0 bytes
src/mock_data/test.txt | 1128 -----------------
src/mock_data/viz.svg | 1 -
src/util/dataReducers.js | 3 +-
src/views/Explanation/Explanation.js | 2 +-
stories/Explanation.js | 72 ++
28 files changed, 368 insertions(+), 1464 deletions(-)
create mode 100644 src/__tests__/components/chart/ScatterChart.test.js
create mode 100644 src/__tests__/components/chart/VerticalBarChartCard.test.js
create mode 100644 src/__tests__/components/explanation/DecodedDFTable.test.js
create mode 100644 src/__tests__/components/explanation/ICEResult.test.js
create mode 100644 src/__tests__/components/explanation/ICEResultTable.test.js
create mode 100644 src/__tests__/components/explanation/ShapResult.test.js
create mode 100644 src/__tests__/components/explanation/SkaterResult.test.js
create mode 100644 src/__tests__/components/explanation/TemporalStability.test.js
delete mode 100644 src/components/chart/DecisionTree.js
delete mode 100644 src/components/chart/R3DecisionTree.js
delete mode 100644 src/components/explanation/FairMLResult.js
delete mode 100644 src/components/explanation/ante_hoc.js
delete mode 100644 src/mock_data/Template.js
delete mode 100644 src/mock_data/dependence_plot.png
delete mode 100644 src/mock_data/explainer.html
delete mode 100644 src/mock_data/scratch.png
delete mode 100644 src/mock_data/test.txt
delete mode 100644 src/mock_data/viz.svg
diff --git a/src/__tests__/components/chart/ScatterChart.test.js b/src/__tests__/components/chart/ScatterChart.test.js
new file mode 100644
index 00000000..190279d4
--- /dev/null
+++ b/src/__tests__/components/chart/ScatterChart.test.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import ScatterChartCard from '../../../components/chart/ScatterChartCard';
+import {parseTemporalStabilityPredictionResultList}
+from '../../../util/dataReducers';
+import {temporalStabilityResult} from '../../../../stories/Explanation';
+import ReactApexChart from 'react-apexcharts';
+
+const temporalStabilityPredictionResult =
+parseTemporalStabilityPredictionResultList(temporalStabilityResult, '2_3301');
+
+it('renders', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(ReactApexChart).length).toBe(1);
+ const chartProps = element.find(ReactApexChart).props();
+ expect(chartProps.series[0].data.length).toBe(temporalStabilityPredictionResult.length);
+});
+
+it('no data', () => {
+ const element = shallow();
+ expect(element.find(ReactApexChart).length).toBe(0);
+});
+
diff --git a/src/__tests__/components/chart/VerticalBarChartCard.test.js b/src/__tests__/components/chart/VerticalBarChartCard.test.js
new file mode 100644
index 00000000..d7043a80
--- /dev/null
+++ b/src/__tests__/components/chart/VerticalBarChartCard.test.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import ReactApexChart from 'react-apexcharts';
+import VerticalBarChartCard from '../../../components/chart/VerticalBarChartCard';
+
+const labels = ['event', 'event1', 'event2', 'event3', 'event4'];
+const data = [1, 0.8, 0.1, 0.3, 0];
+const count = [1, 2, 1, 3, 9];
+
+
+describe('VerticalBarChartCard', () => {
+ it('renders with empty data', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(ReactApexChart).length).toBe(0);
+ });
+
+ it('renders with empty labels', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(ReactApexChart).length).toBe(1);
+
+ const chartProps = element.find(ReactApexChart).props();
+ expect(chartProps.options.xaxis.categories.length).toBe(0);
+ expect(chartProps.series[0].data.length).toBe(count.length);
+ expect(chartProps.series[1].data.length).toBe(data.length);
+ expect(chartProps.options.xaxis.categories.length).toBe(0);
+ });
+
+ it('renders with non empty data and label', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(ReactApexChart).length).toBe(1);
+
+ const chartProps = element.find(ReactApexChart).props();
+ expect(chartProps.options.xaxis.categories.length).toBe(labels.length);
+ expect(chartProps.series[0].data.length).toBe(count.length);
+ expect(chartProps.series[1].data.length).toBe(data.length);
+ });
+});
diff --git a/src/__tests__/components/explanation/DecodedDFTable.test.js b/src/__tests__/components/explanation/DecodedDFTable.test.js
new file mode 100644
index 00000000..d7d55baa
--- /dev/null
+++ b/src/__tests__/components/explanation/DecodedDFTable.test.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import DecodedDFTable from '../../../components/explanation/DecodedDFTable';
+import {getDecodedDFTable} from '../../../util/dataReducers';
+import {DataTable, TableBody, TableColumn, TableHeader, TablePagination, TableRow} from 'react-md/lib/DataTables/index';
+import {decodedDFResultList} from '../../../../stories/Explanation';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+
+
+const decodedDFResult = getDecodedDFTable(decodedDFResultList);
+
+describe('Dedocded DF Table', () => {
+ it('renders', () => {
+ const element = shallow( );
+ expect(element).toBeDefined();
+ expect(element.find(DataTable).length).toBe(1);
+ expect(element.find(CircularProgress).length).toBe(0);
+ expect(element.find(DataTable).at(0).find(TableRow).length).toBe(decodedDFResult.data.length+1);
+ expect(element.find(DataTable).at(0).find(TableHeader).find(TableRow).length).toBe(1);
+ expect(element.find(DataTable).at(0).find(TableBody).find(TableRow).length).toBe(decodedDFResult.data.length);
+ expect(element.find(DataTable).at(0).find(TableHeader)
+ .find(TableColumn).length).toBe(decodedDFResult.headers.length);
+ expect(element.find(TablePagination).length).toBe(1);
+ });
+
+ it('no element', () => {
+ const element = shallow( );
+ expect(element).toBeDefined();
+ expect(element.find(DataTable).length).toBe(0);
+ expect(element.find(TablePagination).length).toBe(0);
+ expect(element.find(TableRow).length).toBe(0);
+ expect(element.find(CircularProgress).length).toBe(1);
+ });
+});
diff --git a/src/__tests__/components/explanation/ICEResult.test.js b/src/__tests__/components/explanation/ICEResult.test.js
new file mode 100644
index 00000000..ca998aa6
--- /dev/null
+++ b/src/__tests__/components/explanation/ICEResult.test.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import ICEResult from '../../../components/explanation/ICEResult';
+import IceResultTable from '../../../components/explanation/IceResultTable';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+import VerticalBarChartCard from '../../../components/chart/VerticalBarChartCard';
+import {parseICEResult} from '../../../util/dataReducers';
+import {iceResultList} from '../../../../stories/Explanation';
+import SelectField from 'react-md/lib/SelectFields';
+
+const iceResult = parseICEResult(iceResultList);
+
+describe('ICE result', () => {
+ it('All data loaded', () => {
+ const element = shallow( );
+ expect(element).toBeDefined();
+ expect(element.find(SelectField).length).toBe(1);
+ expect(element.find(SelectField).at(0).props().menuItems.length).toBe(2);
+
+ expect(element.find(VerticalBarChartCard).length).toBe(1);
+ expect(element.find(IceResultTable).length).toBe(0);
+
+ expect(element.find(CircularProgress).length).toBe(0);
+ });
+
+ it('None of the data loaded', () => {
+ const element = shallow( );
+ expect(element).toBeDefined();
+ expect(element.find(SelectField).length).toBe(1);
+ expect(element.find(SelectField).at(0).props().menuItems.length).toBe(2);
+ expect(element.find(VerticalBarChartCard).length).toBe(1);
+ expect(element.find(IceResultTable).length).toBe(0);
+ expect(element.find(CircularProgress).length).toBe(1);
+ });
+});
diff --git a/src/__tests__/components/explanation/ICEResultTable.test.js b/src/__tests__/components/explanation/ICEResultTable.test.js
new file mode 100644
index 00000000..1d217413
--- /dev/null
+++ b/src/__tests__/components/explanation/ICEResultTable.test.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import IceResultTable from '../../../components/explanation/IceResultTable';
+import {getIceResultListTable} from '../../../util/dataReducers';
+import {DataTable, TableBody, TableColumn, TableHeader, TablePagination, TableRow} from 'react-md/lib/DataTables/index';
+import {iceResultList} from '../../../../stories/Explanation';
+
+
+const iceResult = getIceResultListTable(iceResultList);
+
+describe('Ice result Table', () => {
+ it('renders', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(DataTable).length).toBe(1);
+ expect(element.find(DataTable).at(0).find(TableRow).length).toBe(iceResult.length+1);
+ expect(element.find(DataTable).at(0).find(TableHeader).find(TableRow).length).toBe(1);
+ expect(element.find(DataTable).at(0).find(TableBody).find(TableRow).length).toBe(iceResult.length);
+ expect(element.find(DataTable).at(0).find(TableHeader)
+ .find(TableColumn).length).toBe(3);
+ expect(element.find(TablePagination).length).toBe(1);
+ });
+});
diff --git a/src/__tests__/components/explanation/ShapResult.test.js b/src/__tests__/components/explanation/ShapResult.test.js
new file mode 100644
index 00000000..c7554426
--- /dev/null
+++ b/src/__tests__/components/explanation/ShapResult.test.js
@@ -0,0 +1,32 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import ShapResult from '../../../components/explanation/ShapResult';
+import {shapResult} from '../../../../stories/Explanation';
+import InlineSVG from 'svg-inline-react';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+
+describe('Shap result', () => {
+ it('renders with data', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(InlineSVG).length).toBe(1);
+ expect(element.find(CircularProgress).length).toBe(0);
+ });
+
+ it('renders without data', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(InlineSVG).length).toBe(0);
+ expect(element.find(CircularProgress).length).toBe(1);
+ });
+});
diff --git a/src/__tests__/components/explanation/SkaterResult.test.js b/src/__tests__/components/explanation/SkaterResult.test.js
new file mode 100644
index 00000000..37de0065
--- /dev/null
+++ b/src/__tests__/components/explanation/SkaterResult.test.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import SkaterResult from '../../../components/explanation/SkaterResult';
+import {skaterResult} from '../../../../stories/Explanation';
+import InlineSVG from 'svg-inline-react';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+
+describe('Skater result', () => {
+ it('renders with data', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(InlineSVG).length).toBe(1);
+ expect(element.find(CircularProgress).length).toBe(0);
+ });
+
+ it('renders without data', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(InlineSVG).length).toBe(0);
+ expect(element.find(CircularProgress).length).toBe(1);
+ });
+});
diff --git a/src/__tests__/components/explanation/TemporalStability.test.js b/src/__tests__/components/explanation/TemporalStability.test.js
new file mode 100644
index 00000000..ca653e2d
--- /dev/null
+++ b/src/__tests__/components/explanation/TemporalStability.test.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import {shallow} from 'enzyme';
+import TemporalStability from '../../../components/explanation/TemporalStability';
+import {limeTemporalStabilityResult, temporalStabilityResult} from '../../../../stories/Explanation';
+import CircularProgress from 'react-md/lib/Progress/CircularProgress';
+import PredictionLineChart from '../../../components/chart/PredictionLineChart';
+import ScatterChartCard from '../../../components/chart/ScatterChartCard';
+
+
+describe('Temporal stability', () => {
+ it('All data loaded', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(PredictionLineChart).length).toBe(1);
+ expect(element.find(ScatterChartCard).length).toBe(1);
+ expect(element.find(CircularProgress).length).toBe(0);
+ });
+
+ it('None of the data loaded', () => {
+ const element = shallow();
+ expect(element).toBeDefined();
+ expect(element.find(PredictionLineChart).length).toBe(1);
+ expect(element.find(ScatterChartCard).length).toBe(1);
+ expect(element.find(CircularProgress).length).toBe(2);
+ });
+});
diff --git a/src/__tests__/components/explanation/post_hoc.test.js b/src/__tests__/components/explanation/post_hoc.test.js
index 137c0494..0f112aaa 100644
--- a/src/__tests__/components/explanation/post_hoc.test.js
+++ b/src/__tests__/components/explanation/post_hoc.test.js
@@ -5,7 +5,7 @@ import HorizontalBarChartCard from '../../../components/chart/HorizontalBarChart
import {parseLimeResult} from '../../../util/dataReducers';
import {limeList} from '../../../../stories/Explanation';
-describe('TraceTable', () => {
+describe('Lime result', () => {
it('renders without data', () => {
const element = shallow( (dispatch) => {
jsonAjax(
diff --git a/src/components/chart/DecisionTree.js b/src/components/chart/DecisionTree.js
deleted file mode 100644
index 9b66def1..00000000
--- a/src/components/chart/DecisionTree.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/* eslint-disable max-len */
-import React from 'react';
-import {Graphviz} from 'graphviz-react';
-class DecisionTree extends React.Component {
- constructor(props) {
- super(props);
- }
- render() {
- return prefix_1 ≤ 23.5 gini = 0.5 samples = 100.0% value = [0.5, 0.5] class = prefix_2>];
- 1 [fillcolor=cornsilk, label= prefix_2 ≤ 30.5 gini = 0.38 samples = 64.8% value = [0.255, 0.745] class = prefix_2>];
- 0 -> 1 [color=steelblue, headlabel="True", labelangle=45, labeldistance="2.5"];
- 2 [fillcolor=cornsilk, label= prefix_2 ≤ 3.5 gini = 0.123 samples = 53.9% value = [0.066, 0.934] class = prefix_2>];
- 1 -> 2 [color=steelblue];
- 3 [fillcolor=coral, label= gini = 0.0 samples = 0.4% value = [1.0, 0.0] class = prefix_1>];
- 2 -> 3 [color=steelblue];
- 4 [fillcolor=cornsilk, label= prefix_1 ≤ 12.5 gini = 0.099 samples = 53.5% value = [0.052, 0.948] class = prefix_2>];
- 2 -> 4 [color=steelblue];
- 5 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 28.5% value = [0.0, 1.0] class = prefix_2>];
- 4 -> 5 [color=steelblue];
- 6 [fillcolor=cornsilk, label= prefix_2 ≤ 9.0 gini = 0.193 samples = 25.0% value = [0.108, 0.892] class = prefix_2>];
- 4 -> 6 [color=steelblue];
- 7 [fillcolor=lightsteelblue, label= gini = -0.0 samples = 20.2% value = [0.0, 1.0] class = prefix_2>];
- 6 -> 7 [color=steelblue];
- 8 [fillcolor=cornsilk, label= prefix_1 ≤ 20.0 gini = 0.498 samples = 4.7% value = [0.472, 0.528] class = prefix_2>];
- 6 -> 8 [color=steelblue];
- 9 [fillcolor=coral, label= gini = 0.305 samples = 2.2% value = [0.812, 0.188] class = prefix_1>];
- 8 -> 9 [color=steelblue];
- 12 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 2.5% value = [0.0, 1.0] class = prefix_2>];
- 8 -> 12 [color=steelblue];
- 13 [fillcolor=cornsilk, label= prefix_1 ≤ 11.5 gini = 0.261 samples = 10.9% value = [0.846, 0.154] class = prefix_1>];
- 1 -> 13 [color=steelblue];
- 14 [fillcolor=cornsilk, label= prefix_2 ≤ 35.5 gini = 0.498 samples = 3.1% value = [0.467, 0.533] class = prefix_2>];
- 13 -> 14 [color=steelblue];
- 15 [fillcolor=coral, label= gini = 0.0 samples = 0.4% value = [1.0, 0.0] class = prefix_1>];
- 14 -> 15 [color=steelblue];
- 16 [fillcolor=cornsilk, label= prefix_1 ≤ 5.5 gini = 0.44 samples = 2.6% value = [0.327, 0.673] class = prefix_2>];
- 14 -> 16 [color=steelblue];
- 17 [fillcolor=coral, label= gini = 0.411 samples = 0.8% value = [0.711, 0.289] class = prefix_1>];
- 16 -> 17 [color=steelblue];
- 20 [fillcolor=cornsilk, label= prefix_2 ≤ 44.5 gini = 0.186 samples = 1.9% value = [0.104, 0.896] class = prefix_2>];
- 16 -> 20 [color=steelblue];
- 21 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 1.8% value = [0.0, 1.0] class = prefix_2>];
- 20 -> 21 [color=steelblue];
- 22 [fillcolor=coral, label= gini = 0.0 samples = 0.1% value = [1.0, 0.0] class = prefix_1>];
- 20 -> 22 [color=steelblue];
- 23 [fillcolor=cornsilk, label= prefix_1 ≤ 19.5 gini = 0.091 samples = 7.8% value = [0.952, 0.048] class = prefix_1>];
- 13 -> 23 [color=steelblue];
- 24 [fillcolor=coral, label= gini = 0.0 samples = 7.2% value = [1.0, 0.0] class = prefix_1>];
- 23 -> 24 [color=steelblue];
- 25 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 0.7% value = [0.0, 1.0] class = prefix_2>];
- 23 -> 25 [color=steelblue];
- 26 [fillcolor=cornsilk, label= prefix_2 ≤ 7.0 gini = 0.297 samples = 35.2% value = [0.819, 0.181] class = prefix_1>];
- 0 -> 26 [color=steelblue, headlabel="False", labelangle="-45", labeldistance="2.5"];
- 27 [fillcolor=cornsilk, label= prefix_2 ≤ 3.5 gini = 0.124 samples = 3.0% value = [0.066, 0.934] class = prefix_2>];
- 26 -> 27 [color=steelblue];
- 28 [fillcolor=coral, label= gini = 0.0 samples = 0.1% value = [1.0, 0.0] class = prefix_1>];
- 27 -> 28 [color=steelblue];
- 29 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 2.9% value = [0.0, 1.0] class = prefix_2>];
- 27 -> 29 [color=steelblue];
- 30 [fillcolor=cornsilk, label= prefix_2 ≤ 42.5 gini = 0.238 samples = 32.2% value = [0.862, 0.138] class = prefix_1>];
- 26 -> 30 [color=steelblue];
- 31 [fillcolor=cornsilk, label= prefix_1 ≤ 24.5 gini = 0.179 samples = 29.8% value = [0.9, 0.1] class = prefix_1>];
- 30 -> 31 [color=steelblue];
- 32 [fillcolor=coral, label= gini = 0.0 samples = 13.2% value = [1.0, 0.0] class = prefix_1>];
- 31 -> 32 [color=steelblue];
- 33 [fillcolor=cornsilk, label= prefix_2 ≤ 23.5 gini = 0.31 samples = 16.6% value = [0.808, 0.192] class = prefix_1>];
- 31 -> 33 [color=steelblue];
- 34 [fillcolor=cornsilk, label= prefix_2 ≤ 11.5 gini = 0.07 samples = 11.9% value = [0.964, 0.036] class = prefix_1>];
- 33 -> 34 [color=steelblue];
- 35 [fillcolor=coral, label= gini = 0.0 samples = 9.5% value = [1.0, 0.0] class = prefix_1>];
- 34 -> 35 [color=steelblue];
- 36 [fillcolor=cornsilk, label= prefix_2 ≤ 15.5 gini = 0.322 samples = 2.4% value = [0.799, 0.201] class = prefix_1>];
- 34 -> 36 [color=steelblue];
- 37 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 0.8% value = [0.0, 1.0] class = prefix_2>];
- 36 -> 37 [color=steelblue];
- 38 [fillcolor=coral, label= gini = -0.0 samples = 1.7% value = [1.0, 0.0] class = prefix_1>];
- 36 -> 38 [color=steelblue];
- 39 [fillcolor=cornsilk, label= prefix_2 ≤ 38.5 gini = 0.268 samples = 4.7% value = [0.159, 0.841] class = prefix_2>];
- 33 -> 39 [color=steelblue];
- 40 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 4.3% value = [0.0, 1.0] class = prefix_2>];
- 39 -> 40 [color=steelblue];
- 41 [fillcolor=coral, label= gini = 0.0 samples = 0.4% value = [1.0, 0.0] class = prefix_1>];
- 39 -> 41 [color=steelblue];
- 42 [fillcolor=cornsilk, label= prefix_2 ≤ 45.0 gini = 0.149 samples = 2.4% value = [0.081, 0.919] class = prefix_2>];
- 30 -> 42 [color=steelblue];
- 43 [fillcolor=lightsteelblue, label= gini = 0.0 samples = 2.3% value = [0.0, 1.0] class = prefix_2>];
- 42 -> 43 [color=steelblue];
- 44 [fillcolor=coral, label= gini = -0.0 samples = 0.1% value = [1.0, 0.0] class = prefix_1>];
- 42 -> 44 [color=steelblue];
- }`} />
- ;
- }
-}
-
-export default DecisionTree;
diff --git a/src/components/chart/PredictionLineChart.js b/src/components/chart/PredictionLineChart.js
index 5e1f7768..e1c3cdd5 100644
--- a/src/components/chart/PredictionLineChart.js
+++ b/src/components/chart/PredictionLineChart.js
@@ -36,16 +36,13 @@ class PredictionLineChart extends React.Component {
max: this.props.data.length +1,
tickAmount: this.props.data.length +1,
title: {
- text: 'Time'
+ text: 'Feature'
}
},
yaxis: {
title: {
- text: 'Prediction'
+ text: 'Importance'
},
- min: -1,
- max: 2,
- tickAmount: 3,
axisBorder: {
show: true,
color: '#000000',
@@ -59,13 +56,13 @@ class PredictionLineChart extends React.Component {
}
},
legend: {
- position: 'top',
+ position: 'bottom',
horizontalAlign: 'right',
- floating: true,
+ floating: false,
}
},
};
- const height = '350em';
+ const height = '450em';
const chart = (
-
-
- );
-}
-}
-export default R3DecisionTree;
-
diff --git a/src/components/explanation/DecodedDFTable.js b/src/components/explanation/DecodedDFTable.js
index cfd8bd7d..135a726a 100644
--- a/src/components/explanation/DecodedDFTable.js
+++ b/src/components/explanation/DecodedDFTable.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
-class IceResultTable extends PureComponent {
+class DecodedDFTable extends PureComponent {
constructor(props) {
super(props);
this.state = {
@@ -49,6 +49,7 @@ class IceResultTable extends PureComponent {
{!this.props.isDecodedValueLoaded ? : null}
+ {this.props.values.length>0 ?
@@ -72,7 +73,8 @@ class IceResultTable extends PureComponent {
rows={this.props.values.length}
rowsPerPageLabel={'Rows per page'}
onPagination={this.handlePagination.bind(this)}/>
-
+ : null
+ }
);
@@ -84,11 +86,11 @@ class IceResultTable extends PureComponent {
}
}
-IceResultTable.propTypes = {
+DecodedDFTable.propTypes = {
values: PropTypes.array.isRequired,
headers: PropTypes.array.isRequired,
isDecodedValueLoaded: PropTypes.bool.isRequired,
jobId: PropTypes.any.isRequired,
};
-export default IceResultTable;
+export default DecodedDFTable;
diff --git a/src/components/explanation/FairMLResult.js b/src/components/explanation/FairMLResult.js
deleted file mode 100644
index ac4c2dba..00000000
--- a/src/components/explanation/FairMLResult.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import React, {PureComponent} from 'react';
-import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
-import PropTypes from 'prop-types';
-import SelectField from 'react-md/lib/SelectFields';
-import HorizontalBarChartCard from '../../components/chart/HorizontalBarChartCard';
-import {parseFairMLResult} from '../../util/dataReducers';
-
-class ShapResult extends PureComponent {
- constructor(props) {
- super(props);
- this.state = {
- };
- }
- getTraceSelector() {
- return (
-
- );
- }
-
- render() {
- const fairMLResult = parseFairMLResult([{'label': 'Age_1', 'value': 0.5},
- {'label': 'CType_1', 'value': 0.5},
- {'label': 'ClType_1', 'value': 0.5},
- {'label': 'ClaimValue_1', 'value': 0.5},
- {'label': 'PClaims_1', 'value': 0.5},
- {'label': 'lifecycle:transition_1', 'value': 0.5},
- {'label': 'org:resource_1', 'value': 0.5}]);
- const horizontalBarChart =
;
- return (
-
-
FairML result
-
-
Select the prefix
- {this.getTraceSelector()}
-
-
{horizontalBarChart}
-
-
- );
- }
-}
-ShapResult.propTypes = {
- iceResult: PropTypes.any,
- jobId: PropTypes.any,
-};
-export default ShapResult;
diff --git a/src/components/explanation/ShapResult.js b/src/components/explanation/ShapResult.js
index 12c8ad0f..7ae3bb7f 100644
--- a/src/components/explanation/ShapResult.js
+++ b/src/components/explanation/ShapResult.js
@@ -1,7 +1,6 @@
import React, {PureComponent} from 'react';
import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
import PropTypes from 'prop-types';
-import SelectField from 'react-md/lib/SelectFields';
import InlineSVG from 'svg-inline-react';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
diff --git a/src/components/explanation/SkaterResult.js b/src/components/explanation/SkaterResult.js
index 4bf28559..a5294183 100644
--- a/src/components/explanation/SkaterResult.js
+++ b/src/components/explanation/SkaterResult.js
@@ -1,7 +1,6 @@
import React, {PureComponent} from 'react';
import {Card, CardTitle, CardText} from 'react-md/lib/Cards/index';
import PropTypes from 'prop-types';
-import viz from '../../mock_data/viz.svg';
import InlineSVG from 'svg-inline-react';
import CircularProgress from 'react-md/lib/Progress/CircularProgress';
diff --git a/src/components/explanation/TemporalStability.js b/src/components/explanation/TemporalStability.js
index c543446b..2302fcaf 100644
--- a/src/components/explanation/TemporalStability.js
+++ b/src/components/explanation/TemporalStability.js
@@ -13,8 +13,7 @@ const TemporalStability = (props) => {
parseTemporalStabilityLimeResultList(props.limeTemporalChartData, props.traceId);
const temporalStabilityPredictionResult =
parseTemporalStabilityPredictionResultList(props.predictionTemportalChartData, props.traceId);
-
- return
+ return
diff --git a/src/components/explanation/ante_hoc.js b/src/components/explanation/ante_hoc.js
deleted file mode 100644
index 4848889d..00000000
--- a/src/components/explanation/ante_hoc.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Created by Williams.Rizzi on 9/9/19.
- */
-import React from 'react';
-import {Card, CardText, CardTitle} from 'react-md/lib/Cards/index';
-import PropTypes from 'prop-types';
-import FetchState from './../FetchState';
-import {fetchStatePropType, jobPropType, selectLabelProptype} from '../../propTypes';
-
-const AnteHocExplanation = (props) => {
- // const selectChange = (value, _) => {
- // props.splitChange(value);
- // };
-
- return
-
-
- asdf
-
-
- ;
-};
-
-
-AnteHocExplanation.propTypes = {
- jobs: PropTypes.arrayOf(jobPropType).isRequired,
- splitLabels: selectLabelProptype,
- fetchState: fetchStatePropType,
- methodChange: PropTypes.func.isRequired,
- splitChange: PropTypes.func.isRequired,
- prefixLengths: PropTypes.arrayOf(PropTypes.string).isRequired,
- prefixChange: PropTypes.func.isRequired,
- selectedPrefixes: PropTypes.arrayOf(PropTypes.number).isRequired,
- selectedSplitId: PropTypes.number.isRequired,
- filterOptionChange: PropTypes.func.isRequired,
- labelChange: PropTypes.func.isRequired,
- filterOptions: PropTypes.shape({
- encodings: PropTypes.arrayOf(PropTypes.string).isRequired,
- clusterings: PropTypes.arrayOf(PropTypes.string).isRequired,
- classification: PropTypes.arrayOf(PropTypes.string).isRequired,
- regression: PropTypes.arrayOf(PropTypes.string).isRequired,
- timeSeriesPrediction: PropTypes.arrayOf(PropTypes.string).isRequired,
- labelling: PropTypes.any.isRequired,
- attributeNames: PropTypes.arrayOf(PropTypes.string).isRequired,
- thresholds: PropTypes.arrayOf(PropTypes.number).isRequired,
- padding: PropTypes.string.isRequired
- }).isRequired,
- predictionMethod: PropTypes.string.isRequired
-};
-export default AnteHocExplanation;
diff --git a/src/mock_data/Template.js b/src/mock_data/Template.js
deleted file mode 100644
index 025a5960..00000000
--- a/src/mock_data/Template.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-let Template = React.createReactClass({
- render: function () {
- return (Mi HTML
);
- }
-});
-module.exports = Template;
diff --git a/src/mock_data/dependence_plot.png b/src/mock_data/dependence_plot.png
deleted file mode 100644
index 83c4717d1f0fdfcf994b829208c346d82b38e6bd..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 26054
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