diff --git a/.coverage.DESKTOP-ATMEKSV.10780.XNWpwYfx b/.coverage.DESKTOP-ATMEKSV.10780.XNWpwYfx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.12404.XzQmGlCx b/.coverage.DESKTOP-ATMEKSV.12404.XzQmGlCx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.12452.XgsSHyzx b/.coverage.DESKTOP-ATMEKSV.12452.XgsSHyzx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.21288.XCZBWtjx b/.coverage.DESKTOP-ATMEKSV.21288.XCZBWtjx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.21748.XBOljdvx b/.coverage.DESKTOP-ATMEKSV.21748.XBOljdvx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.24064.XFYCqtPx b/.coverage.DESKTOP-ATMEKSV.24064.XFYCqtPx
deleted file mode 100644
index e1f7e6f75f5aa9a7a33884193b67b7cc22082200..0000000000000000000000000000000000000000
Binary files a/.coverage.DESKTOP-ATMEKSV.24064.XFYCqtPx and /dev/null differ
diff --git a/.coverage.DESKTOP-ATMEKSV.26128.XrTwIHQx b/.coverage.DESKTOP-ATMEKSV.26128.XrTwIHQx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.26336.XXhjOUCx b/.coverage.DESKTOP-ATMEKSV.26336.XXhjOUCx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.27368.XKadoIex b/.coverage.DESKTOP-ATMEKSV.27368.XKadoIex
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.27856.XpjNuPSx b/.coverage.DESKTOP-ATMEKSV.27856.XpjNuPSx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.28136.XQytruKx b/.coverage.DESKTOP-ATMEKSV.28136.XQytruKx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.30088.XBTNpNAx b/.coverage.DESKTOP-ATMEKSV.30088.XBTNpNAx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.31644.XFWeLHFx b/.coverage.DESKTOP-ATMEKSV.31644.XFWeLHFx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.32652.XxCzZPCx b/.coverage.DESKTOP-ATMEKSV.32652.XxCzZPCx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.32976.XFBoIPNx b/.coverage.DESKTOP-ATMEKSV.32976.XFBoIPNx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.33768.XqlATslx b/.coverage.DESKTOP-ATMEKSV.33768.XqlATslx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.33992.XFaaFKJx b/.coverage.DESKTOP-ATMEKSV.33992.XFaaFKJx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.35124.XBfpxDZx b/.coverage.DESKTOP-ATMEKSV.35124.XBfpxDZx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/.coverage.DESKTOP-ATMEKSV.35624.XJVIwqYx b/.coverage.DESKTOP-ATMEKSV.35624.XJVIwqYx
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Outputs_Bayes_None_Calib/emcee_sampler.h5 b/Outputs_Bayes_None_Calib/emcee_sampler.h5
new file mode 100644
index 0000000000000000000000000000000000000000..bd7c2effd1b69997af86c87a8380da8ba2b9ad3d
Binary files /dev/null and b/Outputs_Bayes_None_Calib/emcee_sampler.h5 differ
diff --git a/docs/diagrams/.$Structure_BayesInf.drawio.dtmp b/docs/diagrams/.$Structure_BayesInf.drawio.dtmp
new file mode 100644
index 0000000000000000000000000000000000000000..bb32f9077e4d990a49743e90a0e4ea0837c77a5d
--- /dev/null
+++ b/docs/diagrams/.$Structure_BayesInf.drawio.dtmp
@@ -0,0 +1,449 @@
+<mxfile host="Electron" modified="2024-04-10T14:28:07.605Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="Yia9ahrH6Vnw8ZCcm-TH" version="22.1.11" type="device" pages="2">
+  <diagram name="Class and function structure" id="efOe0Jku58RX-i1bv-3b">
+    <mxGraphModel dx="1686" dy="1114" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-1" value="_kernel_rbf" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="1070" y="200" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-2" value="_logpdf" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="860" y="130" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-10" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BayesInf&lt;/b&gt;&lt;/p&gt;&lt;hr size=&quot;1&quot;&gt;&lt;div style=&quot;height:2px;&quot;&gt;&lt;/div&gt;" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="-80" y="280" width="1270" height="820" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-24" value="if self.bootstrap &lt;br&gt;or self.bayes_loocv &lt;br&gt;or self.just_analysis" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;labelBackgroundColor=#ffae00;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-13">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-18">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-42" value="if self.name != &#39;valid&#39;&lt;br&gt;and self.inference_method != &#39;rejection&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-31">
+          <mxGeometry x="0.5646" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-22">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-43" value="if self.inference_method == &#39;mcmc&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-32">
+          <mxGeometry x="-0.0958" y="-1" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-19">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-52" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#C2C2C2;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-33">
+          <mxGeometry x="-0.112" y="1" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-21">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-47" value="if self.plot_post_pred" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-34">
+          <mxGeometry x="0.2399" y="-1" relative="1" as="geometry">
+            <mxPoint y="1" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-20">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-46" value="if self.plot_map_pred" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-35">
+          <mxGeometry x="0.4183" y="-1" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-55" value="if self.bootstrap" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-54">
+          <mxGeometry x="0.1816" y="3" relative="1" as="geometry">
+            <mxPoint x="1" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-56">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-58" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-57">
+          <mxGeometry x="0.7182" y="2" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-59">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-61" value="if self.error_model&lt;br&gt;and self.name == &#39;calib&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-60">
+          <mxGeometry x="0.3024" y="2" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-9" value="create_inference" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1">
+          <mxGeometry x="405" y="539" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-25" value="if len(self.perturbed_data) == 0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-14">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-27" value="if not self.emulator" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-15">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-16">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-44" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-29">
+          <mxGeometry x="0.4722" y="1" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-17">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-41" value="if self.emulator" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-30">
+          <mxGeometry x="0.6143" y="-3" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-59">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="340" y="680" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-63" value="if self.error_model&lt;br&gt;and self.name == &#39;valid&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-62">
+          <mxGeometry x="-0.3906" relative="1" as="geometry">
+            <mxPoint y="156" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-13" value="perform_bootstrap" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="40" y="310" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-14" value="_perturb_data" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="-40" y="560" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-15" value="_eval_model" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="1050" y="660" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-16" target="xary-zVek9Bg-A1b1ZmA-1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-49" value="if hasattr bias_inputs&amp;nbsp;&lt;br&gt;and not hasattr error_model" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#ffae00;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-38">
+          <mxGeometry x="0.3126" y="-3" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-16" target="xary-zVek9Bg-A1b1ZmA-2">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-16" value="normpdf" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="650" y="390" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-17" target="xary-zVek9Bg-A1b1ZmA-2">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-50" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-40">
+          <mxGeometry x="-0.6073" y="-5" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-17" value="_corr_factor_BME" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="650" y="450" width="110" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-18" value="_rejection_sampling" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="400" y="990" width="120" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-26" value="if not self.emulator&amp;nbsp;&lt;br&gt;and not self.inference_method == &#39;rejection&#39;&amp;nbsp;&lt;br&gt;and self.name == &#39;calib" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-19" target="xary-zVek9Bg-A1b1ZmA-15">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-19" target="xary-zVek9Bg-A1b1ZmA-1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-48" value="if sigma2_prior is not None&lt;br&gt;and if hasattr bias_inputs&lt;br&gt;and if not hasattr error_model" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#ffae00;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-37">
+          <mxGeometry x="-0.5544" y="-1" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-19" value="_posterior_predictive" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="675" y="590" width="130" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-20" target="xary-zVek9Bg-A1b1ZmA-15">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-45" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#cdcbcb;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-28">
+          <mxGeometry x="0.0517" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-20" value="_plot_max_a_posteriori" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="495" y="790" width="140" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-21" value="plot_post_predictive" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="630" y="720" width="120" height="50" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-22" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MCMC&lt;/b&gt;&lt;/p&gt;&lt;hr size=&quot;1&quot;&gt;&lt;div style=&quot;height:2px;&quot;&gt;&lt;/div&gt;" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
+          <mxGeometry x="1230" y="425" width="760" height="275" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-36" value="Note: Arrows indicate function calls, beginning calls the end" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
+          <mxGeometry x="10" y="10" width="190" height="30" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-51" value="Color meanings:&lt;br&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;red: wrong, change&lt;br&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;orange: seems off, look at again" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
+          <mxGeometry x="20" y="70" width="220" height="30" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-53" value="plot_log_BME" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="220" y="980" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-56" value="plot_post_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="660" y="840" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-59" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="35" y="840" width="120" height="60" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+  <diagram id="ME5gyYpVqUByTnAIOcMV" name="Parameter and function interaction">
+    <mxGraphModel dx="2049" dy="1366" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-1" value="engine" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="160" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-3" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="240" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-71" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-4" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-4" value="emulator" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="320" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-5" value="name" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="400" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-6" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-6" value="bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="480" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-7" value="req_outputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="560" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-8" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-8" value="selected_indices" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="640" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-9" value="prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="720" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-68" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-11" value="n_prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="800" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-12" value="measured_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="880" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-13" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-13" value="inference_method" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="960" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-14" value="mcmc_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1040" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-15" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-15" value="perturbed_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1120" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-16" value="bayes_loocv" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1200" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-17" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-17" value="n_bootstrap_itrs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1280" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-18" value="bootstrap_noise" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1360" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-78" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-19" value="just_analysis" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1440" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-20" value="valid_metrics" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1520" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-21" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-21" value="plot_post_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1600" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-22" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-22" value="plot_map_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1680" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-23" value="max_a_posteriori" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1760" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-24" value="corner_title_fmt" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1840" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-25" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-25" value="out_dir" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1920" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-26" value="error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2000" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-56" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-72" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-27" value="bias_inputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2080" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-28" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-28" value="measurement_error" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2160" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-29" value="sigma2s" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2240" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-30" value="log_likes" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2320" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-31" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-31" value="dtype" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2400" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-32" value="create_inference" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="400" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-39" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-39" value="n_tot_measurement" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2480" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-42" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-42" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2560" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-48" value="posterior_df" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2640" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-53" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="560" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-60" value="perform_bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="720" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-75" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-69" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-69" value="__mean_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2720" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-70" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-70" value="_std_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2800" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-73" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-73" value="__model_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2880" width="120" height="60" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/docs/diagrams/Structure_BayesInf.drawio b/docs/diagrams/Structure_BayesInf.drawio
index 1651230d37cc9da9120a7f0ae60ff3450d8f225a..ddabd26efb05c7db4ee7a49855f1a3585a883d58 100644
--- a/docs/diagrams/Structure_BayesInf.drawio
+++ b/docs/diagrams/Structure_BayesInf.drawio
@@ -1,6 +1,6 @@
-<mxfile host="Electron" modified="2024-04-10T11:36:50.177Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="zH0uklPxig_FBrKRFuLP" version="22.1.11" type="device">
-  <diagram name="Page-1" id="efOe0Jku58RX-i1bv-3b">
-    <mxGraphModel dx="836" dy="1114" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+<mxfile host="Electron" modified="2024-04-10T14:28:03.443Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.11 Chrome/114.0.5735.289 Electron/25.9.8 Safari/537.36" etag="3hqTB6OXl10kbEaaeQUl" version="22.1.11" type="device" pages="2">
+  <diagram name="Class and function structure" id="efOe0Jku58RX-i1bv-3b">
+    <mxGraphModel dx="1686" dy="1114" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
       <root>
         <mxCell id="0" />
         <mxCell id="1" parent="0" />
@@ -11,7 +11,7 @@
           <mxGeometry x="860" y="130" width="120" height="60" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-10" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BayesInf&lt;/b&gt;&lt;/p&gt;&lt;hr size=&quot;1&quot;&gt;&lt;div style=&quot;height:2px;&quot;&gt;&lt;/div&gt;" style="verticalAlign=top;align=left;overflow=fill;fontSize=12;fontFamily=Helvetica;html=1;whiteSpace=wrap;" vertex="1" parent="1">
-          <mxGeometry x="40" y="280" width="1150" height="620" as="geometry" />
+          <mxGeometry x="-80" y="280" width="1270" height="820" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-24" value="if self.bootstrap &lt;br&gt;or self.bayes_loocv &lt;br&gt;or self.just_analysis" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;labelBackgroundColor=#ffae00;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-13">
           <mxGeometry relative="1" as="geometry" />
@@ -56,6 +56,30 @@
             <mxPoint as="offset" />
           </mxGeometry>
         </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-55" value="if self.bootstrap" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-54">
+          <mxGeometry x="0.1816" y="3" relative="1" as="geometry">
+            <mxPoint x="1" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-56">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-58" value="always" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#FF9A03;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-57">
+          <mxGeometry x="0.7182" y="2" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-9" target="xary-zVek9Bg-A1b1ZmA-59">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-61" value="if self.error_model&lt;br&gt;and self.name == &#39;calib&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-60">
+          <mxGeometry x="0.3024" y="2" relative="1" as="geometry">
+            <mxPoint as="offset" />
+          </mxGeometry>
+        </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-9" value="create_inference" style="html=1;whiteSpace=wrap;strokeWidth=2;" vertex="1" parent="1">
           <mxGeometry x="405" y="539" width="110" height="50" as="geometry" />
         </mxCell>
@@ -81,11 +105,21 @@
             <mxPoint as="offset" />
           </mxGeometry>
         </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-13" target="xary-zVek9Bg-A1b1ZmA-59">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="340" y="680" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-63" value="if self.error_model&lt;br&gt;and self.name == &#39;valid&#39;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;" vertex="1" connectable="0" parent="xary-zVek9Bg-A1b1ZmA-62">
+          <mxGeometry x="-0.3906" relative="1" as="geometry">
+            <mxPoint y="156" as="offset" />
+          </mxGeometry>
+        </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-13" value="perform_bootstrap" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
-          <mxGeometry x="150" y="310" width="110" height="50" as="geometry" />
+          <mxGeometry x="40" y="310" width="110" height="50" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-14" value="_perturb_data" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
-          <mxGeometry x="150" y="760" width="110" height="50" as="geometry" />
+          <mxGeometry x="-40" y="560" width="110" height="50" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-15" value="_eval_model" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
           <mxGeometry x="1050" y="660" width="110" height="50" as="geometry" />
@@ -116,7 +150,7 @@
           <mxGeometry x="650" y="450" width="110" height="50" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-18" value="_rejection_sampling" style="html=1;whiteSpace=wrap;" vertex="1" parent="1">
-          <mxGeometry x="330" y="790" width="120" height="50" as="geometry" />
+          <mxGeometry x="400" y="990" width="120" height="50" as="geometry" />
         </mxCell>
         <mxCell id="xary-zVek9Bg-A1b1ZmA-26" value="if not self.emulator&amp;nbsp;&lt;br&gt;and not self.inference_method == &#39;rejection&#39;&amp;nbsp;&lt;br&gt;and self.name == &#39;calib" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="xary-zVek9Bg-A1b1ZmA-19" target="xary-zVek9Bg-A1b1ZmA-15">
           <mxGeometry relative="1" as="geometry" />
@@ -155,6 +189,260 @@
         <mxCell id="xary-zVek9Bg-A1b1ZmA-51" value="Color meanings:&lt;br&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;red: wrong, change&lt;br&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;orange: seems off, look at again" style="text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
           <mxGeometry x="20" y="70" width="220" height="30" as="geometry" />
         </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-53" value="plot_log_BME" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="220" y="980" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-56" value="plot_post_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="660" y="840" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="xary-zVek9Bg-A1b1ZmA-59" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="35" y="840" width="120" height="60" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+  <diagram id="ME5gyYpVqUByTnAIOcMV" name="Parameter and function interaction">
+    <mxGraphModel dx="2049" dy="1366" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-1" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-1" value="engine" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="160" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-3" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="240" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-71" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-4" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-4" value="emulator" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="320" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-5" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-5" value="name" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="400" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-6" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-6" value="bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="480" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-7" value="req_outputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="560" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-8" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-8" value="selected_indices" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="640" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-35" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-9" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-9" value="prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="720" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-68" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-11" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-11" value="n_prior_samples" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="800" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-12" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-12" value="measured_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="880" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-13" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-13" value="inference_method" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="960" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-14" value="mcmc_params" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1040" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-15" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-15" value="perturbed_data" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1120" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-77" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-16" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-16" value="bayes_loocv" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1200" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-17" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-17" value="n_bootstrap_itrs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1280" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-18" value="bootstrap_noise" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1360" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-78" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-19" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-19" value="just_analysis" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1440" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-20" value="valid_metrics" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1520" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-21" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-21" value="plot_post_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1600" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-22" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-22" value="plot_map_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1680" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-23" value="max_a_posteriori" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1760" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-24" value="corner_title_fmt" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1840" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-25" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-25" value="out_dir" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="1920" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-26" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-26" value="error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2000" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-56" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-72" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-27" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-27" value="bias_inputs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2080" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-28" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-28" value="measurement_error" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2160" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-29" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-29" value="sigma2s" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2240" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-30" value="log_likes" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2320" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-31" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-31" value="dtype" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2400" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-32" value="create_inference" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="400" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-39" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-39" value="n_tot_measurement" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2480" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-42" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-42" value="Discrepancy" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2560" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-32">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-48" target="K5oJ7VEt7dPmeK6pba1f-53">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-48" value="posterior_df" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2640" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-53" value="create_error_model" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="560" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-60" value="perform_bootstrap" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="720" y="20" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-75" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-69" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-69" value="__mean_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2720" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-70" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-70" value="_std_pce_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2800" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-74" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="K5oJ7VEt7dPmeK6pba1f-73" target="K5oJ7VEt7dPmeK6pba1f-60">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="K5oJ7VEt7dPmeK6pba1f-73" value="__model_prior_pred" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="40" y="2880" width="120" height="60" as="geometry" />
+        </mxCell>
       </root>
     </mxGraphModel>
   </diagram>
diff --git a/.coverage b/examples/.coverage
similarity index 81%
rename from .coverage
rename to examples/.coverage
index e61eed4b7c43a3f551e07789589a565c8682ff7d..254e10e4371d703eefec0f0437f9c0575be3f5ec 100644
Binary files a/.coverage and b/examples/.coverage differ
diff --git a/examples/analytical-function/example_analytical_function.py b/examples/analytical-function/example_analytical_function.py
index 9ec23f8cdaae003c33bac4cfe75e9a1a4d82bc42..37900127ab39018eef4af9dc5fa3f0326e2f4eeb 100644
--- a/examples/analytical-function/example_analytical_function.py
+++ b/examples/analytical-function/example_analytical_function.py
@@ -227,7 +227,8 @@ if __name__ == "__main__":
     MetaModelOpts.ExpDesign = ExpDesign
     engine = Engine(MetaModelOpts, Model, ExpDesign)
     engine.start_engine()
-    engine.train_sequential()
+    #engine.train_sequential()
+    engine.train_normal()
 
     # Load the objects
     # with open(f"PCEModel_{Model.name}.pkl", "rb") as input:
@@ -266,9 +267,9 @@ if __name__ == "__main__":
 
     # BayesOpts.selected_indices = [0, 3, 5,  7, 9]
     # BME Bootstrap
-    # BayesOpts.bootstrap = True
-    # BayesOpts.n_bootstrap_itrs = 500
-    # BayesOpts.bootstrap_noise = 100
+    BayesOpts.bootstrap = True
+    BayesOpts.n_bootstrap_itrs = 500
+    BayesOpts.bootstrap_noise = 100
 
     # Bayesian cross validation
     BayesOpts.bayes_loocv = True  # TODO: test what this does
@@ -296,31 +297,34 @@ if __name__ == "__main__":
     BayesOpts.Discrepancy = DiscrepancyOpts
 
     # -- (Option C) --
-    # DiscOutputOpts = Input()
-    # # # OutputName = 'Z'
-    # DiscOutputOpts.add_marginals()
-    # DiscOutputOpts.Marginals[0].Nnme = '$\sigma^2_{\epsilon}$'
-    # DiscOutputOpts.Marginals[0].dist_type = 'uniform'
-    # DiscOutputOpts.Marginals[0].parameters =  [0, 10]
-    # BayesOpts.Discrepancy = {'known': DiscrepancyOpts,
-    #                           'infer': Discrepancy(DiscOutputOpts)}
-
-    # BayesOpts.bias_inputs = {'Z':np.arange(0, 10, 1.).reshape(-1,1) / 9}
-    # DiscOutputOpts = Input()
-    # # OutputName = 'lambda'
-    # DiscOutputOpts.add_marginals()
-    # DiscOutputOpts.Marginals[0].name = '$\lambda$'
-    # DiscOutputOpts.Marginals[0].dist_type = 'uniform'
-    # DiscOutputOpts.Marginals[0].parameters = [0, 1]
-
-    # # OutputName = 'sigma_f'
-    # DiscOutputOpts.add_marginals()
-    # DiscOutputOpts.Marginals[1].Name = '$\sigma_f$'
-    # DiscOutputOpts.Marginals[1].dist_type = 'uniform'
-    # DiscOutputOpts.Marginals[1].parameters = [0, 1e-4]
-    # BayesOpts.Discrepancy = Discrepancy(DiscOutputOpts)
-    # BayesOpts.Discrepancy = {'known': DiscrepancyOpts,
-    #                           'infer': Discrepancy(DiscOutputOpts)}
+    if 0:
+        DiscOutputOpts = Input()
+        # # # OutputName = 'Z'
+        DiscOutputOpts.add_marginals()
+        DiscOutputOpts.Marginals[0].Nnme = '$\sigma^2_{\epsilon}$'
+        DiscOutputOpts.Marginals[0].dist_type = 'uniform'
+        DiscOutputOpts.Marginals[0].parameters =  [0, 10]
+        #BayesOpts.Discrepancy = {'known': DiscrepancyOpts,
+        #                          'infer': Discrepancy(DiscOutputOpts)}
+    
+        BayesOpts.bias_inputs = {'Z':np.arange(0, 10, 1.).reshape(-1,1) / 9}
+        
+        DiscOutputOpts = Input()
+        # OutputName = 'lambda'
+        DiscOutputOpts.add_marginals()
+        DiscOutputOpts.Marginals[0].name = '$\lambda$'
+        DiscOutputOpts.Marginals[0].dist_type = 'uniform'
+        DiscOutputOpts.Marginals[0].parameters = [0, 1]
+    
+        # # OutputName = 'sigma_f'
+        DiscOutputOpts.add_marginals()
+        DiscOutputOpts.Marginals[1].Name = '$\sigma_f$'
+        DiscOutputOpts.Marginals[1].dist_type = 'uniform'
+        DiscOutputOpts.Marginals[1].parameters = [0, 1e-4]
+        #BayesOpts.Discrepancy = Discrepancy(DiscOutputOpts)
+        BayesOpts.Discrepancy = {'known': DiscrepancyOpts,
+                                  'infer': Discrepancy(DiscOutputOpts)}
+    
     # Start the calibration/inference
     Bayes_PCE = BayesOpts.create_inference()
 
diff --git a/src/bayesvalidrox/bayes_inference/bayes_inference.py b/src/bayesvalidrox/bayes_inference/bayes_inference.py
index 44e90b77c69b4c2c7bd27639727c5d2bd4fe8720..888a689f82b4840a37459423d89fd5c5182e2293 100644
--- a/src/bayesvalidrox/bayes_inference/bayes_inference.py
+++ b/src/bayesvalidrox/bayes_inference/bayes_inference.py
@@ -221,7 +221,6 @@ class BayesInference:
                  corner_title_fmt='.2e', out_dir = ''):
 
         self.engine = engine
-        self.MetaModel = engine.MetaModel
         self.Discrepancy = discrepancy
         self.emulator = emulator
         self.name = name
@@ -244,32 +243,43 @@ class BayesInference:
         self.max_a_posteriori = max_a_posteriori
         self.corner_title_fmt = corner_title_fmt
         self.out_dir = out_dir
+        
+        # Other properties and parameters (found in code, but never set)
+        self.error_model = False # TODO: no example or use case for this!
+        self.bias_inputs = None
+        self.measurement_error = None # TODO: what is this?
+        self.sigma2s = None
+        self.log_likes = None
+        self.n_tot_measurement = None
+        self.Discrepancy = None
+        self.posterior_df = None
+        self.error_MetaModel = None
+        self._mean_pce_prior_pred = None
+        self._std_pce_prior_pred = None
+        self.__model_prior_pred = None
+        
+        # System settings
+        if os.name == 'nt':
+            print('')
+            print('WARNING: Performing the inference on windows can lead to reduced accuracy!')
+            print('')
+            self.dtype=np.longdouble
+        else:
+            self.dtype=np.float128
 
-    # -------------------------------------------------------------------------
-    def create_inference(self):
+    def setup_inference(self):
         """
-        Starts the inference.
-
-        Returns
-        -------
-        BayesInference : obj
-            The Bayes inference object.
-            
-        # TODO: should this function really return the class?
-
+        This function sets up the inference by checking the inputs and getting 
+        needed data.
         """
-        # Set some variables
-        MetaModel = self.MetaModel
         Model = self.engine.Model
-        n_params = MetaModel.n_params
-        output_names = Model.Output.names
-        par_names = self.engine.ExpDesign.par_names
         
         # Create output directory
         if self.out_dir == '':
-            self.out_dir = f'Outputs_Bayes_{Model.name}_{self.name}'
+            self.out_dir = f'Outputs_Bayes_{self.engine.Model.name}_{self.name}'
         os.makedirs(self.out_dir, exist_ok=True)
         
+        
         # If the prior is set by the user, take it, else generate from ExpDes
         if self.prior_samples is None:
             self.prior_samples = self.engine.ExpDesign.generate_samples(
@@ -287,7 +297,8 @@ class BayesInference:
             self.n_prior_samples = self.prior_samples.shape[0]
 
         # ---------- Preparation of observation data ----------
-        # Read observation data and perturb it if requested.
+        # Read observation data 
+        # TODO: later use valid #of measurements. but here only get the model observations?
         if self.measured_data is None:
             self.measured_data = Model.read_observation(case=self.name)
         # Convert measured_data to a data frame
@@ -297,11 +308,13 @@ class BayesInference:
         # Extract the total number of measurement points
         if self.name.lower() == 'calib':
             self.n_tot_measurement = Model.n_obs
-        else:
+        elif self.name.lower() == 'valid':
             self.n_tot_measurement = Model.n_obs_valid
+        else:
+            raise AttributeError('The set inference type is not known! Use either `calib` or `valid`')
 
         # Find measurement error (if not given) for post predictive plot
-        if not hasattr(self, 'measurement_error'):
+        if self.measurement_error is None:
             if isinstance(self.Discrepancy, dict):
                 Disc = self.Discrepancy['known']
             else:
@@ -314,62 +327,95 @@ class BayesInference:
                     self.measurement_error = np.sqrt(Disc.parameters)
                 except TypeError:
                     pass
+        # TODO: need a transformation for given measurement error?
+                
+        # Get Discrepancy type
+        opt_sigma_flag = isinstance(self.Discrepancy, dict)
+        opt_sigma = None
+        # Option A: known error with unknown bias term
+        if opt_sigma_flag and opt_sigma is None:
+            opt_sigma = 'A'
+        # Option B: The sigma2 is known (no bias term)
+        elif self.Discrepancy.parameters is not None:
+            opt_sigma = 'B'
+        # Option C: The sigma2 is unknown (bias term including error)
+        elif not isinstance(self.Discrepancy.InputDisc, str):
+            opt_sigma = 'C'
+        self.Discrepancy.opt_sigma = opt_sigma
+        
+        # Set MCMC params if used
+        if self.inference_method.lower() == 'mcmc':
+            if self.mcmc_params is None:
+                self.mcmc_params = {}
+            par_list = ['init_samples', 'n_walkers', 'n_burn', 'n_steps', 
+                        'moves', 'multiprocessing', 'verbose']
+            init_val = [None, 100, 200, 100000, None, False, False]
+            for i in range(len(par_list)):
+                if par_list[i] not in list(self.mcmc_params.keys()):
+                    self.mcmc_params[par_list[i]] = init_val[i]
+
+
+    # -------------------------------------------------------------------------
+    def create_inference(self):
+        """
+        Starts the inference.
 
+        Returns
+        -------
+        BayesInference : obj
+            The Bayes inference object.
+            
+        # TODO: should this function really return the class?
+
+        """
+        # Do general set up and check some parameters
+        self.setup_inference()
+        
         # ---------- Preparation of variance for covariance matrix ----------
-        # Independent and identically distributed
+        # Independent and identically distributed # TODO: ??
         total_sigma2 = dict()
-        opt_sigma_flag = isinstance(self.Discrepancy, dict)
-        opt_sigma = None
-        for key_idx, key in enumerate(output_names):
+        opt_sigma = self.Discrepancy.opt_sigma
+        for key_idx, key in enumerate(self.engine.Model.Output.names):
             # Find opt_sigma
-            if opt_sigma_flag and opt_sigma is None:
-                # Option A: known error with unknown bias term
-                opt_sigma = 'A'
-                known_discrepancy = self.Discrepancy['known']  # TODO: the syntax here looks different from expected
-                self.Discrepancy = self.Discrepancy['infer'] # TODO: the syntax here looks different from expected
+            if opt_sigma == 'A':
+                known_discrepancy = self.Discrepancy['known']
+                self.Discrepancy = self.Discrepancy['infer']
                 sigma2 = np.array(known_discrepancy.parameters[key])
 
-            elif self.Discrepancy.parameters is not None:
-                # Option B: The sigma2 is known (no bias term)
-                opt_sigma = 'B'
+            elif opt_sigma == 'B':
                 sigma2 = np.array(self.Discrepancy.parameters[key])
 
-            elif not isinstance(self.Discrepancy.InputDisc, str):
-                # Option C: The sigma2 is unknown (bias term including error)
-                opt_sigma = 'C'
+            elif opt_sigma == 'C':
                 n_measurement = self.measured_data[key].values.shape
                 sigma2 = np.zeros((n_measurement[0]))
-
             total_sigma2[key] = sigma2
 
-        self.Discrepancy.opt_sigma = opt_sigma
         self.Discrepancy.total_sigma2 = total_sigma2
 
         # If inferred sigma2s obtained from e.g. calibration are given
         try:
             self.sigma2s = self.Discrepancy.get_sample(self.n_prior_samples)
         except:
-            pass #TODO: should an error be raised in this case?
+            pass #TODO: should an error be raised in this case? Should this at least be checked against opt_sigma?
 
         # ---------------- Bootstrap & TOM --------------------
-        
         if self.bootstrap or self.bayes_loocv or self.just_analysis:
-            self.perform_bootstrap(opt_sigma, total_sigma2)            
+            self.perform_bootstrap(total_sigma2)            
         else:
             print('No bootstrap for TOM performed!') # TODO: stop the code? Use n_bootstrap = 1?
         
         # ---------------- Parameter Bayesian inference ----------------
+        # Convert to a dataframe if samples are provided after calibration.
         if self.name.lower() == 'valid':
-            # Convert to a dataframe if samples are provided after calibration.
-            self.posterior_df = pd.DataFrame(self.prior_samples, columns=par_names)
+            self.posterior_df = pd.DataFrame(self.prior_samples, columns=self.engine.ExpDesign.par_names)
+        # Instantiate the MCMC object
         elif self.inference_method.lower() == 'mcmc':
-            # Instantiate the MCMC object
             MCMC_Obj = MCMC(self)
             self.posterior_df = MCMC_Obj.run_sampler(
                 self.measured_data, total_sigma2
                 )
+        # Rejection sampling
         elif self.inference_method.lower() == 'rejection':
-            # Rejection sampling
             self.posterior_df = self._rejection_sampling()
         else:
             raise AttributeError('The chosen inference method is not available!')
@@ -383,100 +429,93 @@ class BayesInference:
         print('-'*50)
 
         # -------- Model Discrepancy -----------
-        if hasattr(self, 'error_model') and self.error_model \
-           and self.name.lower() == 'calib':
+        if self.error_model and self.name.lower() == 'calib': # TODO: where is this used and what does it actually do there?
+               self.create_error_model(opt_sigma = opt_sigma, 
+                                       type_='posterior', sampler = MCMC_Obj)
+
+        # -------- Posterior predictive -----------
+        self._posterior_predictive()
+
+        # ------------------ Visualization --------------------
+        # Posterior parameters
+        self.plot_post_params(opt_sigma)
+        
+        # Plot MAP
+        if self.plot_map_pred:
+            self._plot_max_a_posteriori()
+
+        # Plot log_BME dist
+        if self.bootstrap:
+            self.plot_log_BME()
+
+        # Plot posterior predictive
+        if self.plot_post_pred:
+            self._plot_post_predictive()
+
+        return self
+    
+    def create_error_model(self, type_ = 'posterior', opt_sigma = 'B', sampler = None):
+        """
+        Creates an error model in the engine.MetaModel based on input dist 
+        samples of the chosen type
+
+        Parameters
+        ----------
+        opt_sigma : string, optional
+            Type of uncertainty description, only used if type_=='posterior'.
+            The default is 'B'
+        type_ : string
+            Type of parameter samples to use, either 'prior' or 'posterior'. 
+            The default is 'posterior'.
+        sampler : MCMC, optional
+            Should be an MCMC object if type=='posterior' and MCMC is used in 
+            the inference.In al other cases this parameter is not needed.
+
+        Returns
+        -------
+        None.
+
+        """
+        n_params = self.engine.MetaModel.n_params
+        
+        # Get MAP estimate from prior samples
+        if type_ == 'prior':
+            # Select prior ? mean as MAP
+            MAP_theta = self.prior_samples.mean(axis=0).reshape((1, n_params))
+
+            # Evaluate the (meta-)model at the MAP
+            y_MAP, y_std_MAP = self.engine.MetaModel.eval_metamodel(samples=MAP_theta)
+
+            # Train a GPR meta-model using MAP
+            self.error_MetaModel = self.engine.MetaModel.create_model_error(
+                self.bias_inputs, y_MAP, self.measured_data, name=self.name
+                )
+        
+        # Get MAP estimate from posterior samples
+        if type_ == 'posterior':
             if self.inference_method.lower() == 'mcmc':
-                self.error_MetaModel = MCMC_Obj.error_MetaModel
+                self.error_MetaModel = sampler.error_MetaModel
             else:
                 # Select posterior mean as MAP
                 if opt_sigma == "B":
                     posterior_df = self.posterior_df.values
                 else:
-                    posterior_df = self.posterior_df.values[:, :-Model.n_outputs]
+                    posterior_df = self.posterior_df.values[:, :-self.engine.Model.n_outputs]
 
                 # Select posterior mean as Maximum a posteriori
                 map_theta = posterior_df.mean(axis=0).reshape((1, n_params))
                 # map_theta = stats.mode(Posterior_df,axis=0)[0]
 
                 # Evaluate the (meta-)model at the MAP
-                y_MAP, y_std_MAP = MetaModel.eval_metamodel(samples=map_theta)
+                y_MAP, y_std_MAP = self.engine.MetaModel.eval_metamodel(samples=map_theta)
 
                 # Train a GPR meta-model using MAP
-                self.error_MetaModel = MetaModel.create_model_error(
-                    self.bias_inputs, y_MAP, Name=self.name
+                self.error_MetaModel = self.engine.MetaModel.create_model_error(
+                    self.bias_inputs, y_MAP, self.measured_data, name=self.name
                     )
 
-        # -------- Posterior perdictive -----------
-        self._posterior_predictive()
-
-        # -----------------------------------------------------
-        # ------------------ Visualization --------------------
-        # -----------------------------------------------------
-        # Create Output directory, if it doesn't exist already.
-
-        # -------- Posterior parameters --------
-        if opt_sigma != "B":
-            par_names.extend(
-                [self.Discrepancy.InputDisc.Marginals[i].name for i
-                 in range(len(self.Discrepancy.InputDisc.Marginals))]
-                )
-        # Pot with corner
-        figPosterior = corner.corner(self.posterior_df.to_numpy(),
-                                     labels=par_names,
-                                     quantiles=[0.15, 0.5, 0.85],
-                                     show_titles=True,
-                                     title_fmt=self.corner_title_fmt,
-                                     labelpad=0.2,
-                                     use_math_text=True,
-                                     title_kwargs={"fontsize": 28},
-                                     plot_datapoints=False,
-                                     plot_density=False,
-                                     fill_contours=True,
-                                     smooth=0.5,
-                                     smooth1d=0.5)
-
-        # Loop over axes and set x limits
-        if opt_sigma == "B":
-            axes = np.array(figPosterior.axes).reshape(
-                (len(par_names), len(par_names))
-                )
-            for yi in range(len(par_names)):
-                ax = axes[yi, yi]
-                ax.set_xlim(self.engine.ExpDesign.bound_tuples[yi])
-                for xi in range(yi):
-                    ax = axes[yi, xi]
-                    ax.set_xlim(self.engine.ExpDesign.bound_tuples[xi])
-        plt.close()
-
-        # Turn off gridlines
-        for ax in figPosterior.axes:
-            ax.grid(False)
-
-        if self.emulator:
-            plotname = f'/Posterior_Dist_{Model.name}_emulator'
-        else:
-            plotname = f'/Posterior_Dist_{Model.name}'
-
-        figPosterior.set_size_inches((24, 16))
-        figPosterior.savefig(f'./{self.out_dir}{plotname}.pdf',
-                             bbox_inches='tight')
-
-        # -------- Plot MAP --------
-        if self.plot_map_pred:
-            self._plot_max_a_posteriori()
-
-        # -------- Plot log_BME dist --------
-        if self.bootstrap:
-            self.plot_log_BME()
-
-        # -------- Posterior perdictives --------
-        if self.plot_post_pred:
-            # Plot the posterior predictive
-            self._plot_post_predictive()
-
-        return self
     
-    def perform_bootstrap(self, opt_sigma, total_sigma2):
+    def perform_bootstrap(self, total_sigma2):
         """
         Perform bootstrap to get TOM (??)
         
@@ -491,9 +530,9 @@ class BayesInference:
         None.
 
         """
-        MetaModel = self.MetaModel
-        n_params = MetaModel.n_params
+        MetaModel = self.engine.MetaModel
         output_names = self.engine.Model.Output.names
+        opt_sigma = self.Discrepancy.opt_sigma
 
         # Adding some zero mean noise to the observation function
         if len(self.perturbed_data) == 0:
@@ -504,19 +543,8 @@ class BayesInference:
             self.n_bootstrap_itrs = len(self.perturbed_data)
 
         # -------- Model Discrepancy -----------
-        if hasattr(self, 'error_model') and self.error_model \
-           and self.name.lower() != 'calib':# TODO: what should be set so that this is tested?
-            # Select prior ? mean as MAP
-            MAP_theta = self.prior_samples.mean(axis=0).reshape((1, n_params))
-
-            # Evaluate the (meta-)model at the MAP
-            y_MAP, y_std_MAP = MetaModel.eval_metamodel(samples=MAP_theta)
-
-            # Train a GPR meta-model using MAP
-            self.error_MetaModel = MetaModel.create_model_error(
-                self.bias_inputs, y_MAP, Name=self.name
-                )
-
+        if self.error_model and self.name.lower() == 'valid':# TODO: what should be set so that this is tested?
+            self.create_error_model(type_='prior')
         # -----------------------------------------------------
         # ----- Loop over the perturbed observation data ------
         # -----------------------------------------------------
@@ -536,10 +564,9 @@ class BayesInference:
             self._std_pce_prior_pred = y_std
 
             # Correct the predictions with Model discrepancy
-            if hasattr(self, 'error_model') and self.error_model: # TODO this does not check for calib?
+            if self.error_model: # TODO this does not check for calib?
                 y_hat_corr, y_std = self.error_MetaModel.eval_model_error(
-                    self.bias_inputs, self.__mean_pce_prior_pred
-                    )
+                    self.bias_inputs, self.__mean_pce_prior_pred)
                 self.__mean_pce_prior_pred = y_hat_corr
                 self._std_pce_prior_pred = y_std
 
@@ -548,12 +575,13 @@ class BayesInference:
                 surrError = MetaModel.rmse
             else:
                 surrError = None
-
+            model_evals = self.__mean_pce_prior_pred
+            
+        # Evaluate the model
         else:
-            # Evaluate the original model
             self.__model_prior_pred = self._eval_model(
-                samples=self.prior_samples, key='PriorPred'
-                )
+                samples=self.prior_samples, key='PriorPred')
+            model_evals = self.__model_prior_pred
             surrError = None
         
         # Start the likelihood-BME computations for the perturbed data
@@ -562,17 +590,9 @@ class BayesInference:
                 total=self.n_bootstrap_itrs,
                 desc="Bootstrapping the BME calculations", ascii=True
                 ):
-            print('')
-            #print(itr_idx, data)
-            #print(np.nonzero(data))
-
+            
             # ---------------- Likelihood calculation ----------------
-            if self.emulator: # TODO: do this outside of the loop?
-                model_evals = self.__mean_pce_prior_pred
-            else:
-                model_evals = self.__model_prior_pred
-
-            # Leave one out  # TODO: why is this loo? It just looks at perturbed data?
+            # Leave one out (see form of perturbed data)
             if self.bayes_loocv or self.just_analysis:
                 # Consider only non-zero entries
                 self.selected_indices = np.nonzero(data)[0]
@@ -587,7 +607,7 @@ class BayesInference:
                 }
 
             # Unknown sigma2
-            if opt_sigma == 'C' or hasattr(self, 'sigma2s'):
+            if opt_sigma == 'C' or self.sigma2s is not None:
                 logLikelihoods[:, itr_idx] = self.normpdf(
                     model_evals, data_dict, total_sigma2,
                     sigma2=self.sigma2s, std=surrError
@@ -602,7 +622,7 @@ class BayesInference:
             # BME (log)
             log_BME[itr_idx] = np.log(
                 np.nanmean(np.exp(logLikelihoods[:, itr_idx],
-                                  dtype=np.longdouble))#float128))
+                                  dtype=self.dtype))
                 )
 
             # BME correction when using Emulator
@@ -656,18 +676,15 @@ class BayesInference:
         self.log_BME = log_BME
 
         # BMECorrFactor (log) (Size: 1,n_bootstrap_itr)
+        # BME = BME + BMECorrFactor
         if self.emulator:
-            self.log_BME_corr_factor = BME_Corr
-            # BME = BME + BMECorrFactor
-            self.log_BME += self.log_BME_corr_factor
+            self.log_BME += BME_Corr
 
         if 'kld' in list(map(str.lower, self.valid_metrics)):
             self.KLD = KLD
         if 'inf_entropy' in list(map(str.lower, self.valid_metrics)):
             self.inf_entropy = inf_entropy
 
-    
-
 
     # -------------------------------------------------------------------------
     def _perturb_data(self, data, output_names):
@@ -859,8 +876,7 @@ class BayesInference:
                 covMatrix = np.diag(tot_sigma2s)
 
                 # Check the type error term
-                if hasattr(self, 'bias_inputs') and \
-                   not hasattr(self, 'error_model'):
+                if self.bias_inputs != None and self.error_model == None:
                     # Infer a Bias model usig Gaussian Process Regression
                     bias_inputs = np.hstack(
                         (self.bias_inputs[out],
@@ -906,7 +922,7 @@ class BayesInference:
             A dictionary with known values of the covariance diagonal entries,
             a.k.a sigma^2.
         logBME : ??
-            ??
+            The log_BME obtained from the estimated likelihoods
 
         Returns
         -------
@@ -915,7 +931,7 @@ class BayesInference:
 
         """
         # Extract the requested model outputs for likelihood calulation
-        MetaModel = self.MetaModel
+        MetaModel = self.engine.MetaModel
         samples = self.engine.ExpDesign.X
         model_outputs = self.engine.ExpDesign.Y
         n_samples = samples.shape[0]
@@ -997,7 +1013,7 @@ class BayesInference:
         if self.prior_samples is None:
             raise AttributeError('No prior samples available!')
 
-        if not hasattr(self, 'log_likes'):
+        if self.log_likes is None:
             raise AttributeError('No log-likelihoods available!')
         
         # Get sigmas # TODO: is this data uncertainty?
@@ -1018,11 +1034,7 @@ class BayesInference:
             index = 0
         
         # Use longdouble on windows, float128 on linux
-        if os.name != 'nt':
-            likelihoods = np.exp(self.log_likes[:, index], dtype=np.float128)
-        else:
-            print('WARNING: Performing the inference on windows can lead to reduced accuracy!')
-            likelihoods = np.exp(self.log_likes[:, index], dtype=np.longdouble)
+        likelihoods = np.exp(self.log_likes[:, index], dtype=self.dtype)
 
         n_samples = len(likelihoods)
         norm_likelihoods = likelihoods / np.max(likelihoods)
@@ -1057,7 +1069,7 @@ class BayesInference:
 
         """
 
-        MetaModel = self.MetaModel
+        MetaModel = self.engine.MetaModel
         Model = self.engine.Model
 
         # Read observation data and perturb it if requested # TODO: where is the perturbation?
@@ -1067,11 +1079,10 @@ class BayesInference:
         if not isinstance(self.measured_data, pd.DataFrame):
             self.measured_data = pd.DataFrame(self.measured_data)
 
-        # X_values
+        # X_values and prior sigma2
         x_values = self.engine.ExpDesign.x_values
-
         try:
-            sigma2_prior = self.Discrepancy.sigma2_prior
+            sigma2_prior = self.Discrepancy.sigma2_prior # TODO: what is this? Looks to be built for a different Discrepancy structure
         except:
             sigma2_prior = None
 
@@ -1079,7 +1090,7 @@ class BayesInference:
         posterior_df = self.posterior_df
 
         # Take care of the sigma2
-        if sigma2_prior is not None:
+        if sigma2_prior is not None: # TODO: why is this the if for this code?
             try:
                 sigma2s = posterior_df[self.Discrepancy.name].values # TODO: what is Discrepancy.name?
                 posterior_df = posterior_df.drop(
@@ -1090,10 +1101,10 @@ class BayesInference:
 
         # Posterior predictive
         if self.emulator:
-            if self.inference_method == 'rejection': # TODO: combine these two?
-                prior_pred = self.__mean_pce_prior_pred
-            if self.name.lower() != 'calib':
-                post_pred = self.__mean_pce_prior_pred
+            if self.inference_method == 'rejection': # TODO: combine these two? Why is there no post_pred_std for rejection sampling?
+                prior_pred = self._mean_pce_prior_pred
+            if self.name.lower() == 'valid':
+                post_pred = self._mean_pce_prior_pred
                 post_pred_std = self._std_pce_prior_pred
             else:
                 post_pred, post_pred_std = MetaModel.eval_metamodel( # TODO: recheck if this is needed
@@ -1103,7 +1114,7 @@ class BayesInference:
         else: # TODO: see emulator version
             if self.inference_method == 'rejection':
                 prior_pred = self.__model_prior_pred
-            if self.name.lower() != 'calib':
+            if self.name.lower() == 'valid':
                 post_pred = self.__mean_pce_prior_pred,
                 post_pred_std = self._std_pce_prior_pred
             else:
@@ -1111,13 +1122,13 @@ class BayesInference:
                     samples=posterior_df.values, key='PostPred'
                     )
         # Correct the predictions with Model discrepancy
-        if hasattr(self, 'error_model') and self.error_model:
+        if self.error_model:
             y_hat, y_std = self.error_MetaModel.eval_model_error(
                 self.bias_inputs, post_pred
                 )
             post_pred, post_pred_std = y_hat, y_std
 
-        # Add discrepancy from likelihood Sample to the current posterior runs
+        # Add discrepancy from likelihood samples to the current posterior runs
         total_sigma2 = self.Discrepancy.total_sigma2
         post_pred_withnoise = copy.deepcopy(post_pred)
         for varIdx, var in enumerate(Model.Output.names):
@@ -1129,11 +1140,10 @@ class BayesInference:
                 tot_sigma2 = clean_sigma2[:len(pred)]
                 cov = np.diag(tot_sigma2)
 
-                # Check the type error term
+                # Account for additional error terms
                 if sigma2_prior is not None:
                     # Inferred sigma2s
-                    if hasattr(self, 'bias_inputs') and \
-                       not hasattr(self, 'error_model'):
+                    if self.bias_inputs != None and self.error_model == None:
                         # TODO: Infer a Bias model usig GPR
                         bias_inputs = np.hstack((
                             self.bias_inputs[var], pred.reshape(-1, 1)))
@@ -1149,6 +1159,7 @@ class BayesInference:
                         # Convert biasSigma2s to a covMatrix
                         cov += sigma2 * np.eye(len(pred))
 
+                # Add predictive metamodel error/uncertainty
                 if self.emulator:
                     if hasattr(MetaModel, 'rmse') and \
                        MetaModel.rmse is not None:
@@ -1159,7 +1170,7 @@ class BayesInference:
                     cov += np.diag(stdPCE**2)
 
                 # Sample a multivariate normal distribution with mean of
-                # prediction and variance of cov
+                # posterior prediction and variance of cov
                 post_pred_withnoise[var][i] = np.random.multivariate_normal(
                     pred, cov, 1
                     )
@@ -1242,10 +1253,9 @@ class BayesInference:
 
         """
 
-        MetaModel = self.MetaModel
+        MetaModel = self.engine.MetaModel
         Model = self.engine.Model
         opt_sigma = self.Discrepancy.opt_sigma
-
         # -------- Find MAP and run MetaModel and origModel --------
         # Compute the MAP
         if self.max_a_posteriori.lower() == 'mean':
@@ -1330,7 +1340,80 @@ class BayesInference:
 
         pdf.close()
         
+    def plot_post_params(self, opt_sigma):
+        """
+        Plots the multivar. posterior parameter distribution.
+        
+
+        Parameters
+        ----------
+        opt_sigma : string
+            Type of uncertainty description available.
+
+        Returns
+        -------
+        None.
+
+        """
+        par_names = self.engine.ExpDesign.par_names
+        if opt_sigma != "B":
+            par_names.extend(
+                [self.Discrepancy.InputDisc.Marginals[i].name for i
+                 in range(len(self.Discrepancy.InputDisc.Marginals))]
+                )
+        # Pot with corner
+        figPosterior = corner.corner(self.posterior_df.to_numpy(),
+                                     labels=par_names,
+                                     quantiles=[0.15, 0.5, 0.85],
+                                     show_titles=True,
+                                     title_fmt=self.corner_title_fmt,
+                                     labelpad=0.2,
+                                     use_math_text=True,
+                                     title_kwargs={"fontsize": 28},
+                                     plot_datapoints=False,
+                                     plot_density=False,
+                                     fill_contours=True,
+                                     smooth=0.5,
+                                     smooth1d=0.5)
+
+        # Loop over axes and set x limits
+        if opt_sigma == "B":
+            axes = np.array(figPosterior.axes).reshape(
+                (len(par_names), len(par_names))
+                )
+            for yi in range(len(par_names)):
+                ax = axes[yi, yi]
+                ax.set_xlim(self.engine.ExpDesign.bound_tuples[yi])
+                for xi in range(yi):
+                    ax = axes[yi, xi]
+                    ax.set_xlim(self.engine.ExpDesign.bound_tuples[xi])
+        plt.close()
+
+        # Turn off gridlines
+        for ax in figPosterior.axes:
+            ax.grid(False)
+
+        if self.emulator:
+            plotname = f'/Posterior_Dist_{self.engine.Model.name}_emulator'
+        else:
+            plotname = f'/Posterior_Dist_{self.engine.Model.name}'
+
+        figPosterior.set_size_inches((24, 16))
+        figPosterior.savefig(f'./{self.out_dir}{plotname}.pdf',
+                             bbox_inches='tight')
+        
+        plt.clf()
+
+        
     def plot_log_BME(self):
+        """
+        Plots the log_BME if bootstrap is active.
+
+        Returns
+        -------
+        None.
+
+        """
         
         # Computing the TOM performance
         self.log_BME_tom = stats.chi2.rvs(
@@ -1353,13 +1436,14 @@ class BayesInference:
         ax.legend(handles=legend_elements)
 
         if self.emulator:
-            plotname = f'/BME_hist_{self.Model.name}_emulator'
+            plotname = f'/BME_hist_{self.engine.Model.name}_emulator'
         else:
-            plotname = f'/BME_hist_{self.Model.name}'
+            plotname = f'/BME_hist_{self.engine.Model.name}'
 
-        plt.savefig(f'./{self.self.out_dir}{plotname}.pdf', bbox_inches='tight')
+        plt.savefig(f'./{self.out_dir}{plotname}.pdf', bbox_inches='tight')
+        
         plt.show()
-        plt.close()
+        plt.clf()
 
 
     # -------------------------------------------------------------------------
@@ -1382,11 +1466,10 @@ class BayesInference:
 
                 # --- Read prior and posterior predictive ---
                 if self.inference_method == 'rejection' and \
-                   self.name.lower() != 'valid':
+                   self.name.lower() == 'calib':
                     #  --- Prior ---
                     # Load posterior predictive
-                    f = h5py.File(
-                        f'{self.out_dir}/priorPredictive.hdf5', 'r+')
+                    f = h5py.File(f'{self.out_dir}/priorPredictive.hdf5', 'r+')
 
                     try:
                         x_coords = np.array(f[f"x_values/{out_name}"])
@@ -1516,3 +1599,5 @@ class BayesInference:
 
                 fig.savefig(f'./{self.out_dir}{plotname}_{out_name}.pdf',
                             bbox_inches='tight')
+                
+        plt.clf()
diff --git a/src/bayesvalidrox/bayes_inference/mcmc.py b/src/bayesvalidrox/bayes_inference/mcmc.py
index d78d15b5fd90dc4477da7d0fd58da835acc75310..a672583bae6e1c273bf7d080062502f96bbf9199 100755
--- a/src/bayesvalidrox/bayes_inference/mcmc.py
+++ b/src/bayesvalidrox/bayes_inference/mcmc.py
@@ -15,6 +15,182 @@ import shutil
 os.environ["OMP_NUM_THREADS"] = "1"
 
 
+# -------------------------------------------------------------------------
+def _check_ranges(theta, ranges): # TODO: this is a replica of exp_designs.check_ranges
+    """
+    This function checks if theta lies in the given ranges.
+
+    Parameters
+    ----------
+    theta : array
+        Proposed parameter set.
+    ranges : nested list
+        List of the praremeter ranges.
+
+    Returns
+    -------
+    c : bool
+        If it lies in the given range, it return True else False.
+
+    """
+    c = True
+    # traverse in the list1
+    for i, bounds in enumerate(ranges):
+        x = theta[i]
+        # condition check
+        if x < bounds[0] or x > bounds[1]:
+            c = False
+            return c
+    return c
+
+# -------------------------------------------------------------------------
+def gelman_rubin(chain, return_var=False):
+    """
+    The potential scale reduction factor (PSRF) defined by the variance
+    within one chain, W, with the variance between chains B.
+    Both variances are combined in a weighted sum to obtain an estimate of
+    the variance of a parameter \\( \\theta \\).The square root of the
+    ratio of this estimates variance to the within chain variance is called
+    the potential scale reduction.
+    For a well converged chain it should approach 1. Values greater than
+    1.1 typically indicate that the chains have not yet fully converged.
+
+    Source: http://joergdietrich.github.io/emcee-convergence.html
+
+    https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py
+
+    Parameters
+    ----------
+    chain : array (n_walkers, n_steps, n_params)
+        The emcee ensamples.
+
+    Returns
+    -------
+    R_hat : float
+        The Gelman-Robin values.
+
+    """
+    chain = np.array(chain)
+    m_chains, n_iters = chain.shape[:2]
+
+    # Calculate between-chain variance
+    θb = np.mean(chain, axis=1)
+    θbb = np.mean(θb, axis=0)
+    B_over_n = ((θbb - θb)**2).sum(axis=0)
+    B_over_n /= (m_chains - 1)
+
+    # Calculate within-chain variances
+    ssq = np.var(chain, axis=1, ddof=1)
+    W = np.mean(ssq, axis=0)
+
+    # (over) estimate of variance
+    var_θ = W * (n_iters - 1) / n_iters + B_over_n
+
+    if return_var:
+        return var_θ
+    else:
+        # The square root of the ratio of this estimates variance to the
+        # within chain variance
+        R_hat = np.sqrt(var_θ / W)
+        return R_hat
+
+
+# -------------------------------------------------------------------------
+def _iterative_scheme(N1, N2, q11, q12, q21, q22, r0, neff, tol,
+                      maxiter, criterion):
+    """
+    Iterative scheme as proposed in Meng and Wong (1996) to estimate the
+    marginal likelihood
+
+    """
+    l1 = q11 - q12
+    l2 = q21 - q22
+    # To increase numerical stability,
+    # subtracting the median of l1 from l1 & l2 later
+    lstar = np.median(l1)
+    s1 = neff/(neff + N2)
+    s2 = N2/(neff + N2)
+    r = r0
+    r_vals = [r]
+    logml = np.log(r) + lstar
+    criterion_val = 1 + tol
+
+    i = 0
+    while (i <= maxiter) & (criterion_val > tol):
+        rold = r
+        logmlold = logml
+        numi = np.exp(l2 - lstar)/(s1 * np.exp(l2 - lstar) + s2 * r)
+        deni = 1/(s1 * np.exp(l1 - lstar) + s2 * r)
+        if np.sum(~np.isfinite(numi))+np.sum(~np.isfinite(deni)) > 0:
+            warnings.warn(
+                """Infinite value in iterative scheme, returning NaN.
+                 Try rerunning with more samples.""")
+        r = (N1/N2) * np.sum(numi)/np.sum(deni)
+        r_vals.append(r)
+        logml = np.log(r) + lstar
+        i += 1
+        if criterion == 'r':
+            criterion_val = np.abs((r - rold)/r)
+        elif criterion == 'logml':
+            criterion_val = np.abs((logml - logmlold)/logml)
+
+    if i >= maxiter:
+        return dict(logml=np.NaN, niter=i, r_vals=np.asarray(r_vals))
+    else:
+        return dict(logml=logml, niter=i)
+
+# -------------------------------------------------------------------------
+def _my_ESS(x):
+    """
+    Compute the effective sample size of estimand of interest.
+    Vectorised implementation.
+    https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py
+
+
+    Parameters
+    ----------
+    x : array of shape (n_walkers, n_steps)
+        MCMC Samples.
+
+    Returns
+    -------
+    int
+        Effective sample size.
+
+    """
+    # Format the intput
+    try:
+        x = np.array(x)
+    except(AttributeError):
+        print('The input cannot be formatted!')
+    if x.ndim >2 or x.ndim <2:
+        raise AttributeError('The input should be 2D!')
+    m_chains, n_iters = x.shape
+
+    def variogram(t):
+        variogram = ((x[:, t:] - x[:, :(n_iters - t)])**2).sum()
+        variogram /= (m_chains * (n_iters - t))
+        return variogram
+
+    post_var = gelman_rubin(x, return_var=True)
+
+    t = 1
+    rho = np.ones(n_iters)
+    negative_autocorr = False
+
+    # Iterate until the sum of consecutive estimates of autocorrelation is
+    # negative
+    while not negative_autocorr and (t < n_iters):
+        rho[t] = 1 - variogram(t) / (2 * post_var)
+
+        if not t % 2:
+            negative_autocorr = sum(rho[t-1:t+1]) < 0
+
+        t += 1
+
+    return int(m_chains*n_iters / (1 + 2*rho[1:t].sum()))
+
+
 class MCMC:
     """
     A class for bayesian inference via a Markov-Chain Monte-Carlo (MCMC)
@@ -41,62 +217,64 @@ class MCMC:
     """
 
     def __init__(self, BayesOpts):
-
+        # Inputs
         self.BayesOpts = BayesOpts
+        
+        # Param inits
+        self.counter = 0
+        self.observation = None
+        self.total_sigma2 = None
+        
+        # Get general params from BayesOpts
+        self.out_dir = self.BayesOpts.out_dir
+        
+        # Get MCMC parameters ftom BayesOpts
+        pars = self.BayesOpts.mcmc_params
+        self.initsamples = pars['init_samples']
+        if isinstance(self.initsamples, pd.DataFrame):
+            self.initsamples = self.initsamples.values
+        self.nsteps = int(pars['n_steps'])
+        self.nwalkers = int(pars['n_walkers'])
+        self.nburn = pars['n_burn']
+        self.moves = pars['moves']
+        self.mp = pars['multiprocessing']
+        self.verbose = pars['verbose']
 
     def run_sampler(self, observation, total_sigma2):
+        """
+        Run the MCMC sampler for the given observations and stdevs.
 
+        Parameters
+        ----------
+        observation : TYPE
+            DESCRIPTION.
+        total_sigma2 : TYPE
+            DESCRIPTION.
+
+        Returns
+        -------
+        Posterior_df : TYPE
+            DESCRIPTION.
+
+        """
+        # Get init values
         BayesObj = self.BayesOpts
-        MetaModel = BayesObj.engine.MetaModel
-        Model = BayesObj.engine.Model
         Discrepancy = self.BayesOpts.Discrepancy
-        n_cpus = Model.n_cpus
-        priorDist = BayesObj.engine.ExpDesign.JDist
-        ndim = MetaModel.n_params
-        self.counter = 0
-        output_dir = f'Outputs_Bayes_{Model.name}_{self.BayesOpts.name}'
-        if not os.path.exists(output_dir):
-            os.makedirs(output_dir)
+        n_cpus = BayesObj.engine.Model.n_cpus
+        ndim = BayesObj.engine.MetaModel.n_params
+        if not os.path.exists(self.out_dir):
+            os.makedirs(self.out_dir)
 
+        # Save inputs
         self.observation = observation
         self.total_sigma2 = total_sigma2
 
-        # Unpack mcmc parameters given to BayesObj.mcmc_params
-        self.initsamples = None
-        self.nwalkers = 100
-        self.nburn = 200
-        self.nsteps = 100000
-        self.moves = None
-        self.mp = False
-        self.verbose = False
-
-        # Extract initial samples
-        if 'init_samples' in BayesObj.mcmc_params:
-            self.initsamples = BayesObj.mcmc_params['init_samples']
-            if isinstance(self.initsamples, pd.DataFrame):
-                self.initsamples = self.initsamples.values
-
-        # Extract number of steps per walker
-        if 'n_steps' in BayesObj.mcmc_params:
-            self.nsteps = int(BayesObj.mcmc_params['n_steps'])
-        # Extract number of walkers (chains)
-        if 'n_walkers' in BayesObj.mcmc_params:
-            self.nwalkers = int(BayesObj.mcmc_params['n_walkers'])
-        # Extract moves
-        if 'moves' in BayesObj.mcmc_params:
-            self.moves = BayesObj.mcmc_params['moves']
-        # Extract multiprocessing
-        if 'multiprocessing' in BayesObj.mcmc_params:
-            self.mp = BayesObj.mcmc_params['multiprocessing']
-        # Extract verbose
-        if 'verbose' in BayesObj.mcmc_params:
-            self.verbose = BayesObj.mcmc_params['verbose']
-
         # Set initial samples
         np.random.seed(0)
         if self.initsamples is None:
             try:
-                initsamples = priorDist.sample(self.nwalkers).T
+                initsamples = BayesObj.engine.ExpDesign.JDist.sample(self.nwalkers).T
+                initsamples = np.swapaxes(np.array([initsamples]),0,1) # TODO: test if this still works with multiple input dists
             except:
                 # when aPCE selected - gaussian kernel distribution
                 inputSamples = self.BayesOpts.engine.ExpDesign.raw_data.T
@@ -125,7 +303,7 @@ class MCMC:
                     initsamples[:, idx_dim] = dist.rvs(size=self.nwalkers)
 
                 # Update lower and upper
-                MetaModel.ExpDesign.bound_tuples = bound_tuples
+                BayesObj.engine.MetaModel.ExpDesign.bound_tuples = bound_tuples
 
         # Check if sigma^2 needs to be inferred
         if Discrepancy.opt_sigma != 'B':
@@ -133,8 +311,6 @@ class MCMC:
 
             # Update initsamples
             initsamples = np.hstack((initsamples, sigma2_samples))
-
-            # Update ndim
             ndim = initsamples.shape[1]
 
             # Discrepancy bound
@@ -146,10 +322,8 @@ class MCMC:
         print("\n>>>> Bayesian inference with MCMC for "
               f"{self.BayesOpts.name} started. <<<<<<")
 
-        # Set up the backend
-        filename = f"{output_dir}/emcee_sampler.h5"
-        backend = emcee.backends.HDFBackend(filename)
-        # Clear the backend in case the file already exists
+        # Set up the backend and clear it in case the file already exists
+        backend = emcee.backends.HDFBackend(f"{self.out_dir}/emcee_sampler.h5")
         backend.reset(self.nwalkers, ndim)
 
         # Define emcee sampler
@@ -176,8 +350,8 @@ class MCMC:
                         )
 
                     # Reset sampler
-                    sampler.reset()
                     pos = pos.coords
+                    sampler.reset()
                 else:
                     pos = initsamples
 
@@ -252,13 +426,13 @@ class MCMC:
                 # output current autocorrelation estimate
                 if self.verbose:
                     print(f"Mean autocorr. time estimate: {np.nanmean(tau):.3f}")
-                    list_gr = np.round(self.gelman_rubin(sampler.chain), 3)
+                    list_gr = np.round(gelman_rubin(sampler.chain), 3)
                     print("Gelman-Rubin Test*: ", list_gr)
 
                 # check convergence
                 converged = np.all(tau*autocorreverynsteps < sampler.iteration)
                 converged &= np.all(np.abs(tauold - tau) / tau < 0.01)
-                converged &= np.all(self.gelman_rubin(sampler.chain) < 1.1)
+                converged &= np.all(gelman_rubin(sampler.chain) < 1.1)
 
                 if converged:
                     break
@@ -277,7 +451,7 @@ class MCMC:
         thin = int(0.5*np.nanmin(tau)) if int(0.5*np.nanmin(tau)) != 0 else 1
         finalsamples = sampler.get_chain(discard=burnin, flat=True, thin=thin)
         acc_fr = np.nanmean(sampler.acceptance_fraction)
-        list_gr = np.round(self.gelman_rubin(sampler.chain[:, burnin:]), 3)
+        list_gr = np.round(gelman_rubin(sampler.chain[:, burnin:]), 3)
 
         # Print summary
         print('\n')
@@ -307,7 +481,7 @@ class MCMC:
 
         # Plot traces
         if self.verbose and self.nsteps < 10000:
-            pdf = PdfPages(output_dir+'/traceplots.pdf')
+            pdf = PdfPages(self.out_dir+'/traceplots.pdf')
             fig = plt.figure()
             for parIdx in range(ndim):
                 # Set up the axes with gridspec
@@ -334,7 +508,6 @@ class MCMC:
 
                 # Destroy the current plot
                 plt.clf()
-
             pdf.close()
 
         # plot development of autocorrelation estimate
@@ -348,33 +521,9 @@ class MCMC:
             plt.ylim(0, np.nanmax(taus)+0.1*(np.nanmax(taus)-np.nanmin(taus)))
             plt.xlabel("number of steps")
             plt.ylabel(r"mean $\hat{\tau}$")
-            fig1.savefig(f"{output_dir}/autocorrelation_time.pdf",
+            fig1.savefig(f"{self.out_dir}/autocorrelation_time.pdf",
                          bbox_inches='tight')
 
-        # logml_dict = self.marginal_llk_emcee(sampler, self.nburn, logp=None,
-        # maxiter=5000)
-        # print('\nThe Bridge Sampling Estimation is "
-        #       f"{logml_dict['logml']:.5f}.')
-
-        # # Posterior-based expectation of posterior probablity
-        # postExpPostLikelihoods = np.mean(sampler.get_log_prob(flat=True)
-        # [self.nburn*self.nwalkers:])
-
-        # # Posterior-based expectation of prior densities
-        # postExpPrior = np.mean(self.log_prior(emcee_trace.T))
-
-        # # Posterior-based expectation of likelihoods
-        # postExpLikelihoods_emcee = postExpPostLikelihoods - postExpPrior
-
-        # # Calculate Kullback-Leibler Divergence
-        # KLD_emcee = postExpLikelihoods_emcee - logml_dict['logml']
-        # print("Kullback-Leibler divergence: %.5f"%KLD_emcee)
-
-        # # Information Entropy based on Entropy paper Eq. 38
-        # infEntropy_emcee = logml_dict['logml'] - postExpPrior -
-        #                    postExpLikelihoods_emcee
-        # print("Information Entropy: %.5f" %infEntropy_emcee)
-
         Posterior_df = pd.DataFrame(finalsamples, columns=par_names)
 
         return Posterior_df
@@ -397,8 +546,7 @@ class MCMC:
             returned otherwise an array.
 
         """
-
-        MetaModel = self.BayesOpts.MetaModel
+        MetaModel = self.BayesOpts.engine.MetaModel
         Discrepancy = self.BayesOpts.Discrepancy
 
         # Find the number of sigma2 parameters
@@ -417,7 +565,7 @@ class MCMC:
 
         for i in range(nsamples):
             # Check if the sample is within the parameters' range
-            if self._check_ranges(theta[i], params_range):
+            if _check_ranges(theta[i], params_range):
                 # Check if all dists are uniform, if yes priors are equal.
                 if all(MetaModel.input_obj.Marginals[i].dist_type == 'uniform'
                        for i in range(MetaModel.n_params)):
@@ -429,7 +577,7 @@ class MCMC:
 
                 # Check if bias term needs to be inferred
                 if Discrepancy.opt_sigma != 'B':
-                    if self._check_ranges(theta[i, -n_sigma2:],
+                    if _check_ranges(theta[i, -n_sigma2:],
                                           disc_bound_tuples):
                         if all('unif' in disc_marginals[i].dist_type for i in
                                range(Discrepancy.ExpDesign.ndim)):
@@ -463,21 +611,20 @@ class MCMC:
         """
 
         BayesOpts = self.BayesOpts
-        MetaModel = BayesOpts.MetaModel
+        MetaModel = BayesOpts.engine.MetaModel
         Discrepancy = self.BayesOpts.Discrepancy
 
         # Find the number of sigma2 parameters
         if Discrepancy.opt_sigma != 'B':
             disc_bound_tuples = Discrepancy.ExpDesign.bound_tuples
             n_sigma2 = len(disc_bound_tuples)
-        else:
-            n_sigma2 = -len(theta)
-        # Check if bias term needs to be inferred
-        if Discrepancy.opt_sigma != 'B':
+            # Check if bias term should be inferred
             sigma2 = theta[:, -n_sigma2:]
             theta = theta[:, :-n_sigma2]
         else:
+            n_sigma2 = -len(theta)
             sigma2 = None
+        
         theta = theta if theta.ndim != 1 else theta.reshape((1, -1))
 
         # Evaluate Model/MetaModel at theta
@@ -561,12 +708,11 @@ class MCMC:
         """
 
         BayesObj = self.BayesOpts
-        MetaModel = BayesObj.MetaModel
         Model = BayesObj.engine.Model
 
         if BayesObj.emulator:
             # Evaluate the MetaModel
-            mean_pred, std_pred = MetaModel.eval_metamodel(samples=theta)
+            mean_pred, std_pred = BayesObj.engine.MetaModel.eval_metamodel(samples=theta)
         else:
             # Evaluate the origModel
             mean_pred, std_pred = dict(), dict()
@@ -610,8 +756,7 @@ class MCMC:
             A error model.
 
         """
-        BayesObj = self.BayesOpts
-        MetaModel = BayesObj.MetaModel
+        MetaModel = self.BayesOpts.engine.MetaModel
 
         # Prepare the poster samples
         try:
@@ -636,60 +781,10 @@ class MCMC:
 
         # Train a GPR meta-model using MAP
         error_MetaModel = MetaModel.create_model_error(
-            BayesObj.BiasInputs, y_map, name='Calib')
+            self.BayesOpts.BiasInputs, y_map, name='Calib')
 
         return error_MetaModel
 
-    # -------------------------------------------------------------------------
-    def gelman_rubin(self, chain, return_var=False):
-        """
-        The potential scale reduction factor (PSRF) defined by the variance
-        within one chain, W, with the variance between chains B.
-        Both variances are combined in a weighted sum to obtain an estimate of
-        the variance of a parameter \\( \\theta \\).The square root of the
-        ratio of this estimates variance to the within chain variance is called
-        the potential scale reduction.
-        For a well converged chain it should approach 1. Values greater than
-        1.1 typically indicate that the chains have not yet fully converged.
-
-        Source: http://joergdietrich.github.io/emcee-convergence.html
-
-        https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py
-
-        Parameters
-        ----------
-        chain : array (n_walkers, n_steps, n_params)
-            The emcee ensamples.
-
-        Returns
-        -------
-        R_hat : float
-            The Gelman-Robin values.
-
-        """
-        m_chains, n_iters = chain.shape[:2]
-
-        # Calculate between-chain variance
-        θb = np.mean(chain, axis=1)
-        θbb = np.mean(θb, axis=0)
-        B_over_n = ((θbb - θb)**2).sum(axis=0)
-        B_over_n /= (m_chains - 1)
-
-        # Calculate within-chain variances
-        ssq = np.var(chain, axis=1, ddof=1)
-        W = np.mean(ssq, axis=0)
-
-        # (over) estimate of variance
-        var_θ = W * (n_iters - 1) / n_iters + B_over_n
-
-        if return_var:
-            return var_θ
-        else:
-            # The square root of the ratio of this estimates variance to the
-            # within chain variance
-            R_hat = np.sqrt(var_θ / W)
-            return R_hat
-
     # -------------------------------------------------------------------------
     def marginal_llk_emcee(self, sampler, nburn=None, logp=None, maxiter=1000):
         """
@@ -748,7 +843,7 @@ class MCMC:
             samples_4_iter[var, :] = x2.flatten()
 
             # effective sample size of samples_4_iter, scalar
-            effective_n[var] = self._my_ESS(x2)
+            effective_n[var] = _my_ESS(x2)
 
         # median effective sample size (scalar)
         neff = np.median(effective_n)
@@ -772,7 +867,7 @@ class MCMC:
         q21 = logp(gen_samples.T)
 
         # Run iterative scheme:
-        tmp = self._iterative_scheme(
+        tmp = _iterative_scheme(
             N1, N2, q11, q12, q21, q22, r0, neff, tol1, maxiter, 'r'
             )
         if ~np.isfinite(tmp['logml']):
@@ -782,7 +877,7 @@ class MCMC:
                 " usual.")
             # use geometric mean as starting value
             r0_2 = np.sqrt(tmp['r_vals'][-2]*tmp['r_vals'][-1])
-            tmp = self._iterative_scheme(
+            tmp = _iterative_scheme(
                 q11, q12, q21, q22, r0_2, neff, tol2, maxiter, 'logml'
                 )
 
@@ -791,119 +886,3 @@ class MCMC:
             q11=q11, q12=q12, q21=q21, q22=q22
             )
         return marg_llk
-
-    # -------------------------------------------------------------------------
-    def _iterative_scheme(self, N1, N2, q11, q12, q21, q22, r0, neff, tol,
-                          maxiter, criterion):
-        """
-        Iterative scheme as proposed in Meng and Wong (1996) to estimate the
-        marginal likelihood
-
-        """
-        l1 = q11 - q12
-        l2 = q21 - q22
-        # To increase numerical stability,
-        # subtracting the median of l1 from l1 & l2 later
-        lstar = np.median(l1)
-        s1 = neff/(neff + N2)
-        s2 = N2/(neff + N2)
-        r = r0
-        r_vals = [r]
-        logml = np.log(r) + lstar
-        criterion_val = 1 + tol
-
-        i = 0
-        while (i <= maxiter) & (criterion_val > tol):
-            rold = r
-            logmlold = logml
-            numi = np.exp(l2 - lstar)/(s1 * np.exp(l2 - lstar) + s2 * r)
-            deni = 1/(s1 * np.exp(l1 - lstar) + s2 * r)
-            if np.sum(~np.isfinite(numi))+np.sum(~np.isfinite(deni)) > 0:
-                warnings.warn(
-                    """Infinite value in iterative scheme, returning NaN.
-                     Try rerunning with more samples.""")
-            r = (N1/N2) * np.sum(numi)/np.sum(deni)
-            r_vals.append(r)
-            logml = np.log(r) + lstar
-            i += 1
-            if criterion == 'r':
-                criterion_val = np.abs((r - rold)/r)
-            elif criterion == 'logml':
-                criterion_val = np.abs((logml - logmlold)/logml)
-
-        if i >= maxiter:
-            return dict(logml=np.NaN, niter=i, r_vals=np.asarray(r_vals))
-        else:
-            return dict(logml=logml, niter=i)
-
-    # -------------------------------------------------------------------------
-    def _my_ESS(self, x):
-        """
-        Compute the effective sample size of estimand of interest.
-        Vectorised implementation.
-        https://github.com/jwalton3141/jwalton3141.github.io/blob/master/assets/posts/ESS/rwmh.py
-
-
-        Parameters
-        ----------
-        x : array of shape (n_walkers, n_steps)
-            MCMC Samples.
-
-        Returns
-        -------
-        int
-            Effective sample size.
-
-        """
-        m_chains, n_iters = x.shape
-
-        def variogram(t):
-            variogram = ((x[:, t:] - x[:, :(n_iters - t)])**2).sum()
-            variogram /= (m_chains * (n_iters - t))
-            return variogram
-
-        post_var = self.gelman_rubin(x, return_var=True)
-
-        t = 1
-        rho = np.ones(n_iters)
-        negative_autocorr = False
-
-        # Iterate until the sum of consecutive estimates of autocorrelation is
-        # negative
-        while not negative_autocorr and (t < n_iters):
-            rho[t] = 1 - variogram(t) / (2 * post_var)
-
-            if not t % 2:
-                negative_autocorr = sum(rho[t-1:t+1]) < 0
-
-            t += 1
-
-        return int(m_chains*n_iters / (1 + 2*rho[1:t].sum()))
-
-    # -------------------------------------------------------------------------
-    def _check_ranges(self, theta, ranges):
-        """
-        This function checks if theta lies in the given ranges.
-
-        Parameters
-        ----------
-        theta : array
-            Proposed parameter set.
-        ranges : nested list
-            List of the praremeter ranges.
-
-        Returns
-        -------
-        c : bool
-            If it lies in the given range, it return True else False.
-
-        """
-        c = True
-        # traverse in the list1
-        for i, bounds in enumerate(ranges):
-            x = theta[i]
-            # condition check
-            if x < bounds[0] or x > bounds[1]:
-                c = False
-                return c
-        return c
diff --git a/src/bayesvalidrox/pylink/pylink.py b/src/bayesvalidrox/pylink/pylink.py
index 227a51ab38cd834e7e85f6193d83563c7ed3437a..637f42317e6f97815e51ce0b331b61c03f26a85b 100644
--- a/src/bayesvalidrox/pylink/pylink.py
+++ b/src/bayesvalidrox/pylink/pylink.py
@@ -231,7 +231,7 @@ class PyLinkForwardModel(object):
                 self.observations_valid = self.observations_valid
             else:
                 raise Exception("Please provide the observation data as a "
-                                "dictionary via observations attribute or pass"
+                                "dictionary via observations_valid attribute or pass"
                                 " the csv-file path to MeasurementFile "
                                 "attribute")
             # Compute the number of observation
diff --git a/src/bayesvalidrox/surrogate_models/surrogate_models.py b/src/bayesvalidrox/surrogate_models/surrogate_models.py
index a13a96cc53da289b08f05683234c7d7203b6ed8e..5968d3a06bcf0281c39f06ea43f647a19d4cfaa0 100644
--- a/src/bayesvalidrox/surrogate_models/surrogate_models.py
+++ b/src/bayesvalidrox/surrogate_models/surrogate_models.py
@@ -1305,6 +1305,7 @@ class MetaModel():
              extracted data.
         y : array of shape (n_outputs,)
             The model response for the MAP parameter set.
+        MeasuredData :  
         name : str, optional
             Calibration or validation. The default is `'Calib'`.
 
@@ -1325,6 +1326,8 @@ class MetaModel():
 
         # Fitting GPR based bias model
         for out in outputNames:
+            print(out)
+            print(X[out])
             nan_idx = ~np.isnan(MeasuredData[out])
             # Select data
             try:
diff --git a/tests/test_BayesInference.py b/tests/test_BayesInference.py
index 7fbb79195799724a8ae820a2c777c99c0b86d9b0..70bcdbc40c7748f5d58936981b354fcff2b933f8 100644
--- a/tests/test_BayesInference.py
+++ b/tests/test_BayesInference.py
@@ -6,17 +6,21 @@ Tests are available for the following functions
     _logpdf                 - x
     _kernel_rbf             - x
 class BayesInference:
-    create_inference
-    perform_bootstrap
+    setup_inference         - x
+    create_inference        - x
+    perform_bootstrap       Need working model for tests without emulator
     _perturb_data           - x
+    create_error_model      Error in the MetaModel
     _eval_model             Need working model to test this
-    normpdf
+    normpdf                 - x
     _corr_factor_BME_old    - removed
     _corr_factor_BME        - x
     _rejection_sampling     - x
-    _posterior_predictive
-    _plot_max_a_posteriori
-    _plot_post_predictive
+    _posterior_predictive   - x
+    plot_post_params        - x 
+    plot_log_BME            - x
+    _plot_max_a_posteriori  Need working model to test this
+    _plot_post_predictive   - x
 """
 import sys
 sys.path.append("src/")
@@ -360,6 +364,184 @@ def test_normpdf_allsigmas() -> None:
     bi = BayesInference(engine)
     bi.normpdf(expdes.Y, obs_data, total_sigma2s, sigma2=sigma2, std=total_sigma2s)
 
+#%% Test setup_inference
+
+def test_setup_inference_noobservation() -> None:
+    """
+    Test the object setup without given observations
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    with pytest.raises(Exception) as excinfo:
+        bi.setup_inference()
+    assert str(excinfo.value) == 'Please provide the observation data as a dictionary via observations attribute or pass the csv-file path to MeasurementFile attribute'
+    
+def test_setup_inference() -> None:
+    """
+    Test the object setup with observations
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])}
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.setup_inference() 
+    
+def test_setup_inference_priorsamples() -> None:
+    """
+    Test the object setup with prior samples set by hand
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])}
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.prior_samples = np.swapaxes(np.array([np.random.normal(0,1,100)]),0,1)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.setup_inference()  
+    
+def test_setup_inference_valid() -> None:
+    """
+    Test the object setup for valid
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations_valid = {'Z':np.array([0.45])}
+    mod.observations_valid = {'Z':np.array([0.45]), 'x_values':np.array([0])}
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.name = 'valid'
+    bi.setup_inference()  
+    
+def test_setup_inference_noname() -> None:
+    """
+    Test the object setup for an invalid inference name
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])}
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.name = ''
+    with pytest.raises(Exception) as excinfo:
+        bi.setup_inference()
+    assert str(excinfo.value) == 'The set inference type is not known! Use either `calib` or `valid`'
+    
+    
 
 #%% Test perform_bootstrap
    
@@ -367,12 +549,51 @@ def test_perform_bootstrap() -> None:
     """
     Do bootstrap
     """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
     
-    opt_sigma = 'B'
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    expdes.x_values = np.array([0]) #  Error in plots if this is not available
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} # Error if x_values not given
+    mod.Output.names = ['Z']
+    mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True 
+    bi.plot_post_pred = False
     total_sigma2s = {'Z':np.array([0.15])}
-    bi.perform_bootstrap(opt_sigma, total_sigma2s)
+    bi.setup_inference()
+    bi.perform_bootstrap(total_sigma2s)
     
-if __name__ == '__main__':
+   
+def test_perform_bootstrap_bayesloocv() -> None:
+    """
+    Do bootstrap
+    """
     inp = Input()
     inp.add_marginals()
     inp.Marginals[0].dist_type = 'normal'
@@ -388,35 +609,493 @@ if __name__ == '__main__':
     mm = MetaModel(inp)
     mm.n_params = 1
     mm.fit(expdes.X, expdes.Y)
-    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(mm.pce_deg))
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} # Error if x_values not given
+    mod.Output.names = ['Z']
+    mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True 
+    bi.plot_post_pred = False
+    total_sigma2s = {'Z':np.array([0.15])}
+    bi.setup_inference()
+    bi.bayes_loocv = True
+    bi.perform_bootstrap(total_sigma2s)
+    
+#%% Test create_error_model
+
+def create_error_model_prior() -> None:
+    """ 
+    Test creating MetaModel error-model for 'prior'
+    """
+    # TODO: there are issues with the expected formats from the MetaModel
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} 
+    mod.Output.names = ['Z']
+    mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True 
+    bi.setup_inference()
+    bi.bias_inputs = expdes.X
+    bi.create_error_model(type_ = 'prior', opt_sigma = 'B', sampler = None)
+    
+def create_error_model_posterior() -> None:
+    """ 
+    Test creating MetaModel error-model for 'posterior'
+    """
+    # TODO: there are issues with the expected formats from the MetaModel
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} 
+    mod.Output.names = ['Z']
+    mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True 
+    bi.setup_inference()
+    bi.bias_inputs = expdes.X
+    bi.posterior_df = posterior
+    bi.create_error_model(type_ = 'posterior', opt_sigma = 'B', sampler = None)
+      
+#%% Test _posterior_predictive
+
+def test_posterior_predictive() -> None:
+    """
+    Test posterior predictions
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    prior_samples = np.swapaxes(np.array([np.random.normal(0,1,10)]),0,1)
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    expdes.x_values = np.array([0]) #  Error in plots if this is not available
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    y_hat, y_std = mm.eval_metamodel(prior_samples)
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45])}
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} # Error if x_values not given
+    mod.Output.names = ['Z']
+    mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    total_sigma2s = {'Z':np.array([0.15])}
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True
+    bi.plot_post_pred = False 
+    bi.posterior_df = posterior
+    bi.bias_inputs = expdes.X
+    bi._mean_pce_prior_pred = y_hat
+    bi._std_pce_prior_pred = y_std
+    bi.Discrepancy.total_sigma2 = total_sigma2s
+    bi.setup_inference()
+    bi._posterior_predictive()
+def test_posterior_predictive_rejection() -> None:
+    """
+    Test posterior predictions with rejection inference
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    prior_samples = np.swapaxes(np.array([np.random.normal(0,1,10)]),0,1)
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    expdes.x_values = np.array([0]) #  Error in plots if this is not available
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    y_hat, y_std = mm.eval_metamodel(prior_samples)
     
     mod = PL()
     mod.observations = {'Z':np.array([0.45])}
     mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} # Error if x_values not given
     mod.Output.names = ['Z']
+    mod.n_obs = 1
     
     engine = Engine(mm, mod, expdes)
     
     sigma2Dict = {'Z':np.array([0.05])}
     sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    total_sigma2s = {'Z':np.array([0.15])}
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
     obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
     DiscrepancyOpts = Discrepancy('')
     DiscrepancyOpts.type = 'Gaussian'
     DiscrepancyOpts.parameters = (obsData*0.15)**2
     
+    bi = BayesInference(engine)
+    bi.Discrepancy = DiscrepancyOpts
+    bi.bootstrap = True
+    bi.plot_post_pred = False 
+    bi.posterior_df = posterior
+    bi.bias_inputs = expdes.X
+    bi._mean_pce_prior_pred = y_hat
+    bi._std_pce_prior_pred = y_std
+    bi.Discrepancy.total_sigma2 = total_sigma2s
+    bi.inference_method = 'rejection'
+    bi.setup_inference()
+    bi._posterior_predictive()
+
+#%% Test plot_post_params
+
+def test_plot_post_params() -> None:
+    """
+    Plot posterior dist
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
+    bi.posterior_df = posterior
+    bi.plot_post_params('B')
+    
+def test_plot_post_params_noemulator() -> None:
+    """
+    Plot posterior dist with emulator = False
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
+    bi.posterior_df = posterior
+    bi.emulator = False
+    bi.plot_post_params('B')
+
+
+#%% Test plot_log_BME
+
+def test_plot_log_BME() -> None:
+    """
+    Show the log_BME from bootstrapping
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1    
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi.log_BME = np.array([[0,0.2],[0,0.2]])
+    bi.n_tot_measurement = 1
+    bi.plot_log_BME()
+
+def test_plot_log_BME_noemulator() -> None:
+    """
+    Show the log_BME from bootstrapping with emulator = False
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1    
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi.log_BME = np.array([[0,0.2],[0,0.2]])
+    bi.n_tot_measurement = 1
+    bi.emulator = False
+    bi.plot_log_BME()
+
+#%% Test _plot_max_a_posteriori
+
+def test_plot_max_a_posteriori_rejection() -> None:
+    """
+    Plot MAP estimate for rejection
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi.inference_method = 'rejection'
+    bi._plot_post_predictive()
+
+
+def test_plot_max_a_posteriori() -> None:
+    """
+    Plot MAP estimate
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi._plot_post_predictive()
+
+
+#%% Test _plot_post_predictive
+
+
+def test_plot_post_predictive_rejection() -> None:
+    """
+    Plot posterior predictions for rejection
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi.inference_method = 'rejection'
+    bi._plot_post_predictive()
+
+
+def test_plot_post_predictive() -> None:
+    """
+    Plot posterior predictions
+    """
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mod = PL()
+    engine = Engine(mm, mod, expdes)
+    
+    bi = BayesInference(engine)
+    bi._plot_post_predictive()
+
+    
+#%% Main runs
+if __name__ == '__main__':
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    #prior_samples = np.swapaxes(np.array([np.random.normal(0,1,10)]),0,1)
+    
+    expdes = ExpDesigns(inp)
+    expdes.init_param_space(max_deg=1)
+    expdes.n_init_samples = 2
+    #expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    #expdes.x_values = np.array([0]) #  Error in plots if this is not 
+    
+    mm = MetaModel(inp)
+    mm.n_params = 1
+    mm.fit(expdes.X, expdes.Y)
+    #expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(1))
+    #y_hat, y_std = mm.eval_metamodel(prior_samples)
+    
+    mod = PL()
+    #mod.observations = {'Z':np.array([0.45])}
+    #mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} # Error if x_values not given
+    #mod.Output.names = ['Z']
+    #mod.n_obs = 1
+    
+    engine = Engine(mm, mod, expdes)
+    
+    #sigma2Dict = {'Z':np.array([0.05])}
+    #sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame({'Z':np.array([0.45]), 'x_values':np.array([0])}, columns=mod.Output.names)
+    DiscrepancyOpts = Discrepancy('')
+    DiscrepancyOpts.type = 'Gaussian'
+    DiscrepancyOpts.parameters = (obsData*0.15)**2
+    DiscrepancyOpts.opt_sigma = 'B'
+    
     bi = BayesInference(engine)
     bi.Discrepancy = DiscrepancyOpts # Error if this not class 'DiscrepancyOpts' or dict(?)
-    bi.bootstrap = True # Error if this and bayes_loocv and just_analysis are all False?
-    bi.plot_post_pred = False # Remaining issue in the violinplot
+    #bi.bootstrap = True # Error if this and bayes_loocv and just_analysis are all False?
+    #bi.plot_post_pred = False # Remaining issue in the violinplot
     #bi.error_model = True
     #bi.bayes_loocv = True
-    bi.create_inference()
-    stop
-    opt_sigma = 'B'
-    total_sigma2s = {'Z':np.array([0.15])}
-    data = pd.DataFrame()
-    data['Z'] = [0.45]
-    data['x_values'] = [0.3]
-    bi.measured_data = data
-    bi.perform_bootstrap(opt_sigma, total_sigma2s)
-    
\ No newline at end of file
+    #if 0:
+    #    bi.create_inference()
+    #opt_sigma = 'B'
+    #total_sigma2s = {'Z':np.array([0.15])}
+    #data = pd.DataFrame()
+    #data['Z'] = [0.45]
+    #data['x_values'] = [0.3]
+    #bi.setup_inference()
+    #bi.perform_bootstrap(total_sigma2s)
+    posterior = pd.DataFrame()
+    posterior[None] = [0,1,0.5]
+    bi.posterior_df = posterior
+    #bi.bias_inputs = expdes.X
+    #bi._mean_pce_prior_pred = y_hat
+    #bi._std_pce_prior_pred = y_std
+    #bi.Discrepancy.total_sigma2 = total_sigma2s
+    #bi.create_error_model(type_ = 'posterior', opt_sigma = 'B', sampler = None)
+    #bi._posterior_predictive()
+    #bi.plot_post_params('B')
+    #bi.log_BME = np.array([[0,0.2],[0,0.2]])
+    #bi.n_tot_measurement = 1
+    #bi.plot_log_BME()
+    bi.inference_method = 'rejection'
+    bi._plot_max_a_posteriori()
\ No newline at end of file
diff --git a/tests/test_MCMC.py b/tests/test_MCMC.py
index 50f6d69b67449ef0647e777f876dd10210566d8f..762ff1ae8feb735bf91a77c554f3437f03fa9712 100644
--- a/tests/test_MCMC.py
+++ b/tests/test_MCMC.py
@@ -2,6 +2,10 @@
 """
 Test the MCM class of bayesvalidrox
 Tests are available for the following functions
+_check_ranges           - x
+gelmain_rubin
+_iterative_scheme
+_my_ESS                 - x
 Class MCMC: 
     run_sampler
     log_prior
@@ -9,20 +13,25 @@ Class MCMC:
     log_posterior
     eval_model
     train_error_model
-    gelmain_rubin
     marginal_llk_emcee
-    _iterative_scheme
-    _my_ESS
-    _check_ranges
 """
+import emcee
 import sys
 sys.path.append("src/")
 sys.path.append("../src/")
+import pandas as pd
 import pytest
 import numpy as np
 
+from bayesvalidrox.surrogate_models.inputs import Input
+from bayesvalidrox.surrogate_models.exp_designs import ExpDesigns
+from bayesvalidrox.surrogate_models.surrogate_models import MetaModel
+from bayesvalidrox.pylink.pylink import PyLinkForwardModel as PL
+from bayesvalidrox.surrogate_models.engine import Engine
+from bayesvalidrox.bayes_inference.discrepancy import Discrepancy
 from bayesvalidrox.bayes_inference.mcmc import MCMC
 from bayesvalidrox.bayes_inference.bayes_inference import BayesInference
+from bayesvalidrox.bayes_inference.mcmc import _check_ranges, gelman_rubin, _my_ESS, _iterative_scheme
 
 #%% Test MCMC init
 
@@ -30,15 +39,229 @@ def test_MCMC() -> None:
     """
     Construct an MCMC object
     """
-    MCMC('')
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
     
-def test_MCMC() -> None:
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    expdes.x_values = np.array([0]) 
+    
+    mm = MetaModel(inp)
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(mm.pce_deg))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} 
+    mod.Output.names = ['Z']
+    engine = Engine(mm, mod, expdes)
+    
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    disc = Discrepancy('')
+    disc.type = 'Gaussian'
+    disc.parameters = (obsData*0.15)**2
+    disc.opt_sigma = 'B'
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = disc 
+    bi.inference_method = 'mcmc'
+    bi.setup_inference()
+    MCMC(bi)
+    
+#%% Test run_sampler
+
+def test_run_sampler() -> None:
     """
-    Construct an MCMC object
+    Run short MCMC
+
+    Returns
+    -------
+    None
+        DESCRIPTION.
+
     """
-    MCMC('')
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    expdes.x_values = np.array([0]) 
+    
+    mm = MetaModel(inp)
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(mm.pce_deg))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])} 
+    mod.Output.names = ['Z']
+    engine = Engine(mm, mod, expdes)
     
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    disc = Discrepancy('')
+    disc.type = 'Gaussian'
+    disc.parameters = (obsData*0.15)**2
+    disc.opt_sigma = 'B'
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = disc 
+    bi.inference_method = 'mcmc'
+    bi.setup_inference()
+    total_sigma2s = {'Z':np.array([0.15])}
+    mcmc = MCMC(bi)
+    mcmc.nburn = 10
+    mcmc.nsteps = 50
+    mcmc.run_sampler(mod.observations, total_sigma2s)
+    
+
 
+#%% Test log_prior
 
+#%% Test log_likelihood
+
+#%% Test log_posterior
+
+#%% Test eval_model
+
+#%% Test train_error_model
+
+#%% Test gelmain_rubin
+
+def test_gelman_rubin() -> None:
+    """
+    Calculate gelman-rubin
+    """
+    
+    chain = [[[1],[2]]]
+    assert gelman_rubin(chain) == np.array([None])
+
+def test_gelman_rubin_returnvar() -> None:
+    """
+    Calculate gelman-rubin returning var
+    """
+    
+    chain = [[[1],[2]]]
+    assert gelman_rubin(chain, return_var = True) == np.array([None])
+
+#%% Test marginal_llk_emcee
+    
+#%% Test _iterative_scheme
+
+def test_iterative_scheme_r() -> None:
+    """
+    Run iterative calc in mode r
+    """
+    _iterative_scheme(1, 1, 0, 1, 2, 3, 4, 1, 1, 10, 'r')
+    
+
+def test_iterative_scheme_0iter() -> None:
+    """
+    Run iterative calc in mode r with 0 iterations
+    """
+    _iterative_scheme(1, 1, 0, 1, 2, 3, 4, 1, 1, 0, 'r')
+    
+
+def test_iterative_scheme_logml() -> None:
+    """
+    Run iterative calc in mode logml
+    """
+    _iterative_scheme(1, 1, 0, 1, 2, 3, 4, 1, 1, 10, 'logml')
+
+#%% Test _my_ESS
+
+def test_my_ESS() -> None:
+    """
+    Get ESS
+    """
+    chain = [[[1],[2]]][0]
+    _my_ESS(chain)
+
+def test_my_ESS_1d() -> None:
+    """
+    Get ESS with wrong dimensions
+    """
+    chain = [[[1],[2]]][0][0]
+    with pytest.raises(AttributeError) as excinfo:
+        _my_ESS(chain)
+    assert str(excinfo.value) == 'The input should be 2D!'
+
+#%% Test _check_ranges
+
+def test_check_ranges() -> None:
+    """
+    Check to see if theta lies in expected ranges
+    """
+    theta = [0.5,1.2]
+    ranges = [[0,1],[1,2]]
+    assert _check_ranges(theta, ranges) == True
+    
+def test_check_ranges_inv() -> None:
+    """
+    Check to see if theta lies not in expected ranges
+    """
+    theta = [1.5,1.2]
+    ranges = [[0,1],[1,2]]
+    assert _check_ranges(theta, ranges) == False
+ 
+
+#%% Main
+
+if __name__ == '__main__':
+    inp = Input()
+    inp.add_marginals()
+    inp.Marginals[0].dist_type = 'normal'
+    inp.Marginals[0].parameters = [0,1]
+    
+    expdes = ExpDesigns(inp)
+    expdes.n_init_samples = 2
+    expdes.n_max_samples = 4
+    expdes.X = np.array([[0],[1],[0.5]])
+    expdes.Y = {'Z':[[0.4],[0.5],[0.45]]}
+    #expdes.x_values = np.array([0]) #  Error in plots if this is not available
+    
+    mm = MetaModel(inp)
+    mm.fit(expdes.X, expdes.Y)
+    expdes.generate_ED(expdes.n_init_samples, transform=True, max_pce_deg=np.max(mm.pce_deg))
+    
+    mod = PL()
+    mod.observations = {'Z':np.array([0.45]), 'x_values':np.array([0])}
+    mod.Output.names = ['Z']
+    
+    engine = Engine(mm, mod, expdes)
+    
+    sigma2Dict = {'Z':np.array([0.05])}
+    sigma2Dict = pd.DataFrame(sigma2Dict, columns = ['Z'])
+    obsData = pd.DataFrame(mod.observations, columns=mod.Output.names)
+    disc = Discrepancy('')
+    disc.type = 'Gaussian'
+    disc.parameters = (obsData*0.15)**2
+    disc.opt_sigma = 'B'
+    
+    bi = BayesInference(engine)
+    bi.Discrepancy = disc 
+    bi.inference_method = 'mcmc'
+    bi.setup_inference()
+    
+    #chain = [[[1],[2]]]
+    total_sigma2s = {'Z':np.array([0.15])}
+    mcmc = MCMC(bi)
+    mcmc.nsteps = 50
+    mcmc.nburn = 10
+    mcmc.run_sampler(mod.observations, total_sigma2s)
+    #mcmc.gelmain_rubin(chain)
     
+    chain = [[[1],[2]]]
+    gelman_rubin(chain, return_var=True)
 
+    _iterative_scheme(1, 1, 0, 1, 2, 3, 4, 1, 1, 10, 'r')
\ No newline at end of file