From 2705967237080aad0927aa26dced83caa9bab3f9 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 01:31:18 -0500
Subject: [PATCH 01/30] add cicd image

---
 docker/cicd/Dockerfile | 17 +++++++++++++++++
 docker/cicd/README.md  |  5 +++++
 docker/cicd/build.sh   |  8 ++++++++
 docker/cicd/deploy.sh  |  9 +++++++++
 4 files changed, 39 insertions(+)
 create mode 100644 docker/cicd/Dockerfile
 create mode 100644 docker/cicd/README.md
 create mode 100755 docker/cicd/build.sh
 create mode 100755 docker/cicd/deploy.sh

diff --git a/docker/cicd/Dockerfile b/docker/cicd/Dockerfile
new file mode 100644
index 00000000..891955c7
--- /dev/null
+++ b/docker/cicd/Dockerfile
@@ -0,0 +1,17 @@
+FROM ubuntu:disco
+LABEL One-Off Coder "info@oneoffcoder.com"
+
+ENV CONDA_HOME=/usr/local/conda
+ENV PATH=${CONDA_HOME}/bin:${PATH}
+
+# setup ubuntu
+RUN apt-get update -y \
+    && apt-get upgrade -y \
+    && apt-get -y install wget \
+    && apt-get clean
+
+# setup conda
+RUN wget -q https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh -O /tmp/anaconda.sh \
+    && /bin/bash /tmp/anaconda.sh -b -p $CONDA_HOME \
+    && $CONDA_HOME/bin/pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx \
+    && $CONDA_HOME/bin/conda update -n root conda -y
diff --git a/docker/cicd/README.md b/docker/cicd/README.md
new file mode 100644
index 00000000..5ffa2eeb
--- /dev/null
+++ b/docker/cicd/README.md
@@ -0,0 +1,5 @@
+![One-Off Coder Logo](../logo.png "One-Off Coder")
+
+# Purpose
+
+This docker container is meant to be used for CI/CD to publish the books.
diff --git a/docker/cicd/build.sh b/docker/cicd/build.sh
new file mode 100755
index 00000000..24986760
--- /dev/null
+++ b/docker/cicd/build.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+AWS_URL=982057254752.dkr.ecr.us-east-1.amazonaws.com
+
+docker build --no-cache -t book-cicd:local .
+
+docker tag book-cicd:local $AWS_URL/book-cicd:0.0.1
+docker tag book-cicd:local $AWS_URL/book-cicd:latest
\ No newline at end of file
diff --git a/docker/cicd/deploy.sh b/docker/cicd/deploy.sh
new file mode 100755
index 00000000..39acec22
--- /dev/null
+++ b/docker/cicd/deploy.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# NOTE: make sure you have created an AWS CLI conda environment
+
+AWS_URL=982057254752.dkr.ecr.us-east-1.amazonaws.com
+
+$(aws ecr get-login --no-include-email --region us-east-1)
+docker push $AWS_URL/book-cicd:0.0.1
+docker push $AWS_URL/book-cicd:latest
\ No newline at end of file

From 555ddb3c6bc640946faf14d923b713b8005959bf Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 01:47:54 -0500
Subject: [PATCH 02/30] add

---
 buildspec.yml | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 buildspec.yml

diff --git a/buildspec.yml b/buildspec.yml
new file mode 100644
index 00000000..a909acf0
--- /dev/null
+++ b/buildspec.yml
@@ -0,0 +1,42 @@
+version: 0.2
+
+env:
+  variables:
+    CONDA_HOME: "/usr/local/conda"
+    PATH: "${CONDA_HOME}/bin:${PATH}"
+    JAVA_INTRO: "./sphinx/java-intro"
+    PYTHON_INTRO: "./sphinx/python-intro"
+    PYTORCH_INTRO: "./sphinx/pytorch-intro"
+    SCIKIT_INTRO: "./sphinx/scikit-intro"
+    SPARK_INTRO: "./sphinx/spark-intro"
+
+phases:
+  install:
+    commands:
+      - echo Entered the install phase...
+      - apt-get update -y
+      - apt-get -y install wget
+      - wget -q https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh -O /tmp/anaconda.sh
+      - /bin/bash /tmp/anaconda.sh -b -p $CONDA_HOME
+      - $CONDA_HOME/bin/pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx
+    finally:
+      - echo Install finished
+  pre_build:
+    commands:
+      - echo Entered the pre-build phase...
+    finally:
+      - echo Prebuild finished 
+  build:
+    commands:
+      - echo Entered the build phase...
+      - cd $JAVA_INTRO && make clean && make html && cd ..
+      - cd $PYTHON_INTRO && make clean && make html && cd ..
+      - cd $PYTORCH_INTRO && make clean && make html && cd ..
+      - cd $SCIKIT_INTRO && make clean && make html && cd ..
+      - cd $SPARK_INTRO && make clean && make html && cd ..
+    finally:
+      - echo Build finished
+  post_build:
+    commands:
+      - echo Entered the post_build phase...
+      - echo Build completed on `date`

From 86b65d8b5173760c2a7218c706f990515e85127f Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 01:54:05 -0500
Subject: [PATCH 03/30] specify runtime

---
 buildspec.yml | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/buildspec.yml b/buildspec.yml
index a909acf0..d522224c 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -12,13 +12,11 @@ env:
 
 phases:
   install:
+    runtime-versions:
+      python: 3.7
     commands:
       - echo Entered the install phase...
-      - apt-get update -y
-      - apt-get -y install wget
-      - wget -q https://repo.anaconda.com/archive/Anaconda3-2019.10-Linux-x86_64.sh -O /tmp/anaconda.sh
-      - /bin/bash /tmp/anaconda.sh -b -p $CONDA_HOME
-      - $CONDA_HOME/bin/pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx
+      - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx
     finally:
       - echo Install finished
   pre_build:

From 44401dd3454a9443024ac97a0ed7ee16fd49118a Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:21:10 -0500
Subject: [PATCH 04/30] update

---
 buildspec.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index d522224c..26a4154c 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -13,7 +13,7 @@ env:
 phases:
   install:
     runtime-versions:
-      python: 3.7
+      python: "3.7"
     commands:
       - echo Entered the install phase...
       - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx
@@ -22,6 +22,8 @@ phases:
   pre_build:
     commands:
       - echo Entered the pre-build phase...
+      - python --version
+      - pip --version
     finally:
       - echo Prebuild finished 
   build:

From ca05c26584affdb6c72b13a6e038e0d4c98fd87e Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:26:54 -0500
Subject: [PATCH 05/30] update

---
 buildspec.yml | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/buildspec.yml b/buildspec.yml
index 26a4154c..0c4f9985 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -1,15 +1,5 @@
 version: 0.2
 
-env:
-  variables:
-    CONDA_HOME: "/usr/local/conda"
-    PATH: "${CONDA_HOME}/bin:${PATH}"
-    JAVA_INTRO: "./sphinx/java-intro"
-    PYTHON_INTRO: "./sphinx/python-intro"
-    PYTORCH_INTRO: "./sphinx/pytorch-intro"
-    SCIKIT_INTRO: "./sphinx/scikit-intro"
-    SPARK_INTRO: "./sphinx/spark-intro"
-
 phases:
   install:
     runtime-versions:
@@ -29,11 +19,7 @@ phases:
   build:
     commands:
       - echo Entered the build phase...
-      - cd $JAVA_INTRO && make clean && make html && cd ..
-      - cd $PYTHON_INTRO && make clean && make html && cd ..
-      - cd $PYTORCH_INTRO && make clean && make html && cd ..
-      - cd $SCIKIT_INTRO && make clean && make html && cd ..
-      - cd $SPARK_INTRO && make clean && make html && cd ..
+      - cd sphinx/java-intro && make clean && make html && cd ../..
     finally:
       - echo Build finished
   post_build:

From 862918db96f16727164073bdfc7c0999edd33cb6 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:29:26 -0500
Subject: [PATCH 06/30] update

---
 buildspec.yml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 0c4f9985..ff968979 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,7 +6,7 @@ phases:
       python: "3.7"
     commands:
       - echo Entered the install phase...
-      - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx
+      - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
     finally:
       - echo Install finished
   pre_build:
@@ -20,6 +20,10 @@ phases:
     commands:
       - echo Entered the build phase...
       - cd sphinx/java-intro && make clean && make html && cd ../..
+      - cd sphinx/python-intro && make clean && make html && cd ../..
+      - cd sphinx/pytorch-intro && make clean && make html && cd ../..
+      - cd sphinx/scikit-intro && make clean && make html && cd ../..
+      - cd sphinx/spark-intro && make clean && make html && cd ../..
     finally:
       - echo Build finished
   post_build:

From e1cc5aeb43c68f7208bdcf4dc818fff4d18d57de Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:35:54 -0500
Subject: [PATCH 07/30] update

---
 buildspec.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/buildspec.yml b/buildspec.yml
index ff968979..367870e4 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,6 +6,7 @@ phases:
       python: "3.7"
     commands:
       - echo Entered the install phase...
+      - apt-get install pandoc -y
       - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
     finally:
       - echo Install finished

From dd18976eeae79faead7267c5a5817ad6e560e76e Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:37:51 -0500
Subject: [PATCH 08/30] update

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 367870e4..1fef90e9 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,7 +6,7 @@ phases:
       python: "3.7"
     commands:
       - echo Entered the install phase...
-      - apt-get install pandoc -y
+      - apt-get -q install pandoc -y
       - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
     finally:
       - echo Install finished

From 3277532775ac8a152954fb2a10a2bb5a3c32f29e Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:42:23 -0500
Subject: [PATCH 09/30] update

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 1fef90e9..3486855e 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -7,7 +7,7 @@ phases:
     commands:
       - echo Entered the install phase...
       - apt-get -q install pandoc -y
-      - pip install sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
+      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
     finally:
       - echo Install finished
   pre_build:

From bd8c14b0c425d66c910cc2c211fd3cf219705b3c Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:43:44 -0500
Subject: [PATCH 10/30] update

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 3486855e..a6c75f1a 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,7 +6,7 @@ phases:
       python: "3.7"
     commands:
       - echo Entered the install phase...
-      - apt-get -q install pandoc -y
+      - apt-get -qq install pandoc -y
       - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
     finally:
       - echo Install finished

From 8a625f9eb483edbe15a9e4f7693d7f4cd65bc8e8 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:49:24 -0500
Subject: [PATCH 11/30] upload to s3

---
 buildspec.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/buildspec.yml b/buildspec.yml
index a6c75f1a..d7d21dbe 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -30,4 +30,5 @@ phases:
   post_build:
     commands:
       - echo Entered the post_build phase...
+      - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com
       - echo Build completed on `date`

From 5d9fa3cb967b8c7bead5a92c4722d5dbafc27d11 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:51:42 -0500
Subject: [PATCH 12/30] trim

---
 buildspec.yml | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/buildspec.yml b/buildspec.yml
index d7d21dbe..0f5bd869 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -5,30 +5,20 @@ phases:
     runtime-versions:
       python: "3.7"
     commands:
-      - echo Entered the install phase...
       - apt-get -qq install pandoc -y
       - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
-    finally:
-      - echo Install finished
   pre_build:
     commands:
-      - echo Entered the pre-build phase...
       - python --version
       - pip --version
-    finally:
-      - echo Prebuild finished 
   build:
     commands:
-      - echo Entered the build phase...
       - cd sphinx/java-intro && make clean && make html && cd ../..
       - cd sphinx/python-intro && make clean && make html && cd ../..
       - cd sphinx/pytorch-intro && make clean && make html && cd ../..
       - cd sphinx/scikit-intro && make clean && make html && cd ../..
       - cd sphinx/spark-intro && make clean && make html && cd ../..
-    finally:
-      - echo Build finished
   post_build:
     commands:
-      - echo Entered the post_build phase...
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com
       - echo Build completed on `date`

From c6754f0ba671bd80057e2c9fee34a434137612c8 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 02:59:20 -0500
Subject: [PATCH 13/30] remove

---
 buildspec.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 0f5bd869..dcfe5640 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -20,5 +20,4 @@ phases:
       - cd sphinx/spark-intro && make clean && make html && cd ../..
   post_build:
     commands:
-      - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com
       - echo Build completed on `date`

From 4c6bfd40c3626b41fdaf27dd0d84b02ebe0a0e59 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 03:15:55 -0500
Subject: [PATCH 14/30] zip

---
 buildspec.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/buildspec.yml b/buildspec.yml
index dcfe5640..815e036e 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -20,4 +20,5 @@ phases:
       - cd sphinx/spark-intro && make clean && make html && cd ../..
   post_build:
     commands:
+      - cd sphinx/java-intro/build/html && zip -r /tmp/java-intro.zip . && cd ../../../..
       - echo Build completed on `date`

From 031116c0b4a8fb84c424f4cb9350e044fb46b61c Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 03:21:07 -0500
Subject: [PATCH 15/30] use aws cli

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 815e036e..0f5bd869 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -20,5 +20,5 @@ phases:
       - cd sphinx/spark-intro && make clean && make html && cd ../..
   post_build:
     commands:
-      - cd sphinx/java-intro/build/html && zip -r /tmp/java-intro.zip . && cd ../../../..
+      - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com
       - echo Build completed on `date`

From bec0ecbd50ebe3bc0f822db175cf4110a74eb138 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 03:27:00 -0500
Subject: [PATCH 16/30] sync all

---
 buildspec.yml | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 0f5bd869..34ebb679 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -20,5 +20,9 @@ phases:
       - cd sphinx/spark-intro && make clean && make html && cd ../..
   post_build:
     commands:
-      - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com
+      - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/python-intro/build/html s3://learn-python.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/pytorch-intro/build/html s3://learn-pytorch.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/scikit-intro/build/html s3://learn-scikit.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/spark-intro/build/html s3://learn-spark.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 61fb7fb755ed23b29d514ef892fd9a322c82b621 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Wed, 6 Nov 2019 14:22:33 -0500
Subject: [PATCH 17/30] add datascience

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index 34ebb679..a7b80553 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -18,6 +18,7 @@ phases:
       - cd sphinx/pytorch-intro && make clean && make html && cd ../..
       - cd sphinx/scikit-intro && make clean && make html && cd ../..
       - cd sphinx/spark-intro && make clean && make html && cd ../..
+      - cd sphinx/datascience && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -25,4 +26,5 @@ phases:
       - aws s3 sync sphinx/pytorch-intro/build/html s3://learn-pytorch.oneoffcoder.com --quiet
       - aws s3 sync sphinx/scikit-intro/build/html s3://learn-scikit.oneoffcoder.com --quiet
       - aws s3 sync sphinx/spark-intro/build/html s3://learn-spark.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/datascience/build/html s3://datascience.oneoffcoder.com --quiet
       - echo Build completed on `date`

From f6ac30b360377e44781e58e6109f25d0f105048b Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Thu, 7 Nov 2019 15:37:07 -0500
Subject: [PATCH 18/30] add project

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index a7b80553..b760499f 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -19,6 +19,7 @@ phases:
       - cd sphinx/scikit-intro && make clean && make html && cd ../..
       - cd sphinx/spark-intro && make clean && make html && cd ../..
       - cd sphinx/datascience && make clean && make html && cd ../..
+      - cd sphinx/python-dothis && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -27,4 +28,5 @@ phases:
       - aws s3 sync sphinx/scikit-intro/build/html s3://learn-scikit.oneoffcoder.com --quiet
       - aws s3 sync sphinx/spark-intro/build/html s3://learn-spark.oneoffcoder.com --quiet
       - aws s3 sync sphinx/datascience/build/html s3://datascience.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/python-dothis/build/html s3://python.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 3bf61e8eea365cad96133d37a979190af98a9307 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Tue, 12 Nov 2019 00:13:49 -0500
Subject: [PATCH 19/30] build scratch too

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index b760499f..5148e272 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -20,6 +20,7 @@ phases:
       - cd sphinx/spark-intro && make clean && make html && cd ../..
       - cd sphinx/datascience && make clean && make html && cd ../..
       - cd sphinx/python-dothis && make clean && make html && cd ../..
+      - cd sphinx/scratch && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -29,4 +30,5 @@ phases:
       - aws s3 sync sphinx/spark-intro/build/html s3://learn-spark.oneoffcoder.com --quiet
       - aws s3 sync sphinx/datascience/build/html s3://datascience.oneoffcoder.com --quiet
       - aws s3 sync sphinx/python-dothis/build/html s3://python.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/scratch/build/html s3://scratch.oneoffcoder.com --quiet
       - echo Build completed on `date`

From c5543c456cd5dc7c8492e649c74d0ee5ef026aa1 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Tue, 19 Nov 2019 21:43:13 -0500
Subject: [PATCH 20/30] build tello and makeblock

---
 buildspec.yml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index 5148e272..8250abbb 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -21,6 +21,8 @@ phases:
       - cd sphinx/datascience && make clean && make html && cd ../..
       - cd sphinx/python-dothis && make clean && make html && cd ../..
       - cd sphinx/scratch && make clean && make html && cd ../..
+      - cd sphinx/tello && make clean && make html && cd ../..
+      - cd sphinx/makeblock && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -31,4 +33,6 @@ phases:
       - aws s3 sync sphinx/datascience/build/html s3://datascience.oneoffcoder.com --quiet
       - aws s3 sync sphinx/python-dothis/build/html s3://python.oneoffcoder.com --quiet
       - aws s3 sync sphinx/scratch/build/html s3://scratch.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/tello/build/html s3://tello.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/makeblock/build/html s3://makeblock.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 48de1e95c27004f540a65eebc3a0224954a4374a Mon Sep 17 00:00:00 2001
From: Jee Vang <super@Shengs-MBP.fios-router.home>
Date: Fri, 22 Nov 2019 10:19:00 -0500
Subject: [PATCH 21/30] build r book

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index 8250abbb..efba7b54 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -23,6 +23,7 @@ phases:
       - cd sphinx/scratch && make clean && make html && cd ../..
       - cd sphinx/tello && make clean && make html && cd ../..
       - cd sphinx/makeblock && make clean && make html && cd ../..
+      - cd sphinx/r-intro && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -35,4 +36,5 @@ phases:
       - aws s3 sync sphinx/scratch/build/html s3://scratch.oneoffcoder.com --quiet
       - aws s3 sync sphinx/tello/build/html s3://tello.oneoffcoder.com --quiet
       - aws s3 sync sphinx/makeblock/build/html s3://makeblock.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/r-intro/build/html s3://r.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 2b944e10a4d02bb5e4d77bd9503d64f53829cdb9 Mon Sep 17 00:00:00 2001
From: Jee Vang <super@Shengs-MBP.fios-router.home>
Date: Fri, 22 Nov 2019 10:40:16 -0500
Subject: [PATCH 22/30] build excel too

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index efba7b54..af41f61a 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -24,6 +24,7 @@ phases:
       - cd sphinx/tello && make clean && make html && cd ../..
       - cd sphinx/makeblock && make clean && make html && cd ../..
       - cd sphinx/r-intro && make clean && make html && cd ../..
+      - cd sphinx/excel && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -37,4 +38,5 @@ phases:
       - aws s3 sync sphinx/tello/build/html s3://tello.oneoffcoder.com --quiet
       - aws s3 sync sphinx/makeblock/build/html s3://makeblock.oneoffcoder.com --quiet
       - aws s3 sync sphinx/r-intro/build/html s3://r.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/excel/build/html s3://excel.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 383914f678c4408976a05f086ff257383fd6efd3 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Fri, 29 Nov 2019 16:42:55 -0500
Subject: [PATCH 23/30] add docker

---
 buildspec.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/buildspec.yml b/buildspec.yml
index af41f61a..248c17ed 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -25,6 +25,7 @@ phases:
       - cd sphinx/makeblock && make clean && make html && cd ../..
       - cd sphinx/r-intro && make clean && make html && cd ../..
       - cd sphinx/excel && make clean && make html && cd ../..
+      - cd sphinx/docker && make clean && make html && cd ../..
   post_build:
     commands:
       - aws s3 sync sphinx/java-intro/build/html s3://learn-java.oneoffcoder.com --quiet
@@ -39,4 +40,5 @@ phases:
       - aws s3 sync sphinx/makeblock/build/html s3://makeblock.oneoffcoder.com --quiet
       - aws s3 sync sphinx/r-intro/build/html s3://r.oneoffcoder.com --quiet
       - aws s3 sync sphinx/excel/build/html s3://excel.oneoffcoder.com --quiet
+      - aws s3 sync sphinx/docker/build/html s3://docker.oneoffcoder.com --quiet
       - echo Build completed on `date`

From 8bbbbe845d6c67e1eb73cfa8ef5f78659165ec03 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Thu, 5 Dec 2019 09:23:05 -0500
Subject: [PATCH 24/30] add package

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 248c17ed..65c8af65 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,7 +6,7 @@ phases:
       python: "3.7"
     commands:
       - apt-get -qq install pandoc -y
-      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinx-autobuild nbsphinx -q
+      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild nbsphinx -q
   pre_build:
     commands:
       - python --version

From 08348c3f22420e9da23c280b92f7edf3045bd060 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Thu, 5 Dec 2019 22:50:06 -0500
Subject: [PATCH 25/30] add ext

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 65c8af65..8922e1c6 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -6,7 +6,7 @@ phases:
       python: "3.7"
     commands:
       - apt-get -qq install pandoc -y
-      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild nbsphinx -q
+      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild sphinx-sitemap nbsphinx -q
   pre_build:
     commands:
       - python --version

From 3cff71f2f29fffee30ee6595cb8c1fe16a3b611d Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Tue, 24 Mar 2020 04:43:29 -0400
Subject: [PATCH 26/30] update

---
 buildspec.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/buildspec.yml b/buildspec.yml
index 8922e1c6..e47bac01 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -5,6 +5,7 @@ phases:
     runtime-versions:
       python: "3.7"
     commands:
+      - lsb_release -a
       - apt-get -qq install pandoc -y
       - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild sphinx-sitemap nbsphinx -q
   pre_build:

From a4221ddd16f772b302b9abf21c0a7eb88c4de344 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Mon, 25 May 2020 13:10:42 -0400
Subject: [PATCH 27/30] update

---
 buildspec.yml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index e47bac01..6cefc0aa 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -3,8 +3,9 @@ version: 0.2
 phases:
   install:
     runtime-versions:
-      python: "3.7"
+      python: "3.8"
     commands:
+      - apt-get update
       - lsb_release -a
       - apt-get -qq install pandoc -y
       - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild sphinx-sitemap nbsphinx -q

From 6ffd15c0b074a2b132397af2ad65841abaa490ed Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Tue, 1 Dec 2020 01:24:23 -0500
Subject: [PATCH 28/30] add package

---
 buildspec.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildspec.yml b/buildspec.yml
index 6cefc0aa..e4e7df9b 100644
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -8,7 +8,7 @@ phases:
       - apt-get update
       - lsb_release -a
       - apt-get -qq install pandoc -y
-      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild sphinx-sitemap nbsphinx -q
+      - pip install ipython sphinx sphinx_rtd_theme sphinxcontrib-bibtex sphinxcontrib-blockdiag sphinx-autobuild sphinx-sitemap jupyter-sphinx nbsphinx -q
   pre_build:
     commands:
       - python --version

From 437b7249f9d6a71272807a2cb2532c1a4e3cb1c9 Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Thu, 8 Feb 2024 16:10:18 -0500
Subject: [PATCH 29/30] fix wording

---
 sphinx/datascience/source/d-separation.ipynb | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sphinx/datascience/source/d-separation.ipynb b/sphinx/datascience/source/d-separation.ipynb
index 459bb3a2..d06ace02 100644
--- a/sphinx/datascience/source/d-separation.ipynb
+++ b/sphinx/datascience/source/d-separation.ipynb
@@ -159,10 +159,10 @@
     "- Output: True or False\n",
     "- Find all paths, $P$, between $X$ and $Y$\n",
     "- For each path $p$ in $P$\n",
-    "  - if $p$ is inactive, return True\n",
-    "- return False\n",
+    "  - if $p$ is active, return False\n",
+    "- return True\n",
     "\n",
-    "In the algorithm above, if we find any path in $G$ between $X$ and $Y$ (given $Z$) that is active, then $X$ and $Y$ are d-connected; if we cannot find any active path between $X$ and $Y$ (given $Z$) in $G$ then they are d-separated. The idea of an active and inactive path comes through understanding the configuration of triplets. In general, there are 3 types of triplet configurations.\n",
+    "In the algorithm above, if we find any path in $G$ between $X$ and $Y$ (given $Z$) that is active, then $X$ and $Y$ are d-connected; if we cannot find any active path between $X$ and $Y$ (given $Z$) in $G$ then they are d-separated. The idea of an active and inactive path comes through understanding the configuration of triplets in a DAG. In general, there are 3 types of triplet configurations.\n",
     "\n",
     "- serial: $X \\rightarrow Z \\rightarrow Y$ (causal chain)\n",
     "- diverging: $X \\leftarrow Z \\rightarrow Y$ (common cause)\n",

From c0f033d8ac42d41cfac1fd0ecd90c79d556b0bae Mon Sep 17 00:00:00 2001
From: "Jee Vang, Ph.D" <vangjee@gmail.com>
Date: Thu, 8 Feb 2024 17:51:55 -0500
Subject: [PATCH 30/30] add

---
 sphinx/datascience/source/Untitled2.ipynb | 233 +++++++++++++
 sphinx/datascience/source/Untitled3.ipynb | 383 ++++++++++++++++++++++
 2 files changed, 616 insertions(+)
 create mode 100644 sphinx/datascience/source/Untitled2.ipynb
 create mode 100644 sphinx/datascience/source/Untitled3.ipynb

diff --git a/sphinx/datascience/source/Untitled2.ipynb b/sphinx/datascience/source/Untitled2.ipynb
new file mode 100644
index 00000000..325f892e
--- /dev/null
+++ b/sphinx/datascience/source/Untitled2.ipynb
@@ -0,0 +1,233 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "02b06357-7fae-4b8d-a507-23600b4c301b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from pybbn.graph.dag import Bbn\n",
+    "from pybbn.graph.edge import Edge, EdgeType\n",
+    "from pybbn.graph.jointree import EvidenceBuilder\n",
+    "from pybbn.graph.node import BbnNode\n",
+    "from pybbn.graph.variable import Variable\n",
+    "from pybbn.pptc.inferencecontroller import InferenceController\n",
+    "\n",
+    "C = BbnNode(Variable(0, 'confounder', ['false', 'true']), [0.8, 0.2])\n",
+    "T = BbnNode(Variable(1, 'treatment', ['false', 'true']), [0.8, 0.2, 0.2, 0.8])\n",
+    "M = BbnNode(Variable(2, 'mediator', ['false', 'true']), [0.75, 0.25, 0.1, 0.9])\n",
+    "Y = BbnNode(Variable(3, 'output', ['false', 'true']), [0.99, 0.01, 0.6, 0.4, 0.55, 0.45, 0.2, 0.8])\n",
+    "\n",
+    "bbn = Bbn() \\\n",
+    "    .add_node(C) \\\n",
+    "    .add_node(T) \\\n",
+    "    .add_node(M) \\\n",
+    "    .add_node(Y) \\\n",
+    "    .add_edge(Edge(C, T, EdgeType.DIRECTED)) \\\n",
+    "    .add_edge(Edge(T, M, EdgeType.DIRECTED)) \\\n",
+    "    .add_edge(Edge(C, Y, EdgeType.DIRECTED)) \\\n",
+    "    .add_edge(Edge(M, Y, EdgeType.DIRECTED))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "d457dd2b-d1b5-4638-8c7c-2938865dcb33",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from pybbn.pptc.inferencecontroller import InferenceController\n",
+    "\n",
+    "join_tree = InferenceController.apply(bbn)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "aa86f6e8-dcd2-4154-947f-7663324406d8",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import pandas as pd\n",
+    "from pybbn.sampling.sampling import LogicSampler\n",
+    "\n",
+    "sampler = LogicSampler(bbn)\n",
+    "samples = sampler.get_samples(n_samples=1_000, seed=37)\n",
+    "\n",
+    "df = pd.DataFrame(samples).rename(columns={0: 'C', 1: 'T', 2: 'M', 3: 'Y'})"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "6963204f-12f5-49aa-b43e-45ba3edae2cf",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>C</th>\n",
+       "      <th>T</th>\n",
+       "      <th>M</th>\n",
+       "      <th>Y</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>false</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>...</th>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "      <td>...</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>995</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>996</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>997</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>998</th>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>999</th>\n",
+       "      <td>false</td>\n",
+       "      <td>true</td>\n",
+       "      <td>true</td>\n",
+       "      <td>false</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "<p>1000 rows × 4 columns</p>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "         C      T      M      Y\n",
+       "0     true   true   true   true\n",
+       "1    false  false  false  false\n",
+       "2    false  false   true   true\n",
+       "3    false   true   true  false\n",
+       "4    false  false  false  false\n",
+       "..     ...    ...    ...    ...\n",
+       "995  false  false  false  false\n",
+       "996  false  false  false  false\n",
+       "997  false  false   true   true\n",
+       "998  false  false  false  false\n",
+       "999  false   true   true  false\n",
+       "\n",
+       "[1000 rows x 4 columns]"
+      ]
+     },
+     "execution_count": 17,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e7f7985c-30a6-4fe4-9cc3-fd9717f946c6",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/sphinx/datascience/source/Untitled3.ipynb b/sphinx/datascience/source/Untitled3.ipynb
new file mode 100644
index 00000000..22ea5c0e
--- /dev/null
+++ b/sphinx/datascience/source/Untitled3.ipynb
@@ -0,0 +1,383 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "2ab878db-7cb6-4c5d-917a-08f69aedadd0",
+   "metadata": {},
+   "source": [
+    "- [4.6 - The Backdoor Adjustment](https://www.youtube.com/watch?v=U1S8Rq8IcrY)\n",
+    "- [07-5 d-Separation and Backdoor Criterion](https://www.youtube.com/watch?v=yoPk3PL9-KY)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "cc7c8d90-2acc-4025-bf73-da251ce58403",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import networkx as nx\n",
+    "from collections import namedtuple\n",
+    "\n",
+    "Graph = namedtuple('Graph', 'u, d')\n",
+    "\n",
+    "def get_edges(s):\n",
+    "    edges = s.split('\\n')\n",
+    "    edges = map(lambda line: line.split('->'), edges)\n",
+    "    edges = map(lambda tokens: tuple([t.strip() for t in tokens]), edges)\n",
+    "    edges = list(edges)\n",
+    "\n",
+    "    return edges\n",
+    "\n",
+    "def get_directed_graph(edges):\n",
+    "    g = nx.DiGraph()\n",
+    "    g.add_edges_from(edges)\n",
+    "\n",
+    "    return g\n",
+    "\n",
+    "def get_undirected_graph(edges):\n",
+    "    g = nx.Graph()\n",
+    "    g.add_edges_from(edges)\n",
+    "\n",
+    "    return g\n",
+    "\n",
+    "def get_graph(s):\n",
+    "    e = get_edges(s)\n",
+    "\n",
+    "    d = get_directed_graph(e)\n",
+    "    u = get_undirected_graph(e)\n",
+    "    g = Graph(u, d)\n",
+    "\n",
+    "    return g"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "2ec83469-b16d-4050-accb-9ac5df8db0f0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s = '''\n",
+    "W2 -> W1\n",
+    "W2 -> W3\n",
+    "W1 -> T\n",
+    "C -> T\n",
+    "T -> M\n",
+    "W3 -> Y\n",
+    "C -> Y\n",
+    "M -> Y\n",
+    "'''.strip()\n",
+    "\n",
+    "g1 = get_graph(s)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "b02b7d53-96a4-4065-a657-63d434cbe40f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "s = '''\n",
+    "W -> Z\n",
+    "U -> Z\n",
+    "U -> T\n",
+    "Z -> X\n",
+    "X -> T\n",
+    "X -> Y\n",
+    "T -> Y\n",
+    "'''.strip()\n",
+    "\n",
+    "g2 = get_graph(s)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "13f7d287-1a26-46e0-b824-b95784dd845a",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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",
+      "text/plain": [
+       "<Figure size 1000x350 with 2 Axes>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "\n",
+    "def plot_graph(g, ax):\n",
+    "    pos = nx.nx_agraph.graphviz_layout(g.d, prog='dot')\n",
+    "    \n",
+    "    nx.draw_networkx_nodes(\n",
+    "        G=g.d,\n",
+    "        pos=pos,\n",
+    "        ax=ax,\n",
+    "        node_size=100,\n",
+    "        alpha=0.5,\n",
+    "        node_color='red'\n",
+    "    )\n",
+    "    \n",
+    "    nx.draw_networkx_labels(\n",
+    "        G=g.d,\n",
+    "        pos=pos,\n",
+    "        ax=ax,\n",
+    "        font_size=15,\n",
+    "        font_color='black',\n",
+    "        alpha=1.0\n",
+    "    )\n",
+    "    \n",
+    "    nx.draw_networkx_edges(\n",
+    "        G=g.d,\n",
+    "        pos=pos,\n",
+    "        alpha=0.25,\n",
+    "        arrowsize=30,\n",
+    "        ax=ax\n",
+    "    )\n",
+    "\n",
+    "fig, ax = plt.subplots(1, 2, figsize=(10, 3.5))\n",
+    "\n",
+    "plot_graph(g1, ax[0])\n",
+    "plot_graph(g2, ax[1])\n",
+    "\n",
+    "ax[0].set_title('Graph 1')\n",
+    "ax[1].set_title('Graph 2')\n",
+    "\n",
+    "fig.tight_layout()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 42,
+   "id": "1f25dc9d-675c-44ea-a840-0d949999aac1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import itertools\n",
+    "\n",
+    "def get_all_paths(g, start, stop):\n",
+    "    return nx.all_simple_paths(g.u, start, stop)\n",
+    "\n",
+    "def get_path_triplets(path):\n",
+    "    if len(path) < 3:\n",
+    "        return [path]\n",
+    "    else:\n",
+    "        return [path[i:i+3] for i in range(0, len(path) - 2)]\n",
+    "\n",
+    "def get_triplet_type(g, x, z, y):\n",
+    "    x_children = set(g.d.successors(x))\n",
+    "    z_children = set(g.d.successors(z))\n",
+    "    y_children = set(g.d.successors(y))\n",
+    "\n",
+    "    if z in x_children and y in z_children:\n",
+    "        return 'serial'\n",
+    "    if z in y_children and x in z_children:\n",
+    "        return 'serial'\n",
+    "    if x in z_children and y in z_children:\n",
+    "        return 'diverging'\n",
+    "    if z in x_children and z in y_children:\n",
+    "        return 'converging'\n",
+    "    raise Exception(f'cannot determine triplet configuration: x={x}, z={z}, y={y}')\n",
+    "\n",
+    "def is_active_triplet(g, x, z, y, evidence=set()):\n",
+    "    triplet_type = get_triplet_type(g, x, z, y)\n",
+    "\n",
+    "    if triplet_type in {'serial', 'diverging'}:\n",
+    "        if z in evidence:\n",
+    "            return False\n",
+    "        else:\n",
+    "            return True\n",
+    "    else:\n",
+    "        z_set = nx.descendants(g.d, z)\n",
+    "        z_set.add(z)\n",
+    "\n",
+    "        if len(z_set & evidence) > 0:\n",
+    "            return True\n",
+    "        else:\n",
+    "            return False\n",
+    "\n",
+    "def is_active_path(g, path, evidence=set()):\n",
+    "    if len(path) < 3:\n",
+    "        if path[0] in evidence or path[-1] in evidence:\n",
+    "            return False\n",
+    "        else:\n",
+    "            return True\n",
+    "\n",
+    "    path_triplets = get_path_triplets(path)\n",
+    "\n",
+    "    for x, z, y in path_triplets:\n",
+    "        if not is_active_triplet(g, x, z, y, evidence):\n",
+    "            return False\n",
+    "    return True\n",
+    "\n",
+    "def get_colliders(g, path):\n",
+    "    if len(path) < 3:\n",
+    "        return []\n",
+    "\n",
+    "    path_triplets = get_path_triplets(path)\n",
+    "    return [z for x, z, y in path_triplets if get_triplet_type(g, x, z, y) == 'converging']\n",
+    "    \n",
+    "def get_paths(g, x, y):\n",
+    "    paths = get_all_paths(g, x, y)\n",
+    "    return [{'path': p, 'is_active': is_active_path(g, p), 'colliders': get_colliders(g, p)} for p in paths]\n",
+    "\n",
+    "def get_backdoors(g, x, y):\n",
+    "    paths = get_paths(g, x, y)\n",
+    "\n",
+    "    colliders = [p['colliders'] for p in paths if p['is_active'] == False]\n",
+    "    colliders = itertools.chain(*colliders)\n",
+    "    colliders = set(colliders)\n",
+    "    print(f'{colliders=}')\n",
+    "    \n",
+    "    descendants = nx.descendants(g.d, x)\n",
+    "    print(f'{descendants=}')\n",
+    "\n",
+    "    exclude = colliders | descendants | {x, y}\n",
+    "    print(f'{exclude=}')\n",
+    "\n",
+    "    candidates = [[n for n in p['path'] if n not in exclude] for p in paths if p['is_active'] == True]\n",
+    "    print(f'{candidates=}')\n",
+    "    candidates = itertools.chain(*candidates)\n",
+    "    candidates = set(candidates)\n",
+    "\n",
+    "    return candidates"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 43,
+   "id": "a082128c-24c3-430d-8150-103de15f563f",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "colliders={'T', 'Z'}\n",
+      "descendants={'T', 'X', 'Y', 'Z'}\n",
+      "exclude={'W', 'Z', 'T', 'X', 'Y'}\n",
+      "candidates=[[], []]\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "set()"
+      ]
+     },
+     "execution_count": 43,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_backdoors(g2, 'W', 'Y')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "id": "721553f8-1353-484a-b9ae-09ee3592ecc0",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'path': ['T', 'W1', 'W2', 'W3', 'Y'], 'is_active': True, 'colliders': []},\n",
+       " {'path': ['T', 'C', 'Y'], 'is_active': True, 'colliders': []},\n",
+       " {'path': ['T', 'M', 'Y'], 'is_active': True, 'colliders': []}]"
+      ]
+     },
+     "execution_count": 34,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_paths(g1, 'T', 'Y')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "id": "f46b2bab-2d5d-40e0-b259-44580c72ca40",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'C', 'W1', 'W2', 'W3'}"
+      ]
+     },
+     "execution_count": 35,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_backdoors(g1, 'T', 'Y')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "id": "ea267693-713d-46fa-a8dc-265c8fc244e3",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'path': ['W', 'Z', 'U', 'T', 'X', 'Y'],\n",
+       "  'is_active': False,\n",
+       "  'colliders': ['Z', 'T']},\n",
+       " {'path': ['W', 'Z', 'U', 'T', 'Y'], 'is_active': False, 'colliders': ['Z']},\n",
+       " {'path': ['W', 'Z', 'X', 'T', 'Y'], 'is_active': True, 'colliders': []},\n",
+       " {'path': ['W', 'Z', 'X', 'Y'], 'is_active': True, 'colliders': []}]"
+      ]
+     },
+     "execution_count": 36,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "get_paths(g2, 'W', 'Y')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6cb379ca-9c17-4d76-a371-bac56b335ea0",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
