From c10f614f57249c37b482d334e06e6dd0e16a933e Mon Sep 17 00:00:00 2001
From: Nianchen Deng <dengnianchen@sjtu.edu.cn>
Date: Sat, 8 May 2021 21:35:20 +0800
Subject: [PATCH] sync

---
 .clang-format                           | 108 ++++
 .vscode/settings.json                   |   1 -
 .vscode/tasks.json                      |  17 -
 batch_export_net.sh                     |  42 ++
 batch_infer.sh                          |  35 +-
 components/fnr.py                       |  54 +-
 components/foveation.py                 |  35 +-
 cpp/Makefile.config                     |   4 +-
 cpp/msl_infer/Common.h                  | 155 ------
 cpp/msl_infer/Encoder.cu                |  15 +-
 cpp/msl_infer/Encoder.h                 |   3 +-
 cpp/msl_infer/Enhancement.cu            |   2 +-
 cpp/msl_infer/Enhancement.h             |   2 +-
 cpp/msl_infer/InferPipeline.cpp         |  99 ++--
 cpp/msl_infer/InferPipeline.h           |  24 +-
 cpp/msl_infer/Msl.cpp                   |  29 +-
 cpp/msl_infer/Msl.h                     |  20 +-
 cpp/msl_infer/Net.cpp                   |   2 +-
 cpp/msl_infer/Net.h                     |   2 +-
 cpp/msl_infer/Nmsl2.cpp                 | 111 ++--
 cpp/msl_infer/Nmsl2.h                   |   4 +-
 cpp/msl_infer/Renderer.cu               |  30 +-
 cpp/msl_infer/Renderer.h                |   9 +-
 cpp/msl_infer/Resource.h                | 159 ------
 cpp/msl_infer/Sampler.cu                |  49 +-
 cpp/msl_infer/Sampler.h                 |  19 +-
 cpp/msl_infer/SynthesisPipeline.cpp     | 135 ++---
 cpp/msl_infer/SynthesisPipeline.h       |  68 +--
 cpp/msl_infer/View.cu                   |   2 +-
 cpp/msl_infer/View.h                    |   2 +-
 cpp/msl_infer_test/Makefile             |   2 +-
 cpp/msl_infer_test/main.cpp             | 648 ++++++++++++------------
 cpp/{msl_infer => utils}/Formatter.h    |   0
 cpp/{msl_infer => utils}/Logger.cpp     |   0
 cpp/{msl_infer => utils}/Logger.h       |   2 +-
 cpp/utils/Resource.h                    | 136 +++++
 cpp/utils/common.h                      | 138 +++++
 cpp/utils/cuda.h                        |  11 +
 cpp/{msl_infer => utils}/half.h         |   0
 cpp/{msl_infer => utils}/thread_index.h |   0
 data/spherical_view_syn.py              |  18 +-
 notebook/gen_demo_mono.ipynb            |  38 +-
 notebook/gen_demo_stereo.ipynb          | 194 +++----
 notebook/test_foveation.ipynb           |  28 +-
 notebook/test_spherical_view_syn.ipynb  |  65 +--
 single_infer.sh                         |  30 ++
 tools/convert_data_desc.py              |   2 +-
 tools/export_snerf_fast.py              |  62 ++-
 tools/gen_eval_table.py                 |  91 ++++
 49 files changed, 1413 insertions(+), 1289 deletions(-)
 create mode 100644 .clang-format
 delete mode 100644 .vscode/tasks.json
 create mode 100755 batch_export_net.sh
 delete mode 100644 cpp/msl_infer/Common.h
 delete mode 100644 cpp/msl_infer/Resource.h
 rename cpp/{msl_infer => utils}/Formatter.h (100%)
 rename cpp/{msl_infer => utils}/Logger.cpp (100%)
 rename cpp/{msl_infer => utils}/Logger.h (95%)
 create mode 100644 cpp/utils/Resource.h
 create mode 100644 cpp/utils/common.h
 create mode 100644 cpp/utils/cuda.h
 rename cpp/{msl_infer => utils}/half.h (100%)
 rename cpp/{msl_infer => utils}/thread_index.h (100%)
 create mode 100755 single_infer.sh
 create mode 100644 tools/gen_eval_table.py

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..edc803a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,108 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:   
+  AfterClass:      true
+  AfterControlStatement: false
+  AfterEnum:       true
+  AfterFunction:   true
+  AfterNamespace:  true
+  AfterObjCDeclaration: true
+  AfterStruct:     true
+  AfterUnion:      true
+  BeforeCatch:     false
+  BeforeElse:      false
+  IndentBraces:    false
+  SplitEmptyFunction: true
+  SplitEmptyRecord: true
+  SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit:     100
+CommentPragmas:  '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:   
+  - foreach
+  - Q_FOREACH
+  - BOOST_FOREACH
+IncludeCategories: 
+  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
+    Priority:        2
+  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
+    Priority:        3
+  - Regex:           '.*'
+    Priority:        1
+IncludeIsMainRegex: '(Test)?$'
+IndentCaseLabels: false
+IndentWidth:     4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 4
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+ReflowComments:  true
+SortIncludes:    false
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 1
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+TabWidth:        4
+UseTab:          Never
+...
+
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d6a0452..920979e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -11,5 +11,4 @@
         "__nullptr": "cpp"
     },
     "python.pythonPath": "/home/dengnc/miniconda3/bin/python",
-    "jupyter.jupyterServerType": "local"
 }
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
deleted file mode 100644
index 12388cd..0000000
--- a/.vscode/tasks.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    // See https://go.microsoft.com/fwlink/?LinkId=733558
-    // for the documentation about the tasks.json format
-    "version": "2.0.0",
-    "tasks": [
-        {
-            "label": "echo",
-            "type": "shell",
-            "command": "echo Hello",
-            "problemMatcher": [],
-            "group": {
-                "kind": "build",
-                "isDefault": true
-            }
-        }
-    ]
-}
\ No newline at end of file
diff --git a/batch_export_net.sh b/batch_export_net.sh
new file mode 100755
index 0000000..3a1f8f6
--- /dev/null
+++ b/batch_export_net.sh
@@ -0,0 +1,42 @@
+#/usr/bin/bash
+
+datadir='data/__new/classroom_fovea_r360x80_t0.6'
+onnxdir="$datadir/eval_onnx"
+trtdir="$datadir/eval_trt"
+epochs=50
+
+if [ ! -d "$onnxdir" ]; then
+    echo "make directory for ONNX"
+    mkdir $onnxdir
+fi
+if [ ! -d "$trtdir" ]; then
+    echo "make directory for TensorRT"
+    mkdir $trtdir
+    mkdir $trtdir/time
+fi
+
+# nets: 1, 2, 4, 8
+# layers: 2, 4, 8
+# channels: 64 128 256 512 1024
+for n_nets in 1 2 4 8; do
+    for n_layers in 2 4 8; do
+        for nf in 64 128 256 512 1024; do
+            configid="eval@snerffast${n_nets}-rgb_e6_fc${nf}x${n_layers}_d1.00-7.00_s64_~p"
+            exportname="eval_${n_nets}x${nf}x${n_layers}"
+            pth_path="$datadir/$configid/model-epoch_$epochs.pth"
+            onnx_path="$onnxdir/$exportname.onnx"
+            trt_path="$trtdir/$exportname.trt"
+            time_perf_path="$trtdir/time/$exportname.json"
+            if [ -f "$pth_path" ]; then
+                if [ ! -f "$onnx_path" ]; then
+                    # Export ONNX model
+                    python tools/export_snerf_fast.py $pth_path -b 65536 -o $onnx_path
+                fi
+                if [ ! -f "$trt_path" ]; then
+                    # Export TensorRT engine
+                    trtexec --onnx=$onnx_path --fp16 --saveEngine=$trt_path --workspace=4096 --exportTimes=$time_perf_path --noDataTransfers
+                fi
+            fi
+        done
+    done
+done
\ No newline at end of file
diff --git a/batch_infer.sh b/batch_infer.sh
index 3ebd340..cbeae90 100755
--- a/batch_infer.sh
+++ b/batch_infer.sh
@@ -8,7 +8,7 @@ epochs=50
 
 # nets: 1, 2, 4, 8
 # layers: 2, 4, 8
-# channels: 128 256 512
+# channels: 64 128 256 512 1024
 n_nets_arr=(1 2 4 8 1 2 4 8 1 2 4 8)
 n_layers_arr=(2 2 2 2 4 4 4 4 8 8 8 8)
 n_nets=${n_nets_arr[$testcase]}
@@ -16,21 +16,22 @@ n_layers=${n_layers_arr[$testcase]}
 
 for nf in 64 128 256 512 1024; do
     configid="eval@snerffast${n_nets}-rgb_e6_fc${nf}x${n_layers}_d1.00-7.00_s64_~p"
-    if [ -f "$datadir/$configid/model-epoch_$epochs.pth" ]; then
-        continue
-    fi
-    cont_epoch=0
-    for ((i=$epochs-1;i>0;i--)) do
-        if [ -f "$datadir/$configid/model-epoch_$i.pth" ]; then
-            cont_epoch=$i
-            break
+    if [ ! -f "$datadir/$configid/model-epoch_$epochs.pth" ]; then
+        cont_epoch=0
+        for ((i=$epochs-1;i>0;i--)) do
+            if [ -f "$datadir/$configid/model-epoch_$i.pth" ]; then
+                cont_epoch=$i
+                break
+            fi
+        done
+        if [ ${cont_epoch} -gt 0 ]; then
+            python run_spherical_view_syn.py $trainset -e $epochs -m $configid/model-epoch_${cont_epoch}.pth
+        else
+            python run_spherical_view_syn.py $trainset -i $configid -e $epochs
         fi
-    done
-    if [ ${cont_epoch} -gt 0 ]; then
-        python run_spherical_view_syn.py $trainset -e $epochs -m $configid/model-epoch_${cont_epoch}.pth
-    else
-        python run_spherical_view_syn.py $trainset -i $configid -e $epochs
     fi
-    python run_spherical_view_syn.py $trainset -t -m $configid/model-epoch_$epochs.pth -o perf
-    python run_spherical_view_syn.py $testset -t -m $configid/model-epoch_$epochs.pth -o perf
-done
+    if ! ls $datadir/$configid/output_$epochs/perf_r120x80* >/dev/null 2>&1; then
+        python run_spherical_view_syn.py $trainset -t -m $configid/model-epoch_$epochs.pth -o perf
+        python run_spherical_view_syn.py $testset -t -m $configid/model-epoch_$epochs.pth -o perf
+    fi
+done
\ No newline at end of file
diff --git a/components/fnr.py b/components/fnr.py
index 8cf165c..cdad505 100644
--- a/components/fnr.py
+++ b/components/fnr.py
@@ -14,7 +14,6 @@ class FoveatedNeuralRenderer(object):
                  layers_res: List[Tuple[int, int]],
                  layers_net: nn.ModuleList,
                  output_res: Tuple[int, int], *,
-                 using_mask=True,
                  device: torch.device = None):
         super().__init__()
         self.layers_net = layers_net.to(device=device)
@@ -34,7 +33,6 @@ class FoveatedNeuralRenderer(object):
             'normalized': True
         }, output_res, device=device)
         self.foveation = Foveation(layers_fov, layers_res, output_res, device=device)
-        self.layers_mask = self.foveation.get_layers_mask() if using_mask else None
         self.device = device
 
     def to(self, device: torch.device):
@@ -43,8 +41,6 @@ class FoveatedNeuralRenderer(object):
         self.cam.to(device)
         for cam in self.layers_cam:
             cam.to(device)
-        if self.layers_mask is not None:
-            self.layers_mask = self.layers_mask.to(device)
         self.device = device
         return self
 
@@ -52,32 +48,46 @@ class FoveatedNeuralRenderer(object):
         return self.render(*args, **kwds)
 
     def render(self, view: Trans, gaze, right_gaze=None, *,
-               stereo_disparity=0, ret_raw=False) -> Union[Mapping[str, torch.Tensor], Tuple[Mapping[str, torch.Tensor]]]:
+               stereo_disparity=0,
+               using_mask=True,
+               ret_raw=False) -> Union[Mapping[str, torch.Tensor], Tuple[Mapping[str, torch.Tensor]]]:
         if stereo_disparity > TINY_FLOAT:
             left_view = Trans(
-                view.trans_point(torch.tensor([-stereo_disparity / 2, 0, 0], device=view.device())),
+                view.trans_point(torch.tensor([-stereo_disparity / 2, 0, 0], device=self.device)),
                 view.r)
             right_view = Trans(
-                view.trans_point(torch.tensor([stereo_disparity / 2, 0, 0], device=view.device())),
+                view.trans_point(torch.tensor([stereo_disparity / 2, 0, 0], device=self.device)),
                 view.r)
             left_gaze = gaze
             right_gaze = gaze if right_gaze is None else right_gaze
+
+            left_layers_mask = self.foveation.get_layers_mask(left_gaze) \
+                if using_mask else [None] * 3
+            right_layers_mask = self.foveation.get_layers_mask(right_gaze) \
+                if using_mask else [None] * 3
             res_raw_left = [
-                self._render(i, left_view, left_gaze if i < 2 else None)['color']
+                self._render(self.layers_net[i], self.layers_cam[i], left_view,
+                             left_gaze if i < 2 else None,
+                             layer_mask=left_layers_mask[i])['color']
                 for i in range(3)
             ]
             res_raw_right = [
-                self._render(i, right_view, right_gaze if i < 2 else None)['color']
+                self._render(self.layers_net[i], self.layers_cam[i], right_view,
+                             right_gaze if i < 2 else None,
+                             layer_mask=right_layers_mask[i])['color']
                 for i in range(3)
             ]
             return self._gen_output(res_raw_left, left_gaze, ret_raw), \
                 self._gen_output(res_raw_right, right_gaze, ret_raw)
         else:
+            layers_mask = self.foveation.get_layers_mask(gaze) if using_mask else None
             res_raw = [
-                self._render(i, view, gaze if i < 2 else None)['color']
+                self._render(self.layers_net[i], self.layers_cam[i], view, gaze if i < 2 else None,
+                             layer_mask=layers_mask[i] if layers_mask is not None else None)['color']
                 for i in range(3)
             ]
             return self._gen_output(res_raw, gaze, ret_raw)
+
         '''
         if mono_trans != None and shift == 0:  # do warp
             fovea_depth[torch.isnan(fovea_depth)] = 50
@@ -105,25 +115,25 @@ class FoveatedNeuralRenderer(object):
         ], (gaze[0], gaze[1]), [0, shift, shift] if shift != 0 else None)
         '''
 
-    def _render(self, layer: int, view: Trans, gaze=None, ret_depth=False) -> Mapping[str, torch.Tensor]:
-        net = self.layers_net[layer]
-        cam = self.layers_cam[layer]
+    def _render(self, net, cam: CameraParam, view: Trans, gaze=None, *,
+                ret_depth=False,
+                layer_mask=None) -> Mapping[str, torch.Tensor]:
         if gaze is not None:
             cam = self._adjust_cam(cam, gaze)
-        rays_o, rays_d = cam.get_global_rays(view, True)  # (1, N, 3)
-        if self.layers_mask is not None and layer < len(self.layers_mask):
-            mask = self.layers_mask[layer] >= 0
-            rays_o = rays_o[:, mask]
-            rays_d = rays_d[:, mask]
+        rays_o, rays_d = cam.get_global_rays(view, False)  # (1, H, W, 3)
+        if layer_mask is not None:
+            infer_mask = layer_mask >= 0
+            rays_o = rays_o[:, infer_mask]
+            rays_d = rays_d[:, infer_mask]
             net_output = net(rays_o.view(-1, 3), rays_d.view(-1, 3), ret_depth=ret_depth)
             ret = {
-                'color': torch.zeros(1, cam.res[0], cam.res[1], 3)
+                'color': torch.zeros(1, cam.res[0], cam.res[1], 3, device=self.device)
             }
-            ret['color'][:, mask] = net_output['color']
+            ret['color'][:, infer_mask] = net_output['color']
             ret['color'] = ret['color'].permute(0, 3, 1, 2)
             if ret_depth:
                 ret['depth'] = torch.zeros(1, cam.res[0], cam.res[1])
-                ret['depth'][:, mask] = net_output['depth']
+                ret['depth'][:, infer_mask] = net_output['depth']
             return ret
         else:
             net_output = net(rays_o.view(-1, 3), rays_d.view(-1, 3), ret_depth=ret_depth)
@@ -140,7 +150,7 @@ class FoveatedNeuralRenderer(object):
             'blended': blended
         }
         if ret_raw:
-            ret['layers_raw'] = layers_img,
+            ret['layers_raw'] = layers_img
             ret['blended_raw'] = self.foveation.synthesis(layers_img, gaze)
         return ret
 
diff --git a/components/foveation.py b/components/foveation.py
index 32ef769..00e4a20 100644
--- a/components/foveation.py
+++ b/components/foveation.py
@@ -31,7 +31,7 @@ class Foveation(object):
 
     def synthesis(self, layers: List[torch.Tensor],
                   fovea_center: Tuple[float, float],
-                  shifts: List[int] = None) -> torch.Tensor:
+                  shifts: List[int] = None, do_blend=True) -> torch.Tensor:
         """
         Generate foveated retinal image by blending fovea layers
         **Note: current implementation only support two fovea layers**
@@ -55,8 +55,12 @@ class Foveation(object):
             if shifts != None:
                 grid = img.horizontal_shift(grid, shifts[i], -2)
             # (1, 1, H:out, W:out)
-            blend = nn_f.grid_sample(self.eye_fovea_blend[i][None, None, ...], grid)
-            output.mul_(1 - blend).add_(nn_f.grid_sample(layers[i], grid) * blend)
+            if do_blend:
+                blend = nn_f.grid_sample(self.eye_fovea_blend[i][None, None], grid, align_corners=False)
+                output.mul_(1 - blend).add_(nn_f.grid_sample(layers[i], grid, align_corners=False) * blend)
+            else:
+                blend = nn_f.grid_sample(torch.ones_like(self.eye_fovea_blend[i][None, None]), grid, align_corners=False)
+                output.mul_(1 - blend).add_(nn_f.grid_sample(layers[i], grid, align_corners=False) * blend)
         return output
 
     def get_layer_size_in_final_image(self, i: int) -> int:
@@ -94,7 +98,7 @@ class Foveation(object):
         r = torch.norm(p - R, dim=2)  # (size, size, 2)
         return misc.smooth_step(R, R * self.blend, r)
 
-    def get_layers_mask(self) -> List[torch.Tensor]:
+    def get_layers_mask(self, gaze) -> List[torch.Tensor]:
         """
         Generate mask images for layers[:-1]
         the meaning of values in mask images:
@@ -106,15 +110,26 @@ class Foveation(object):
         :return: Mask images for layers except outermost
         """
         layers_mask = []
-        for i in range(self.n_layers - 1):
+        for i in range(self.n_layers):
             layers_mask.append(torch.ones(*self.layers_res[i], device=self.device) * -1)
-            r = torch.norm(misc.meshgrid(*self.layers_res[i], normalize=True).to(device=self.device) * 2 - 1, dim=-1)
+            if i == self.n_layers - 1:
+                c = torch.tensor([
+                    (gaze[0] + 0.5 * self.out_res[1]) / self.out_res[0],
+                    (gaze[1] + 0.5 * self.out_res[0]) / self.out_res[0]
+                ], device=self.device)
+            else:
+                c = torch.tensor([0.5, 0.5], device=self.device)
+            coord = misc.meshgrid(*self.layers_res[i]).to(device=self.device) / self.layers_res[i][0]
+            r = 2 * torch.norm(coord - c, dim=-1)
             inner_radius = self.get_source_layer_cover_size_in_target_layer(
-                self.layers_fov[i - 1], self.layers_fov[i],
-                self.layers_res[i][0]) / self.layers_res[i][0] if i > 0 else 0
-            bounds = [inner_radius * (1 - self.blend), inner_radius, self.blend, 1]
+                self.layers_fov[i - 1], self.layers_fov[i], self.layers_res[i][0]) / self.layers_res[i][0] \
+                if i > 0 else 0
+            if i == self.n_layers - 1:
+                bounds = [inner_radius * (1 - self.blend), inner_radius, 100, 100]
+            else:
+                bounds = [inner_radius * (1 - self.blend), inner_radius, self.blend, 1]
             for bi in range(len(bounds) - 1):
                 region = torch.logical_and(r > bounds[bi], r <= bounds[bi + 1])
                 layers_mask[i][region] = bi + \
                     (r[region] - bounds[bi]) / (bounds[bi + 1] - bounds[bi])
-        return layers_mask
\ No newline at end of file
+        return layers_mask
diff --git a/cpp/Makefile.config b/cpp/Makefile.config
index 908140b..6c677db 100644
--- a/cpp/Makefile.config
+++ b/cpp/Makefile.config
@@ -128,7 +128,7 @@ endif
 #########################
 INCPATHS=
 LIBPATHS=
-COMMON_LIBS= -lGLEW -lglfw3 -lGL -lX11 -lpthread -lXrandr -lXinerama -lXcursor -lXi -ldl
+COMMON_LIBS= -lGLEW -lglfw -lGL -lX11 -lpthread -lXrandr #-lXinerama -lXcursor -lXi -ldl
 
 # Add extra libraries if TRT_STATIC is enabled
 ifeq ($(TRT_STATIC), 1)
@@ -207,7 +207,7 @@ else ifeq ($(TARGET), aarch64)
   endif
 endif
 ifeq ($(ENABLE_MYELIN), 1)
-  COMMON_LIBS += $(MYELIN_LIB) $(NVRTC_LIB)
+  #COMMON_LIBS += $(MYELIN_LIB) $(NVRTC_LIB)
 endif
 
 .SUFFIXES:
diff --git a/cpp/msl_infer/Common.h b/cpp/msl_infer/Common.h
deleted file mode 100644
index e9898ac..0000000
--- a/cpp/msl_infer/Common.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#pragma once
-#include <memory>
-#include <stdexcept>
-#include <vector>
-#include <string>
-#include <sstream>
-#include <GL/glew.h>
-#include <cuda_gl_interop.h>
-#include "../glm/glm.hpp"
-#include "Logger.h"
-
-inline unsigned int getElementSize(nv::DataType t)
-{
-	switch (t)
-	{
-	case nv::DataType::kINT32:
-		return 4;
-	case nv::DataType::kFLOAT:
-		return 4;
-	case nv::DataType::kHALF:
-		return 2;
-	case nv::DataType::kBOOL:
-	case nv::DataType::kINT8:
-		return 1;
-	}
-	throw std::runtime_error("Invalid DataType.");
-	return 0;
-}
-
-template <typename T>
-void dumpRow(std::ostream &os, T* buf, size_t n)
-{
-	os << buf[0];
-	for (size_t i = 1; i < n; ++i) {
-		os << " " << buf[i];
-	}
-	os << std::endl;
-}
-
-template <typename T>
-void dumpHostBuffer(std::ostream &os, void *buf, size_t bufSize, size_t rowCount, size_t maxDumpRows = 0)
-{
-	T *typedBuf = static_cast<T *>(buf);
-	size_t numItems = bufSize / sizeof(T);
-	size_t nInLastRow = numItems % rowCount;
-	size_t rows;
-	if (nInLastRow == 0) {
-		rows = numItems / rowCount;
-		nInLastRow = rowCount;
-	} else {
-		rows = numItems / rowCount + 1;
-	}
-	if (maxDumpRows == 0) {
-		for (size_t i = 0; i < rows - 1; ++i) {
-			dumpRow(os, typedBuf, rowCount);
-			typedBuf += rowCount;
-		}
-		dumpRow(os, typedBuf, nInLastRow);
-	} else {
-		for (size_t i = 0; i < maxDumpRows / 2; ++i)
-			dumpRow(os, typedBuf + i * rowCount, rowCount);
-		os << "..." << std::endl;
-		for (size_t i = rows - maxDumpRows + maxDumpRows / 2; i < rows - 1; ++i)
-			dumpRow(os, typedBuf + i * rowCount, rowCount);
-		dumpRow(os, typedBuf + (rows - 1) * rowCount, nInLastRow);
-	}
-}
-
-class CudaStream
-{
-public:
-	CudaStream()
-	{
-		cudaStreamCreate(&stream);
-	}
-
-	operator cudaStream_t()
-	{
-		return stream;
-	}
-
-	virtual ~CudaStream()
-	{
-		cudaStreamDestroy(stream);
-	}
-
-private:
-	cudaStream_t stream;
-};
-
-class CudaEvent
-{
-public:
-	CudaEvent()
-	{
-		cudaEventCreate(&mEvent);
-	}
-
-	operator cudaEvent_t()
-	{
-		return mEvent;
-	}
-
-	virtual ~CudaEvent()
-	{
-		cudaEventDestroy(mEvent);
-	}
-
-private:
-	cudaEvent_t mEvent;
-};
-
-struct CudaMapScope
-{
-	std::vector<cudaGraphicsResource_t> resources_;
-	cudaStream_t stream_;
-
-	CudaMapScope(const std::vector<cudaGraphicsResource_t> &resources,
-				 cudaStream_t stream = nullptr) : resources_(resources), stream_(stream) {}
-
-	~CudaMapScope()
-	{
-		if (!resources_.empty())
-			cudaGraphicsUnmapResources(resources_.size(),
-									   resources_.data(), stream_);
-	}
-
-	cudaError_t map()
-	{
-		if (!resources_.empty())
-			return cudaGraphicsMapResources(resources_.size(),
-											resources_.data(), stream_);
-		return cudaSuccess;
-	}
-};
-
-template <typename T>
-struct Destroy
-{
-	void operator()(T *t)
-	{
-		if (t != nullptr)
-			t->destroy();
-	}
-};
-
-template <class T>
-using uptr = std::unique_ptr<T, ::Destroy<T>>;
-template <class T>
-using sptr = std::shared_ptr<T>;
-
-#define INTERVAL(__start__, __end__) (((__end__) - (__start__)) / (float)CLOCKS_PER_SEC * 1000)
-
-#include "Resource.h"
-#include "Formatter.h"
\ No newline at end of file
diff --git a/cpp/msl_infer/Encoder.cu b/cpp/msl_infer/Encoder.cu
index 51e0d16..589f6c7 100644
--- a/cpp/msl_infer/Encoder.cu
+++ b/cpp/msl_infer/Encoder.cu
@@ -1,5 +1,5 @@
 #include "Encoder.h"
-#include "thread_index.h"
+#include "../utils/cuda.h"
 
 /// idx3.z = 0: x, y, z, sin(x), sin(y), sin(z), cos(x), cos(y), cos(z)
 /// idx3.z = 1: sin(2x), sin(2y), sin(2z), cos(2x), cos(2y), cos(2z)
@@ -7,12 +7,11 @@
 /// idx3.z = n_freq-1: sin(2^(n_freq-1)x), sin(2^(n_freq-1)y), sin(2^(n_freq-1)z),
 ///                    cos(2^(n_freq-1)x), cos(2^(n_freq-1)y), cos(2^(n_freq-1)z)
 /// Dispatch (n_batch, n_chns, n_freqs)
-__global__ void cu_encode(float *output, float *input, float *freqs, uint n)
-{
+__global__ void cu_encode(float *output, float *input, float *freqs, uint n) {
     glm::uvec3 idx3 = IDX3;
     if (idx3.x >= n)
         return;
-    uint n = blockDim.x, inChns = blockDim.y, nFreqs = blockDim.z;
+    uint inChns = blockDim.y, nFreqs = blockDim.z;
     uint i = idx3.x, chn = idx3.y, freq = idx3.z;
     uint elem = i * inChns + chn;
     uint outChns = inChns * (nFreqs * 2 + 1);
@@ -26,16 +25,14 @@ __global__ void cu_encode(float *output, float *input, float *freqs, uint n)
     output[base + inChns * (freq * 2 + 2)] = c;
 }
 
-void Encoder::encode(sptr<CudaArray<float>> output, sptr<CudaArray<float>> input)
-{
+void Encoder::encode(sptr<CudaArray<float>> output, sptr<CudaArray<float>> input) {
     dim3 blkSize(1024 / _chns / _multires, _chns, _multires);
     dim3 grdSize((uint)ceil(input->n() / (float)blkSize.x), 1, 1);
-    cu_encode<<<grdSize, blkSize>>>(output->getBuffer(), *input, *_freqs, input->n());
+    CU_INVOKE(cu_encode)(output->getBuffer<float>(), *input, *_freqs, input->n());
     CHECK_EX(cudaGetLastError());
 }
 
-void Encoder::_genFreqArray()
-{
+void Encoder::_genFreqArray() {
     float *arr = new float[_multires];
     arr[0] = 1.0f;
     for (auto i = 1; i < _multires; ++i)
diff --git a/cpp/msl_infer/Encoder.h b/cpp/msl_infer/Encoder.h
index 98e4a08..ef56566 100644
--- a/cpp/msl_infer/Encoder.h
+++ b/cpp/msl_infer/Encoder.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
 class Encoder {
 public:
@@ -14,5 +14,4 @@ private:
     sptr<CudaArray<float>> _freqs;
 
     void _genFreqArray();
-
 };
\ No newline at end of file
diff --git a/cpp/msl_infer/Enhancement.cu b/cpp/msl_infer/Enhancement.cu
index c928ea5..9fb12ea 100644
--- a/cpp/msl_infer/Enhancement.cu
+++ b/cpp/msl_infer/Enhancement.cu
@@ -1,5 +1,5 @@
 #include "Enhancement.h"
-#include "thread_index.h"
+#include "../utils/cuda.h"
 
 #define max(__a__, __b__) (__a__ > __b__ ? __a__ : __b__)
 #define min(__a__, __b__) (__a__ < __b__ ? __a__ : __b__)
diff --git a/cpp/msl_infer/Enhancement.h b/cpp/msl_infer/Enhancement.h
index b7c6d90..0c99f7d 100644
--- a/cpp/msl_infer/Enhancement.h
+++ b/cpp/msl_infer/Enhancement.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
 class Enhancement
 {
diff --git a/cpp/msl_infer/InferPipeline.cpp b/cpp/msl_infer/InferPipeline.cpp
index 5f3fbed..76a84af 100644
--- a/cpp/msl_infer/InferPipeline.cpp
+++ b/cpp/msl_infer/InferPipeline.cpp
@@ -1,40 +1,34 @@
 #include "InferPipeline.h"
 #include "Nmsl2.h"
 
-InferPipeline::InferPipeline(
-    const std::string &netDir, bool isNmsl, uint batchSize,
-    uint samples) : _batchSize(batchSize),
-                    _samples(samples),
-                    _sampler(new Sampler({1.0f, 50.0f}, samples)),
-                    _encoder(new Encoder(10, 3)),
-                    _renderer(new Renderer()),
-                    _net(isNmsl ? new Nmsl2(batchSize, samples) : new Msl(batchSize, samples))
-{
-    uint batchSizeForNet = _batchSize * _samples;
-    _sphericalCoords = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(batchSizeForNet));
-    _depths = sptr<CudaArray<float>>(new CudaArray<float>(batchSizeForNet));
-    _encoded = sptr<CudaArray<float>>(new CudaArray<float>(batchSizeForNet * _encoder->outDim()));
-    _layeredColors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(batchSizeForNet));
-    _net->load(netDir);
+InferPipeline::InferPipeline(sptr<Msl> net, uint nRays, uint nSamplesPerRay, glm::vec2 depthRange,
+                             int encodeDim, int coordChns)
+    : _nRays(nRays),
+      _nSamplesPerRay(nSamplesPerRay),
+      _net(net),
+      _sampler(new Sampler(depthRange, nSamplesPerRay, coordChns == 3)),
+      _encoder(new Encoder(encodeDim, coordChns)),
+      _renderer(new Renderer()) {
+    uint nSamples = _nRays * _nSamplesPerRay;
+    _coords = sptr<CudaArray<float>>(new CudaArray<float>(nSamples * coordChns));
+    _depths = sptr<CudaArray<float>>(new CudaArray<float>(nSamples));
+    _encoded = sptr<CudaArray<float>>(new CudaArray<float>(nSamples * _encoder->outDim()));
+    _layeredColors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(nSamples));
     _net->bindResources(_encoded.get(), _depths.get(), _layeredColors.get());
 }
 
-void InferPipeline::run(sptr<CudaArray<glm::vec4>> o_colors,
-                        sptr<CudaArray<glm::vec3>> rays,
-                        glm::vec3 rayOrigin, bool showPerf)
-{
+void InferPipeline::run(sptr<CudaArray<glm::vec4>> o_colors, sptr<CudaArray<glm::vec3>> rays,
+                        glm::vec3 origin, bool showPerf) {
 
     CudaEvent eStart, eSampled, eEncoded, eInferred, eRendered;
 
     cudaEventRecord(eStart);
 
-    _sampler->sampleOnRays(_sphericalCoords, _depths, rays, rayOrigin);
+    _sampler->sampleOnRays(_coords, _depths, rays, origin);
 
     cudaEventRecord(eSampled);
-    
-    sptr<CudaArray<float>> coords(new CudaArray<float>((float *)_sphericalCoords->getBuffer(),
-                                                       _sphericalCoords->n() * 3));
-    _encoder->encode(_encoded, coords);
+
+    _encoder->encode(_encoded, _coords);
 
     cudaEventRecord(eEncoded);
 
@@ -46,8 +40,7 @@ void InferPipeline::run(sptr<CudaArray<glm::vec4>> o_colors,
 
     cudaEventRecord(eRendered);
 
-    if (showPerf)
-    {
+    if (showPerf) {
         CHECK_EX(cudaDeviceSynchronize());
 
         float timeTotal, timeSample, timeEncode, timeInfer, timeRender;
@@ -59,34 +52,34 @@ void InferPipeline::run(sptr<CudaArray<glm::vec4>> o_colors,
 
         std::ostringstream sout;
         sout << "Infer pipeline: " << timeTotal << "ms (Sample: " << timeSample
-             << "ms, Encode: " << timeEncode << "ms, Infer: "
-             << timeInfer << "ms, Render: " << timeRender << "ms)";
+             << "ms, Encode: " << timeEncode << "ms, Infer: " << timeInfer
+             << "ms, Render: " << timeRender << "ms)";
         Logger::instance.info(sout.str());
     }
     /*
-	{
-		std::ostringstream sout;
-		sout << "Rays:" << std::endl;
-		dumpFloatArray(sout, *rays, 10);
-		Logger::instance.info(sout.str());
-	}
-	{
-		std::ostringstream sout;
-		sout << "Spherical coords:" << std::endl;
-		dumpFloatArray(sout, *sphericalCoords, 10);
-		Logger::instance.info(sout.str());
-	}
-	{
-		std::ostringstream sout;
-		sout << "Depths:" << std::endl;
-		dumpFloatArray(sout, *depths, 10);
-		Logger::instance.info(sout.str());
-	}
-	{
-		std::ostringstream sout;
-		sout << "Encoded:" << std::endl;
-		dumpFloatArray(sout, *encoded, 10, encoder.outDim());
-		Logger::instance.info(sout.str());
-	}
-	*/
+    {
+        std::ostringstream sout;
+        sout << "Rays:" << std::endl;
+        dumpFloatArray(sout, *rays, 10);
+        Logger::instance.info(sout.str());
+    }
+    {
+        std::ostringstream sout;
+        sout << "Spherical coords:" << std::endl;
+        dumpFloatArray(sout, *sphericalCoords, 10);
+        Logger::instance.info(sout.str());
+    }
+    {
+        std::ostringstream sout;
+        sout << "Depths:" << std::endl;
+        dumpFloatArray(sout, *depths, 10);
+        Logger::instance.info(sout.str());
+    }
+    {
+        std::ostringstream sout;
+        sout << "Encoded:" << std::endl;
+        dumpFloatArray(sout, *encoded, 10, encoder.outDim());
+        Logger::instance.info(sout.str());
+    }
+    */
 }
\ No newline at end of file
diff --git a/cpp/msl_infer/InferPipeline.h b/cpp/msl_infer/InferPipeline.h
index aa27fc1..74e9dc1 100644
--- a/cpp/msl_infer/InferPipeline.h
+++ b/cpp/msl_infer/InferPipeline.h
@@ -1,26 +1,26 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 #include "../msl_infer/Sampler.h"
 #include "../msl_infer/Encoder.h"
 #include "../msl_infer/Renderer.h"
 #include "../msl_infer/Msl.h"
 
-class InferPipeline
-{
-public:
-    InferPipeline(const std::string &netDir, bool isNmsl, uint batchSize, uint samples);
+class InferPipeline {
+  public:
+    InferPipeline(sptr<Msl> net, uint nRays, uint nSamplesPerRay,
+                  glm::vec2 depthRange, int encodeDim, int coordChns);
 
-    void run(sptr<CudaArray<glm::vec4>> o_colors, sptr<CudaArray<glm::vec3>> rays,
-             glm::vec3 rayOrigin, bool showPerf = false);
+    void run(sptr<CudaArray<glm::vec4>> o_colors, sptr<CudaArray<glm::vec3>> rays, glm::vec3 origin,
+             bool showPerf = false);
 
-private:
-    uint _batchSize;
-    uint _samples;
+  private:
+    uint _nRays;
+    uint _nSamplesPerRay;
+    sptr<Msl> _net;
     sptr<Sampler> _sampler;
     sptr<Encoder> _encoder;
     sptr<Renderer> _renderer;
-    sptr<Msl> _net;
-    sptr<CudaArray<glm::vec3>> _sphericalCoords;
+    sptr<CudaArray<float>> _coords;
     sptr<CudaArray<float>> _depths;
     sptr<CudaArray<float>> _encoded;
     sptr<CudaArray<glm::vec4>> _layeredColors;
diff --git a/cpp/msl_infer/Msl.cpp b/cpp/msl_infer/Msl.cpp
index b6ff71a..e966669 100644
--- a/cpp/msl_infer/Msl.cpp
+++ b/cpp/msl_infer/Msl.cpp
@@ -1,37 +1,28 @@
 #include "Msl.h"
 #include <time.h>
 
-Msl::Msl(int batchSize, int samples) : batchSize(batchSize), samples(samples), net(nullptr) {}
+Msl::Msl() : net(nullptr) {}
 
-bool Msl::load(const std::string &netDir)
-{
+bool Msl::load(const std::string &netPath) {
     net = new Net();
-    if (!net->load(netDir + "msl.trt"))
-        return false;
-    return true;
+    if (net->load(netPath))
+        return true;
+    dispose();
+    return false;
 }
 
-void Msl::bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors)
-{
+void Msl::bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors) {
     net->bindResource("Encoded", resEncoded);
     net->bindResource("Depths", resDepths);
     net->bindResource("Colors", resColors);
 }
 
-bool Msl::infer()
-{
-    if (!net->infer())
-        return false;
-    return true;
-}
+bool Msl::infer() { return net->infer(); }
 
-bool Msl::dispose()
-{
-    if (net != nullptr)
-    {
+void Msl::dispose() {
+    if (net != nullptr) {
         net->dispose();
         delete net;
         net = nullptr;
     }
-    return true;
 }
diff --git a/cpp/msl_infer/Msl.h b/cpp/msl_infer/Msl.h
index c8fa96b..0a9e3e7 100644
--- a/cpp/msl_infer/Msl.h
+++ b/cpp/msl_infer/Msl.h
@@ -1,21 +1,15 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 #include "Net.h"
 
-class Msl
-{
+class Msl {
 public:
-	int batchSize;
-	int samples;
     Net *net;
 
-	Msl(int batchSize, int samples);
+    Msl();
 
-	virtual bool load(const std::string &netDir);
-
-	virtual void bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors);
-
-	virtual bool infer();
-
-	virtual bool dispose();
+    virtual bool load(const std::string &netDir);
+    virtual void bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors);
+    virtual bool infer();
+    virtual void dispose();
 };
diff --git a/cpp/msl_infer/Net.cpp b/cpp/msl_infer/Net.cpp
index 8477569..ec54135 100644
--- a/cpp/msl_infer/Net.cpp
+++ b/cpp/msl_infer/Net.cpp
@@ -1,4 +1,4 @@
-#include "half.h"
+#include "../utils/half.h"
 #include "Net.h"
 #include <fstream>
 #include <numeric>
diff --git a/cpp/msl_infer/Net.h b/cpp/msl_infer/Net.h
index 28e25dc..425508e 100644
--- a/cpp/msl_infer/Net.h
+++ b/cpp/msl_infer/Net.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
 
 class Net {
diff --git a/cpp/msl_infer/Nmsl2.cpp b/cpp/msl_infer/Nmsl2.cpp
index ecd0f19..5d41d0f 100644
--- a/cpp/msl_infer/Nmsl2.cpp
+++ b/cpp/msl_infer/Nmsl2.cpp
@@ -1,68 +1,65 @@
 #include "Nmsl2.h"
 #include <time.h>
 
-Nmsl2::Nmsl2(int batchSize, int samples) : Msl(batchSize, samples),
-										   resRaw1(nullptr), resRaw2(nullptr),
-										   fcNet1(nullptr), fcNet2(nullptr), catNet(nullptr) {}
+Nmsl2::Nmsl2(int batchSize, int samples)
+    : batchSize(batchSize),
+      samples(samples),
+      resRaw1(nullptr),
+      resRaw2(nullptr),
+      fcNet1(nullptr),
+      fcNet2(nullptr),
+      catNet(nullptr) {}
 
-bool Nmsl2::load(const std::string &netDir)
-{
-	fcNet1 = new Net();
-	fcNet2 = new Net();
-	catNet = new Net();
-	if (!fcNet1->load(netDir + "fc1.trt") || !fcNet2->load(netDir + "fc2.trt") ||
-		!catNet->load(netDir + "cat.trt"))
-		return false;
-	resRaw1 = sptr<Resource>(new CudaBuffer(batchSize * samples / 2 * sizeof(float4)));
-	resRaw2 = sptr<Resource>(new CudaBuffer(batchSize * samples / 2 * sizeof(float4)));
-	return true;
+bool Nmsl2::load(const std::string &netDir) {
+    fcNet1 = new Net();
+    fcNet2 = new Net();
+    catNet = new Net();
+    if (!fcNet1->load(netDir + "fc1.trt") || !fcNet2->load(netDir + "fc2.trt") ||
+        !catNet->load(netDir + "cat.trt"))
+        return false;
+    resRaw1 = sptr<Resource>(new CudaBuffer(batchSize * samples / 2 * sizeof(float4)));
+    resRaw2 = sptr<Resource>(new CudaBuffer(batchSize * samples / 2 * sizeof(float4)));
+    return true;
 }
 
-void Nmsl2::bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors)
-{
-	fcNet1->bindResource("Encoded", resEncoded);
-	fcNet1->bindResource("Raw", resRaw1.get());
-	fcNet2->bindResource("Encoded", resEncoded);
-	fcNet2->bindResource("Raw", resRaw2.get());
-	catNet->bindResource("Raw1", resRaw1.get());
-	catNet->bindResource("Raw2", resRaw2.get());
-	catNet->bindResource("Depths", resDepths);
-	catNet->bindResource("Colors", resColors);
+void Nmsl2::bindResources(Resource *resEncoded, Resource *resDepths, Resource *resColors) {
+    fcNet1->bindResource("Encoded", resEncoded);
+    fcNet1->bindResource("Raw", resRaw1.get());
+    fcNet2->bindResource("Encoded", resEncoded);
+    fcNet2->bindResource("Raw", resRaw2.get());
+    catNet->bindResource("Raw1", resRaw1.get());
+    catNet->bindResource("Raw2", resRaw2.get());
+    catNet->bindResource("Depths", resDepths);
+    catNet->bindResource("Colors", resColors);
 }
 
-bool Nmsl2::infer()
-{
-	//CudaStream stream1, stream2;
-	if (!fcNet1->infer())
-		return false;
-	if (!fcNet2->infer())
-		return false;
-	if (!catNet->infer())
-		return false;
-	return true;
+bool Nmsl2::infer() {
+    // CudaStream stream1, stream2;
+    if (!fcNet1->infer())
+        return false;
+    if (!fcNet2->infer())
+        return false;
+    if (!catNet->infer())
+        return false;
+    return true;
 }
 
-bool Nmsl2::dispose()
-{
-	if (fcNet1 != nullptr)
-	{
-		fcNet1->dispose();
-		delete fcNet1;
-		fcNet1 = nullptr;
-	}
-	if (fcNet2 != nullptr)
-	{
-		fcNet2->dispose();
-		delete fcNet2;
-		fcNet2 = nullptr;
-	}
-	if (catNet != nullptr)
-	{
-		catNet->dispose();
-		delete catNet;
-		catNet = nullptr;
-	}
-	resRaw1 = nullptr;
-	resRaw2 = nullptr;
-	return true;
+void Nmsl2::dispose() {
+    if (fcNet1 != nullptr) {
+        fcNet1->dispose();
+        delete fcNet1;
+        fcNet1 = nullptr;
+    }
+    if (fcNet2 != nullptr) {
+        fcNet2->dispose();
+        delete fcNet2;
+        fcNet2 = nullptr;
+    }
+    if (catNet != nullptr) {
+        catNet->dispose();
+        delete catNet;
+        catNet = nullptr;
+    }
+    resRaw1 = nullptr;
+    resRaw2 = nullptr;
 }
diff --git a/cpp/msl_infer/Nmsl2.h b/cpp/msl_infer/Nmsl2.h
index e023e06..3f2e711 100644
--- a/cpp/msl_infer/Nmsl2.h
+++ b/cpp/msl_infer/Nmsl2.h
@@ -9,6 +9,8 @@ public:
 	Net *fcNet1;
 	Net *fcNet2;
 	Net *catNet;
+	uint batchSize;
+	uint samples;
 
 	Nmsl2(int batchSize, int samples);
 
@@ -18,6 +20,6 @@ public:
 
 	virtual bool infer();
 
-	virtual bool dispose();
+	virtual void dispose();
 
 };
diff --git a/cpp/msl_infer/Renderer.cu b/cpp/msl_infer/Renderer.cu
index b702144..29c35cc 100644
--- a/cpp/msl_infer/Renderer.cu
+++ b/cpp/msl_infer/Renderer.cu
@@ -1,32 +1,28 @@
 #include "Renderer.h"
-#include "thread_index.h"
+#include "../utils/cuda.h"
 
-/// Dispatch (n, 1, 1)
-__global__ void cu_render(glm::vec4 *o_colors, glm::vec4 *layeredColors, uint samples, uint n)
-{
+/// Dispatch (n_rays, -)
+__global__ void cu_render(glm::vec4 *o_colors, glm::vec4 *layeredColors, uint samples, uint nRays) {
     glm::uvec3 idx3 = IDX3;
-    if (idx3.x >= n)
+    uint rayIdx = idx3.x;
+    if (rayIdx >= nRays)
         return;
     glm::vec4 outColor;
-    for (int i = samples - 1; i >= 0; --i)
-    {
-        glm::vec4 c = layeredColors[idx3.x * samples + i];
+    for (int si = samples - 1; si >= 0; --si) {
+        glm::vec4 c = layeredColors[rayIdx * samples + si];
         outColor = outColor * (1 - c.a) + c * c.a;
     }
     outColor.a = 1.0f;
     o_colors[idx3.x] = outColor;
 }
 
-Renderer::Renderer()
-{
-}
+Renderer::Renderer() {}
 
 void Renderer::render(sptr<CudaArray<glm::vec4>> o_colors,
-                      sptr<CudaArray<glm::vec4>> layeredColors)
-{
-    dim3 blockSize(1024);
-    dim3 gridSize((uint)ceil(o_colors->n() / (float)blockSize.x));
-    cu_render<<<gridSize, blockSize>>>(*o_colors, *layeredColors, layeredColors->n() / o_colors->n(),
-                                       o_colors->n());
+                      sptr<CudaArray<glm::vec4>> layeredColors) {
+    dim3 blkSize(1024);
+    dim3 grdSize(ceilDiv(o_colors->n(), blkSize.x));
+    CU_INVOKE(cu_render)
+    (*o_colors, *layeredColors, layeredColors->n() / o_colors->n(), o_colors->n());
     CHECK_EX(cudaGetLastError());
 }
\ No newline at end of file
diff --git a/cpp/msl_infer/Renderer.h b/cpp/msl_infer/Renderer.h
index 20766cf..4e48a0e 100644
--- a/cpp/msl_infer/Renderer.h
+++ b/cpp/msl_infer/Renderer.h
@@ -1,10 +1,15 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
 class Renderer {
 public:
     Renderer();
 
+    /**
+     * @brief
+     *
+     * @param o_colors
+     * @param layeredColors
+     */
     void render(sptr<CudaArray<glm::vec4>> o_colors, sptr<CudaArray<glm::vec4>> layeredColors);
-
 };
\ No newline at end of file
diff --git a/cpp/msl_infer/Resource.h b/cpp/msl_infer/Resource.h
deleted file mode 100644
index 7a53eca..0000000
--- a/cpp/msl_infer/Resource.h
+++ /dev/null
@@ -1,159 +0,0 @@
-#pragma once
-#include <map>
-#include <vector>
-
-class Resource
-{
-public:
-	virtual ~Resource() {}
-
-	virtual void *getBuffer() const = 0;
-
-	virtual size_t size() const = 0;
-};
-
-class CudaBuffer : public Resource
-{
-public:
-	CudaBuffer(void *buffer = nullptr, size_t size = 0) : _buffer(buffer), _ownBuffer(false), _size(size) {}
-	CudaBuffer(size_t size) : _buffer(nullptr), _ownBuffer(true), _size(size)
-	{
-		CHECK_EX(cudaMalloc(&_buffer, size));
-	}
-	CudaBuffer(const CudaBuffer &rhs) = delete;
-
-	virtual ~CudaBuffer()
-	{
-		if (!_ownBuffer || _buffer == nullptr)
-			return;
-		try
-		{
-			CHECK_EX(cudaFree(_buffer));
-		}
-		catch (std::exception &ex)
-		{
-			Logger::instance.warning(std::string("Exception raised in destructor: ") + ex.what());
-		}
-		_buffer = nullptr;
-		_ownBuffer = false;
-	}
-
-	virtual void *getBuffer() const { return _buffer; }
-
-	virtual size_t size() const { return _size; }
-
-private:
-	void *_buffer;
-	bool _ownBuffer;
-	size_t _size;
-};
-
-template <typename T>
-class CudaArray : public CudaBuffer
-{
-public:
-	CudaArray(size_t n) : CudaBuffer(n * sizeof(T)) {}
-	CudaArray(T *buffer, size_t n) : CudaBuffer(buffer, n * sizeof(T)) {}
-	CudaArray(const CudaArray<T> &rhs) = delete;
-
-	size_t n() const { return size() / sizeof(T); }
-
-	operator T *() { return (T *)getBuffer(); }
-};
-
-class GraphicsResource : public Resource
-{
-public:
-	cudaGraphicsResource_t getHandler() { return _res; }
-
-	virtual ~GraphicsResource()
-	{
-		if (_res == nullptr)
-			return;
-		try
-		{
-			CHECK_EX(cudaGraphicsUnregisterResource(_res));
-		}
-		catch (std::exception &ex)
-		{
-			Logger::instance.warning(std::string("Exception raised in destructor: ") + ex.what());
-		}
-		_res = nullptr;
-	}
-
-	virtual size_t size() const { return _size; }
-
-protected:
-	cudaGraphicsResource_t _res;
-	size_t _size;
-
-	GraphicsResource() : _res(nullptr), _size(0) {}
-};
-
-template<typename T>
-class GlTextureResource : public GraphicsResource
-{
-public:
-	GlTextureResource(GLuint textureID, glm::uvec2 textureSize)
-	{
-		CHECK_EX(cudaGraphicsGLRegisterImage(&_res, textureID, GL_TEXTURE_2D,
-											 cudaGraphicsRegisterFlagsWriteDiscard));
-		_size = textureSize.x * textureSize.y * sizeof(T);
-		_textureSize = textureSize;
-	}
-
-	virtual ~GlTextureResource()
-	{
-		cudaGraphicsUnmapResources(1, &_res, 0);
-	}
-
-	virtual void *getBuffer() const {
-		cudaArray_t buffer;
-		try{
-			CHECK_EX(cudaGraphicsSubResourceGetMappedArray(&buffer, _res, 0, 0));
-		} catch (...) {
-			return nullptr;
-		}
-		return buffer;
-	}
-
-	operator T *() { return (T *)getBuffer(); }
-	
-	glm::uvec2 textureSize () { return _textureSize; }
-
-private:
-	glm::uvec2 _textureSize;
-
-};
-
-class Resources
-{
-public:
-	std::map<std::string, Resource *> resources;
-	std::vector<cudaGraphicsResource_t> graphicsResources;
-
-	void addResource(const std::string &name, Resource *res)
-	{
-		auto gres = dynamic_cast<GraphicsResource *>(res);
-		if (gres != nullptr)
-			graphicsResources.push_back(gres->getHandler());
-		resources[name] = res;
-	}
-
-	void clear()
-	{
-		resources.clear();
-		graphicsResources.clear();
-	}
-};
-
-template <typename T>
-void dumpFloatArray(std::ostream &so, CudaArray<T> &arr, size_t maxDumpRows = 0,
-					size_t elemsPerRow = 1)
-{
-	T *hostArr = new T[arr.n()];
-	cudaMemcpy(hostArr, arr.getBuffer(), arr.n() * sizeof(T), cudaMemcpyDeviceToHost);
-	dumpHostBuffer<float>(so, hostArr, arr.n() * sizeof(T),
-						  sizeof(T) / sizeof(float) * elemsPerRow, maxDumpRows);
-	delete[] hostArr;
-}
\ No newline at end of file
diff --git a/cpp/msl_infer/Sampler.cu b/cpp/msl_infer/Sampler.cu
index 9b8534b..5d8dcdd 100644
--- a/cpp/msl_infer/Sampler.cu
+++ b/cpp/msl_infer/Sampler.cu
@@ -1,8 +1,7 @@
 #include "Sampler.h"
-#include "thread_index.h"
+#include "../utils/cuda.h"
 
-__device__ glm::vec3 _raySphereIntersect(glm::vec3 p, glm::vec3 v, float r, float &o_depth)
-{
+__device__ glm::vec3 _raySphereIntersect(glm::vec3 p, glm::vec3 v, float r, float &o_depth) {
     float pp = glm::dot(p, p);
     float vv = glm::dot(v, v);
     float pv = glm::dot(p, v);
@@ -10,36 +9,36 @@ __device__ glm::vec3 _raySphereIntersect(glm::vec3 p, glm::vec3 v, float r, floa
     return p + o_depth * v;
 }
 
-__device__ float _getAngle(float x, float y)
-{
+__device__ float _getAngle(float x, float y) {
     return -atan(x / y) + (y < 0) * (float)M_PI + 0.5f * (float)M_PI;
 }
 
 /**
- * Dispatch with block_size=(n_samples, 1024)
+ * Dispatch with block_size=(n_samples, *), grid_size=(1, nRays/*)
+ * Index with (sample_idx, ray_idx)
  */
-__global__ void cu_sampleOnRays(glm::vec3 *o_sphericalCoords, float *o_depths, glm::vec3 *rays,
-                                glm::vec3 rayCenter, float range0, float rangeStep, uint n)
-{
+__global__ void cu_sampleOnRays(float *o_coords, float *o_depths, glm::vec3 *rays, uint nRays,
+                                glm::vec3 origin, Range range, bool outputRadius) {
     glm::uvec3 idx3 = IDX3;
-    uint rayIdx = flattenIdx({idx3.y, idx3.z, 0});
-    if (rayIdx >= n)
-        return;
     uint idx = flattenIdx(idx3);
-    float r_reciprocal = rangeStep * idx3.x + range0;
-    glm::vec3 p = _raySphereIntersect(rayCenter, rays[rayIdx], 1.0f / r_reciprocal, o_depths[idx]);
-    o_sphericalCoords[idx] = glm::vec3(r_reciprocal, _getAngle(p.x, p.z), acos(p.y * r_reciprocal));
+    uint sampleIdx = idx3.x;
+    uint rayIdx = idx3.y;
+    if (rayIdx >= nRays)
+        return;
+    float r_reciprocal = range.get(sampleIdx);
+    glm::vec3 p = _raySphereIntersect(origin, rays[rayIdx], 1.0f / r_reciprocal, o_depths[idx]);
+    glm::vec3 sp(r_reciprocal, _getAngle(p.x, p.z), acos(p.y * r_reciprocal));
+    if (outputRadius)
+        ((glm::vec3 *)o_coords)[idx] = sp;
+    else
+        ((glm::vec2 *)o_coords)[idx] = {sp.y, sp.z};
 }
 
-void Sampler::sampleOnRays(sptr<CudaArray<glm::vec3>> o_sphericalCoords, sptr<CudaArray<float>> o_depths,
-                           sptr<CudaArray<glm::vec3>> rays,
-                           glm::vec3 rayCenter)
-{
-    dim3 blockSize(_samples, 1024 / _samples);
-    dim3 gridSize(1, (uint)ceil(rays->n() / (float)blockSize.y));
-    cu_sampleOnRays<<<gridSize, blockSize>>>(*o_sphericalCoords, *o_depths, *rays, rayCenter,
-                                             _dispRange.x,
-                                             (_dispRange.y - _dispRange.x) / (_samples - 1),
-                                             rays->n());
+void Sampler::sampleOnRays(sptr<CudaArray<float>> o_coords, sptr<CudaArray<float>> o_depths,
+                           sptr<CudaArray<glm::vec3>> rays, glm::vec3 rayCenter) {
+    dim3 blkSize(_dispRange.steps(), 1024 / _dispRange.steps());
+    dim3 grdSize(1, (uint)ceil(rays->n() / (float)blkSize.y));
+    CU_INVOKE(cu_sampleOnRays)
+    (*o_coords, *o_depths, *rays, rays->n(), rayCenter, _dispRange, _outputRadius);
     CHECK_EX(cudaGetLastError());
 }
\ No newline at end of file
diff --git a/cpp/msl_infer/Sampler.h b/cpp/msl_infer/Sampler.h
index 4ebf3ab..3883a76 100644
--- a/cpp/msl_infer/Sampler.h
+++ b/cpp/msl_infer/Sampler.h
@@ -1,18 +1,15 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
-class Sampler
-{
+class Sampler {
 public:
-    Sampler(glm::vec2 depthRange, uint samples) : _dispRange(1.0f / depthRange.x, 1.0f / depthRange.y),
-                                                  _samples(samples) {}
+    Sampler(glm::vec2 depthRange, uint samples, bool outputRadius)
+        : _dispRange(1.0f / depthRange, samples), _outputRadius(outputRadius) {}
 
-    void sampleOnRays(sptr<CudaArray<glm::vec3>> o_sphericalCoords,
-                      sptr<CudaArray<float>> o_depths,
-                      sptr<CudaArray<glm::vec3>> rays,
-                      glm::vec3 rayCenter);
+    void sampleOnRays(sptr<CudaArray<float>> o_coords, sptr<CudaArray<float>> o_depths,
+                      sptr<CudaArray<glm::vec3>> rays, glm::vec3 rayCenter);
 
 private:
-    glm::vec2 _dispRange;
-    uint _samples;
+    Range _dispRange;
+    bool _outputRadius;
 };
\ No newline at end of file
diff --git a/cpp/msl_infer/SynthesisPipeline.cpp b/cpp/msl_infer/SynthesisPipeline.cpp
index f7e04d6..9e8af36 100644
--- a/cpp/msl_infer/SynthesisPipeline.cpp
+++ b/cpp/msl_infer/SynthesisPipeline.cpp
@@ -1,18 +1,22 @@
 #include "SynthesisPipeline.h"
 
-SynthesisPipeline::SynthesisPipeline(
-    const std::string &netDir, bool isNmsl, uint batchSize,
-    uint samples) : _batchSize(batchSize),
-                    _samples(samples),
-                    _inferPipeline(new InferPipeline(netDir, isNmsl, batchSize, samples)),
-                    _rays(new CudaArray<glm::vec3>(batchSize)),
-                    _colors(new CudaArray<glm::vec4>(batchSize))
-{
-    _glResultBuffer = _createGlResultBuffer(_batchSize);
+SynthesisPipeline::SynthesisPipeline(sptr<Msl> net, sptr<Camera> cam, uint nSamples,
+                                     glm::vec2 depthRange, int encodeDim, int coordChns,
+                                     float enhanceSigma, float enhanceFe)
+    : _nRays(cam->res().x * cam->res().y),
+      _nSamples(nSamples),
+      _enhanceSigma(enhanceSigma),
+      _enhanceFe(enhanceFe),
+      _cam(cam),
+      _inferPipeline(new InferPipeline(net, _nRays, nSamples, depthRange, encodeDim, coordChns)),
+      _enhancement(new Enhancement(cam->res())),
+      _rays(new CudaArray<glm::vec3>(_nRays)),
+      _colors(new CudaArray<glm::vec4>(_nRays)) {
+    _glResultBuffer = _createGlResultBuffer(_nRays);
+    _glResultTextures.push_back(_createGlResultTexture(_cam->res()));
 }
 
-void SynthesisPipeline::run(View &view)
-{
+void SynthesisPipeline::run(View &view) {
     CudaEvent eStart, eGenRays, eInferred, eEnhanced;
 
     cudaEventRecord(eStart);
@@ -38,8 +42,9 @@ void SynthesisPipeline::run(View &view)
     cudaEventElapsedTime(&timeEnhance, eInferred, eEnhanced);
     {
         std::ostringstream sout;
-        sout << typeid(*this).name() << " => Total: " << timeTotal << "ms (Gen rays: " << timeGenRays
-             << "ms, Infer: " << timeInfer << "ms, Enhance: " << timeEnhance << "ms)";
+        sout << typeid(*this).name() << " => Total: " << timeTotal
+             << "ms (Gen rays: " << timeGenRays << "ms, Infer: " << timeInfer
+             << "ms, Enhance: " << timeEnhance << "ms)";
         Logger::instance.info(sout.str());
     }
 
@@ -53,13 +58,21 @@ void SynthesisPipeline::run(View &view)
     _uploadResultToTextures();
 }
 
-GLuint SynthesisPipeline::getGlResultTexture(int index)
-{
-    return _glResultTextures[index];
+GLuint SynthesisPipeline::getGlResultTexture(int index) { return _glResultTextures[index]; }
+
+void SynthesisPipeline::_genRays(View &view) { view.transVectors(_rays, _cam->localRays()); }
+
+void SynthesisPipeline::_enhance() { _enhancement->run(_colors, _enhanceSigma, _enhanceFe); }
+
+void SynthesisPipeline::_uploadResultToTextures() {
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _glResultBuffer);
+    glBindTexture(GL_TEXTURE_2D, _glResultTextures[0]);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _cam->res().x, _cam->res().y, GL_RGBA, GL_FLOAT, 0);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 }
 
-GLuint SynthesisPipeline::_createGlResultTexture(glm::uvec2 res)
-{
+GLuint SynthesisPipeline::_createGlResultTexture(glm::uvec2 res) {
     GLuint textureID;
     glEnable(GL_TEXTURE_2D);
     glGenTextures(1, &textureID);
@@ -72,91 +85,11 @@ GLuint SynthesisPipeline::_createGlResultTexture(glm::uvec2 res)
     return textureID;
 }
 
-GLuint SynthesisPipeline::_createGlResultBuffer(uint elements)
-{
+GLuint SynthesisPipeline::_createGlResultBuffer(uint elements) {
     GLuint glBuffer;
     glGenBuffers(1, &glBuffer);
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBuffer);
-    glBufferData(GL_PIXEL_UNPACK_BUFFER, elements * sizeof(glm::vec4),
-                 nullptr, GL_STREAM_DRAW);
+    glBufferData(GL_PIXEL_UNPACK_BUFFER, elements * sizeof(glm::vec4), nullptr, GL_STREAM_DRAW);
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
     return glBuffer;
-}
-
-FoveaSynthesisPipeline::FoveaSynthesisPipeline(
-    glm::uvec2 res, float fov,
-    uint samples) : SynthesisPipeline("../nets/fovea_mono/", false, res.x * res.y, samples),
-                    _foveaCamera(fov, res / 2u, res),
-                    _enhancement(new Enhancement(res))
-{
-    _glResultTextures.push_back(_createGlResultTexture(res));
-}
-
-void FoveaSynthesisPipeline::_genRays(View &view)
-{
-    view.transVectors(_rays, _foveaCamera.localRays());
-}
-
-void FoveaSynthesisPipeline::_enhance()
-{
-    _enhancement->run(_colors, 3.0f, 0.2f);
-}
-
-void FoveaSynthesisPipeline::_uploadResultToTextures()
-{
-    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _glResultBuffer);
-    glBindTexture(GL_TEXTURE_2D, _glResultTextures[0]);
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _foveaCamera.res().x, _foveaCamera.res().y,
-                    GL_RGBA, GL_FLOAT, 0);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-}
-
-PeriphSynthesisPipeline::PeriphSynthesisPipeline(
-    glm::uvec2 midRes, float midFov, glm::uvec2 periphRes, float periphFov,
-    uint samples) : SynthesisPipeline("../nets/periph/", false,
-                                      midRes.x * midRes.y + periphRes.x * periphRes.y,
-                                      samples),
-                    _midCamera(midFov, midRes / 2u, midRes),
-                    _periphCamera(periphFov, periphRes / 2u, periphRes),
-                    _midEnhancement(new Enhancement(midRes)),
-                    _periphEnhancement(new Enhancement(periphRes))
-{
-    uint midPixels = midRes.x * midRes.y;
-    uint periphPixels = periphRes.x * periphRes.y;
-    _midRays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(*_rays, midPixels));
-    _periphRays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(
-        (glm::vec3 *)*_rays + midPixels, periphPixels));
-    _glResultTextures.push_back(_createGlResultTexture(midRes));
-    _glResultTextures.push_back(_createGlResultTexture(periphRes));
-    _midColors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(*_colors, midPixels));
-    _periphColors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(
-        (glm::vec4 *)*_colors + midPixels, periphPixels));
-}
-
-void PeriphSynthesisPipeline::_genRays(View &view)
-{
-    view.transVectors(_midRays, _midCamera.localRays());
-    view.transVectors(_periphRays, _periphCamera.localRays());
-}
-
-void PeriphSynthesisPipeline::_enhance()
-{
-    _midEnhancement->run(_midColors, 5.0f, 0.2f);
-    _periphEnhancement->run(_periphColors, 5.0f, 0.2f);
-}
-
-
-void PeriphSynthesisPipeline::_uploadResultToTextures()
-{
-    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _glResultBuffer);
-    glBindTexture(GL_TEXTURE_2D, _glResultTextures[0]);
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _midCamera.res().x, _midCamera.res().y,
-                    GL_RGBA, GL_FLOAT, 0);
-    glBindTexture(GL_TEXTURE_2D, _glResultTextures[1]);
-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
-                    _periphCamera.res().x, _periphCamera.res().y, GL_RGBA, GL_FLOAT,
-                    (void *)(_midCamera.res().x * _midCamera.res().y * sizeof(glm::vec4)));
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-}
+}
\ No newline at end of file
diff --git a/cpp/msl_infer/SynthesisPipeline.h b/cpp/msl_infer/SynthesisPipeline.h
index d06856e..22a7153 100644
--- a/cpp/msl_infer/SynthesisPipeline.h
+++ b/cpp/msl_infer/SynthesisPipeline.h
@@ -1,71 +1,35 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 #include "InferPipeline.h"
 #include "View.h"
 #include "Enhancement.h"
 
-class SynthesisPipeline
-{
+class SynthesisPipeline {
 public:
-    SynthesisPipeline(const std::string &netDir, bool isNmsl,
-                      uint batchSize, uint samples);
+    SynthesisPipeline(sptr<Msl> net, sptr<Camera> cam, uint nSamples, glm::vec2 depthRange,
+                      int encodeDim, int coordChns, float enhanceSigma, float enhanceFe);
 
-    void run(View& view);
+    void run(View &view);
 
     GLuint getGlResultTexture(int index);
 
 protected:
-    uint _batchSize;
-    uint _samples;
-    std::vector<GLuint> _glResultTextures;
-    GLuint _glResultBuffer;
+    uint _nRays;
+    uint _nSamples;
+    float _enhanceSigma;
+    float _enhanceFe;
+    sptr<Camera> _cam;
     sptr<InferPipeline> _inferPipeline;
+    sptr<Enhancement> _enhancement;
     sptr<CudaArray<glm::vec3>> _rays;
     sptr<CudaArray<glm::vec4>> _colors;
+    std::vector<GLuint> _glResultTextures;
+    GLuint _glResultBuffer;
 
-    virtual void _genRays(View& view) = 0;
-    virtual void _enhance() = 0;
-    virtual void _uploadResultToTextures() = 0;
+    void _genRays(View &view);
+    void _enhance();
+    void _uploadResultToTextures();
 
     GLuint _createGlResultTexture(glm::uvec2 res);
     GLuint _createGlResultBuffer(uint elements);
-
-};
-
-class FoveaSynthesisPipeline : public SynthesisPipeline
-{
-public:
-    FoveaSynthesisPipeline(glm::uvec2 res, float fov, uint samples);
-
-protected:
-    virtual void _genRays(View& view);
-    virtual void _enhance();
-    virtual void _uploadResultToTextures();
-
-private:
-    Camera _foveaCamera;
-    sptr<Enhancement> _enhancement;
-};
-
-class PeriphSynthesisPipeline : public SynthesisPipeline
-{
-public:
-    PeriphSynthesisPipeline(glm::uvec2 midRes, float midFov,
-                            glm::uvec2 periphRes, float periphFov,
-                            uint samples);
-
-protected:
-    virtual void _genRays(View& view);
-    virtual void _enhance();
-    virtual void _uploadResultToTextures();
-
-private:
-    Camera _midCamera;
-    Camera _periphCamera;
-    sptr<CudaArray<glm::vec3>> _midRays;
-    sptr<CudaArray<glm::vec3>> _periphRays;
-    sptr<CudaArray<glm::vec4>> _midColors;
-    sptr<CudaArray<glm::vec4>> _periphColors;
-    sptr<Enhancement> _midEnhancement;
-    sptr<Enhancement> _periphEnhancement;
 };
\ No newline at end of file
diff --git a/cpp/msl_infer/View.cu b/cpp/msl_infer/View.cu
index 2e00dec..eda4f03 100644
--- a/cpp/msl_infer/View.cu
+++ b/cpp/msl_infer/View.cu
@@ -1,6 +1,6 @@
 #include "View.h"
 #include <cuda_runtime.h>
-#include "thread_index.h"
+#include "../utils/cuda.h"
 
 __global__ void cu_genLocalRays(glm::vec3 *o_rays, glm::vec2 f, glm::vec2 c, glm::uvec2 res)
 {
diff --git a/cpp/msl_infer/View.h b/cpp/msl_infer/View.h
index f8d4772..97d377b 100644
--- a/cpp/msl_infer/View.h
+++ b/cpp/msl_infer/View.h
@@ -1,5 +1,5 @@
 #pragma once
-#include "Common.h"
+#include "../utils/common.h"
 
 
 class Camera {
diff --git a/cpp/msl_infer_test/Makefile b/cpp/msl_infer_test/Makefile
index 1d96fd8..f9184e9 100644
--- a/cpp/msl_infer_test/Makefile
+++ b/cpp/msl_infer_test/Makefile
@@ -1,6 +1,6 @@
 OUTNAME_RELEASE = msl_infer_test
 OUTNAME_DEBUG   = msl_infer_test_debug
-EXTRA_DIRECTORIES = ../msl_infer
+EXTRA_DIRECTORIES = ../msl_infer ../utils
 .NOTPARALLEL:
 MAKEFILE ?= ../Makefile.config
 include $(MAKEFILE)
diff --git a/cpp/msl_infer_test/main.cpp b/cpp/msl_infer_test/main.cpp
index 36ad4de..38eb0b7 100644
--- a/cpp/msl_infer_test/main.cpp
+++ b/cpp/msl_infer_test/main.cpp
@@ -7,388 +7,386 @@
 #include "../msl_infer/View.h"
 #include "../glm/gtx/transform.hpp"
 
-static const struct
-{
-	float x, y;
-	float u, v;
-} vertices[4] = {
-	{-1.0f, -1.0f, 0.f, 1.f},
-	{1.0f, -1.0f, 1.f, 1.f},
-	{1.0f, 1.0f, 1.f, 0.f},
-	{-1.0f, 1.0f, 0.f, 0.f}};
-
-static const char *vertex_shader_text =
-	"#version 300 es\n"
-	"uniform mat4 MVP;\n"
-	"in vec2 vUV;\n"
-	"in vec2 vPos;\n"
-	"out vec2 uv;\n"
-	"void main()\n"
-	"{\n"
-	"    gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
-	"    uv = vUV;\n"
-	"}\n";
+static const struct {
+    float x, y;
+    float u, v;
+} vertices[4] = {{-1.0f, -1.0f, 0.f, 1.f},
+                 {1.0f, -1.0f, 1.f, 1.f},
+                 {1.0f, 1.0f, 1.f, 0.f},
+                 {-1.0f, 1.0f, 0.f, 0.f}};
+
+static const char *vertex_shader_text = "#version 300 es\n"
+                                        "uniform mat4 MVP;\n"
+                                        "in vec2 vUV;\n"
+                                        "in vec2 vPos;\n"
+                                        "out vec2 uv;\n"
+                                        "void main()\n"
+                                        "{\n"
+                                        "    gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
+                                        "    uv = vUV;\n"
+                                        "}\n";
 
 static const char *fragment_shader_text =
-	"#version 300 es\n"
-	"#undef lowp\n"
-	"#undef mediump\n"
-	"#undef highp\n"
-	"precision mediump float;\n"
-	"out vec4 FragColor;\n"
-	"in vec2 uv;\n"
-	"uniform sampler2D tex;\n"
-	"uniform float R;\n"
-	"uniform vec2 foveaCenter;\n"
-	"uniform vec2 screenRes;\n"
-	"void main()\n"
-	"{\n"
-	"    if(R<1e-5) {\n"
-	"        FragColor = texture(tex, uv);\n"
-	"        return;\n"
-	"    }\n"
-	"    vec2 p = uv * screenRes;\n"
-	"    float r = distance(p, foveaCenter);\n"
-	"    vec2 coord = (p - foveaCenter) / R / 2.0 + 0.5;\n"
-	"    if(coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) {\n"
-	"        FragColor = vec4(0, 0, 0, 0);\n"
-	"        return;\n"
-	"    }\n"
-	"    vec4 c = texture(tex, coord);\n"
-	"    float alpha = 1.0 - smoothstep(R * 0.6, R, r);\n"
-	"    c.a = c.a * alpha;\n"
-	"    FragColor = c;\n"
-	"}\n";
-
-void inferFovea(void *o_imageData, View &view)
-{
-	glm::uvec2 foveaRes(128, 128);
-	size_t foveaPixels = foveaRes.x * foveaRes.y;
-	size_t totalPixels = foveaPixels;
-	size_t samples = 32;
-
-	Camera foveaCam(20, foveaRes / 2u, foveaRes);
-	InferPipeline inferPipeline("../nets/fovea_mono/", true, totalPixels, samples);
-
-	auto local_rays = foveaCam.localRays();
-	auto rays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(totalPixels));
-	auto colors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(totalPixels));
-
-	CudaEvent eStart, eGenRays, eInferred, eEnhanced;
-
-	cudaEventRecord(eStart);
-
-	view.transVectors(rays, local_rays);
-
-	cudaEventRecord(eGenRays);
-
-	inferPipeline.run(colors, rays, view.t(), true);
-
-	cudaEventRecord(eInferred);
-
-	// TODO Enhance
-
-	cudaEventRecord(eEnhanced);
-
-	CHECK_EX(cudaDeviceSynchronize());
-
-	float timeTotal, timeGenRays, timeInfer, timeEnhance;
-	cudaEventElapsedTime(&timeTotal, eStart, eEnhanced);
-	cudaEventElapsedTime(&timeGenRays, eStart, eGenRays);
-	cudaEventElapsedTime(&timeInfer, eGenRays, eInferred);
-	cudaEventElapsedTime(&timeEnhance, eInferred, eEnhanced);
-	{
-		std::ostringstream sout;
-		sout << "Fovea => Total: " << timeTotal << "ms (Gen rays: " << timeGenRays
-			 << "ms, Infer: " << timeInfer << "ms, Enhance: " << timeEnhance << "ms)";
-		Logger::instance.info(sout.str());
-	}
-	cudaMemcpy(o_imageData, colors->getBuffer(), colors->size(), cudaMemcpyDeviceToHost);
+    "#version 300 es\n"
+    "#undef lowp\n"
+    "#undef mediump\n"
+    "#undef highp\n"
+    "precision mediump float;\n"
+    "out vec4 FragColor;\n"
+    "in vec2 uv;\n"
+    "uniform sampler2D tex;\n"
+    "uniform float R;\n"
+    "uniform vec2 foveaCenter;\n"
+    "uniform vec2 screenRes;\n"
+    "void main()\n"
+    "{\n"
+    "    if(R<1e-5) {\n"
+    "        FragColor = texture(tex, uv);\n"
+    "        return;\n"
+    "    }\n"
+    "    vec2 p = uv * screenRes;\n"
+    "    float r = distance(p, foveaCenter);\n"
+    "    vec2 coord = (p - foveaCenter) / R / 2.0 + 0.5;\n"
+    "    if(coord.x < 0.0 || coord.x > 1.0 || coord.y < 0.0 || coord.y > 1.0) {\n"
+    "        FragColor = vec4(0, 0, 0, 0);\n"
+    "        return;\n"
+    "    }\n"
+    "    vec4 c = texture(tex, coord);\n"
+    "    float alpha = 1.0 - smoothstep(R * 0.6, R, r);\n"
+    "    c.a = c.a * alpha;\n"
+    "    FragColor = c;\n"
+    "}\n";
+
+/*void inferFovea(void *o_imageData, View &view) {
+    glm::uvec2 foveaRes(128, 128);
+    size_t foveaPixels = foveaRes.x * foveaRes.y;
+    size_t totalPixels = foveaPixels;
+    size_t samples = 32;
+
+    Camera foveaCam(20, foveaRes / 2u, foveaRes);
+    InferPipeline inferPipeline("../nets/fovea_mono/", true, totalPixels, samples);
+
+    auto local_rays = foveaCam.localRays();
+    auto rays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(totalPixels));
+    auto colors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(totalPixels));
+
+    CudaEvent eStart, eGenRays, eInferred, eEnhanced;
+
+    cudaEventRecord(eStart);
+
+    view.transVectors(rays, local_rays);
+
+    cudaEventRecord(eGenRays);
+
+    inferPipeline.run(colors, rays, view.t(), true);
+
+    cudaEventRecord(eInferred);
+
+    // TODO Enhance
+
+    cudaEventRecord(eEnhanced);
+
+    CHECK_EX(cudaDeviceSynchronize());
+
+    float timeTotal, timeGenRays, timeInfer, timeEnhance;
+    cudaEventElapsedTime(&timeTotal, eStart, eEnhanced);
+    cudaEventElapsedTime(&timeGenRays, eStart, eGenRays);
+    cudaEventElapsedTime(&timeInfer, eGenRays, eInferred);
+    cudaEventElapsedTime(&timeEnhance, eInferred, eEnhanced);
+    {
+        std::ostringstream sout;
+        sout << "Fovea => Total: " << timeTotal << "ms (Gen rays: " << timeGenRays
+             << "ms, Infer: " << timeInfer << "ms, Enhance: " << timeEnhance << "ms)";
+        Logger::instance.info(sout.str());
+    }
+    cudaMemcpy(o_imageData, colors->getBuffer(), colors->size(), cudaMemcpyDeviceToHost);
 }
 
-void inferOther(void *o_imageData, View &view)
-{
-	glm::uvec2 midRes(256, 256);
-	glm::uvec2 periphRes(230, 256);
-	size_t midPixels = midRes.x * midRes.y;
-	size_t periphPixels = periphRes.x * periphRes.y;
-	size_t totalPixels = midPixels + periphPixels;
-	size_t samples = 16;
-
-	Camera midCam(45.0f, {128.0f, 128.0f}, midRes);
-	Camera periphCam(110.0f, {115.0f, 128.0f}, periphRes);
-	InferPipeline inferPipeline("../nets/periph/", true, totalPixels, samples);
+void inferOther(void *o_imageData, View &view) {
+    glm::uvec2 midRes(256, 256);
+    glm::uvec2 periphRes(230, 256);
+    size_t midPixels = midRes.x * midRes.y;
+    size_t periphPixels = periphRes.x * periphRes.y;
+    size_t totalPixels = midPixels + periphPixels;
+    size_t samples = 16;
 
-	auto midLocalRays = midCam.localRays();
-	auto periphLocalRays = periphCam.localRays();
-	auto rays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(totalPixels));
-	auto midRays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(*rays, midPixels));
-	auto periphRays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>((glm::vec3 *)*rays + midPixels, periphPixels));
-	auto colors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(totalPixels));
+    Camera midCam(45.0f, {128.0f, 128.0f}, midRes);
+    Camera periphCam(110.0f, {115.0f, 128.0f}, periphRes);
+    InferPipeline inferPipeline("../nets/periph/", true, totalPixels, samples);
 
-	CudaEvent eStart, eGenRays, eInferred, eEnhanced;
+    auto midLocalRays = midCam.localRays();
+    auto periphLocalRays = periphCam.localRays();
+    auto rays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(totalPixels));
+    auto midRays = sptr<CudaArray<glm::vec3>>(new CudaArray<glm::vec3>(*rays, midPixels));
+    auto periphRays = sptr<CudaArray<glm::vec3>>(
+        new CudaArray<glm::vec3>((glm::vec3 *)*rays + midPixels, periphPixels));
+    auto colors = sptr<CudaArray<glm::vec4>>(new CudaArray<glm::vec4>(totalPixels));
 
-	cudaEventRecord(eStart);
+    CudaEvent eStart, eGenRays, eInferred, eEnhanced;
 
-	view.transVectors(midRays, midLocalRays);
-	view.transVectors(periphRays, periphLocalRays);
+    cudaEventRecord(eStart);
 
-	cudaEventRecord(eGenRays);
+    view.transVectors(midRays, midLocalRays);
+    view.transVectors(periphRays, periphLocalRays);
 
-	inferPipeline.run(colors, rays, view.t(), true);
+    cudaEventRecord(eGenRays);
 
-	cudaEventRecord(eInferred);
+    inferPipeline.run(colors, rays, view.t(), true);
 
-	// TODO Enhance
+    cudaEventRecord(eInferred);
 
-	cudaEventRecord(eEnhanced);
+    // TODO Enhance
 
-	CHECK_EX(cudaDeviceSynchronize());
+    cudaEventRecord(eEnhanced);
 
-	float timeTotal, timeGenRays, timeInfer, timeEnhance;
-	cudaEventElapsedTime(&timeTotal, eStart, eEnhanced);
-	cudaEventElapsedTime(&timeGenRays, eStart, eGenRays);
-	cudaEventElapsedTime(&timeInfer, eGenRays, eInferred);
-	cudaEventElapsedTime(&timeEnhance, eInferred, eEnhanced);
-	{
-		std::ostringstream sout;
-		sout << "Mid & Periph => Total: " << timeTotal << "ms (Gen rays: " << timeGenRays
-			 << "ms, Infer: " << timeInfer << "ms, Enhance: " << timeEnhance << "ms)";
-		Logger::instance.info(sout.str());
-	}
-	cudaMemcpy(o_imageData, colors->getBuffer(), colors->size(), cudaMemcpyDeviceToHost);
-}
+    CHECK_EX(cudaDeviceSynchronize());
 
-static void error_callback(int error, const char *description)
-{
-	fprintf(stderr, "Error: %s\n", description);
+    float timeTotal, timeGenRays, timeInfer, timeEnhance;
+    cudaEventElapsedTime(&timeTotal, eStart, eEnhanced);
+    cudaEventElapsedTime(&timeGenRays, eStart, eGenRays);
+    cudaEventElapsedTime(&timeInfer, eGenRays, eInferred);
+    cudaEventElapsedTime(&timeEnhance, eInferred, eEnhanced);
+    {
+        std::ostringstream sout;
+        sout << "Mid & Periph => Total: " << timeTotal << "ms (Gen rays: " << timeGenRays
+             << "ms, Infer: " << timeInfer << "ms, Enhance: " << timeEnhance << "ms)";
+        Logger::instance.info(sout.str());
+    }
+    cudaMemcpy(o_imageData, colors->getBuffer(), colors->size(), cudaMemcpyDeviceToHost);
+}*/
+
+static void error_callback(int error, const char *description) {
+    fprintf(stderr, "Error: %s\n", description);
 }
 
-static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
-{
-	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
-		glfwSetWindowShouldClose(window, GLFW_TRUE);
+static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
+    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
+        glfwSetWindowShouldClose(window, GLFW_TRUE);
 }
 
-GLFWwindow *initGl(uint windowWidth, uint windowHeight)
-{
-	glfwSetErrorCallback(error_callback);
-	if (!glfwInit())
-		return nullptr;
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-	//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-	//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-	/*glfwWindowHint(GLFW_DEPTH_BITS, 0);
-	glfwWindowHint(GLFW_STENCIL_BITS, 0);
-
-	glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
-
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
-
-	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-	*/
-	GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, "LearnOpenGL", NULL, NULL);
-	if (!window)
-	{
-		glfwTerminate();
-		return nullptr;
-	}
-	glfwSetKeyCallback(window, key_callback);
-	glfwMakeContextCurrent(window);
-	glfwSwapInterval(1);
-
-	/*if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
+GLFWwindow *initGl(uint windowWidth, uint windowHeight) {
+    glfwSetErrorCallback(error_callback);
+    if (!glfwInit())
+        return nullptr;
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+    // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+    // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+    /*glfwWindowHint(GLFW_DEPTH_BITS, 0);
+    glfwWindowHint(GLFW_STENCIL_BITS, 0);
+
+    glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
+
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
+
+    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+    */
+    GLFWwindow *window = glfwCreateWindow(windowWidth, windowHeight, "LearnOpenGL", NULL, NULL);
+    if (!window) {
+        glfwTerminate();
+        return nullptr;
+    }
+    glfwSetKeyCallback(window, key_callback);
+    glfwMakeContextCurrent(window);
+    glfwSwapInterval(1);
+
+    /*if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
     {
         std::cout << "Failed to initialize GLAD" << std::endl;
         return -1;
     }*/
 
-	glewInit();
-	glViewport(0, 0, windowWidth, windowHeight);
-	glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
+    glewInit();
+    glViewport(0, 0, windowWidth, windowHeight);
+    glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
 
-	Logger::instance.info("OpenGL is initialized");
+    Logger::instance.info("OpenGL is initialized");
 
-	return window;
+    return window;
 }
 
-GLuint createGlTexture(uint width, uint height)
-{
-	GLuint textureID;
-	glEnable(GL_TEXTURE_2D);
-	glGenTextures(1, &textureID);
-	glBindTexture(GL_TEXTURE_2D, textureID);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
-	glBindTexture(GL_TEXTURE_2D, 0);
-	glDisable(GL_TEXTURE_2D);
-	return textureID;
+GLuint createGlTexture(uint width, uint height) {
+    GLuint textureID;
+    glEnable(GL_TEXTURE_2D);
+    glGenTextures(1, &textureID);
+    glBindTexture(GL_TEXTURE_2D, textureID);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glDisable(GL_TEXTURE_2D);
+    return textureID;
 }
 
-void checkCompileErrors(unsigned int shader, std::string type)
-{
-	int success;
-	char infoLog[1024];
-	if (type != "PROGRAM")
-	{
-		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
-		if (!success)
-		{
-			glGetShaderInfoLog(shader, 1024, NULL, infoLog);
-			std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
-					  << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
-		}
-	}
-	else
-	{
-		glGetProgramiv(shader, GL_LINK_STATUS, &success);
-		if (!success)
-		{
-			glGetProgramInfoLog(shader, 1024, NULL, infoLog);
-			std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
-					  << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
-		}
-	}
+void checkCompileErrors(unsigned int shader, std::string type) {
+    int success;
+    char infoLog[1024];
+    if (type != "PROGRAM") {
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+        if (!success) {
+            glGetShaderInfoLog(shader, 1024, NULL, infoLog);
+            std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
+                      << infoLog << "\n -- --------------------------------------------------- -- "
+                      << std::endl;
+        }
+    } else {
+        glGetProgramiv(shader, GL_LINK_STATUS, &success);
+        if (!success) {
+            glGetProgramInfoLog(shader, 1024, NULL, infoLog);
+            std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
+                      << infoLog << "\n -- --------------------------------------------------- -- "
+                      << std::endl;
+        }
+    }
 }
 
-GLuint loadShaderProgram()
-{
-	GLuint vertex_shader, fragment_shader, program;
-	vertex_shader = glCreateShader(GL_VERTEX_SHADER);
-	glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
-	glCompileShader(vertex_shader);
-	checkCompileErrors(vertex_shader, "VERTEX");
-
-	fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
-	glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
-	glCompileShader(fragment_shader);
-	checkCompileErrors(fragment_shader, "FRAGMENT");
-
-	program = glCreateProgram();
-	glAttachShader(program, vertex_shader);
-	glAttachShader(program, fragment_shader);
-	glLinkProgram(program);
-	checkCompileErrors(program, "PROGRAM");
-
-	Logger::instance.info("Shader program is loaded");
-	return program;
+GLuint loadShaderProgram() {
+    GLuint vertex_shader, fragment_shader, program;
+    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
+    glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
+    glCompileShader(vertex_shader);
+    checkCompileErrors(vertex_shader, "VERTEX");
+
+    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
+    glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
+    glCompileShader(fragment_shader);
+    checkCompileErrors(fragment_shader, "FRAGMENT");
+
+    program = glCreateProgram();
+    glAttachShader(program, vertex_shader);
+    glAttachShader(program, fragment_shader);
+    glLinkProgram(program);
+    checkCompileErrors(program, "PROGRAM");
+
+    Logger::instance.info("Shader program is loaded");
+    return program;
 }
 
-int main(void)
-{
-	Logger::instance.logLevel = 3;
-
-	GLFWwindow *window;
-	GLuint vertex_buffer, program;
-	GLint mvp_location, vpos_location, vcol_location;
-
-	window = initGl(800, 800);
-
-	glGenBuffers(1, &vertex_buffer);
-	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
-	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
-
-	program = loadShaderProgram();
-	GLuint shaderProp_tex = glGetUniformLocation(program, "tex");
-	GLuint shaderProp_R = glGetUniformLocation(program, "R");
-	GLuint shaderProp_screenRes = glGetUniformLocation(program, "screenRes");
-	GLuint shaderProp_foveaCenter = glGetUniformLocation(program, "foveaCenter");
-
-	mvp_location = glGetUniformLocation(program, "MVP");
-	vpos_location = glGetAttribLocation(program, "vPos");
-	vcol_location = glGetAttribLocation(program, "vUV");
-
-	glEnableVertexAttribArray(vpos_location);
-	glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
-						  sizeof(vertices[0]), (void *)0);
-	glEnableVertexAttribArray(vcol_location);
-	glVertexAttribPointer(vcol_location, 2, GL_FLOAT, GL_FALSE,
-						  sizeof(vertices[0]), (void *)(sizeof(float) * 2));
-
-	sptr<FoveaSynthesisPipeline> foveaSynthesisPipeline(
-		new FoveaSynthesisPipeline({128, 128}, 20, 32));
-	sptr<PeriphSynthesisPipeline> periphSynthesisPipeline(
-		new PeriphSynthesisPipeline({256, 256}, 45, {230, 256}, 110, 16));
-	View view({}, {});
-	auto glFoveaTex = foveaSynthesisPipeline->getGlResultTexture(0);
-	auto glMidTex = periphSynthesisPipeline->getGlResultTexture(0);
-	auto glPeriphTex = periphSynthesisPipeline->getGlResultTexture(1);
-
-	Logger::instance.info("Start main loop");
-
-	auto l = 1.428f;
-	glm::vec2 screenRes(1440.0f, 1600.0f);
-	glm::mat4 mvp = glm::ortho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f);
-
-	glEnable(GL_BLEND);
+int main(void) {
+    Logger::instance.logLevel = 3;
+
+    GLFWwindow *window;
+    GLuint vertex_buffer, program;
+    GLint mvp_location, vpos_location, vcol_location;
+
+    window = initGl(800, 800);
+
+    glGenBuffers(1, &vertex_buffer);
+    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+
+    program = loadShaderProgram();
+    GLuint shaderProp_tex = glGetUniformLocation(program, "tex");
+    GLuint shaderProp_R = glGetUniformLocation(program, "R");
+    GLuint shaderProp_screenRes = glGetUniformLocation(program, "screenRes");
+    GLuint shaderProp_foveaCenter = glGetUniformLocation(program, "foveaCenter");
+
+    mvp_location = glGetUniformLocation(program, "MVP");
+    vpos_location = glGetAttribLocation(program, "vPos");
+    vcol_location = glGetAttribLocation(program, "vUV");
+
+    glEnableVertexAttribArray(vpos_location);
+    glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void *)0);
+    glEnableVertexAttribArray(vcol_location);
+    glVertexAttribPointer(vcol_location, 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]),
+                          (void *)(sizeof(float) * 2));
+
+    sptr<Msl> foveaNet(new Msl());
+    foveaNet->load("");
+    sptr<Msl> periphNet(new Msl());
+    periphNet->load("");
+    sptr<Camera> foveaCam(new Camera(20, {128, 128}, {256, 256}));
+    sptr<Camera> midCam(new Camera(45, {128, 128}, {256, 256}));
+    sptr<Camera> periphCam(new Camera(110, {115, 128}, {230, 256}));
+    uint nSamples = 64;
+    uint encodeDim = 6;
+    uint coordChns = 2;
+    glm::vec2 depthRange(1.0f, 7.0f);
+    sptr<SynthesisPipeline> synthesisPipelines[] = {
+        sptr<SynthesisPipeline>(new SynthesisPipeline(foveaNet, foveaCam, nSamples, depthRange,
+                                                      encodeDim, coordChns, 3.0f, 0.2f)),
+        sptr<SynthesisPipeline>(new SynthesisPipeline(periphNet, midCam, nSamples, depthRange,
+                                                      encodeDim, coordChns, 5.0f, 0.2f)),
+        sptr<SynthesisPipeline>(new SynthesisPipeline(periphNet, periphCam, nSamples, depthRange,
+                                                      encodeDim, coordChns, 5.0f, 0.2f)),
+    };
+    View view({}, {});
+    auto glFoveaTex = synthesisPipelines[0]->getGlResultTexture(0);
+    auto glMidTex = synthesisPipelines[1]->getGlResultTexture(0);
+    auto glPeriphTex = synthesisPipelines[2]->getGlResultTexture(0);
+
+    Logger::instance.info("Start main loop");
+
+    auto l = 1.428f;
+    glm::vec2 screenRes(1440.0f, 1600.0f);
+    glm::mat4 mvp = glm::ortho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f);
+
+    glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	GLuint queries[1];
-	glGenQueries(1, queries);
+    GLuint queries[1];
+    glGenQueries(1, queries);
 
-	while (!glfwWindowShouldClose(window))
-	{
-		foveaSynthesisPipeline->run(view);
-		periphSynthesisPipeline->run(view);
+    while (!glfwWindowShouldClose(window)) {
+		for (int i = 0; i < 3; ++i)
+			synthesisPipelines[i]->run(view);
 
-		glClear(GL_COLOR_BUFFER_BIT);
+        glClear(GL_COLOR_BUFFER_BIT);
 
         // Start query 1
         glBeginQuery(GL_TIME_ELAPSED, queries[0]);
 
-		glUseProgram(program);
-		glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (float *)&mvp[0][0]);
-		glUniform1i(shaderProp_tex, 0);
-		glEnable(GL_TEXTURE_2D);
-		glActiveTexture(GL_TEXTURE0);
+        glUseProgram(program);
+        glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (float *)&mvp[0][0]);
+        glUniform1i(shaderProp_tex, 0);
+        glEnable(GL_TEXTURE_2D);
+        glActiveTexture(GL_TEXTURE0);
 
-		glUniform1f(shaderProp_R, 0.0f);
-		glUniform2f(shaderProp_screenRes, 1440, 1600);
-		glUniform2f(shaderProp_foveaCenter, 720, 800);
-		glBindTexture(GL_TEXTURE_2D, glPeriphTex);
-		glDrawArrays(GL_QUADS, 0, 4);
+        glUniform1f(shaderProp_R, 0.0f);
+        glUniform2f(shaderProp_screenRes, 1440, 1600);
+        glUniform2f(shaderProp_foveaCenter, 720, 800);
+        glBindTexture(GL_TEXTURE_2D, glPeriphTex);
+        glDrawArrays(GL_QUADS, 0, 4);
 
-		glUniform1f(shaderProp_R, screenRes.y * 0.5f * 0.414 / l);
-		glUniform2f(shaderProp_screenRes, 1440, 1600);
-		glUniform2f(shaderProp_foveaCenter, 720, 800);
-		glBindTexture(GL_TEXTURE_2D, glMidTex);
-		glDrawArrays(GL_QUADS, 0, 4);
+        glUniform1f(shaderProp_R, screenRes.y * 0.5f * 0.414 / l);
+        glUniform2f(shaderProp_screenRes, 1440, 1600);
+        glUniform2f(shaderProp_foveaCenter, 720, 800);
+        glBindTexture(GL_TEXTURE_2D, glMidTex);
+        glDrawArrays(GL_QUADS, 0, 4);
 
-		glUniform1f(shaderProp_R, screenRes.y * 0.5f * 0.176f / l);
-		glUniform2f(shaderProp_screenRes, 1440, 1600);
-		glUniform2f(shaderProp_foveaCenter, 720, 800);
-		glBindTexture(GL_TEXTURE_2D, glFoveaTex);
-		glDrawArrays(GL_QUADS, 0, 4);
+        glUniform1f(shaderProp_R, screenRes.y * 0.5f * 0.176f / l);
+        glUniform2f(shaderProp_screenRes, 1440, 1600);
+        glUniform2f(shaderProp_foveaCenter, 720, 800);
+        glBindTexture(GL_TEXTURE_2D, glFoveaTex);
+        glDrawArrays(GL_QUADS, 0, 4);
 
-		glDisable(GL_TEXTURE_2D);
+        glDisable(GL_TEXTURE_2D);
 
         glEndQuery(GL_TIME_ELAPSED);
 
         GLint available = 0;
-		while (!available)
+        while (!available)
             glGetQueryObjectiv(queries[0], GL_QUERY_RESULT_AVAILABLE, &available);
         // timer queries can contain more than 32 bits of data, so always
         // query them using the 64 bit types to avoid overflow
         GLuint64 timeElapsed = 0;
-		glGetQueryObjectui64v(queries[0], GL_QUERY_RESULT, &timeElapsed);
+        glGetQueryObjectui64v(queries[0], GL_QUERY_RESULT, &timeElapsed);
 
-		{
-			std::ostringstream sout;
-			sout << "Blending: " << timeElapsed / 10000 / 100.0f << "ms" << std::endl;
-			Logger::instance.info(sout.str());
-		}
+        {
+            std::ostringstream sout;
+            sout << "Blending: " << timeElapsed / 10000 / 100.0f << "ms" << std::endl;
+            Logger::instance.info(sout.str());
+        }
 
-		glfwSwapBuffers(window);
-		glfwPollEvents();
-	}
+        glfwSwapBuffers(window);
+        glfwPollEvents();
+    }
 
-	foveaSynthesisPipeline = nullptr;
-	periphSynthesisPipeline = nullptr;
+	for (int i = 0; i < 3; ++i)
+		synthesisPipelines[i] = nullptr;
 
-	glfwDestroyWindow(window);
+    glfwDestroyWindow(window);
 
-	glfwTerminate();
-	exit(EXIT_SUCCESS);
+    glfwTerminate();
+    exit(EXIT_SUCCESS);
 }
diff --git a/cpp/msl_infer/Formatter.h b/cpp/utils/Formatter.h
similarity index 100%
rename from cpp/msl_infer/Formatter.h
rename to cpp/utils/Formatter.h
diff --git a/cpp/msl_infer/Logger.cpp b/cpp/utils/Logger.cpp
similarity index 100%
rename from cpp/msl_infer/Logger.cpp
rename to cpp/utils/Logger.cpp
diff --git a/cpp/msl_infer/Logger.h b/cpp/utils/Logger.h
similarity index 95%
rename from cpp/msl_infer/Logger.h
rename to cpp/utils/Logger.h
index e02bbef..d89723f 100644
--- a/cpp/msl_infer/Logger.h
+++ b/cpp/utils/Logger.h
@@ -39,7 +39,7 @@ public:
 		return false;
 	}
 
-	virtual void log(nv::ILogger::Severity severity, const char* msg) override {
+	virtual void log(nv::ILogger::Severity severity, const char* msg) noexcept {
 		if ((int)severity > logLevel)
 			return;
 		if (externalLogFunc == nullptr) {
diff --git a/cpp/utils/Resource.h b/cpp/utils/Resource.h
new file mode 100644
index 0000000..f7f5f0e
--- /dev/null
+++ b/cpp/utils/Resource.h
@@ -0,0 +1,136 @@
+#pragma once
+#include <map>
+#include <vector>
+
+class Resource {
+  public:
+    virtual ~Resource() {}
+
+    virtual void *getBuffer() const = 0;
+
+    virtual size_t size() const = 0;
+};
+
+class CudaBuffer : public Resource {
+  public:
+    CudaBuffer(void *buffer = nullptr, size_t size = 0)
+        : _buffer(buffer), _ownBuffer(false), _size(size) {}
+    CudaBuffer(size_t size) : _buffer(nullptr), _ownBuffer(true), _size(size) {
+        CHECK_EX(cudaMalloc(&_buffer, size));
+    }
+    CudaBuffer(const CudaBuffer &rhs) = delete;
+
+    virtual ~CudaBuffer() {
+        if (!_ownBuffer || _buffer == nullptr)
+            return;
+        try {
+            CHECK_EX(cudaFree(_buffer));
+        } catch (std::exception &ex) {
+            Logger::instance.warning(std::string("Exception raised in destructor: ") + ex.what());
+        }
+        _buffer = nullptr;
+        _ownBuffer = false;
+    }
+
+    virtual void *getBuffer() const { return _buffer; }
+    template <class T> T *getBuffer() const { return (T *)getBuffer(); }
+
+    virtual size_t size() const { return _size; }
+
+  private:
+    void *_buffer;
+    bool _ownBuffer;
+    size_t _size;
+};
+
+template <typename T> class CudaArray : public CudaBuffer {
+  public:
+    CudaArray(size_t n) : CudaBuffer(n * sizeof(T)) {}
+    CudaArray(T *buffer, size_t n) : CudaBuffer(buffer, n * sizeof(T)) {}
+    CudaArray(const CudaArray<T> &rhs) = delete;
+
+    size_t n() const { return size() / sizeof(T); }
+
+    operator T *() { return (T *)getBuffer(); }
+};
+
+class GraphicsResource : public Resource {
+  public:
+    cudaGraphicsResource_t getHandler() { return _res; }
+
+    virtual ~GraphicsResource() {
+        if (_res == nullptr)
+            return;
+        try {
+            CHECK_EX(cudaGraphicsUnregisterResource(_res));
+        } catch (std::exception &ex) {
+            Logger::instance.warning(std::string("Exception raised in destructor: ") + ex.what());
+        }
+        _res = nullptr;
+    }
+
+    virtual size_t size() const { return _size; }
+
+  protected:
+    cudaGraphicsResource_t _res;
+    size_t _size;
+
+    GraphicsResource() : _res(nullptr), _size(0) {}
+};
+
+template <typename T> class GlTextureResource : public GraphicsResource {
+  public:
+    GlTextureResource(GLuint textureID, glm::uvec2 textureSize) {
+        CHECK_EX(cudaGraphicsGLRegisterImage(&_res, textureID, GL_TEXTURE_2D,
+                                             cudaGraphicsRegisterFlagsWriteDiscard));
+        _size = textureSize.x * textureSize.y * sizeof(T);
+        _textureSize = textureSize;
+    }
+
+    virtual ~GlTextureResource() { cudaGraphicsUnmapResources(1, &_res, 0); }
+
+    virtual void *getBuffer() const {
+        cudaArray_t buffer;
+        try {
+            CHECK_EX(cudaGraphicsSubResourceGetMappedArray(&buffer, _res, 0, 0));
+        } catch (...) {
+            return nullptr;
+        }
+        return buffer;
+    }
+
+    operator T *() { return (T *)getBuffer(); }
+
+    glm::uvec2 textureSize() { return _textureSize; }
+
+  private:
+    glm::uvec2 _textureSize;
+};
+
+class Resources {
+  public:
+    std::map<std::string, Resource *> resources;
+    std::vector<cudaGraphicsResource_t> graphicsResources;
+
+    void addResource(const std::string &name, Resource *res) {
+        auto gres = dynamic_cast<GraphicsResource *>(res);
+        if (gres != nullptr)
+            graphicsResources.push_back(gres->getHandler());
+        resources[name] = res;
+    }
+
+    void clear() {
+        resources.clear();
+        graphicsResources.clear();
+    }
+};
+
+template <typename T>
+void dumpFloatArray(std::ostream &so, CudaArray<T> &arr, size_t maxDumpRows = 0,
+                    size_t elemsPerRow = 1) {
+    T *hostArr = new T[arr.n()];
+    cudaMemcpy(hostArr, arr.getBuffer(), arr.n() * sizeof(T), cudaMemcpyDeviceToHost);
+    dumpHostBuffer<float>(so, hostArr, arr.n() * sizeof(T), sizeof(T) / sizeof(float) * elemsPerRow,
+                          maxDumpRows);
+    delete[] hostArr;
+}
\ No newline at end of file
diff --git a/cpp/utils/common.h b/cpp/utils/common.h
new file mode 100644
index 0000000..3065d6d
--- /dev/null
+++ b/cpp/utils/common.h
@@ -0,0 +1,138 @@
+#pragma once
+#include <memory>
+#include <stdexcept>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <GL/glew.h>
+#include <cuda_gl_interop.h>
+#include "../glm/glm.hpp"
+#include "Logger.h"
+
+inline unsigned int getElementSize(nv::DataType t) {
+    switch (t) {
+    case nv::DataType::kINT32:
+        return 4;
+    case nv::DataType::kFLOAT:
+        return 4;
+    case nv::DataType::kHALF:
+        return 2;
+    case nv::DataType::kBOOL:
+    case nv::DataType::kINT8:
+        return 1;
+    }
+    throw std::runtime_error("Invalid DataType.");
+    return 0;
+}
+
+template <typename T> void dumpRow(std::ostream &os, T *buf, size_t n) {
+    os << buf[0];
+    for (size_t i = 1; i < n; ++i) {
+        os << " " << buf[i];
+    }
+    os << std::endl;
+}
+
+template <typename T>
+void dumpHostBuffer(std::ostream &os, void *buf, size_t bufSize, size_t rowCount,
+                    size_t maxDumpRows = 0) {
+    T *typedBuf = static_cast<T *>(buf);
+    size_t numItems = bufSize / sizeof(T);
+    size_t nInLastRow = numItems % rowCount;
+    size_t rows;
+    if (nInLastRow == 0) {
+        rows = numItems / rowCount;
+        nInLastRow = rowCount;
+    } else {
+        rows = numItems / rowCount + 1;
+    }
+    if (maxDumpRows == 0) {
+        for (size_t i = 0; i < rows - 1; ++i) {
+            dumpRow(os, typedBuf, rowCount);
+            typedBuf += rowCount;
+        }
+        dumpRow(os, typedBuf, nInLastRow);
+    } else {
+        for (size_t i = 0; i < maxDumpRows / 2; ++i)
+            dumpRow(os, typedBuf + i * rowCount, rowCount);
+        os << "..." << std::endl;
+        for (size_t i = rows - maxDumpRows + maxDumpRows / 2; i < rows - 1; ++i)
+            dumpRow(os, typedBuf + i * rowCount, rowCount);
+        dumpRow(os, typedBuf + (rows - 1) * rowCount, nInLastRow);
+    }
+}
+
+class CudaStream {
+public:
+    CudaStream() { cudaStreamCreate(&stream); }
+
+    operator cudaStream_t() { return stream; }
+
+    virtual ~CudaStream() { cudaStreamDestroy(stream); }
+
+private:
+    cudaStream_t stream;
+};
+
+class CudaEvent {
+public:
+    CudaEvent() { cudaEventCreate(&mEvent); }
+
+    operator cudaEvent_t() { return mEvent; }
+
+    virtual ~CudaEvent() { cudaEventDestroy(mEvent); }
+
+private:
+    cudaEvent_t mEvent;
+};
+
+struct CudaMapScope {
+    std::vector<cudaGraphicsResource_t> resources_;
+    cudaStream_t stream_;
+
+    CudaMapScope(const std::vector<cudaGraphicsResource_t> &resources,
+                 cudaStream_t stream = nullptr)
+        : resources_(resources), stream_(stream) {}
+
+    ~CudaMapScope() {
+        if (!resources_.empty())
+            cudaGraphicsUnmapResources(resources_.size(), resources_.data(), stream_);
+    }
+
+    cudaError_t map() {
+        if (!resources_.empty())
+            return cudaGraphicsMapResources(resources_.size(), resources_.data(), stream_);
+        return cudaSuccess;
+    }
+};
+
+template <typename T> struct Destroy {
+    void operator()(T *t) {
+        if (t != nullptr)
+            t->destroy();
+    }
+};
+
+class Range {
+public:
+    Range(glm::vec2 bound, uint steps)
+        : _start(bound.x), _step((bound.y - bound.x) / (steps - 1)), _steps(steps) {}
+
+    __host__ __device__ float get(uint i) { return _start + i * _step; }
+    __host__ __device__ float start() { return _start; }
+    __host__ __device__ float stop() { return _start + _step * _steps; }
+    __host__ __device__ float steps() { return _steps; }
+
+private:
+    float _start;
+    float _step;
+    uint _steps;
+};
+
+template <class T> using uptr = std::unique_ptr<T, ::Destroy<T>>;
+template <class T> using sptr = std::shared_ptr<T>;
+
+#define INTERVAL(__start__, __end__) (((__end__) - (__start__)) / (float)CLOCKS_PER_SEC * 1000)
+
+#include "Resource.h"
+#include "Formatter.h"
\ No newline at end of file
diff --git a/cpp/utils/cuda.h b/cpp/utils/cuda.h
new file mode 100644
index 0000000..b394ee7
--- /dev/null
+++ b/cpp/utils/cuda.h
@@ -0,0 +1,11 @@
+#include "thread_index.h"
+
+#ifdef __INTELLISENSE__
+#define CU_INVOKE(__func__) __func__
+#define CU_INVOKE1(__func__, __grdSize__, __blkSize__) __func__
+#else
+#define CU_INVOKE(__func__) __func__<<<grdSize, blkSize>>>
+#define CU_INVOKE1(__func__, __grdSize__, __blkSize__) __func__<<<__grdSize__, __blkSize__>>>
+#endif
+
+inline uint ceilDiv(uint a, uint b) { return (uint)ceil(a / (float)b); }
\ No newline at end of file
diff --git a/cpp/msl_infer/half.h b/cpp/utils/half.h
similarity index 100%
rename from cpp/msl_infer/half.h
rename to cpp/utils/half.h
diff --git a/cpp/msl_infer/thread_index.h b/cpp/utils/thread_index.h
similarity index 100%
rename from cpp/msl_infer/thread_index.h
rename to cpp/utils/thread_index.h
diff --git a/data/spherical_view_syn.py b/data/spherical_view_syn.py
index 2445ad3..e52d758 100644
--- a/data/spherical_view_syn.py
+++ b/data/spherical_view_syn.py
@@ -27,7 +27,7 @@ class SphericalViewSynDataset(object):
 
     def __init__(self, dataset_desc_path: str, load_images: bool = True,
                  load_depths: bool = False, load_bins: bool = False, c: int = color.RGB,
-                 calculate_rays: bool = True, res: Tuple[int, int] = None):
+                 calculate_rays: bool = True, res: Tuple[int, int] = None, load_views=None):
         """
         Initialize data loader for spherical view synthesis task
 
@@ -52,7 +52,7 @@ class SphericalViewSynDataset(object):
         self.load_bins = load_bins
 
         # Load dataset description file
-        self._load_desc(dataset_desc_path, res)
+        self._load_desc(dataset_desc_path, res, load_views)
 
         # Load view images
         if self.load_images:
@@ -98,7 +98,7 @@ class SphericalViewSynDataset(object):
         disp_val = (1 - input[..., 0, :, :]) * (disp_range[1] - disp_range[0]) + disp_range[0]
         return torch.reciprocal(disp_val)
 
-    def _load_desc(self, path, res=None):
+    def _load_desc(self, path, res=None, load_views=None):
         with open(path, 'r', encoding='utf-8') as file:
             data_desc = json.loads(file.read())
         if not data_desc.get('view_file_pattern'):
@@ -127,11 +127,17 @@ class SphericalViewSynDataset(object):
             [view.euler_to_matrix([rot[1], rot[0], 0]) for rot in data_desc['view_rots']]
             if len(data_desc['view_rots'][0]) == 2 else data_desc['view_rots'],
             device=device.default()).view(-1, 3, 3)  # (N, 3, 3)
-        #self.view_centers = self.view_centers[:6]
-        #self.view_rots = self.view_rots[:6]
+        self.view_idxs = torch.tensor(
+            data_desc['views'] if 'views' in data_desc else list(range(self.view_centers.size(0))),
+            device=device.default())
+
+        if load_views is not None:
+            self.view_centers = self.view_centers[load_views]
+            self.view_rots = self.view_rots[load_views]
+            self.view_idxs = self.view_idxs[load_views]
+        
         self.n_views = self.view_centers.size(0)
         self.n_pixels = self.n_views * self.view_res[0] * self.view_res[1]
-        self.view_idxs = data_desc['views'][:self.n_views] if 'views' in data_desc else range(self.n_views)
 
         if 'gl_coord' in data_desc and data_desc['gl_coord'] == True:
             print('Convert from OGL coordinate to DX coordinate (i. e. flip z axis)')
diff --git a/notebook/gen_demo_mono.ipynb b/notebook/gen_demo_mono.ipynb
index e1bde59..67753ad 100644
--- a/notebook/gen_demo_mono.ipynb
+++ b/notebook/gen_demo_mono.ipynb
@@ -70,6 +70,10 @@
     "    plt.subplot(133)\n",
     "    img.plot(images['layers_img'][2])\n",
     "    plt.figure(figsize=(12, 12))\n",
+    "    img.plot(images['overlaid'])\n",
+    "    plt.figure(figsize=(12, 12))\n",
+    "    img.plot(images['blended_raw'])\n",
+    "    plt.figure(figsize=(12, 12))\n",
     "    img.plot(images['blended'])\n",
     "\n",
     "\n",
@@ -87,7 +91,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
@@ -108,12 +112,12 @@
     "fovea_net = load_net(find_file('fovea'))\n",
     "periph_net = load_net(find_file('periph'))\n",
     "renderer = FoveatedNeuralRenderer(fov_list, res_list, nn.ModuleList([fovea_net, periph_net, periph_net]),\n",
-    "                                  res_full, using_mask=False, device=device.default())\n"
+    "                                  res_full, device=device.default())"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -129,13 +133,14 @@
     "    ],\n",
     "    'barbershop': [\n",
     "        [0, 0, 0,   0, 0,   0, 0],\n",
-    "        #[0, 0, 0, 20, 0, -300, 50],\n",
-    "        #[0, 0, 0, -140, -30, 150, -250],\n",
-    "        #[0, 0, 0, -60, -30, 75, -125],\n",
+    "        [0, 0, 0, 20, 0, -300, 50],\n",
+    "        [0, 0, 0, -140, -30, 150, -250],\n",
+    "        [0, 0, 0, -60, -30, 75, -125],\n",
+    "        [0, 0, 0,   -10, -5,   0, 0]\n",
     "    ],\n",
     "    'lobby': [\n",
-    "        #[0, 0, 0, 0, 0, 75, 0],\n",
-    "        #[0, 0, 0, 0, 0, 5, 150],\n",
+    "        [0, 0, 0, 0, 0, 75, 0],\n",
+    "        [0, 0, 0, 0, 0, 5, 150],\n",
     "        [0, 0, 0, -120, 0, 75, 50],\n",
     "    ]\n",
     "}\n",
@@ -143,14 +148,17 @@
     "for i, param in enumerate(params[scene]):\n",
     "    view = Trans(torch.tensor(param[:3], device=device.default()),\n",
     "                 torch.tensor(euler_to_matrix([-param[4], param[3], 0]), device=device.default()).view(3, 3))\n",
-    "    images = renderer(view, param[-2:])\n",
-    "    if False:\n",
+    "    images = renderer(view, param[-2:], using_mask=False, ret_raw=True)\n",
+    "    images['overlaid'] = renderer.foveation.synthesis(images['layers_raw'], param[-2:], do_blend=False)\n",
+    "    if True:\n",
     "        outputdir = '../__demo/mono/'\n",
     "        misc.create_dir(outputdir)\n",
     "        img.save(images['layers_img'][0], f'{outputdir}{scene}_{i}_fovea.png')\n",
     "        img.save(images['layers_img'][1], f'{outputdir}{scene}_{i}_mid.png')\n",
     "        img.save(images['layers_img'][2], f'{outputdir}{scene}_{i}_periph.png')\n",
     "        img.save(images['blended'], f'{outputdir}{scene}_{i}_blended.png')\n",
+    "        img.save(images['overlaid'], f'{outputdir}{scene}_{i}_overlaid.png')\n",
+    "        img.save(images['blended_raw'], f'{outputdir}{scene}_{i}_blended_raw.png')\n",
     "    else:\n",
     "        images = plot_images(images)\n"
    ]
@@ -212,8 +220,9 @@
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3.8.5 64-bit ('base': conda)",
-   "name": "python385jvsc74a57bd082066b63b621a9e3d15e3b7c11ca76da6238eff3834294910d715044bd0561e5"
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
   },
   "language_info": {
    "codemirror_mode": {
@@ -231,9 +240,8 @@
    "interpreter": {
     "hash": "82066b63b621a9e3d15e3b7c11ca76da6238eff3834294910d715044bd0561e5"
    }
-  },
-  "orig_nbformat": 2
+  }
  },
  "nbformat": 4,
  "nbformat_minor": 2
-}
\ No newline at end of file
+}
diff --git a/notebook/gen_demo_stereo.ipynb b/notebook/gen_demo_stereo.ipynb
index a5d6c21..68aab2f 100644
--- a/notebook/gen_demo_stereo.ipynb
+++ b/notebook/gen_demo_stereo.ipynb
@@ -2,37 +2,44 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 5,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Set CUDA:0 as current device.\n"
+     ]
+    }
+   ],
    "source": [
     "import sys\n",
     "import os\n",
     "import torch\n",
+    "import torch.nn as nn\n",
     "import matplotlib.pyplot as plt\n",
     "\n",
     "rootdir = os.path.abspath(sys.path[0] + '/../')\n",
     "sys.path.append(rootdir)\n",
     "\n",
-    "torch.cuda.set_device(2)\n",
+    "torch.cuda.set_device(0)\n",
     "print(\"Set CUDA:%d as current device.\" % torch.cuda.current_device())\n",
     "torch.autograd.set_grad_enabled(False)\n",
     "\n",
     "from data.spherical_view_syn import *\n",
     "from configs.spherical_view_syn import SphericalViewSynConfig\n",
     "from utils import netio\n",
-    "from utils import misc\n",
     "from utils import img\n",
     "from utils import device\n",
-    "from utils import view\n",
+    "from utils.view import *\n",
     "from components.fnr import FoveatedNeuralRenderer\n",
     "\n",
     "\n",
     "def load_net(path):\n",
     "    config = SphericalViewSynConfig()\n",
-    "    config.from_id(path[:-4])\n",
+    "    config.from_id(os.path.splitext(path)[0])\n",
     "    config.SAMPLE_PARAMS['perturb_sample'] = False\n",
-    "    # config.print()\n",
     "    net = config.create_net().to(device.default())\n",
     "    netio.load(path, net)\n",
     "    return net\n",
@@ -45,14 +52,14 @@
     "    return None\n",
     "\n",
     "\n",
-    "def load_views(data_desc_file) -> view.Trans:\n",
+    "def load_views(data_desc_file) -> Trans:\n",
     "    with open(data_desc_file, 'r', encoding='utf-8') as file:\n",
     "        data_desc = json.loads(file.read())\n",
     "        view_centers = torch.tensor(\n",
     "            data_desc['view_centers'], device=device.default()).view(-1, 3)\n",
     "        view_rots = torch.tensor(\n",
     "            data_desc['view_rots'], device=device.default()).view(-1, 3, 3)\n",
-    "        return view.Trans(view_centers, view_rots)\n",
+    "        return Trans(view_centers, view_rots)\n",
     "\n",
     "\n",
     "def plot_cross(center, res):\n",
@@ -78,115 +85,120 @@
     "        color=[0, 1, 0])\n",
     "\n",
     "\n",
-    "def plot_fovea(left_images, right_images, left_center, right_center):\n",
-    "    plt.figure(figsize=(8, 4))\n",
+    "def plot_figures(left_images, right_images, left_center, right_center):\n",
+    "    # Plot Fovea\n",
+    "    plt.figure(figsize=(12, 6))\n",
     "    plt.subplot(121)\n",
-    "    img.plot(left_images['fovea'])\n",
-    "    fovea_res = left_images['fovea'].size()[-2:]\n",
+    "    img.plot(left_images['layers_img'][0])\n",
+    "    fovea_res = left_images['layers_img'][0].size()[-2:]\n",
     "    plot_cross((0, 0), fovea_res)\n",
     "    plt.subplot(122)\n",
-    "    img.plot(right_images['fovea'])\n",
+    "    img.plot(right_images['layers_img'][0])\n",
     "    plot_cross((0, 0), fovea_res)\n",
     "\n",
+    "    # Plot Mid\n",
+    "    plt.figure(figsize=(12, 6))\n",
+    "    plt.subplot(121)\n",
+    "    img.plot(left_images['layers_img'][1])\n",
+    "    plt.subplot(122)\n",
+    "    img.plot(right_images['layers_img'][1])\n",
+    "\n",
+    "    # Plot Periph\n",
+    "    plt.figure(figsize=(12, 6))\n",
+    "    plt.subplot(121)\n",
+    "    img.plot(left_images['layers_img'][2])\n",
+    "    plt.subplot(122)\n",
+    "    img.plot(right_images['layers_img'][2])\n",
+    "\n",
+    "    # Plot Blended\n",
+    "    plt.figure(figsize=(12, 6))\n",
+    "    plt.subplot(121)\n",
+    "    img.plot(left_images['blended'])\n",
+    "    full_res = left_images['blended'].size()[-2:]\n",
+    "    plot_cross(left_center, full_res)\n",
+    "    plt.subplot(122)\n",
+    "    img.plot(right_images['blended'])\n",
+    "    plot_cross(right_center, full_res)\n",
+    "\n",
     "\n",
     "scenes = {\n",
-    "    'gas': '__0_user_study/us_gas_all_in_one',\n",
-    "    'mc': '__0_user_study/us_mc_all_in_one',\n",
-    "    'bedroom': 'bedroom_all_in_one',\n",
-    "    'gallery': 'gallery_all_in_one',\n",
-    "    'lobby': 'lobby_all_in_one'\n",
+    "    'classroom': 'classroom_all',\n",
+    "    'stones': 'stones_all',\n",
+    "    'barbershop': 'barbershop_all',\n",
+    "    'lobby': 'lobby_all'\n",
     "}\n",
     "\n",
+    "\n",
     "fov_list = [20, 45, 110]\n",
-    "res_list = [(128, 128), (256, 256), (256, 230)]\n",
+    "res_list = [(256, 256), (256, 256), (256, 230)]\n",
     "res_full = (1600, 1440)\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 26,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Change working directory to  /home/dengnc/dvs/data/__new/classroom_all\n",
+      "Load net from fovea@snerffast4-rgb_e6_fc256x8_d1.00-7.00_s64_~p.pth ...\n",
+      "Load net from periph@snerffast4-rgb_e6_fc128x4_d1.00-7.00_s64_~p.pth ...\n"
+     ]
+    }
+   ],
    "source": [
-    "centers = {\n",
-    "    'gas': [\n",
-    "        [(3.5, 0), (-3.5, 0)],\n",
-    "        [(1.5, 0), (-1.5, 0)]\n",
-    "    ],\n",
-    "    'mc': [\n",
-    "        [(2, 0), (-2, 0)],\n",
-    "        [(2, 0), (-2, 0)]\n",
+    "params = {\n",
+    "    'classroom': [\n",
+    "        [(0, 0, 0, 0, 0), (1, -83), (-5, -83)],\n",
+    "        [(0, 0, 0, 0, 0), (-171, 55), (-178, 55)],\n",
+    "        [(0, 0, 0, 0, 0), (60, 55), (55, 55)],\n",
+    "        [(0, 0, 0, 0, 0), (138, 160), (130, 160)]\n",
     "    ],\n",
-    "    'bedroom': [\n",
-    "        [(5, 0), (-5, 0)],\n",
-    "        [(6, 0), (-6, 0)],\n",
-    "        [(5, 0), (-5, 0)]\n",
-    "    ],\n",
-    "    'gallery': [\n",
-    "        [(2.5, 0), (-2.5, 0)],\n",
-    "        [(11.5, 0), (-11.5, 0)]\n",
-    "    ]\n",
     "}\n",
-    "scene = 'bedroom'\n",
-    "os.chdir(os.path.join(rootdir, f'data/{scenes[scene]}'))\n",
+    "scene = 'classroom'\n",
+    "os.chdir(f'{rootdir}/data/__new/{scenes[scene]}')\n",
     "print('Change working directory to ', os.getcwd())\n",
     "\n",
     "fovea_net = load_net(find_file('fovea'))\n",
     "periph_net = load_net(find_file('periph'))\n",
-    "\n",
-    "# Load Dataset\n",
-    "views = load_views('demo.json')\n",
-    "print('Dataset loaded.')\n",
-    "print('views:', views.size())\n",
-    "gen = GenFinal(fov_list, res_list, res_full, fovea_net, periph_net,\n",
-    "               device=device.default())\n",
-    "\n",
-    "for view_idx in range(views.size()[0]):\n",
-    "    test_view = views.get(view_idx)\n",
-    "    left_images = gen(centers[scene][view_idx][0], view.Trans(\n",
-    "        test_view.trans_point(\n",
-    "            torch.tensor([-0.03, 0, 0], device=device.default())\n",
-    "        ), test_view.r), mono_trans=test_view)\n",
-    "    right_images = gen(centers[scene][view_idx][1], view.Trans(\n",
-    "        test_view.trans_point(\n",
-    "            torch.tensor([0.03, 0, 0], device=device.default())\n",
-    "        ), test_view.r), mono_trans=test_view)\n",
-    "    #plot_fovea(left_images, right_images, centers[scene][view_idx][0],\n",
-    "    #           centers[scene][view_idx][1])\n",
-    "    outputdir = '../__2_demo/mono_periph/stereo/'\n",
-    "    misc.create_dir(outputdir)\n",
-    "    # for key in images:\n",
-    "    key = 'blended'\n",
-    "    img.save(left_images[key], '%s%s_view%04d_%s_l.png' % (outputdir, scene, view_idx, key))\n",
-    "    img.save(right_images[key], '%s%s_view%04d_%s_r.png' % (outputdir, scene, view_idx, key))\n",
-    "    stereo_overlap = torch.cat([left_images['blended'][:, 0:1], right_images['blended'][:, 1:3]], dim=1)\n",
-    "    img.save(stereo_overlap, '%s%s_view%04d_%s_stereo.png' % (outputdir, scene, view_idx, key))\n",
-    "\n",
-    "    left_images = gen(centers[scene][view_idx][0], view.Trans(\n",
-    "        test_view.trans_point(\n",
-    "            torch.tensor([-0.03, 0, 0], device=device.default())\n",
-    "        ), test_view.r))\n",
-    "    right_images = gen(centers[scene][view_idx][1], view.Trans(\n",
-    "        test_view.trans_point(\n",
-    "            torch.tensor([0.03, 0, 0], device=device.default())\n",
-    "        ), test_view.r))\n",
-    "    #plot_fovea(left_images, right_images, centers[scene][view_idx][0],\n",
-    "    #           centers[scene][view_idx][1])\n",
-    "    outputdir = '../__2_demo/stereo/'\n",
-    "    misc.create_dir(outputdir)\n",
-    "    # for key in images:\n",
-    "    key = 'blended'\n",
-    "    img.save(left_images[key], '%s%s_view%04d_%s_l.png' % (outputdir, scene, view_idx, key))\n",
-    "    img.save(right_images[key], '%s%s_view%04d_%s_r.png' % (outputdir, scene, view_idx, key))\n",
-    "    stereo_overlap = torch.cat([left_images['blended'][:, 0:1], right_images['blended'][:, 1:3]], dim=1)\n",
-    "    img.save(stereo_overlap, '%s%s_view%04d_%s_stereo.png' % (outputdir, scene, view_idx, key))\n"
+    "renderer = FoveatedNeuralRenderer(fov_list, res_list,\n",
+    "                                  nn.ModuleList([fovea_net, periph_net, periph_net]),\n",
+    "                                  res_full, device=device.default())\n",
+    "\n",
+    "for i, param in enumerate(params[scene]):\n",
+    "    view = Trans(torch.tensor(param[0][:3], device=device.default()),\n",
+    "                 torch.tensor(euler_to_matrix([-param[0][4], param[0][3], 0]),\n",
+    "                              device=device.default()).view(3, 3))\n",
+    "    eye_offset = torch.tensor([0.03, 0, 0], device=device.default())\n",
+    "    left_view = Trans(view.trans_point(-eye_offset), view.r)\n",
+    "    right_view = Trans(view.trans_point(eye_offset), view.r)\n",
+    "    left_images, right_images = renderer(view, param[1], param[2],\n",
+    "                                         stereo_disparity=0.06, using_mask=False, ret_raw=False)\n",
+    "    if True:\n",
+    "        outputdir = '../__demo/stereo/'\n",
+    "        misc.create_dir(outputdir)\n",
+    "        img.save(left_images['blended'], '%s%s_%d_l.png' % (outputdir, scene, i))\n",
+    "        img.save(right_images['blended'], '%s%s_%d_r.png' % (outputdir, scene, i))\n",
+    "        stereo_overlap = torch.cat([\n",
+    "            left_images['blended'][:, 0:1],\n",
+    "            right_images['blended'][:, 1:3]\n",
+    "        ], dim=1)\n",
+    "        img.save(stereo_overlap, '%s%s_%d_stereo.png' % (outputdir, scene, i))\n",
+    "    else:\n",
+    "        plot_figures(left_images, right_images, param[1], param[2])\n"
    ]
   }
  ],
  "metadata": {
+  "interpreter": {
+   "hash": "82066b63b621a9e3d15e3b7c11ca76da6238eff3834294910d715044bd0561e5"
+  },
   "kernelspec": {
-   "display_name": "Python 3.7.9 64-bit ('pytorch': conda)",
-   "name": "python379jvsc74a57bd0660ca2a75467d3af74a68fcc6f40bc78ab96b99ff17d2f100b5ca821fbb183f2"
+   "display_name": "Python 3.8.5 64-bit ('base': conda)",
+   "name": "python3"
   },
   "language_info": {
    "codemirror_mode": {
@@ -198,7 +210,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.7.9"
+   "version": "3.8.5"
   },
   "orig_nbformat": 2
  },
diff --git a/notebook/test_foveation.ipynb b/notebook/test_foveation.ipynb
index e0ba19e..77417ad 100644
--- a/notebook/test_foveation.ipynb
+++ b/notebook/test_foveation.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
     {
@@ -10,14 +10,15 @@
      "output_type": "stream",
      "text": [
       "Set CUDA:0 as current device.\n",
-      "14496(22.12%) pixels in layer 0 are masked as skipped\n",
-      "15980(24.38%) pixels in layer 1 are masked as skipped\n"
+      "Layer 0: 14106(21.52%) pixels are masked as skipped, 51430 pixels need to be inferred\n",
+      "Layer 1: 15586(23.78%) pixels are masked as skipped, 49950 pixels need to be inferred\n",
+      "Layer 2: 700(1.19%) pixels are masked as skipped, 58180 pixels need to be inferred\n"
      ]
     },
     {
      "data": {
-      "image/png": "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\n",
-      "text/plain": "<Figure size 432x288 with 2 Axes>"
+      "image/png": "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\n",
+      "text/plain": "<Figure size 864x288 with 3 Axes>"
      },
      "metadata": {
       "needs_background": "light"
@@ -45,20 +46,27 @@
     "\n",
     "\n",
     "foveation = Foveation([20, 45, 110], [(256, 256), (256, 256), (256, 230)], (1600, 1440))\n",
-    "layers_mask = foveation.get_layers_mask()\n",
-    "plt.figure()\n",
+    "layers_mask = foveation.get_layers_mask((0, 0))\n",
+    "plt.figure(figsize=(12, 4))\n",
     "for i, mask in enumerate(layers_mask):\n",
     "    colored_mask = torch.zeros(mask.size(0), mask.size(1), 3, device=mask.device)\n",
-    "    c = torch.tensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]], device=mask.device)\n",
+    "    c = torch.tensor([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 1]], device=mask.device)\n",
     "    for bi in range(3):\n",
     "        region = torch.logical_and(mask > bi, mask < bi + 1)\n",
-    "        colored_mask[region] = c[bi] * (mask[region][..., None] - bi)\n",
+    "        colored_mask[region] = c[bi] + (c[-1] - c[bi]) * (mask[region][..., None] - bi)\n",
     "    plt.subplot(1, len(layers_mask), i + 1)\n",
     "    img.plot(colored_mask)\n",
     "    n_skipped = torch.sum(mask < 0)\n",
     "    n_tot = len(mask.flatten())\n",
-    "    print (f\"{n_skipped}({n_skipped / n_tot * 100:.2f}%) pixels in layer {i} are masked as skipped\")"
+    "    print (f\"Layer {i}: {n_skipped}({n_skipped / n_tot * 100:.2f}%) pixels are masked as skipped, {n_tot - n_skipped} pixels need to be inferred\")"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/notebook/test_spherical_view_syn.ipynb b/notebook/test_spherical_view_syn.ipynb
index d4e81cf..3046052 100644
--- a/notebook/test_spherical_view_syn.ipynb
+++ b/notebook/test_spherical_view_syn.ipynb
@@ -2,17 +2,9 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "Set CUDA:0 as current device.\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
     "import sys\n",
     "import os\n",
@@ -129,27 +121,9 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": null,
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "0 torch.Size([4, 3, 400, 400]) torch.Size([4, 400, 400, 3]) torch.Size([4, 400, 400, 3])\n"
-     ]
-    },
-    {
-     "data": {
-      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZsAAABwCAYAAADIbN0NAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAD0C0lEQVR4nOz9Wayl63nfif3e4RvXvNaed+2az8xDiqNIiRSlltiyLKttx5YjteM00gmcNNBI5yIXAQIk6IsECBIgFx13EhvdDccJbDTstrttS5ZszabE4ZCHPPOpOjXXnqc1fuM75OJbVXWotijSYMXHQT3AObX32mt+v/d9pv///wjvPc/smT2zZ/bMntnTNPlv+g08s2f2zJ7ZM/v/f3vmbJ7ZM3tmz+yZPXV75mye2TN7Zs/smT11e+Zsntkze2bP7Jk9dXvmbJ7ZM3tmz+yZPXV75mye2TN7Zs/smT11e2rORgjxZ4QQ7wshPhBC/G+e1us8s+9vz9bho2HP1uGjYc/W4d+ciafBsxFCKOAG8BXgIfBN4Fe99+/8yF/smf2J9mwdPhr2bB0+GvZsHf7N2tPKbD4HfOC9v+29r4C/B/z5p/Raz+xPtmfr8NGwZ+vw0bBn6/Bv0J6Ws9kGHnzo94fL257Z/2/t2Tp8NOzZOnw07Nk6/Bs0/ZSeV/wrbvueep0Q4q8Df315708rrRkNR6RpSpYXVHWNNTVVWRIGIR4PeKxzBM4CHiM1UZxg6hohBUJIrDVYa/HOPX4rQjx+UaQQKAlaSqzzCAFKSYxp7i+lIFASrRTOeaSShGFAFHkQHilgMsmxVoKoCYKAKNLEcUyR59TWgYdsbqicxzropiFFZTC2JIk0aSKpjSNNWjgPdVXivEBKyMuSLDM4L1GBopMEKBHgPHjnyUpDWRuKLDvx3q/+KNchCINPr62tMVvkmNqglCQOA4SQ1MZQlBVaC6SUgKU2giRJsabGmgrnKqSQSB0hdEJmAn7QIq1oludPfqPf5wMtP8jjv3kPyi7QVNRVgVQBQnhU2Hr8HFGgwHuM8zjncd6jlaAdSuq6RgiB9x7vm/flPUgpWdSe2j56HU82PfuRr4NS4tNXLo04H09xTrC+toJzhvl8gbUSrT2VMVSVxThBGIWEShGoEABrHVnt0DpYXsMa7ywIgbUOW1dICTiHcA4RhiShoq4qqtrQbiUEtSHJcqJAodMQpMTXBlsaitJSO4eJQkw7ZV7UON/spUBZQuUJAkUcRzhnqWuP9w6Q4CSjVoQKNAQpFBP8ZEFmBPMoRipBGGgqJ1A+QylBVdVEUUBVVVQ2pCYilB5TZHjvEUJwdDL+0a9DEH067G3yqNUghECJ5gHWOURxjhQea2u8c6ggwjuD954gTPEIpHxyXVrnEVICj64rQRSG5NkMZwqElAgZglA4U4B3KB0ur21Hv9sHoVnkBVVVYHUbJ3Tzhv7EjfGDmfgBfvPi+7+MALKTu3/iOjwtZ/MQ2PnQ7xeAvQ/fwXv/N4G/CRDGkR9d3OCv/MW/zK/88q/y5vs3ee27bzE5OeStb7/Gx179MdY3txiOQv7g9/6QeO8uLek46K5y6YWP88KFgLPzc8YZFBUcniyojQNX4wGlNHiHq2eU2Tn57IzRaB2dDBh2UvLKUVQGbwu2VodcGLRZG/aZZCXtdsL2hmYwGtMbrlMXGbfunXGwJ1hU93j5xUvk2ZytzcsU+Snvf3DC/b0pkU15OAanQj77/DrH52e8c+sWH3/5AqNuhtKWn/ziz9IfrPKf/42/w8pwhdPJIdOZ4frVTb722j2iVsCXP/8S1WK1cUpFwXceTLl9b59v/v7v3vtRr8PFSzv+P/pP/hf8+m+9RpaXbI96XNzaACm5fX+fB/undOIp69vXqfN9ZLpDv7/J/u4dpJ2TTXYx9YLBxkt01p7j9ckVCiuwCMSjLS084kOXrAS0aA4MlhdzoJsfart0HKIJGBzA8vCXQjSnhG82gRY035EH7SpGx/+YkJzz0wM6owuUiyNWLn4BqTWDdsjP/9gFBu2ARVYynpecz0pqY7i6nvDP/+CrSCxJFBCHEe1WG1wTqHxw5rk91TjnqeuKb/6zv/cjX4c4ifxPf+llfvqLV3jw4C5f/OmfYH11i//bf/Zfc3gwY2XVczw2fPLVq3z9W3cxAn7xZ1+kmG1inWAymfHd3QwV9un3R6ysrbJY5Cgl8QJuvvsGuLJxPt7Ta8V87EKHxWLB2TTn8taA5GxMcueM3uoqzpWoQGOAxcEuk5MF4d4J0UsXOf7UC3z9xhlHR6cMeoKNNSgXY/7Kn/80nU6L2eIIb1NwBXcfHDG+5/hfdyTDj12ASzvw7beZfu0B9yaK3/+5n+GdvWM2L1yg04Gro3OK7AipEspyzOr6ZY6zAW/s9+nJjL03XyMMNFpJ/s//+Y9+HbrrV/0nf+U/ZZZblIQoaAJULQVZZUmn72Af/gvmk0Nag8t0Vq8ghKAdhYQqYFJDkgR8YqfHai/hmzdOOJjW1NbinSXRcPnCRXbPclxxys72Kg8f3mVShRSzc+r8jGJ8j3ZvRJJ0+Es/85N8/NVP8fqdKX/0/j7fna7jllvpkb8RgEMgBchHAfqygCV44lmFfxKECwF++WhBsxfFcp9++Hmb/fmhxy0fLB7/At/+f/6P/8R1eFrO5pvAc0KIK8Au8CvAv//9HiClYH//AO8c7TTBWEOaxLTbLVZX1+l2B8SJIwg1xDG9wHLqHXVpWRQBzkuuP/8K1jqOv/oNnDMoKR4fSr6ekc3PqGyEUz2mi5yoqljrXWZ90OVwPKcqanqdNisbKwxHA9rGkmcLUBmtdh8pE27evsnDM8vK4AJhmfCt79zjKz/7eZTscefWu4SpIW5DPZfEkaKdBnjnGK0G6AcJhydjfu5nPsOv/ca3eO/9d/nkpy7y9lt32do55dL1S7zw3Dr/3T/9fcK0RaeX8Ma7C65trSBwOO/QEgIdPpV1EEKQZTlVVSGVIm3FCCVBKLKiRkmFrQtsnSFkjMmPiTevYiy0tUYPnuPk6B28qzHFGZG6RGk1CoGXvsnePvx6CLQEJT/kfETzu2oCwMcXspbNOtZ26WxYbpzl+jrfOCMJROUukTJMz45QYZticUx/eIkkDqmsZ9SOSCNFpxWThJpBJ+bCmiMvKqQQRKPn+WD3lGqaY+scb8coWxIqx6de/QSllMwKQ2nUU1mHJFYU1ZQgLsiN4qt/8DZ/4S+8zHy+4HS8z2h9hV/5K7/A/+fv/EMCHbC6mvLd92astAf0WhFpHBBKh9SS6eSUrMioixwdhEilMGWF8xVKSXSUoKVECOh0WpQ+wHvBWRRzc7TBcPUKRyenJEHA8dkZRZWQrnUZrK5xabtLKgXOOZzVTKcS4ec8dynmm6/f4Ms/9QW0HPLmu9/k5eevI0kJwgl33zhFntW44Qnnbz9k7+6EIxly4633yDs9OisrHD68RWof0k0jnn/+Cnfv32I6MxyfHNJvrTDfP+Xmrbtsrq/Sabeeyjo431QyAi1RApJQUtaeqnYkZkJw+k28kgRRm+5oGx23CYTkhVXFuNLY3LA9THn+woC1YZt2pPnWrTNuH2coobjU01yKT/CJoBxcJY4dncEm89MpQkUEcR/R9yzObxLoK3z99W/S73T4+KXnOBtPeHvuqZGPncijfyWghKcrZ1gRMbfR0pk8cRx+6TEeOQ6FwC832yO3s4z/Hv/sl/cXH3quRwHihysLf5I9FWfjvTdCiP8Y+A1AAf+l9/7tP/H+S397cnZCWVWEOsBbRxDFJK0WB4cHpO0uVWVJk5jb5wUnxRw2QrZ1wHkGk4lj5YJvNpQAgcO65uNpZfBC0F+5znx+Bj5FqgDMguPTI7bWQ9qhZG4knXaLG7cecP/2Hc7mOa1eyvq6p6bD1YuaQT/m/t4Zx9UhSQCroxRnS3b33mbU6/Dbf/gGO9s7nE8N3Thg1I2RUnLvQc7aWgjVOa+//R6LYsxw5VMUxW0+9xMbPHgwZ3O0zm/+9u8w2AqZzmp+5/f3+PLn15uo3zeRRidSeP+D5cw/7DoATGYl1nmUhG67QxjEGA9lWaMkhFGbbLJL2t8hcAuyPAdgOFjn5GyGk10WpeU42yCT6nHp8tFuUOJ7L3qlGkcil3fRApQWS0fTlBs8sKxyIiU4B+UypJMCArXcKB48jiS7iZSSuqoY7bxEEGhWO13a7YjCGC4OY6x3zVuSAukhQCDikLLI+dTVIePpBE+XKLrAZJGjpGfQThgO++ysC7KiZpYbfusprIMQgqOjnLfeOqI0OVJ6Do6/xU/+1GWq3x+jVMK7b7yLiHOSjuad28eUWc0v/NTFZbnVsdFL2J1XDFc36fZ6ICSmrimKksVijCk91nlCLUlC2USzeASeylhK48iyDHl+RlVXTZDhanQYEbRi2r0U1VHUtSFUIISn17G8dD2m3474wucusygWlOWCYp4yHFzi5p2bVDNNlY7YExGyDMnjDllcUAYxL33207jeEBUEJFHOrbuHfPyli8wXC9ppyqKomZ0doNcv8cGte7z57m1Wh0P0D1hC+uHPJVhUTRZQe09eeZQrCL0hOvznqCShKmdN9SQIkXj6nOOrmJ3VTbY8rPVTkjggDBRbq23iUNKJx5wtSl5Y19SLKc/1BPfHd1HJFllRYK0jjFNMJTDFGC9Cqirn/iTiv/71f8rPf/FL9KzlUlXxIHwJI4LH7/dxMCegoMWGHqPwTFzCEzfx33cQT8rYT5yQ+NDtTSHvw78/eXzjvP70St7Tymzw3v8a8Gs/2J2bN3p6ekJe5MRxiJAglWoiVmspi5ogtPT6XV78/BcZDAcI5uzvTVlZvwhYqqokTTU6UNhJiVQVqBQQlJXB2Ck6bFHVniSC3DlUJDG2JlSCUbdNr93GFjmjNCCICuJ+yta6Z9APmc0zLl66xnff3qPILD/xpcscH0/odnrUtuaf/e7v89zONj/+2Y/zm7/+NlEYEoeqqSsbR1GVJEGXL3zmZ/jt3/6bfOett9hYb1NLyU9/+XMspo5PvrrKP/nNB8ggYXu9RxA2Byi+yWziQBGE0dNZB2A8zZBCEgWKXjtFK0mRF1S1aRwHNVWZEXuBcA6Tn6CkaPoDSDrrL7MXvExFuoyEmmxGSEEgaDIWGufRJPnNBhE0jsMBWI8UAusFxnsC2VzojcNpDkW7fJwDatc8VghQ1ZSgOiOvJygdEcYpYdxnpW1ZHwboMGHYCTG1ASnwxi17MxbhPdbU7B2fc16lXFlN+fSlIWVt+M3X38HXjqoIWWl3GHRSrP3BaQM/zDo0kaTkS1/6dymKmv/df/p/xQNra13idpvPf+5TTMczru30+M3f2ceKhJVVyXg+pZ2sIpSkHwvGLiaKI8IwwCNQounv7O9KvGt6VNLVdON4eVB4lBIsSoe1jk47pj8a4WdzYi0x0wDrSsIoQimPdzVegMQChrW1mK3VLuOzQ/I85613HvLCC6/wy3/lF8mymt2DMy5c+zh/9yxgMl1wdmePNF0j3GmxttrmchRhreV8NuX8fAo2ZDKZECQjDk/2wNW0Wk2v9OTwmKKoiJQkDn5wnNMPtw7LXp2AQAii/D4bxXepigVTSrL5nNnklOHWy4RxmxVdsJ4mRIHnwkqEVCHe+yZAsgYlJcNuwqeuw8FZRugWnOVzoiBmI/VMzm/TDxLOl7ViHabYZEiMZnZ+m7rKYbjNP/rt3+XK6oDetCBIpjxofZpSJt/TuvFC4qRkvx7RlhmBK7Eq+VBF4NHee1Iqe5SliOX/FN/bDlIfrpc9+o6W3ubx834f+8goCHgP0/mcLFsQhgFxFIFvmvfzxaxp6kcxSSuhLA1x3Kbb6xEnEXEU452jKiua+L8Jc631uHKO902dFW8IFKSxwNQlwte0On02ty4QKEUaSuoyQ+KAJrqfzc6psnOm0zO2ti8gVUxuLUnLcHg85fis5OzkDrbKGLYHvPziOnfunVLknjhcprjeUxYlV3dSXv3YKkdH5+zvnfO1r95hPldkC8W8Kvj6N76FDmN+5S+/ymi0gVcRdWURuObQlgqEpNVuP5U1EMB00nxfSRwhhMJ4yPMS5zw6CFhZv0R/sE6dn4KMyOfHJFFIEoXUxtJJNO0kRIomWpZimT0s/xOPrk543HOxy/xcCIHzAuMEleOxs3K+yY7kMgNqGrViCQoRaClIIkkcSpACkQzIZie0e6voICGkInIZyky5tN5GCbDWUldV0/wVsikzCEHa6nBlZ5tWHKBUiDEeLQNa7XXujj3fuX1MVhmEAC2fziyourb80s9fxNT3+e7rX0MqxxtvPOTwqGC+qLn5cJdvfftNVoYDfukXrnH10iZlKcjyKSyvlVYao31NXZaMx2Pm8zmLxRxnDJ12m6KsEFKglKAVKTwOv8xo9yc589LRjSRSCpSSSK0QUi5BIxqFbTJWwJqaOGxzdFzx9W/fIi8WLDLPtYsjrl7eZHJ+yK//+q9xeFRQWThaLMiRmCjCJAnR5ogqSdhfeE5Ozvj6b/8Ga60ZO+stPvPZz7J/tE+/u8lgeB2CVXTcY2drnYsbq6SzjPn7D77/F/qvbc21JaVgI5ywUX4HUU+ZZAvKYsH09JDB5gsk3VUGoWO7GzGZnfOH73yAXV6zzdkjcd7jvMVjaScRW6MWJ5nlj969y2Q+wdSGVii4lBRc7WuECvEyQKgQGaR0tz+NU13Oj++TO8WNkxmVqEmy21w8/126dkxIzXDxHUbZG2jsEnSkuHJhDa+jxjHI5X788B760N6U4nv/bXqpT26T4klgJx/9bbl3EN/fnTy1zOaHMb9Mbaq6YjwZszJaIY1j5rZGaY2xNbPZjKjVIQwChLTUdUna0RhXM5tnqEA1X4j3hGFAEMZICZ+43uGNOxlWBcxnc7K8REpFEGqGwxXipMOF7S2q6QnPX+phpGI+9eS1wXqIIthc11y99gLz+YIPbr+P84bzseGd7B7bW30WmebgdIqKJTdv3uXwWBLp9uOk1TnLrJoxu73gc5//GPNpwfZ2l7KEv//3v05R5ZycnPOJV9f5va/dpKZLu9/n6kqLJGyyO5xDqqZBaWrzVNbBOsd0OkVKRaeVorRCCoWtDQgINNRWsljMcLYgaa+BndLvpQilMdZS5qcM2wXjKvxQbbdx/m7pWPzytg8HStbxuBTmeNSDefRIgfWghUBKjxcC53zjIJaOSktJpCWSPmLiaHVXqYoFWgmGQYU1Je/e2ufq1YsgwHmH9w2qznsBy5+d9/Rbis9e6VHWniRJ8d5xfa1FvxU0aEArEEJjeTrrIKXnH/zaXX75L67w8svXeOO9u7z++i537pwjhOX4aMwv/vwL7D8856uvn7C6ucWFixGDfoN4kkLghceWcyqR0u60CaOELC/YPz3BmBK/dLaRjlHSN9EejkDBvLBU0rPRDggCtSyDNvcxxjY9MtcUv6UQaOFopS3q4oSFK0AEvP3uB1y9ep3T47tIGVIZzcvPBxRVyXC4QlYazsfHCAn9VsiiNJxmhq4v2d07YPrcNusDRVVDLCsGgxUODg64dRzx6lpCr93i45/5FMd5iU6f3gBIISD2C3j4L1gZBbxzssA6mJwf09u4TnewCkGLUUtwOn7Iu3tHXLj8MRazCcFg1BzYUmCNaYIa7/HOYquSlX6XYPgCf3DzDlcGp1zbuoCpLYmSeK8ROMK4RRClVFVO0F7FlQnzyT5R3OHQd+ipktVkwohvsKgCEAtKC/Z0wmL0BZARVWmQUi0rCU9KX48yGc8jQEBz45PsaHk9fuj3Rz2cR0/w4bKaf/zIf7V9JJwNNHVm5zyHR4c8d+05up0288WcKAwpy5JBv48xNUpKrLUoEYB3CBztVpvZYo41poHsag1CUBvH17/zgKjVZzab89777z7Oi6UUvPDcC6yvrQGCQTfl+GRGdxCjBAgkQjhkkHBwekZneA7WUpU5J6czPvXiJu99cIrfm1FWLcaTOZ12j9msYlHMaUftZjGFxBoHlLz+5hG3/g9/l1/4s9cJY82XvvgpRqsx9++/x/17Z3hVU1aae7unvPBKyv4k47lLo6aEZg14gQ4iOv2ns2zWOfKqQghFmkQIIAgUs0WOFNAdjHCuaV4KZzF1hpQBgpJA9QGBd4aunKBEF0ODQnvUkPTLnFywPBCXf6tF06vxNBe0W+b5SjRlHSWfNCu1lERBk3vOCod3EAeCQAuM8wTVKdpOKaqKsLVKqCVrnYjb9+7jW6uMz88JkiYQcN6jPrRxvHPgPXuHh7x/802kDDg56hBKwcpoxPX1FC1bCCmXn+XpFAacg9t3Tvg//V/+Ef/eL12k3Y/5s3/m41y9tsZkuouznrfevc/6yoCz4wwRnjPsd7m/f07/+g7CNx57Y6XPmBTnHFVdkSQJcRxy++4tlJaNY3ce4xzB8rW1AK2grB15XTM/PaOoamqgynOqumY6W5B0NEpKAq3AOaypacVzytpy83ZOGI65fHWLRZZyevKQ3YMTKh/z8osGiqZ4E4UBnVZCEnrmlaF2gvPxhLqsuLd7Thon3Lr1PlevXObk5IS9/QM2R1fAGXCGQSem0E1Q8rRM+Ap18DvMiznjMAERMp8ekvbWsSajyMa0+h3Ozg64/XCP7Z0XWEyPWRQpHeseZwQ8htI3ZSsdKHbvHoBZsLp+hTvn5xy8c4tXL64RBjGPQzKpCLWkqjKq8bsE7W109yrlbBdnz3DpAGUc9ekhnVDx+Y9/jPvlkOzdN3BHX6Va/0mOpg4pnjgbeOJsHv0jEI+dy+M+zvKHR8GhfPz3RxWKJ/f54z//q+yj4Ww8j7Hs+/v7CCHopin365ooCplOJxyfnLC2OUAohXUFi2xBmGiUlkynM6QS1HUN0qOEREqwxlCUhqQj0LqpQD4pzXiKoiAMFVEUcjqZc+vuHp/9ZAfwKO+RwpMXnuFgwK07H3Dt0jWSOKYqPIu85ORshvWGMBa8c2+XlUHJi1eu8kfffo3nt1cgbcpx1jr29ktqU2K14Dd/+xZba31ef/s75KWhKg29JODNNw85O5vx8os9CleSzwWDVq9538uDsLYhWv3AKKgfyqx1eCER3tFJE4QUGOcYzxYIIZraf6351Gd+it29h+zff5vO6BLZ4pxF3KM2hjQNUPUZabDF3ASPOSrfe3E3Pyj5pGfjHvFZgDiUtGIBXhBpgVaCSEsq6ymq5mhpB4ok8ExyS6QFUSAxtUHMbyCEx9QVndYA7WpMVXOclax0A05nJetRGyQYY1EanG1an48QOl4objw8w9UZAYayrnBAnHb4hZ/+CjujHs65P3Vz/eubJI4kMlK89tYZtvS88vIq33n7jA/uHjHqdVEOJpNjotCxOnCczuZ4GT3OQmxdIq3FY3AIrLPUVUmapvSHI+ZnBwRxQFlW5JUl1o0DkDgiDVpFOARhHKJaLXxZkRlDMakxtcT4JuOJogiB42x8ygvPdZkcHnFhOyFNu/yjX/sqX/npz7K1sYJOJPNJhTABebZgOssw1jTlOClxSKxzZIuMrY2ERZbzYLfm6PR9SmPYWrvAH752i+devUy2WHA+mdGOBFpLrHg6+wE86enXoDgiz2a8eXgXU1vagy2uXP8EoZgzLprAdlxY1rZfoJ8mlO0hw+EKj47xQCuccY2j8U0tKwhifNAnF4afvNjndNjlvYcp376/x8efGyDxmGV27+uaOGnjO9sUiyNQMfHwOsX4PnZ6yH4eIrVmHvf4xttv84Uv/FnC4DN8++Y9auF5cbvDtx9k1O5RpeDDgIAP2YdAASx7rU3W88cyGvHh/sv3ItW+n300nA0NYVEqyf7+PsaYJSHMkaQpWgqsrSnLmlYrRkpFFEYo3TTfAx1ifEFtG3JZFGm8dyit6Q9HICAMA6SUWO8eE/YEgG36OEoq+sMh40VJIjyFqTHWMZ5lfOPbhwgFVWUwdQZhwo19wby0nNw6ZjQKabe6vPnOLkdnE5JeD+ke1TA9zjkubq1wcH5KVcHqoMUkm3HyYEE7jfkP/9ovsbd7h//2n3yHVjfhjbcL+h3Pv/elL9Fupfhl41orjUFhbfVU1qAoymXjWBKGIcY4KluTFQVIiQ5T4pbGmYosr2GJya/rjPF0jPeOIAww5YxeUrGwDURbiifBxIcLHk2/Xzy+8VEzthspwiV7TqnmYi5r38BOTYNI87457ONAUhqPzzJ2sj9gsnjAfDEliLsESZsoTnhwdJfBaAutY5xuN+viHcZ5Qi++Z5c45+m0e6zv/Dilg7osiKmpqwp8hRExSmmsNTwFWUEAQq3odfscnZ0SxpJLWwnv3NzHekc7jfnl/8HPsfvwLv+v//fXSPshr31rQrcd8RNf+tSTbphzRApiHeK8YHVjnen5ObPFnEA3778qGyeaV4Z+oh/X3SMtORnPSTodvLUIFWC9w+Fx1hEo1UTISpK0O3jvqSrDzfsFzoa88c4ZP/dzFxiWI15/4yHffPMW5/OaFy+9SBSnRGVMUJZ4Z5qMnRCnNEGgmOQFmQs5Ox3jveTzn3+FB3unHBzPCFptButXOTw45v7BObYaM+wnXNu58lTWQbsMc/ou1hkW0zGDjReQUiF1yGh1k5evX+L3v/kd+hEMtq5zdnLEzvomXjq0FvhlBu+sxXnXXPDe45zFeVjthKy2IxId8PJWi6OThwzWn2N9dcilesa9s4LaSRC66ZfufJb59Ixscpder4X3l7DFGVEkyRdT6ukJD9yQ3nuv8ZUv/wLTwnOjUHysu4/uT/nGeIva6yd54IciwMcIM54ABOSH0WriiRN6RD348BMJml7Q9/0+fySr8iMwa5uexPHJEUVZkKYxxhrCqEFe1XWJkhLvS7yvOT49JmoNCLRnMh3T7QvyrMIYg3MO7xxCyO+pSyJlA2lyDiklQRAQKMWSQ0gcaiZZTZQsMyHrKSrDrYdT4qgkrytu3TtlZXiN6xdeJs/OGE/mPDjMeO/OCQ9uTZnkju1Bh6gfIKRCSIVzNbGOePGVazzYv0cYK9797ow/+4svUleG//vf+ofs7LSRkef4PMdVmssbl9FaAx5rDM46nBQYJymyxVNZgyLP8dbS6rRoxSGBDqkWOXVtCaKIMOlw6cIKpsqp6w+I2uuU2SlR0iXLx3hXYcsKbxP67SkHot2UxD5E/BJ/7ID2CKTwT+q9Aoras6g8cSBYSVXDIjceKT2B8lTWYxyYZV1OCUGY75H6GedCUBYF7dEa2IpFIZlmriHqrmzQjpvv1OOpqxoRRgjf9HCc83jnCbUgjRWm0gjR9AKDyGNtTlHWKCVxTjQHyFMwAVzb2mC03ePoeA+pAu7dyfj8T+zw0gsb/I2/+d8QxY7tnTZ3ds9xJqTfWiEKFN47nLVYYxEBzGdTHIL8Tkmn3SGNYo7OToAG5SkDTVZWQPQYpRQqSV1bEJKqKgCJrWpsXdPA0T3lknErRaOSAXC8f8aV53ucH1i++/YtpvOKWCmCSJNXgunY0GvVjKeW2lgQYH1T3JE6QEjJfDLl/r1zLl+JOTw55/1bd8gXBdNpyebW8wRBTJkXhHHC3Qf7rAxSOskPjs78YcyWc5yzLKan9NauoOOUMIixCFpRwN6dD7C14blLfR7sH9LprDLqRuwe72LMGoGSj8nKTwKT5tqbzxecHD/gxc1VVkcDsiyjEAPOp3Ne2lnhs9eGtOIZb+4twEGdzeimOVXUQq88T5QEyIXH2w461ggbUs8ekk33uL/rOdr/gJ+4OmRw6w1Sv8rV1oLF7D3ecq9gvXx8oX24d/PoRiFYKh+ID4EBmvtI0SisvDBK6Kaa43nNeWmYV+5PDb4+Ms4G37zZ07Mz5vPFUhKFJVJIUtQ5Z5MZAxnT6a0SRm0qq0jaKzjrUVISxS32D0+ZLxbU1iDRSNXUKgOtUUJgl7IZ1hikAB00nj6NQ4SAw4UhryWdUKJkQ+w6m1hWhpr3bx2RG8XFTo92K6UsoN+PODlfkC8KRhsaZzQurwmDqHE2onktLytwU6anC3ZdjheOt9/Y5xOfWMM7iMIek7MJtVV0hzGb692mf2EdztQA1NYymy+YjsdPZQmctYTaMer1CMMI5yHLMjyeIIwItOTBre+wfflVpArRYcr06IAwXUG4BUkSoKVBRSnKnhKpDUrblDi8eNJMbFrRTyDPTYfskeOByvrHSDMlmzKasRAGAoRrvhfjkXZZ/5aeF3oTDu6cU5UVOm5hqjGCLugBzz//MtpUXBgkzBcntKJB0ysy9jEvxT9yHEIQaUWvHTM9KZFS4GxTuhNeUJTNbY+IpE/DmgixIglyJqc5WtakHcV775xyaavH5QsjTk7nJHGKMVPCWNLtafKyIEySx1WCsso5O5qjog7tnmT3wT3iOKasqqZGTyOfkhdNhiGkgkfEW+84Oj0jaVmSXkieFxR50RyeSlBVBmsNi9m04YWEAcWi4OzQ0mppFlmJFAoRCA6OFmQzy+bIYGtDmZWMx+ekLQ2+KRGHWhOFgtl0TraomE0FcSw5OZ2TpjG7B1OcdhhnqMszVkeW7bUr9DsDoujp9M48MD47YLhxjbjVJ+kM8F40RNbz+8xEQhwqWrFCRSmDVspb73+X/eM9djZ+FudBKQWuacs7HG4pgVRa+K2vfYN+p8X86kvsbF1hq59y79RxNi+5ttnl+kabd/YzjPDEYcDljuFgMePcxDgPOowIgz6jUZf66AxTTKjzgvOF4R/+i3/Bj12/xs0PHhCrlzifjlmczGgFNYveJ3Cy2ZficSAolntyWTZblsucbyR6tG4yncvdmJe3Wrx6pcugF1JVjvcfTrmxl9FLNf/s+3yfHxlnY61FGct0OuWDW7fo9nq8dPUqJ+fHmEtrSCVx5pjTQ8dKr8csO2Vy6gnjEd7npOkGUnhu333I8fkxu6e7rPc2CIngj3+BS/TbfLGgyDOSJCIMFRdXV3j43Tscl5J22KH2UBvD2XyBJ0TYFjJQ+By00IzHjqPjCUEcs3lhwMlRjik9a/0efinB4vGY2nI+N9zbmxPFCYtMkSaOy1cH/M7v3kFH8M3X7+CRmNIhEkWURGitsaZGLCPIwjgMEeIHVxD4oSwIQwadmlY7oTIGj+BsMkcKQRjFWGP45re+zdXDO8SD5yknd/DOYcoFSmtGKz02Vvo8OFwgygntqKZ0ig+jVh7j+v0T7Mqjvs0jh2SBUIjHjG0hBcZDbZrswz3i28jmcUF9xuH+DYIwZXF0TG/tOl/43Gc4nVZIWzCILdNMUZuMb373Nb7yxS+jdYCpa6RU1MY0Tsc7vG0c0DCoSYaWJEm4d3gGaKbOIp0jL8oPIxl+5CaEIG1FvHfjhDgNWSziBhH33Ij9wxn7B2NOxwVlcY6tJdmipqwNIgjxzuKsBW9ptVIGA8XCatApRhbM5mOMFzgUOmpK1UVlMMaig6ZPlmrP1iBmPCsQpqKYHDLJLEp4ZBRT5BVGQlkbdFEAnkAHOKeoaoUoPaIqWRm2KPKas6MF7d6I04kj4T4yy6iyCnzKXMT4/oCVXkyUCqqyJAgCUIrp1FDVJdbkZLljZuZ87bu/hfVz+pcjkjhgRTpaNnsq62BNTdxaw1pHkPYbnTLn2UwqsumE4zol7XTQUrDRb/HWe29y4/3v8MLV55pr27tl1s5jrUZnHdZ5skqSrH2ayfgO//K1P2Bz7Raf++Tn6KQD4riBa2i1zCZoysnTxYKNOKRVzzj3KVMgiFPitEUQ1+hkBDJkMd3D+QFff+8GXSX52jff5PLFbV65dpnxW++hbM5i9QtYob+nhPzh8ppbBoByqeahpORCJ+LnX13hyk6bJNINJL4tGPYTPvV8Uyr8fgOCPjLORspGycfUFffuvMvW5gZFUZDP501DSic469na3uLqlav8yz/6Kp1ewqd+7NN86zvfIm33m4hOPGxSe1NjbYXQCpYlD7mM3FSgcMZSlCXj8ZQiz8mKgvbWCmr5NUshGliQ93gf8GMvXqPTCvDOU5YV77z3TZT2oFooNHv3KxId0Gv16LXbtFspSj1pqMVRwmDU4/RsTJllrG0kfOObd6gqi6g1Kxt90kHK/femfOpjLzJIEnDNAZC02njviYznpRCudNv8/lNYgzCOEUIzndzjYy9dI9QBQisOTyekaZuyzLHBgDu3b3H9pSHIBOcFZXZEa3iNJJS0Oz3Ke0fISNFN55zLJ8zlQDZ1NCGaTMU94tLQ/O9Rqq6koB1JAi2Jogb2XBuPXWqlOZZ7xDeOScxuMV3MmZ4doKMeaXvIynCDyeQuUahopQGFNXzz219jcn6CtQalFNYJrFsihFxTHmrch6AdB4T1Ajuf8lxPMZ2fM0wcQV7w5lunbK6uMhh2n8IqsITwJ6yMVplXmr3dGXESUPiK9984ahxDGLB2YYgINQd3cjZWV+kECm8NXnhkEGGcY6ddY5xj73SP89McgcfYhoyZFwapnvQytW+4Non2yFQwm2Tk0xOEDHA2aJ6zyrBVSZIkQAdjLWEUI2XJ1s414nbN0e4dgsixV2RY2zjswcoFwBEkjmG7Q2vkSWPFbCGQsqKjjinOTvjxV3ucXgyXPY8Bs6nluZc/wa29Yz7Yu8HXvv0twjCiXDi6nZA/8/IGSevpBF8IhXU1xuQEgcaj6IeGyOXc2LvHVA15adRrOGXecO/gjNwGDFe2kUu0o9Yh3vmmTOubEpoQgrwyhHEfufoxqvY2907e5+xf/hZ/7mf+DK04BGTTDvCNiOl0PiHwxyQrK8RSsylz6jhh7gV1bXCATnoErQFV3Kac3ccZjY1bdAPL0dERW9vbbFz9LEenp8uqwZM2w6MqQiPR88cQoEqynmq+9Fyf5y53ieOgkZhaBvCBVgSBwrrvX1b+iDibJnrttwKc8axvXeTHP/+TvP7Wm3RX4L0b7+CdIEpirHNEUUP6bIhIHq0URZ4RBiHW2CZ6Xio/P2pMO+cYDobYjiGMIzyaVtKiE0lMucDUhrsPjwhVo/WENSgheeW5y3zm1ed47c33SCJLkmq6qSUUln6nT9rqsZgXJKHk8nqPQGuG7Zjz2QydaZIooJUEIIMGZdevmZxXTM8tKu7TijTWGayP2L15wtrqFitxjC1LnHaMZxW7pw+bkpOQCKUos6cTyUmp8DImClNOjx/SarXZe/gunbYmSRPyckE2P8NnBkSjSBtEHVw9w9uKqHURKQWxBlOXtOwpWqxil+WxViQbUm0omFWeeeEa3s2jBGHpdbQCrZvgo3Zg7FIcUC57Pr4BlAgB2tWI+T3ybEHa3SburGKs5eTwYbOZXEWvlTKdHXHr4V2iqI11TdnF+WUv7xGWw/FY6Xl91Obe5LThqzhHoDSBBqkldWUYT6e0u0+HXKukZG3QIWmn3DiYwwXYu19wtFujw7QBspyeU9Yhi6NzVtc36IUBZZGDVCwqw+5ZhpCKvCio6orKSTwagcTWBVIGOO8a5yM0IJDO0E0TskJyOC3IfYiIQ6TQUNYIb1gZdMirNhKHliXtuObTryYcnAluPyxYG7TYWX2RB7sPCYIeaW8EQjOeG7pdzfpahHWCOJKkkcI5h/WWoiooS8PGaputzTaVcdSVhS3P6ekuOojxppHbXhQZgYFuN8CWFXMXP5V1kEoTpV0Ga5eW5XxPGjge7j5gKlq0e2t0kxAvYHN1lc1Ln0W1z0m6m0/AL0uAkHOPNOQM3kvK2i3XWhO3V9FhD9yMTq9P4MplqfmRQrRF6pSJXeO9gyOurPYIdYJ8lFk7iwA6vS5lUVAUR6jWJnV+jpke4zsrVGrB7u4eP/bqT/JOmJI5jZASLQXdWC8loxrleS0EuXNUttkLbS35xHabFy91Gt6VFI+wT81eFE3pV/0pGgEfEWfTcC4mmQE8+/v7zYHvPVIJWq2UPCuRWMoixzmHlIKqqiiKEoTi9HzC2miFonR4J5FCUVaWQANS4pxide3iY7htXVuiIKAbaSYnh6x023gLr1zawPomCk/ShPXNDSbzMaY2nBeGvSNPIB1Kg9aKditgbadPvx1QmUa0z2rDcCiYzUvm1aJB1cWWcq8kM5LuMMa7gKTdJ9s7oxIF17Z3+MzF60RBSKSbUQlKSia5YZJ/WGzSk83qp7YSvbXn+fM//2U21zdQSvHwaEY8e48wClkUTblMdrfp9NYx1QJretSupFxMaSUaY2qCqAV1gbTntAJDZqNGV01BN4Zu1GjcSWmonac2nto8IfcK0TDbg0BibHM1K9k0J533yMeS7yAWB9hi0vA8+imtdoJUIfPjh2SihdYNbFpLTW/rM9RWUvmQZMl8NtYtZW8aombDH3A4Z0B5kkBTVBVRpJllGQEhRZYjHYzHk6eyBh5L6WaY2nO6P6cQNa1egDGKdDCkOi0wuUXXks8+/yoX1oaEstH1my9yrPV4r3C1JdKKJEwwPuB8URIoy9ZmG601WVmTLXJakSRWMfPM0Eo1/R48F3qEmVG7gLVBhI4kpxPL2kBgnUArTacDsXa4UtLrR3yyFxJIhfURO5stKuPYPao4PMupKsFkGvHGzTnGCkY9Ra+nsXUDyljpBrRDyZ39nM2VgOm0wjoIhEGUJVkdI2VMNh9TLQyBFdStFtOpYbSRPJV1UCpgZf0qUoeEWqIQHB7vc5prOt0R+JpuGiAQdNOAVBkGoaMVAkI1UX8Q4nFLlFJzeDvnmI7H7HQl+wtJVRmk1kQiRjfstAaB+tiXOISZEccRKrnKO8cHbMQLRBpjjaMTCU6VWOoXNvy0fPw+cf86+B6L+T42bvH+w3sMh10+uXmZgxt3SLdfJA41oZLESlI7R/2IF2cFHkdlGnLv8xdatFsBUj6CW4nluAQec278H0f//DH7aDgbsWR00ziXvb09iqJAiUZM0TuHtQZjwPsKawxCauZzw/7xFKlTisWEOEmorefkzJHGlzBOMsnUslG/bIguX1AL+PjFHq9eXEVriUsTQqUQUlAZi/cNKqc4PyUShjgQqEjirCFUgt3TmjCw7B5W1K5JO6/vxKz0AyqrEL5pXEtlUQqubAlmWYevv+0J5DlxO6VYOJRUXNi4TKwj9k8ypGo+b6jAori0GdHe0OSVIY4l3bamLiL+6CnU0aSUdNsdVgYjwkBTVoZZbqmrgqg8ZDYvEHjSVovhygVu33wL6R2jtevsHx5S5jOkSElaHerxAlPmdOMcQ0ygIIoUvRQ22hojJLXxGBTTzCJoVKGdfzRTqEnj1RICLcRyHohruj5aAXhcdpNFNUeHKSpMEUGbrizRruT23dtcuvYqHnjp6kUeTiNm43PyoqDbamGXjPhgyWMScolYtE2P7MbDXcbzGm8LbDUmCkMG/RHtqMWsnJMW6Y9+EQDjHDK0rHXgi5/e4TdfO8ezwFYzgiAmNwVJlDBIe2Sl5Y0PDjFeEMgmaOv3FDujiNoBCvrdgEQrzuYBg45gVnjyErbjRgo/DCTeGwLhOJgdoTKQQrG1NSIrLUpL0kSADlgsLEVlySpHr1BgQXmBV7B7UHBwbhh1NQ7PKFE449nsSU4mhqKoWetLysoxnTkWpWU2s4SuIF9JuLoR8fxWQGUswjk2ByH7hxmRFrw4jEgYcPvWAhVHYDwf21jlYztbxMHTQaMpJbjYVewXnosrKWudmA92HcNBDrLFwhh6aYjAcXp6ykDOsGkbofRSDcM3hGzncUsUmveNkoYXMRvhlL4W3DuvOatC0lSihcPLRw9tZLZsEGLVAALNK5st7oYwzRsdtunM0g4FiZYUlUVpzca1n2Zy+DZRa8g8N+Al+eIhzkX8y+++ydbd25SnFbFfEF55lWT2kFarR3f1IrfPauZV8x4DKemngl6qSWP1WHLqsbSNlI8lixAg/xSB4I+Gs3ns8Q1SKA6PDsnLHB0o5llBIyMCsxy09uwfT9BBi0AXTM4P8U7yztu3+KM/fKuJhNGIJezQL9EujxphHlDS84mdHl98YUSsm15BgytvlHDVUroD59DC46zlZz9+nf3pmNfe3ac0hvWB4vi8JgkVL6wHvH2v4t27C6zxRKGkk0r6HUUceDotSZxppFRcWI14sN/ludU+3tS0NxOOFoq05Xl/d0E7kWytxCgtGXWg026gwDJp9JUW1tJLnw6JTUpBp50SRY0UfV4uGo2ncMDi/AHejXC2ptsfEscJxgq2hitEUYf7+zNa7QFlWXB2dI8oEAgV0nLHnNMDZMOZCUIyL3HG0IojCuNRyhE4qGyzQlqK5UyOZe1YNvI0dpnRatX0cahmuMUepipI+yPi9gDnPUkgODw9QqV98I1GVBQqro0URz6k9E8Op+YIsA1k2CxVDbwgiWN0e5vZ4XdBpVi9w8xUVPOQo9NDUBEqWXkq69AAWWq8kpxnhtWu5sFhgBQjIq9ZGaW0kx4zo1lpeW7s52wMA4aDmCCQtNsaB1TWEkvByaxCekE7EuwfW5KWAu/Y2zfcPywZDTRpKMkqz6KwBEhOpzWjvqYdKw7OaoJQ8NyllJaUVMbz/q0pnTRgbRSwyB0rXcXxuODyWkQQCAIFw45AKsn9B2M6QcRBZnhw5NlZazTn7uyXhFpxOp3R6gTsHnpWunAyNmytJpxNSm49mHJ1Z8DnLgz58Yvb2E9/iqKouLd7zMdfvNys4VNi18YKNDVbgz6fvDIiCTVnZ6eEooMLUgQloYLT8ykPH+4hkFRONNf+8n0pJXF1iUcihFpm7w4tLM7XRAg2ggWxX9BrD1EqoKpNgwxVgsujmAfnBYvS0YkDOnHMoJXibc7F1RbdlmG9F2OsYPagxhiDMBWr268ifUnpJnjnkDqiXuxh5xMeeE8aeGa3voo9eZerW11uvDfhY5/9WT554QWOFw5vm3LusKXZHkV00gCtJFp9aBil948lbPyHiPl/kn00nA0NOskZjxOKyXhCXVW0W20ODw/IS0VRK+I4JJQVs8kJvVbI++8d8Y0HZw066bFonHrMWvcf4kH4x2ROwMPBpOS/+9YBFwYhn7k+bDTIXCM0uAxImnJdc9UQI7naH7D2uSFvPzjg5v0DWnGTLT04LIl0I8/e6iqy0nE2tRyelljriEKJkoJOK2Bns8vFCz0urMWAQ3oID3O88/z4K32EFsznBqXgdGI4Om/GI6QtycowZPcg48g9HZ4NSLydc3J6iBCCo7MxL1xepdrZ4L23v0FPLojiNv1eryk/CUG7NWCeFcRpm9FowI0bNzk5PuRzn/sMdx+OaQVH/NyVHrdOFWdmnUlhiFUTaWvj8cYSqKYZGopGjiYOm3p+oMQTapRvypbWe0rnMdajzm5R5TOkTqirBR5PK01QwnAwzemtbz+ue+dlyXxyhLWaybyAlTYIQV2WBHFTHrDOLQEIHiFhfXXI7uyTOOdouhqCyuRYq0AlPBw/HZ7NPDP80ZszNlcCJjPHaJSyvpYynVs+/fIATx9vPHf3m5LyZ1/skrY0p+c13jjuPMg5mxpq79laC+gnAZNZTV1BJ9XM9nKmhWExd0wzy9EZJJFCSsnl7ZAYwagVMikNe8cVSSzoxYqzcUbSC+h1JJcGNZ1Usr6WkJeWb7w7R0nBWldxMjFklWE8heOxYTYr+YmP92lNNLXVbPcTbuxOaUUK4R068qSRZrEwKC+Jg4TpXNIOFZv9NpdGq3gDBM0YsLKsSONm+moUh2j9lKDPzrI2iuiPuoy6ccOxCkKUDDg/vc/6qMd44jg7GaOEIokk13uKWDcglkCA8KaR4sIveX8CU1uEnWFMSV07wkCzHklMNePmzTtsbq6jtSbUghc2UzqJYnc8p6VKet02u5OceR0QKc+1tYReJyINNPeO5ozzmrg+IwHysIcQkiDpIuOYIOlQzPZZzI8wcZtEF3TdlNX+CnlwlXfe+jZBZ5ud1QHDdkAr1cSBIok1UaiXfKFHKixNNaqpNDziZf9b4Gyaw70hkXnrKIqcqqpZW11jsSgZz+5QG4OwGe+895Dx5D1APiEMPspavKcRVnzUdH40dW7ZEF6iJYwVPDzLSAPJtdGwge9awBuEbRSAvW94GIFq2CBaqebLLTM+f22DVy6u8frNA+7unZC0HIvS4CzMs5rKePqJYn07orKeW/sV45lhMncsKsG1zYTbDzKOzyvOpjVhALUR/PwXRkymhsBJlPd85/aMvPZILUkCwaWNmJW25OtvTZ/KOjhbc/niVfr9Ac452u02Vy5uc+/BLg8ermFObrGzc5k01JRliVKCOE6YZhXeW6qqIi8rwvYKQRgjfIG3gp/73HMsfud1DhcrzHNBP3asxRWtYMaBS8FHaCWxSySMkILSeirfwD6t85TGUZuG92Qd4C36+APqIiPurDZAER2hBOydTekMtljtDVG6ucDu3N+jLCuGLUGUljibIDxMJmOm55Y4CgCJ1gq3hDVfWYnZO404GufL6FkgwhYqSHHWMqvsU1kHax3393MeHFaY2hOFiu3NlLVBzIODkvG04v5RQRIJjs9rPv/xHokSxEqSCMF7RxnTwhCGgr19ix15jic1Web4+LWEcmrx1rPeD/jE5ZhWS1EaxzRzdBJBryXIc8e0cFwYKsrK0wklt49KxmfNXKPxSU6wLjg+KXlwWrI9UlzbarFY1NR1jXOe+0cla13NWe2IQ8GXX9xGCInWcHnYYZGXTLOSt25k/NjFLYStMXVT3ZBCorXm+KhgbTgijhN0oAhDRbuXEgaausgo8hm2fjrrMMtLzjLHpZ2AQGsm85xOEvDG229wsHubi1/5BVzdBJlZMee9e6fsbO+wsdHDG4vQHlPVjzocyz50czY9PBlzfn7GpbUevbTFfNGMha7KEm8dXjdltDRSXFpNafc6/OHv/UOmRze4fPllLq4NUTpECUccKmoriCMFuWCeZwyCgNCcU8cJp4UkjFrIOiOfZOjODtXiAGsEq6M+v/Wtd9naukp//QXOc8WmbwLjNFJEoSYIGvVv7z3Guu8hfSKeUBjEn5JhfiScjRSCnV7Eae4IhKejDMf7u6RpysbaiLpa8K3vPuTgYMrpWdaQ/56QYP97wjzeu++57dH89ceOV3ikkGz3Qq6spaSRblBsSuLcEgnlHXIZSTcq9AoctNM2pqjxZcFPvrTNx69f4Ovv3ObuwQEC6CUKKTxhCG/eXvDixZiXL4TcO6qZLDytCKS3DFuKbhxydVNT5I5+V2NqQ21risKRRpJAw5WdmLxyJEpSVIYHY0f7KZXRrKmoFyfsPwyI0xY60Dhj2Ts6pdXtky1W6Is53d4WdVUSh5ok1FRVjVaS44OHLLKM4coqUgjiuE1V5bz1/m1kNEBkTYBwMCm5rvbZDmd0jeK3q+s4FKXx1M4/Fux8JJfxaLCacTwOJILiFFke4b2j1V8nSbogYL0tsfEW+WLKxZUO1maUZcV80kTe79+9x3Bli8Ggy2w65bW336YqywaiG4fgLHGcIKwhiFqkQtEuc7wMcUh6rRgnNGkUAorffgrrEGrB515K+WDPcDI2FLXl4LjAWbi+HtJPJWJN0UsF/cCz1ZccnpXU1qKF5PmLIcYHRKmkE0gCqVgdKVIleHiYc/egoBVJ5kendPWA124YVvoRK23Nt+/PCXQzjTIMJGEg+ey1Fp22QmrH3YOCbhJw6BwnkxI3l5TWU9eWUGcIJ9DCs6ia+UGSgDjQzGeCeCtFqSbLDwJIY08rrbm/O0aJgLTdQSn1eOaRUooXpWJ1pYt1ltOzMUpptrbW8Uhc6OklKcX86WT6Sod4Y2iq8E0jf2XQ5ce/+BXu37tDHCcsyjn7x7u8d/c2nf42PkjAeY5ODvng3l0GnYQXrlxmZTgEuTxuhcCoHufTu5xMxsSy4OqFi8Q6xc4dxvpG1WQ54ClQkp2VPqsXPs0HN7/FWfY6P/FjnyUOmh6zDgJkaYhUEyzNipJpviAN2wzDgDMZNYoQKMJoQF0cEw8uU80OeXB0TlVmFPVNvtDvIk4F25/4GQadiCgKlkfoo7zFP255eP9h1fYnIwm+n30knE0Uxay2AiJhqUipdIf/9p99lSj+dkO6q2vGkzm1cSDk40wFmkhXCB4LVTbzSZpsRjxK+YBOKBi1Na04QNLoT11eSYgjxSwr0EoirQU8tW2iWOdcI3dvPUGgG3KVlAgp6bQSpuMZZVXxi597ji9/6hr/5A/epTYzVAnHZxWvXIq48aCgly7npXjHZFajpeONDwqGbcUks3TTkAvGcTYrubIeMBxAXlt2VjXPXYhx1iN84wBnZU3/YpdvfONprEPK5sYmOggwpqaqK+4/eMjrr32V0fZLdPtrnB0uCIQjLzLiMMBL1UgE1TMWRRctDZ1W1KDmigKJ4cbtu+xs7fAz0TH3FinH4zktVaGVIgoTZgUY75ZAkSfvZ0lRejIFUDT9FITAlWPqqiBeZlHrHc3MSD52eUQSKr7xtsWbOUdH9+mlzwGeg9MDTqYZQddRFgVv3vyAwsUsrMY6T14IbFUR1gpbFkiVYfIptZFQ5SgpmAuPFx4dRSjxdMpoZe05PKm4shqSBoK8dhgHUQBH04qzaUUnEty4X7HaC3j7dsZ04VnrS5KO5+5uzotbCXXhCAKFKRzjcc2BrXlwWNFOBK1QUJQWKTzdBNqxJwo8az3B+w8LvPNc34g4Ghe8/oHhMy92MM7hjOf2XkaWW9JQEYqSkJBUK7K5oxUKYgmXt4cNWKGT8nvTGWu9IRK/HFBnH0fIztYkkaKVRnTaCZ12inc1UkqOj09pBYJbdw4QKiAMQlwFd++dYKynqhoVeP2Djur8IS2JIgaDEUGocd5hrGN9dZ1oeAljA2R5wL2H9zmYWJLhddLBGqNuys3bt7izd0jtAo5mc249/AYX1gZcv3SRtdEKUgWIsIUcvgLekRcT3ts7o5eUbA/bCOnx1oFvziO8Y3U0IB49x6X0IiLfp5MmaN2chTqIQDgC3fB9onSFg2pGq5rQbQkEjahqoAJavR30cAukYO4lWhoqc0S2OOfdG29iq7eJ/Yw//8t/qeEIec+jlveyAwE0aiOPBTgReCmeqL78CfaRcDZhHOP61xiXc5wIQEjOpzliVvKI1/qIbtcoCHueuJEnJTPnl9MaPHjfZDPCw3o35DOXOzy33UVJSZqGT9AeqmGQC9moBjcNaAUeVBBQ1DXO1g2RTgrqumoITNYRhTFpknKwe4ZxNX/5Sy9wOKv4J7/zFsoXZLnjhZ2Q125kXFiPuLwZoJRiPK/Ji5qDyiClJO3Bu3fnJHHAH7yZsznSPDwqub4Z89aNGf1uAKZh1J8vKm5ls6eyDmmasnPxGs7ZJXoPHhwusF4zPX1If+0CaWeV6dk9ajFi1E6Iw6CJapMO8/mUeVazupHglwi9QbfL8ekZF1oFn90KWDWGYr1HMS24UxYkvW0iabFO4/wTItkjstmji/lxFCWaeb4MnserhKC4TxpZeqpkazRgfdihrkt67Yhvv/FHpFHT2DSm4NaDh6Qr14iTFjfv3OFsmjPP51T5GC8TnLPYsliS3CRaKEIhib2mJSSR1BBEZEDhFWVdPJ11iAR5XvPO2OIlVLXH2ma0gnWOvaPi8RCrYaq4e1AQaMHDY8uooyhqy7yqmS4cp5OKyjhu7xaNqoWUbA5DQi04yizv784Z9jucT2u8NZxNa7bXAurKsXdekuimlzOdWeoSiqykzkqKRYGPNCtpQK8Ts9LvNPN/4pA0Dum1W0RhgNKaYe+InY01EE2JMA4DorDZh1EScuXSGnhHmeXsPjinKE2jgVY7tAoJAkFtHUVRo7XE0ETXYdDwdIx5Ok5fK8FKLyYMAoxpJI36vQ5n50cUszNaiWS0tsWdkzuMhptcHIQ8vP8Bp9OMGsVs/AARpITxkLvHFbvHbzBoJVy7uMOFXpfD8wDjBKoVYwVMZru02n2acYnN7CgtG6CSKTPwnjBKiHxCKw4wziG0XuovNshW4xVaOK5ubfLwNGXqHKESlKbZSR1tKRxYL4haPZRy6MpTzQqOp3OSQPO1b3yVosj4y7/6PyTtdJ70aZZKLI2KxxNB46aX86c7/I+EsxFYrI5xskYqzaMJcX7ZzRdCLCWC+VC5TD6GM/tHTmbJ08A1JFG8Y9QK+MSFFlc32kSBIlAS5UEqSWEqKlODgEAFWGcRQlFXBu89SSKRHpIwBCGoavNkVLVn2fCTtJME70NOD8cIb/lf/dUv8e7dU379979DVRkubYbUtaMXSiIvuHla0E4DdlZj1voBJ+cl3ns6iaPf1igheelSzKgrGc8c0joW1vKddxbklaHMn84hl+dz/tmv/QMQkKRtkjjhxoMz2sNLzI7fJ0r7tLt9TosZrh7T7VxHKEFRVSSpwNmSVqtNO9LUtUEr6PZ6GDvm5PiYamXE1uYF4s4lirJmNt7Dz+7xl0bHPCyHfDCJMU6SixYuXmNRP2H0f1hLo3FIEgZXEIViKD5gNj1hdbVDVWR471ntx/zUz/3F5eTRnPuHx3RG1+mN1kncgg92D8hLy3y8T2/9RVywQplNsXLeAEOMwTtD6C3XEsEXXtzipVevE4WW2ckR3/zmTf7gztFTWYei8nzsSsQ3bpbMMs8r1xNWuyGRjnjt5oww1lxfCwi0pBsLprslg7ag39KEWqKFZO+oZJp7XtiKmcwN3Y5oem3W8/Awo9tqAibpDYH29NKAsvIMWiGXNtukgaAVhWgcZVWxmBco4OpqFyk1Rydjru+scWlrFak0rTSGpbyTsRYvFUiFsZ44Cmm3IjqdBB0qnDfMpnOOT46YzUvq2iNVQLfdwhEgVEBtl3tagLEOYy1SgHEerX0zOVYpQq1/qPHcP4wZU1MWOaEeUVUVZVnx2je/jQz7SB0hhEGHKZubOwzCigf3P2BeWLI8Yz7dJ2oNiNJVFtNDFqYiTobkxnH43fdoJSEtWtRBn0pFiNYaLh5Q6IiqdgTaNde+UDg8hwcndOpjvOjSSRqpmHoJaPH+ka6hRKvmSF8fDsE7rHd0Wwl3T0uc96yE4EzFuQ2ZE9BOA6oaVBhSzw9ZlAtcLDg5ucff/tt/i1/51f+AwWi05P00vTHnGlUDuSS6eudBKsS/DTybsjQcn2TN4e0baYfHiYtf1i6Xn8M/SWiWH7ppTLmmk0Mz87txVsM05LNXunz82hAlmgVZVCVxHFFldilY2MBqS+OJAtVEtcuSTm2bWSbGNjM3qtrggU4SN30DHaC0pPKNYF2302I+y3jzjRsMB23+k7/2s7z5wR6/9907jGdzvn1jRlBnlKqNsZYHRwWDtmT3rObCSsiitFBbZnlFWTjedZYwDLiy2ryXOIYk1tSJ5vDhj34dwjBme/s6izxHSElRVty++QEr2zuErXXOD++wfvFlOv1VJif3kVKSFTVVXdPy0O90GS8sQimyxYJ2bx0hA8p8xr3pCR/bCOmoBXoQ0AlCZmeeIp8R+hlXwzmbm+vURmDsKevPjfhv3gsZ5+4xy/+RCfFkhgYqxhQVDw5P2b54BWMtSZywMtRsXf4Y3377A2S+z5XL13j3/ilbbbh3b4+q8szOHhB114nTPkaEZDOL0hGmqpBSk0aan9lM+J/+T77E8BNfhtY64uANxFu/wY+PYv7Sb9zgH7zxox9JHGrFd2+WbI8CJi3Hvd2Sw8MKkR1xWgqsitk98az0FFXVHMa9VsDBieEoq8krRysSzErHjYcZ60NJkRuKWYUOEy6vtNlYaTPtxYRYXrm0isLRTUOyvOHDeNPMCOp2OgT9ALHW9AM8kJcl38Uz6HWIwgBjHXVVE2hFFGgCrUnSmOGwg9KCP7OSIKXg4HCf6TSnqBoZl3a7TZIkBBEo4amMp6gKJA1kOgoVxljwEC4ht9Z7rGmcjwAq73FPydnkRUEYaAItOT+fcHx8zmw2Z/vyCGVLhPck0tH1Yx7eOyKvBbPxAVk+Jeys0R5exsoWKtUUs2Nm00Ny4YmTPsaGFNkRoTqkNxiR9tY4LTRF7amNW46wEECAEE0f2M1PUdUBJgqZ9TYJggjvHcY0kOf1bsC8jJgVhkD6Bu5cF2wPEzpJwNE0JzELsrJgLYAajfeeMIox2QFhpLBuRJYdc/fwkGrvAPP3/g5/9Vf/Gv3+gKa10JRAAbxYsoc8yEfSHt/HPhLOxhi/5Mc0zf3HeO1lfd7bhnDnlxO2/OPCfvPh4ZG2WnNhIhWdAF7ejLi4EmHqktJa0jRGOom3TRqolMI4R13XTZbkFMJ7KmPRSlEtcqIwXJbu5HLEAWRFTRA0vaRHrHZEc0ggFa0kpVjUvPn6e+xcXON//z//JW4/3OUf/vof8fob56SDlDgFWzuOTiu8M2yvxLxzr8YYcLUlCT2Vk1hn2T8t2RxJhLFo6ZlOy6eyDgIwHj7xiU/gPbz5/i2msynmwV02L16nWJwxPdtnuLpFHvc4Or7PxtoVnHNsbm3TabfYf+sdJuM2WZ6zvrndaM3pkNPplP3jDpPsNsdT6A1W2Ts4pTgd023HhLHkwoU1omSFLJ9RHX+LL13/d/j1dzLMMkUX4omjeeR8hI44nc1IuuuURqDDGB1oyskcuzhlMTlDactoOOBKLRgf3sNUjsXJQ3TYIUlXwBl0qEg7Q6p8jvQgjOElDX/9J0YM1gK8zaAaI/IJ5t27mHFOvX/+VNZhddjhP/73f47dk3O+8/4DblfnSO3JZw7hBN2uXvbJmoFvaQSdSHGvqkkCxdagRRRqet2ElXbC5jBB4bB1RZYX1LWlk0R8c3JOqDUtFRHogEBqBh2F6jfjN4RsYK1KPpL38VTG8AidqWXDqleBJk1jur02caIJgmZA2r17d9k7nOCdIE1T0iRBBW2iRzOKqhrrmn6ota7pyXqPwaOXgqvWNrBo50ApCbWlKGtqaymKiiSJqeqno6gRxS2iMERLxXSak80ztHBE7hwtBIvJggcf3CKbZARZQXW6i/OCtL9D1B4SRimFlU3wolJcGOFtRT2foPwJnaCDUi0WZxOy2TlJu4dsrSAYNHpromkfGGcJpaHbCTDjGlNX3Lmzy/bWJu1ujDHNbKl2pHh+PWVhPd954w9Y37jIoD1CIumnIZ1IcHs/Y3dywEqrAhWxMRpw92DK9oXn+MlPv8Sv/d43KOcdjDMUiz3eePO7TGczfvVX/irb2xew1uJcA+N+pPjx6NqQf8rk2o+Es/H4ZZbiedSdkVI22mbLuTTO+Ea7yz9CRDwBAyyf5HFq19KelzdTrq+nhBqkkFTWsViUhGGjKOtqi7OOMFCNAJ1dqrMi8N5inaPbThqGudYEWmGdpKxr8rzCGEm8RGJJKYijAGMsQkoiFRMFmjhpsb835sHDP+KF53b4yU++zM3bJ3zp088RB5oLmwOCIKCuDZGuuXahIl803By8Z2WU4pwC0ZT/pLd4W1MUOf/bv7H/I18HKZupgqen+5yfnzOb51y89iK333uDXvcB3ZUrzI5vUrSHdHojzo7vsn+838yhDzsUVYWWntl0QllXpHFMUeTNIDYveHt3xlq3Rh99B62aMo5ydVOelDm6e8TWxRW8h5s33ufVL3+MNOwwr2GpY/NYvVsJQawloQhYXb/AKFEkSYIxhgpHnuf8zm//DoMLr4CpaAc1YnZENV0gTg5IvUK21pYjICxClg3b25QIKWiFEV8p9+mdKNx7GvvGbSSaeneP+Z05h28esHec/8jXACDPCu7f/ICdC2v85C//FF4F3Lxzl7/z9/+A8/0Zo9YG7Tjk8vaAdqIZdFuMOoJPP19S5zmzrMLUBmss2AUn+3OEkEip6LRTeu0YISVpek4UBqwMB5RVTWkMztQEaITWYJYoTuOIIr1smTVKxpe2Vrh4cZOtrTUC6ZkvFty5+5A79w+QMqTbbqGDiCTpw5KcWztY5BVB2ChsGGPxUjTXO82BpRtdIpRorkXvzFLdQZEVDeoxiTS+bMpzSRw0oyeegoVaEgRqOYahZDI74/7ePvPcMWgpZvv7fGJrxObL1zBlzr0Hq3z17oJzrfHi0RhlSZx2qYo5Js+JgoRRmPDqRsRqKpEmY/e85P2s4X+5+R3eU1OuXtim2xviRBPgfuOtO9T5lCQAYwRlpZbKKpa6rhpHbBxJKBn21njj1nXuHJ/yudEKLOdFNYAWQX/lIvvnp8iwRuOIlCRp9dhcv8Dq6l1OpWo03HRMMdnjzt07/K3/4v/Bn/vFv8jLL72ClBLViLnTzLyR3xMA/kn2kXA2j+bBSdmUwXCN+qxAIFQAH5KZ8baJrJomtnw8Cc+LpnzWiSUvrCdc32ixtdpjUTQN0ibdk4RBgLNNP8E2uvIoKZHCobSiLA1CCAKtl3BBMMbhEGRljbX2MRAwq10zSwdPmZVo2aDOatcINlokrXYPay3v3TzgOzfuooQnMjMiqZkcFRSVISsMi7wi0oJASqwDpTQmzwl1c7FZ68grS103sutPayUODo55+aUvYpzit3/379BeeZ7RqMt4/y2itEvS22Zycp/VC88RJX0e3HufOx/sk+qcqy+9zIsvfYrbd95HqGa0A0JinEIlaxyX8PDhAuFqerGil0YNS1t6hK+YvfNd3n3/Jt3egKPjMeXpPTY6H+PeRDZDDlnKnS8djRCwEoZcbrUo8hLqjKKISDoJ5+djyrIkdBkCODs8QExn/Oz1LVa+8CJHBzN+9/0zTr1EhxEyjsnyGcjmgBukEb2TjN0/2mXNBATP7eBbIflwwKwS7N2e8TB7OmRCpRQboxEH+2Pu3z9Ch4rLO+t84oVLTOfv8x/8/AvYqqCoak7OZhzunnFrYdBa0YoCkiii22rTSsJlYNaUla1z1MZS2yWZONBkeUlR1hjbBF9KKZIwINSque69awiGgabVTukP+wTaUpYZ4/GcOzdvcD5eMM8sUkdsrG0TBgq5hPmWdeMstJLMs4KqtngcWmnSNCCv7OMyjMIRKElRW6z3LPKCMFCUtUCKuiHVOoekmViaZyVaQlk+nf2gVZPBlVXNvYf3eXA8w8cjrCtJ9s/5Dz+5ydaPvwSv/gV81Mc8eI3g//hf8U8PK7wOG9ULU1MXM3DNhNNN6/hffnbI5/7azyG3PwW6RfXGr/H7v/Ev+S/+8BbHosvD05z903dYG3Z48eo1up0+uY/YPa8wpmQQCzb6/UaYFtmgZcOAvGrOxl63iwpSkiCi00obsJQHLwMI2jy32kNgiaIW28MWde3ZPR/z+mvfwBYLHIo4jXHOUEkHqs3R4T7/4rd+g52dHXrdLs75x3I1QoBW6ol0zZ/0fT6VVfohrclsDPjlrJNlQV7IxpFY22QM3rvlXIglzE4sZbgBBERacHkYcXk9JU4CzrMc5yGNNFI3qLOj8Zwk1BjjGkY6DbzQGEfswQmol2AAQYPaSAKFWg70CoResto9RVU/7jMJpchMw3B23uPLklBrlAbrJZ1OB49iddDjuSvXyesaLZcjw4TCWktlLdILWnHQbFjvqY3BL6Va7BIFkoSev/3rr//I18E5h45ier0hk/duoKIOs5P3Ga7usD+5xcn919m4/lNUImQxOaXTHzKcj4niFq987CXO5zVHR/dw1tDudOl3Ew6OCwajdcaTgl5Qo0hZVCC957iqySYLpCuIFHQTTy+umY5PsMbywXvvEaxfRsge6rHckEAriZAQSUE3DVnRETdOT/hg9yZb6z9NGIYUWYUxFTfe/RZrgwHV/kP++p/7JFe+8suIzjri7u/R/8//EX/3fkVRlwSJI0oSvK8xlSMIFWUQ4qOQt/dmfGfvLg9IuX0043RRMCsjXPvpCEBKKXEooiQljFOcc9y5f8rR8ZjpNOfbb9xjbdBFaEW71afbDdBSURlDbT2hVnRaMdY6ysqg8CRa4ozDe0sgBUJ6WpFmOlvgbY1wjlApwlBjnSUrTDPfaNhna2uNJJbMp1Nu3brB3fuHOCcQIqTVionCFp1Os1eM9VhX42yTIaZJxHRWolWjFtDoz2mkFJRlEzwhGhl7kCjX7OmyWo4dX+7vIAip66Y/GASSytSEQcj5ZM6fGlL/a1ojpNlA+1fXt7h7aun1R2zrOb8iDNuyQJye4usFQkBUHfMTn9rgd379HgtviKKQeVmBVOAs3TDif7R4yBd2Rsj8CGyBD2KSbMy/+7F1whvH/GeTkEKnVK7FwfmC5OF9ruzAsNvhJL+Eso4sO2T3fMb6VkWSJjjvUDoCn4NvQB+DVOOcp99tM53MGiQiklECiQZkwmY/YqUlsAPN7mnNvdu36aUBPmlTiQAdttnYfp7KSTZGL/Nnv/Jl2u1WU0aTvplw6xo+3ONK0/exj4SzgSe5i1RP2P4eBUIglcJas6zXLyfMyWUeB01JIGh0hC6tp/TbUeNQvMN5KKpmXrxdKgK8d2eXk9NzXrp+mX43XfI7mt5LVhoCtewVIairmoWpCbXGSUkgBdZ6ytpQVA35MgoCitpQlBXtKCTUGu+bRlptLXll6KQRVW1pp0lDFKWBI1aVYdBuJorW1iOUIIpCnIPCWYwTRFLRTQM8nllWMFs8Heiz9xDFMdPFgv3TMVK3sGVFGCQMtj7O+OANFifv011/mfnZHcK4xWD1AoNhzqWrVzl87U2iuEUrcsyynMlkRq/bx00zZBBjdYg1gnZsGLQipLAcz7vIoE2ZTZhmCw7Pc4St0cJRPDzBh6eQ9psS2hKJZpZyQlIIJpVABJIoiokG1x7DQKX03L5/h7W1C5zu7vEfXe1xZVXghYF6iqgX/Ds/cYGvnT3g7aLkQi9gomvuLWoKU5O7ioPNDX4Nxd29BYU5w5h9rK2pXaPNFj0lbTRjHYVxhGEIHirriJVmZ2OVb71zn7WVESuDLnlVN1L1tSOINQKBdZZAN1DdoqobDpkU5FUzzlcFetlUtkgtySrDrGy4UXhPaWpW1lbYubCK1nBwcMLtm+9z9/4hi9wThglatamsoZuGSKEoyrrZL345WXbJmXfeoaTEOA80wVKgFJqa2XjBLKsoluXrQAqiQNFKImrr2dpY4XwyQ2lFv9vC2Iaj1kqjJRrRU5YlzjmC4OnMs/HeE2hFVVUIGbK9NkKV54xuPGCcLRi2ILEKyT/CTkqm52P08Tm9TsykKgiEJwpDTNXwdK5Kx1aWcf76LnElkW8dEmjN4q13qadzrp3M+aULr/DrqstsekaeFdx8eM7e8Rlrgx7P91eYmohjtY6xHieaoXrWWpRsDnrrPPPpOS1zhgpjimzeZLc002YP9u9wYzams3qdKOiSxBHDrkCrMWezOZEKcFIxXG2zV9a00xa5NTz/4iusrK41YrjL3ngDt/5w7+bfhnk2niWWGKwxzW1CLNWdBd6LZQ+nme0ghHzMBRFArASb3YCtUczmMCUOJc47qsqgpEAKhVYCr0Jqa7m3f8Kthwe8+tJVwlDjlrMbyto2NWUt6CQRdW0aXDliORwIauuoymas7qgdEYZBw++RzUarjKOoDeN52aDbBIRBgHCeLC8Z9dtUVfUY7DBoh+RVRWUdSoDwqpmcaB1lXZGXhjQMyOu6aZ46Sxg8HQUB7z1pmnA+mTJblARpn+n4GFWM6Ywu8gtf+Tnwnj98/W3C1iqT011WNi6TxCNCFTAeTxB2wsuvfJyjt97jcH+Xbq+D0IOmPh9GFKTcOprSDkour8Zsr/fICkvU7uBtyGSRMi9qlIppdwbcD7eWjeplZvMhQdXKQWEbpej1UZ/MxtRVhTExZ+MzStElp8Wn7JzNo1PcOwKR/WN85dn/vdf5w2/dpb9zlQtrfbaHAcOWQtg2ZxPIqprf6K9Sx+vsXLxOPpsxPT8hbnUxdcVivIstJ09lHYR4NGhOUDnDPC8Jg4BBt4WQkuPzGSpoylxKKbpJSFZVOOdJAkVdG0rjsM4SLfsjSdSMRa+do7aOWW7QOsADSge0uh1W1gZcvLBOHCrKMufBw0OmmSOOB1y61OJ8PKeqLFoJWt6xyEvquhkFEAZqmXE266OVxDvIi4pAQhgqKiuQy1Jor5uwvd5jMstotRN6nRicJS8s+SIjm08Igwbe7XGYumKl32EyXSzL3Go500hQFtXTWQcgUIpiUaCLOfb0PhjDyiRjEcD7R3OC8Iy0kiTvPORrX73DuVZEX/xxrq62uLq9wjff22NaF3jvuZRqwl6KkwGljhBRSF0WyKTF0dce8sHegi57hJdH6LiLyM4bkIGXPDzOCI5usj7o8nxnxIwWSnjwTdBl6qqRw1n2M21ZUOUZN27MuHBhCx00R3135Qq783usxiFprMmzAu8sGkPUGnFS5whVczFWnGhFO/DEWnD3zn0+/uKVJgBaokMf9U71srfu3Pd3Jx8NZwNLwp5YwpfdUgRT4O0SgbZM05q+TjOBxNtGiv/iIOKlCz2ubvWII8U8L5hlFVGgKCvHeVGQhI3seRxq1oYdzqdzprMcrRTGGozzpHFEqMFYy2SRYYwlTSJaYUBZW/KiIK8s3TQi1BpjLbakebw1WOuJowAlA1pxSFHXhEshyZP5nOki49LmCkrKx8CFRtlYEvgG4VEbA8sZ99Z52nEzDyMIApSQeOko86ejBWWsJQwCzsYTyqqmrgVJf4dytkcrbbO+vsnp2QQI0IGg9AHz6RitJVmek1eG0XCLqvZsblwgz6eEaQdFgRS+kZtRLVQaksuIXFVMixJjPaNun+k8o50GtBJHr90iHezwsExYFqd5wrF59KtYjjiGfjugfZ410ZZWXLx4iYP5A1ZakuHulHv7c64mAaW/w+xwzjvvHnGaldShpR1JlICdtQEb/RaHx8dkpSH3EffnBaYsG2UDFSCjFlHSwZmSWfF0nA0eplmBtYAUVLUjCQAlCbVkNl9weWuECtSy8SsIlaK0NVltqGvDWr8NXnE0ntFOAqra4zFUlSVfznLSYcz/7Fc/waUrF1C+4MY77/HB/JQXXnqBVnfAq59YQ+kIoTTOWsq80Swsi5K8qJnPM87PJ8xmGXnegEPKsqKoG+01KQRSg6trBI30kceT1w2ZuXQG6wN8bsmLDISkKEoG/TZdKZf7M6DIK8Axmc6aKkEnoTZPuB71owD1R70MzmMm55iDYzjc57leSugFX/v2Ld4+OKYyBndhi+51SyuI8NttXtq5gAkc691GKfmVi0O8KTkez7kn4L/q7TA+HDO7/y5h3EbJhA6GTdVlJbQk0xnSN040igKur6ecTwvyhWagIzqVYHL/HqQRpVylDleRImKRFUu2v2Vv9y5h6MkLR1FUZFlBt9vB4+n0RqxfHBCrCXiHUIpWHKKDiCju0FMpBri4klAUFQNdMz6bMClzdnf32Njaavbfsl/TtBQs2kq0+/7n0kfC2XjvsfaJYB1LoqZ7JH6IXDoij7MOTyM1H2nJzjDi+e0uF9dbICzeQTuOCHXDpM6qkm47RHiBpRnINV9UfHD/iM997DpJGOBpWNJ51WD3I61RAqzWGCeYFSUs+yVR0Awn8r5pbNraNvNH5PJzOE+oBdNFjhbgxCNFY0FVVgTK4U1NKRUCRxJqAglVDZOioJ+EdOOm5DabZ3it6LdTnPUYWWPqpuT3NKwsC5SWvP6db1BXGmsKtLCEw4v0Esv9O+/x7q171DUI4Wn1N5if3Sdutbm/u0eeZ6yuXMF7zyzLwVrK2pBNjigrg9AepwJaiaSwAWvDiHJesndesjns8cILLzMrck7HM1I9aYYzCbEc2PSvInaCl82Bu79/SBx1kUo3iMQk5cJKn9nBXZjm3DYV//ifv8tbKqXc3mGmJOLiRV7duUpHzCmqgvOpIFSyAWpoxSgMOC2hLBfURQ6ups6njb5XGKGe0hwVh2e8qEE0QoztSOFxzKuaKNSMpwuEc1gh8EvSYyDBKsVkXjBoRWihMN4x7DYzd+q6kXpS2tNrt/nEK5dZW+lyerDHH/7+73H77iGegCQKOdif42kgyWmrTStt0IShsnS6Ce1Oh8FgwIX/L3V/Gqtblt73Yb+11p73fuczn3vuXHNXd3U32U2ySao5KKRoi5KsSHICETZgQ0BiIIgRBB4QJF+iwIgAJwZiJFFsBXYcWaZETRxEsdnsodhDddfUXdOt6Q7nnnvm84573nutlQ/7dIuRo6JM1Q3I9aGq8N57zqn7Pu/da63n+f//v71NpHJQjkvbVLRNS55XpGlKkXVt1NUqp0gL0rykbWpa3XQww0ZT1y2B77NclbhOF3QrhSErOiii57lkZUVZ1rhO152QWA5OFrxzWNBqzc2tHsFjiqvRZcGT9TF7v/RTsP0MIp/ywetv8t5X3yC3lgJwhyOmZcrFKmWw8xT5rets6gW+r1BCsL3WQ5mSowuHVetyIsds7t6kOr7H8uRD0sUJdWN53Unw+kN+oi6Jw4CLcoVGMEg8rq33eGG9z5PPPUV/6wqzk1O++ztf4R+9dcDDk2N6vQArPTbW1kmSPg8vSu49OkPQcG1zC2wnoLLWopsS18IgifA9RVEURMJnPXFIyxqlPCJfMIoUtzdDHhznPJpdECdjXvydL/PEs7dJen32bj9xKawSl+o0gdN+tAT9j8VmA/wwy6xD1fJDHICge7B3Rs8f4IElvpLs9F2ujHwC11C3FUVlsaFP4HVc9diX+KqLusgbjdEtLs4Pr5tc+jYcpSjrhqyoOzgQltD3UFIwW2Z4StILfCLP6W5bQlBr3T1QhWQQBQSei7EagcJYS+BI6kaTVSVR4CGMptEapGJZVCSh3w0ftaGsGpZZzTD2iVy3a8lZyzAJabXhdJ6ThC5VXaM13SnwMSxr4R/82n/L+s4V9q49zb1DSbU4RBt44lOfosjmnJwcg5C4QZ86PybobZDOTlFykyjpkfQS0sUMIR1GgxGNFcxm51jbzaoaI+i7XWtyGAgcLyRyIQ5d0hYi1yHYmNBmJaVpUALsP0cERPBDAK2UkqY25FnJlZ0+pq47bIBtEbNjhp7Da7rl5XcOKOqa9tpVvDLHDxM2rn+KXs9DlAWeFyCVoG4qhOh60VLCOJI08ZC4v8Z8ekJvsI7je1T5iuV0/7HUQQrJtc0Bddt2ohitKZqa2HUYJiEXixVlXQEKx3No6dRAWVHR91UHURMG1xG40utyrDD0hwOee+YmvZ7LvQ/v8qv/3Vc4Os8ZD0e4fp+NUQ+tLcfnKePRgOmqQJ/nrI36pFlGXtQopdBNy2QcdyGQjuTK9oReEqBch96wz2Q8IbiyjXJc6jK7DLGsKIqGVVrQlDlHh+csFilN02JMi+e6nE4X+L6D19T0k4g0K0BYAt/BUS55nqOUIvJc+s6KpbFESchaz30sdVhXgif9Gru+DZGPaCv2PvkMt/70j7H60reZnS+oNrcokNx44qdBuIz7UC2XeK6PAS4uzlBodiYhy9bn/YXqxgLhhPGtbcamYXp0h3QxRbeSD4Xg6aHH0bQhaw111fKZp3b4yWGN84nnsdGI/vYGV49fZ7yY8X85MMyaFoTldPYhN3a3CcIRpncdq1uO5lPGa+LSDyhQAuJ6SrmwVM6QOPKIwoDtYcgiW9Galn7c4Tc8R+J5EeFwG2NayukFj977kK2rOyTjdeIkRoh/xpxS8k+AGg1Aa9096IX8YYKA/ANxNF30fOezcYRla+BxbS3k+mbCxjjAGHEZU6+5WOWXzHsPYzuzpTWa2nY7jOM5Xc+/aambhqbsZi1SdKm+SgiyoqRsGgJHkQQeWluyulPVGGwHRpIK3+kcxk1rKBtNq0uKuukGu61GWIuSkJYl2hgCV5EELpHXxfKkZYu2gn7SCQuQ0DQtceiibddvT/yuB+9GPkUr6A0fEyGy1Ryf5Ujngqs3PIxRNHJA7Gkm61dYehFSfZ+2KSnTU1bnH7IZDzDCpSwyttZH9IKA2blBmoww2sYTEcpN0GVBtrhAeg5+z2cz8tB1QRzA9ijAaM3hvCY2S65tD1kag7C6w3hfJkJcdtJ+KIMXojMcGgur1ZJvv3bKC8/eRucr1nXBkz/9GaJ+zPeDl/ng7iF10+InfUy8zvrVWwRhRFGt6ElFXuRsrW1g/ZAsNeimQgnFztBn3zRIz8X1A6y1Xd2DkCB4PHUQQN00TLOcwOlafN5lZt+4H3Pn/hGLoib2XQauh0WRlQ1CCvKmxfdcsry+zFITbO2uc/36FuNxn7vvvsNv//Zb3H+4ZGdrnes7A4rGoFyXk4sVgyTEcRwupsvL24RkerEAIWkaQ1XU9PsRRdlSljVKSubTHGMtSRIisHieSxT7hL6LoGVze4Px+jphnDAaD1COy1PPPoXWLVVZs1yuqKqGk8MjqlpzcT4lzQqs7fK+sJa6KrDGULYtnufy1N6AqN/nK6/e5zx9PKZOXbfM3zykP34Rkj5lPmOaGo6t4vO/8uf5xnffRvsxstA4rs9qMUeJCG0sZVUThy2h71EVGUoqYuXgOA5VmVEVC/x4jB/1iPobSGGpvIIw2WR96OI6HeKktYrg4JTq3pQm/CqNG+C2Obxxl0+dnfGFNuYr3hDpevgi4PDkFFeec2OwTknErNhCOiHm0gjvS4Oi4uI8pSwrru5tEhUFjrLcuv0Jbty8xf07r9G2XRiqoyR7a2PatuLRasHB4Snj8Ziv/87v8qM/9ZMk/V6HHPhhB+JfvP7QzUYIsQf818AWndzgb1pr/zMhxBj474DrwH3gL1trZ5df8x8B/w6ggf+Ftfaf/mE/R17KnY1tfxhBYxE/5NEYazt/jISNpNtobu70mfQ91CULxVrI84ay0ox6XjfcbzTClaSXLbI4VES+CxbKqmaVdcGLo36IozpVmMWSRB5tasgKjbEVxljmq848FfqKqulmN46StI0GAWXZBSQKY2l0yzjykVKwykvOF10MuutI6qbpso1a0LYTJWgjWBtIdGUIA4c0LRCOS7/vE/Qi1qKI/9N/8Y+Yzn/Istm4fK8/tjpoY5DKYTjeZpWVZFmK5xiCwKPfi3jn/XextssMi8e38JXAFDO8/h756gjrJijHoawbktEWoBC2xpF0ac2mwWT3mFWC0A84bR3MaMDaaETVtEwGElM6rCqNUgJpFAoJqvPUKAyb8pxRv89+HpA2AoukNYaHp2cIf8DxwSN2TnJ+/i/+Es6zX0SmD7nxiec4E4KD9x5x6AUsHYe6KvE9FyNcXFeSlyW17kyzVd2gW01jC5J+iDo9YJkNuJjOqMuc7337yxTpCmOax1KHH0iB+76HNobTWYbrCNb6MEhCqqbBNg1h0j1EyrZBW01ZFiglWWY5UeCysbXNk0/dxnU1b77+Br/x1j0OzzNcL2Q4GBIGIY6SlFWBrhuSJCItSqwxxFFAUZRETkCLJU1THFfhhx5NVdMb9fBdhywvuwOd72KNwfU8qrIhL0p836EqNfcfTDG8A0JwdWvMxvYaQjkEoc94bcygn+D6Hlf2trrWqJDUVU2e5UwvZmSrjMVszmy2YrHovFCjyZC//Y9f5Pj0gqJqH0sdjIU8a9Dff5vVq/t8+60j0lvXaJ66hZCC9b0x2QJk03Rt5Tgm9gVzXZP0eijp4PkhdZUhpSJwPJJkQNgfd+32MEa3DVWZYZCURlCjEaalqTvbRgV88PYRF/cO+JFZS/iZJ7C6IjvJufPenM2e4creNaYmIV+dsdsbkGcZ2ewY31Fc603wiLGma0kr21JVS6omw6060VMYxahlxSD2SaKAMPRIVwW+57KzPuDg8BjH8blxbZ3jU8U7731AXRZ86R//Fj/+xZ9isrHezZ2djxYu/cvcbFrgf2WtfVUI0QNeEUJ8Cfi3gS9ba/8TIcR/CPyHwH8ghHgW+DeB54Ad4HeFEE9aaz9iemT/mbpMdN6TH2i2fwA8+8EuuzXwub0VsTkMQGhWRUHdmk6K6rmdvFla6qalqhq0NnjGYS0JkEJQ1+2lFBDatpMkWyyOI3Dc7uZktUFrwzAKCb2Wum3JKo3jSUKva+GFnofjdn6POPCpGk0cBmAMgde1/lxHkpVduKcwBokgryCqDVpoHGHIq5bQc2m1JisqtjaGbG9vsL6+wWjSQwpDW5Xcu7/PX/zZp3FsyxvvPeLu/snG5Xv9sdZBG8toPGK2WGI0tCrGCXu0umW5yogGOxSrM0y94vlP/RQnx0fcO3iE4/m8+92XuL45oGka9vbGpKs5VVXTlAuE28NR3fXcCshMy2peU+gcKR2+98E+w94+SeCxtTbpeCf9mMBIkkjR8x0cU/DZ4Jzt9ZbffjThrJBIa3HwubJ3jaZuSU4P+B/dCvHmx3DxAeb4Per9E6qkx+2f/TzF/iHpTFNVFdu7VxF2gXRcPN/v/vxaX96oJVVREoY1I6Up0iPSZc5ycc76lWsEYQ/QfPf3fvNjr4O1ltPFCm06tkkUKnwpSYsK6UjaVlPUNUVdUel/9lkOfRfHddncGPHCp58lDhQf3rnDl3//Nc5nDbf3trm20yOOQrQ2zJY5GoHvuTRVTZEXRHFInhW0rSaOAuq6a52FocfFImVz7OJ4PifTFIxmMIjI84q+H3VKxtkCrTVRHFJULXWriXyfxXJF6HvMFxln0wVWOJ1Jwxj80GNzc0IYB7iew87uJoPJJuM4Ym1rs8tL1C1GW6qqJF0uyKuGmzf3GPmC8/Mlf+7f+z9+7HV4mJb8z/7eK4w+/ym0ddn95DPcuL1DaFoOTh9iDJfcoJhef40mvQAaHNdDCkFVVyzm08tNGKLAI2pdhBIgBUEYY4XFPfcoy1WX0iAa7h0+YBxLEDF12fBeELKYXOM3Hha4p28iVEBYSBIjGNY1a5HDIhMd0l5YNgch69EYz2qm8znHH5zjDUasb2yA47G/UpSFw7aqqeqKsiyxQJYuufv+nc7nZTuJcxSEXOSataQhCgIGsUPsJzw8algtprzy4jf4d3/ll9gYR5w++uicwD90s7HWHgFHl/+9EkK8A+wCfw744uVv+6+ArwL/weXrf8daWwH3hBAfAJ8DvvUv/hmXfAQpu8H75ZXvB9lMQggcARs9j92hxyBQJL695KpofNdhFPnkdUNtWhwpadqGqtaEvofvKppGk9cNbVOSVVXnRq4bHNkN/rOsprY1km7gX5QN/TgkcB3iwKcfykv5cdfiq41hUVQ4laWpdBcD6nQqOWMh8nyatsVVnSmsbDqT1zQtGQ8CfAeWpWFrMmBtMma4NubK3hZJHJAvZ0zPTvnW11/m7fcOyLKaptFoHKxQBCoAKD7uOoBAa83D0znIEOX6xIFGV1Me7O+TZQvqYoUTDLl1ZYunn7xJ2bbYh/tEYcSN21fpjya8//AErbuIESUdmlZgTEtbl0jHZZBE9MKQsg1ACVAuItrktNQc5w3vn+0zDB0+/1zCn//skJs7I3qxh25qzj84IDBn/OJkv/MaaMPJXNCuDfjgvfd4Iq9YvrVgyCvI197mtd9+i3dLy/EnnsHxBKGj8aMQKyRC1zgKXEdRVhVR2xJHCa5yyPP00lXfeUiursV88PAcKR02tm90bKHV9LHUodUaYQxV2ZCEDr3AQ1tLkXeHIykExxcFaSW5seN0EUtS8tTta9x66jbjUcTs/Ix/8Pe/xocPp0xGQzZGbbcxGUN2MWd9MmQ4iDm5WBL5Ln4cMF+sEALCyGc+XzGIfcLA5WyWkeY1k0GC0ZBVBZ7rgFLUVSfxv1hkHBxd4ElwPIc0zUnikMhzWC6WIDsa6PFFt4k6jqIfh7RNC1jeeutDRqMe2gpeffltRqMeg1Gffj9hOIyJewm9/gjfD1DDHmPlsDYs2P9wnyiKHksdBILG9VlEA8ZXbpJFffR6jTx5RF5bWtxOsGQasrP7jPoRTVNjrMALQqqiwlWKxmjyLEc6IUFxyuEipW5qeoP1S1RE18Fp2oZx7KBNxSSRjBIHz/FY6AGvFAG0JaIuUHpG4AaU0mN9ueIZZRgkIfOZRVjNz/3oc/zoXkT89I9hFo9493d/n//m5Qe8v5wTJglbwz4XbkiKRaru9uWoGmk133v5ZbRp2dqe0I+G5HXN3vYeDjmJpzAGzi9OuHVtjVVac3S24vvfv8Ov/Mq/wfde/e6/+NHC/8CZjRDiOvBp4CVg83Ijwlp7JITYuPxtu8C3/8CXHVy+9s9/r78G/DXodP7WWkzbIpVEKXUJRRMo1c1F1mKHq2sBV9cCJoMQz7nEoApBXl3ONJTCC50fKtbcOEBrzSzLEaY7tdZNzQ9ai03T0rY1xnQiglZrjP0DQCDAvYwwX9R5N1NBULU1VkgCJWiahuZymGa0i1ASSefZcR2JNi1KKjbX1/jZ0YC1fsT2xpjNrQ02djYZj4dIaUjnM84fPeA79x7w9nv7LPOWqtJsTsbcvrZNWTYgFUo5vH/3PkD0cdchihOk6yNEl+7r2xPS4wfYKOTtdwqmp0c4Xog0kihMmM8vuP/By4xGfaIoBDPk5OiQOIroJzFlUTAYrbOxVXJ4uqA1mqZMKckYKpfICga9NTwFO31B1jho61G1EWHQtSCvrLkMeg6B71DrOY4+BdniyRZlNW3bYhvF2cE+YjVjdTLlnic5eekuJ9tXeM8JSJ65RdJT7J9d4LoOwmgWi3OmTkOTDFiPuhttU9fMqxrXcbpo+cCnaRoiL0Aqy/XdCXceHLOan3fAqu7W/bHXYdiLSIKAKHBRojM6Z4XuPn++IQ49zpcZ2+s9Yt9hPBnz1DNPsLW9xvnxAb/+D77Mvf1z6tryxLWrCCFYLTMcJQniiFWaw6UiCWNY5SXj4QjHERyfzWmNxXVdposcz3XRdG1MR3ZpzEXZUmY5w2ECCC7mKX4UdVY5KUh8DyeJWKY5riOZjHucnC/QEiajQXewNBpHWayBsmkQApaLFY7T3c6Wi4LFsmCVPcAYTRK5XNmaEIY+t5+5xdrGBk1doRyH/Udnj6cOSciNzz/HWW+EG/QRtgbdgFB4juE40+RpStRL8EULRlPXDXVd05QVYeCDbrFYtO4OoYlryM4uODk74eT4gH5vhG1WhKGPtV26fOh0+YwohbUN/ThCSotxXFq3j5QTxoOCPE2ZxEMcX3Izjjg6VoDh+bhkki4gELBY8Sm/wHEa/k40YdY0FPOHjL2AIB4idEuRpZi2ZTE9w5FtpyDME6R0aeqMGxtrLJYVTdPSi2M8b4+qKuj3DUnsc+f9u/zDX/vHZGeH//zb+f+1/qU3GyFEAvwa8L+01i4/AgH6/+sX/ns5Btbavwn8TQAvjK1ynB/iAbhEjnZ4Z0nPF6z1XPqRJAkdktC5DPLrTJZgL0+hFs8VKOnQIqnaltCR+NKjtZamqYj8kLpukcLSGE1jNK5y8KSDq5yuNSagbgVS/WBQW156XrqgQKUUrnSwjqFRXf6TMAKkpqrAU5bYc2mbLkS0NC1+GPDs9Zu88IknGK2NQVfMzo5557V3+f6dezw6XuK7PlXVsr42Zn0S0DY1pxcrpmknKzVty8bagC+9/C7Aw4+7DusbmxYhMVaQLY7Yf+/3GYYtrqfoj04J+jcwuiIa7DEaT5inKxrj4EnFajmnNxizub3H4RuvX0rDLQ8fHHD48AgRxkRRj3Rl0NLB9TwC38fzupaDNAVuU+BYi4ui746QAqqyZJVm6GJKffYqgQfWiMu4lC6y6PjhI15YT3jm5/8C9//el/lPf/1F5taw8XM7OE9+hqbf52q8RJsaUDR1gRcoIt/iuuAoB8/1LoNIPbK0k/42TYvnemhpsbZiKyo4dnOW2seanLe/+/XHUofdjaEV0tLWEEYebatJAodFWmORfPHzn8B1FLd213jm2Se5enOPMp3z3Re/xpe/8QaBn3BtZ5uL2QpHdVL5IAxYrTKK2qBbzWK2oB97KCmpy4rFfImUDr0opKlrBsOY0FNM5xmO7zPo91jmxaUUXaJ8n2VeY62g1eA2DcO4A6fVdY2Ulo1xj0YbmqZla2PEYpEyn80Jg4Cq1lR1TpKEBF6ANTlJFFLWLWVdE8cRIPDclrIyZHnDg4MzQt/l6eefupyn5ORFyf/h//73H0sdrm6t2eDqOhSdQnTU72H1KRZY1YJlLekNR+jsmKvbPdLCoHVDGHTKxizLKLJlJ3xyFNIawsBH2ZS2bYmSkKzIuoN2WVPnKeUgoR96CBSNNVgDviPxgoSiKlGXTn2DwNvdJu53G1moWjxlaFEcfvUdvHqOfJhSnk/Rdw4p767YeMKj6AWMx0PcVtPkZ5zdW9Dka1RG4gYJ7xzO0XVGfxBi6QKJhTDcu/uQKIlIs5TJYMD6ZI35YsXaWKLkDFOteHT00Xynf6nNRgjh0m00/29r7d+/fPlECLF9eXrYBn7wkw6AvT/w5VeAj97yLiXOXYLApY9GCByp6HuCrYHHre2I7VFE6Du4SmLQZFlNVjY4bpcu0DQaxwkIfclikVPWNa2S9AOPJHQvw/EkrlN2EedNw2KVgXToJyGx5yIdhbGa2HXAdvOjfmguUdEtwhocOr6EtbZToFmBbjS+K+iHLk3bRXYgIYgTvvgjN7h6bQffESznMw7vv8/rr7/Jvf0zWuuQpiVPXtvFdV3OLhb04xAhJK4KiIKSfhwAcHo247/8Ry/ywlN7HJ4v5h93HYIwZG0UcXLwIQf7H7KYLWj7gn4ksabFyD5KuQwkOK5imeZkpQbHoJyAsihYpCnj4ejSnCq5dv0qJ0dHVK2mVR7O4Bk0BXdTw2fXJFVZE/gevf6YZXFO5P0zJ/pqueDv/trf4YUnd/jcU31sk10iKMylDNpwcLLi2vyCP/tnPoP6/BfYiBTffe8h00YzVx7S6+SZrlJEgcdFZpFehG9amvwBP/1jfY4eLmh1Q9XUeK7H2njA2UU372tsy9nFiovS8PB4jsKhNz/m2+9/yNrmJtlq9bHXQcruzx+HLlVtcJzO1BxHEYu8wvEFn3z2Jl/4sRcIk4j999/h937vWyxy2Fjbohd6OK5HnMSkRUPghwjpoBGs9QIi3/2h8Vk5DuNhj8UqZzwOiOKA5WrJ+WzFeNRna3PE6fkU6YbEoUeaFwgDu9tr5GXNxWzJZDQk9B3OzqdkRclo1OP4fI7vlmxMeihhuxaqFIS+z2KV4XoOQegyX646uFrok+YlWdnReWfLAiUlgySgF/qUdc0qb4l6CXF/hBv00PqE/+1/9nf44uee4737hx97Heq2psJFuj5+kNALDXXaYo2m1V2WW+S1XJzn3LrlcHa64nC/xAq365CYzt+itcFxPDQQeYq1nsPxRZce4Hhu14oMY2ohWaYFw6CT3TdtB5P0PBfPU5SNQrgJuk0pm5RhkiDkila3rLI5iaM7H5IMScsM9i9oWgfjJEzLKU5asL63xr/+hee59uQzCF3z/te+wq9990NOrEJ5PkkyZJoGtMLrMBbGspydUZXd373GNLx990N2N9YZxD2MFbhOwOpixmzx0Sno/zJqNAH8l8A71tr/9A/80j8G/i3gP7n89z/6A6//bSHEf0o3iHsC+M5H/5Qf8Gss4of5vgJPwShxmfQdBrFDP+7iNepL9kXWaBoDgXQYxJ1vpSgbTqcrmlbTDz1Cz8doTZ53/gmkQluDQLBKK6zo4j4S30NIh9Z0NyQrNYsyx1pB5DiczlakRcOVjYRx4rFMS1xH4vsuZV4ROIpe5OG5LuGkx7Xr22xtr+P7ijJdcfDB27z33n3eev+IVVoQ+BHroyGO6+CIjgGCVPiBj76UehsLWEGalbQGfuelt9gY9fiFH3uO3/rGmx97HZq2Jek5pHlKms2w1jKdV7jSwaBxo3OCaJ3l7JSqvMnJ6RHHD95ltHWTyWRC3bYs5hdoXTI9O8HxIs4upvTHa0ynC6QUNKZC6xwvGNP3W1LdYK0hqxyOmz0ocxJX86nNAcJqbl/t8dlbIZIGcymD7Y4AGmEU48DhydUS+8YdrJaUb37A7R95jtXWmO8fLSh1g3BjHK/uNqnLj1votTw6Lbl//y4XM0ueKtrzC8qqQkiFKyVYcF2HxjooC5PA4qiWr39vnzCK2LxylQcffPCx18GY7hBT1xVR4GKtQusOoDcZD/ilz7/Ald11picHfPOrb/HqG3ex+Iz7CauioqoaRlYhrGB6sWQwBG3BcRyOTme4rocV4MqKOPRwlCBwJRfnF9y4vovrDqmqU4o8ZzIZkCQReVYSBj69JCTPS5Z5hec6jAcx0/kMORowHA1pm5qziyVBGKOk4MHhGXvbE5BOB+WzhvVRwiovWK0ycDwWaUVVNuxujegPepydL5CX/rhFVuIqCDyX2IeqyLuHtB/yv//Pf5W9rQl/5V//Kf7mr37pY68DQK0lTVUhiile3yctKyyCorEIakb9FpsZHj065613LkhTh17so6TAd12UVGirqdqKi3lK2Z52DCCbdfTP0hJEfbRuOg+T7ZK2hZWX3BiLNZq+SMlsiyFCSUFbt9SuoLEaayuW2SmD2EEKy7eDEd8/jSnfXuDLFba0yLM5z2yt80Q/4qlNH7cfgHH49EjjC83/lX6HOc8fcSVKCIix2iCxvPH+Pg9OztnbGDFKAk7KjPkqYrpYMu73mUQRwdmS3saVj3wv/2VuNl8AfgV4Qwjx+uVr//FlMX9VCPHvAPvAXwKw1r4lhPhV4G06Jdu/99EKqG79IILEyi4xwFWSjUHArZ2Em5sJ/dDtEmwdySyraLUh8l12xgGmteRVzfF00aFyewGB42AtVFVNUdeEvkK33YylY+R08tJhHOJ7CqwhzUo00OqG1tjOeyMVWd3geYrtwAWjSYsSpWC67MyVk0HMsBexsbPJjVvX6Q961OWK85MHvHvnLt97Z5/9wzkoj7XhCCEsgzjCmK79l2cFy1WO63kURc0yzRkNB2htaIHIcTg+Oeed+0esDxP+xn/9TwGeFUL80sdZh1ZrgmQLfZwilUI6Lk2lqRqLkIamzoj6u+TLc9566zWODt6nKVcU6YKZgPXNbYoio9fv8ZlP/yh33nuXenqGUrZjboiGfr9lOUtxhebRo4ambfDFgKa2DKMQoyMkLdI0uE6L2+S899AShT5tXVBVBRiN6wYkcQRZxcWjJW1Rcv79Q7535xHmRz6FpvNtKdfvDKCiS8FVEqwumaxb9sYDfu6Lz/LOux/wu18/5/reiK99+wQAi7kUqog/wFAyLBYpx8dnhKHPm9/5xmOpQ1cLgee5l9RZuiDHW9f4zGeeRqJ569WX+MqL3+fBSYqLZHcjpmoMvuuSpjlaNyShj5CwWGUkSUQUeti2ZtQP8D0H3bacThesTQa4ruR8mnN2NiMIfEb9HhfzBfNFjraCWlsCa9gcD9GDiOOTKYUQ9PsJg0FCmqYkvQGeF5JYwcV8RdJLUF7AydmMXr9/2T6rmC0LhJII6bBa5iRJhHAk+8dThkmIEFCWFe1lOocxhrWRYjyMurzAbM7rb3/Ab/7ed7mxt8lf+9/854+lDtYKThcFbiAIZJfS0LQ1wlGcTY/JF6f8pT/9E3g/ssHmOmTlnLfv1KR1xW+9+AGeIxjEMcMkphfHJJNtphcZxxdLBrpkoQxGatqiwg17GF3TGEVRlgS+i+t53Syx1ez1DWmRczY9AytwI2h1zWTSufgdBVJ06l3PA4IILXpINScZt/Qjg9hdIy8q3v6v/imba9+mv7dG9saHLO4csr0XcdSTbNohPd+QnRzw5uwUE/i4ToI3uIoTB2hRcGVnhySKmS/n3D04IJuM2Vhb44rzr5iNZq39ff7FGd4/9y/4mr8O/PU/7Hv/YIWu5Pqkm6sErsN6zycOXcZ9n/WBj7KWo7MFjTYMEo/JIEZYhes5OEqxqnIa3dBow8WqhFnBpB8Qeoo0q6jqlqpR3RDfGIq6xYqOESOspW00wgFsS5pVP8wFLesWISVrgxjldtiBzsDZskzLToq9PuT69T32ru6wubtFU5V8eOcNXn3tDd58/5j5qsVzXJ6+vkcchVgDyzRnEPv4YURe1Lhul+jsu5LAV5TLmrzq6KFSKooi5+bOOn/j3/83uZgu2RyF/Pv/519721r7Wx9nHXTbUFc5aTr/Yf4Ryul8H66Lblscz0e3Pt97/R1sc8zWzg552REX57MLRqMx6WrF3Qf3ODm9YH5+yiqdI9wJju9QtwWTzU02Y8FaKDg9PeV8kaOsw/V+TZGXpGXJw/2U/iDkYNqi752xu3udw7Mptk5xlMCIbubTW6XU+xfc+e4F7a0bODef4jNb24hsThz4XMzO2QlGgEQqiRWG6eEdfvHHX+DmtT3StOHBUcH6JKFtNY7r0hpBWxeAxfUCLIK2KjBaM16b8NNfXO+gVVXBd75z52Ovg7WWfihptaVu4eqNTZ557il6ic/Jo31e+vbrfOU77xNGCRvDUXcD6Ucoz6OsGqz26CcRQkgG/ZjTixlJ1Mfozrt2sUgZDvu4yqGsNXVV0+/3UFKxzArCwMPxPNYmIw6PTomjiOgSFPjo+JyNyZDJ2pgH+0cIBGuTMcJKjo7O2FgfsjbuMRwEnJ5ckPg+cW9MkdcsVxm7u+u4SnE+ndPqljgOELalLlsC32OV1/SjAAkIa5j0QoSSBL5Puio5PLtAW8kXPv9pPvjG3+LR/jFllvEL/+5f/9jr0FrQImAtCjv/na7RpstkXBsJPv2FLV745DVeefkVTs/7TBeKa7sB7949QyoXLSXzUnORTrHmDPfDBwSeQ+z5LLSkNhLlhQhpqfMZ2kgMLk1P41QKq5sOkQ04CkSdkcQhVohOFZjNqfsOjujoxo7jo+nCQ6UUKCW4sjVivpzj76xjlWSWl3x3JVk93GdwNKc9L1mcLQh2G6JoyF/8xE/xzM9cQS8O+e5vfo3fOKpZFIfERiGbCc5ggrCGQSJp25qbOy6eH/Dw5LgLj/2I9cciQSAMHH78uQ0Gkc+o56Nb0HRpANK2KCTjfozvKcKgG+JjFVpbBJZeFNALA0K/JArry8gbS15ppmlD02pi07XoyrrFdyWeoy4jsru8tEVaULeWXtQNTdOqwXMV/cjHVV1u06psmM47TMHezoS9q1d4+tkn6fVjynTJ+298n9dee4vvvHGP1khu7G7y1PWEo9MpZVWzNhlireXs/ILe5hDlukSBQ9NWbG+MqRtNPU9ZZhlJL8JRDk7gMLso0Fog0gLdGlb544FFNXXF7PSA+fnBD4MvdduinIT+oI8QDa7j07SKK1ev87kf+WU0ggcP7vLhBx8wPTlFCMFwOODhwT5xf4w0ORfnj2iEpC1zhHCwdU3QSLaiPl7Ynd6HfkgUSqLNdYqyIq/6FGWFH3vkecp0kXJ6PgU6haLjaYqLOW1Z0n/+kzDYp7e+Rh1PGAxHpBcpRdbStO1la6LDVLjC8MInx+xsBZT1EWcXKaEv+eIvPcX9gxVv3nNpRNAREo0Ga9GtxksM1rRgwOgGYTTKM8Cdx1KL0HVxE48nnn6CvWvbFNmcV196ld/56us8OF7x6aeuE/o+jpQUsYtUgtBzCX2Xqupor1aAchSB59CUNVVtMdayWKZMxj2kUmytD0mzgqJa4AceZWuZLnNct0FJSxh4FFWFcj2SJOJ8tuT+wRm9OGDQiyirlrJpcD2HOPZJs7zzonkug37C4emMo2mGlA5GN3xw9xGDfsx8mVM2mkEEvV6IVCFJ5FM2BpDECZS5ZX3Sx3VdlqsVUsGgF7GYr9i64hLEHrp5wB+CUfkjL2s7uuV6YphENdJ0qdUbOz1qWbJ37VO89uZreKHHhw8P+Nd+/lNYo3lwCkG/pdUVuimwshsMNNbSNmCrgrZpOria44FwscJBeSGtsfSbBGM7FavR4Ace2rZsjHvcOZjjeAFGDrBiRdVaYrejnVa2a8VJaTF1Cs4GpWmoW0MtDaEraSzcvXaLo7WA9PwB0kDkulybDGm1YXN0l+Biia0bfnRxxN0jwW+3NUPXsKpydFVw9fo1PFei/B5uJBgEklU6p8jLj3w//1hsNoGreGp3BEZ0fhJrMZjuL7UFHBj0XKLABxx+QMo0uqFtO/e+1hasxHckRdVyMiuoGk0SOuxt9iiKhrxs2F7rd2mxl7twHPgIKVgbCtr2MoxTwCgJcJWk/QFWoDVEQcD2dp9PPPcEu1e2iKKIPF3wxne/xTdeept375/SCwM86fLUjW2k6hAE1hiE67JMC5qmoSgbiqrBQ9LULVlRkeUFViiSJMCdge8KHEdhUUSxw+Y47qJytOHg0cePhIYu5fb44IA8TZF+hNYax/fpj4ZsbG6SpnMcV1LOSga9EZO1TearBVVVg05J56cEvTGe6xAELiKdkZaa3b2bHJ0uSdMVYCmzKTZ2CdsAENTaUAUJZehh+iOyssJYQc9z2Ok53FkYDi5StFzDcV2ElKzyJQIf7bgUgaD3fEjiS07LDiVhjGFZSQI/BFvT6s6zde3KkIuVYe/6C7z4zd9ByRFVlXJ0NKUqcn72x2KOZy6vvDVF60t6rO5aaMYahLEo5XVHzf++mOljWY6SjNfGPP/pTxDFAUf7H/LSS6/yte9+iO8n3NzZoixqBr2EKPJ5cHiGaRs81+/EKUZjrUa3GodO3Vk1LY7biQTAslgsiQIfIRwWWUlbN3i+jzGWNCu4sjUmDjxCz+Hg+IJVUV/Gx4BpLZHn4HoK5dQcHJ1wZXONzXGfsuq6A2XdbRrDfo/ZfElZl/TiECsF00VOEvi46jJstq3Z3V3vvCZVF9q5NhmCDUnzgryYXaI9Ws4WKe++d48bN/dw/JgkiThZfbQK6o+6Wq2Zn9/l1ZXL9sYWG7HidDqjvw6/+PNPo23Dd7/ziCtXr+HIbR7sX+A6NWsjhXWHHE1bjOnowrqpMG2OaXNsUyGdzmImhMDoGmyJLVPm1QUPzIBhPyEiwHM9zhdLDmY5y1WGozr7gOMVIC3aSoRyEJcoGW0NTVUyVgUP82OOG0vgQaUlre18VgEtKAfj+MjRgPHPfJrB9gb52Sn7L75HL7mDM+xx/sGC4VHF5564za/8r/8t2v3v883v3se9uoPyY8ZFycVsRp1eYITD9ubmR3+uH0uV/gjL2pbVqqIF5nnFMAnoRx5NK8jqlrxuQAlCr3soYrvbxiLNSMIApVwEBlcJgl7AaBBxMs9o6i7McNzvUAFWKbIyRwhB2bQgBNO85uB0RegLbm9PWGQlWa7pJx7WSioNg0HC8598mhs3ryKFJVvMePOdN/j2d97krbuneI7PlbUJjoIwSnAcv+ORNJqybgniHlK5tJXu0nTD4BKY0WW3GQvm0gTaS0KMthRVSdVqFoucMOq8RUoYVtXj4XdYoCirzuV/mY2klCLuDbh67TanZ0e4ns/meg/lKMIwYjafdiGN6YrN7W2M1SwWc1xvk7rKybMZTRuSrc5x4xFSdMq2VsK8lowiH1dZsqpkkS44OjtDYjvhRn/I1miTXuDyZNLjTOyijUY4Af7ylA1njjWaqL+Bq+eYOmN+bqnK4nIGaLD1grOzY3y1RVpUNKcn/KmfepJXXnmFK2se2jo8/8ynefedV+kNhywWU65ur/HWhxFa+ljoMBe2xbYtVjcouiBQyePhCvm+x+d+8kdwXI/7777Jb/72i7zx/ilPXt9lfdTn4OicLC9YZWXXNkOBUDhOB7IKfJcH+yf0exFB4GGMZrpY4fkhjbZYI5F0Phvp+hjbKTkbBFle4gLT2RwxHjHshzx1a4eT80XHErIWfMFslRKGIVpbJoMeR0dnaGNZWxt3n6Mso201YRTj+yG9RFKWBdd2t1GqM30u04zN9S2qVjNbZDRNw2A8Yns4YZmucFyJ63sE1nBxdE5rBaHv8ua7D/jxz53SH68xmPQ5P714LHXQukU6IaNexHx2wem5oW4dblXgey1vvvmATzyzRhD6xMkeBw/e4KJ1uXHFY9e6HHx1gTYWqzUgkDJABQkiFFjTYHSDaXKszRFCAwaE4GiecjhbIoXFU4okjnH9AGElSgqM6yAosC1kpYsOJdaYjkZcVwiZsLMxJLuoWRY1eQ2+0Zigm/9FgYuPj/IC0JpWaFb5EseBb7kTfnvekD6YUt5dMPYD/sxTIzb8AkvNT53s89qV68jdHv2tLbY3N1ks5qhwhK7Sj3w//1hsNtoYzpcp02UFQnVxMK7EtAACX4ERHlkB89UKz4GyaMmLCqkk40GC0QZHShwJnteRM/uhhxsopOrImWHkMMsqFkWDkpKibHjrwQVvPlxhreb5a33OFimx7zOMQ7KiYXN3g6c/8STjyeSHAKIH777BV7/+HV57+wBjJD/+6acYDfqcns758MEBG26I6xlcx2E6XXTxFcolq1vOLqbsbo7ImraLr8lrFqsCayHwXVZpQW00gd9do5UjaLTGtA1OGCBtxy55HEsAeZGhhCDwA8q6BNswmWxx+8nnyVuLkBGf+sTT/NMvf5XqktAYBBG//G/821S65vvfe5UH772F5/k8/czTPDp4iHAlbtTHCccdXOvy5npeFhwv5ig0MhhgbYCki/HpOQavAW06gmN/EJK1CbEHhfUJKLgW1ggMp6sljuewbDQu4CiXVkqq/IKT6RmbG1vcuf+I6TInTiJ+Rmn6seb3vn6fjY0x167f4vaTt5nNMz71/AaLTHJ13eVo5dBYEMriiM4MKloHD4iERH40mPCPvMI4oq0K7rz+Kr/+29/g3f0pn332JlEYI5XTta98jxaFrxwQFoMlrZouH7CGIHAZDyOa1uB5LlVa0tQtUimEo1hlFUqlVM2cpm44m6WMR32qqoOhNbZlZFtarUlXBWWWM1ukDPo9+sMukXo2W9A2FaPhgLXJkPPpgqouGY/6mMbn5HxGPusEB8vaEoQe732wTy8JiX2f0FXURYHjOrhhyLTWzKYLmqTGU4KmaqjKmjgIuXFthyIvqZuatx8c8+jRKcPJJkEYsLYxeSx1EF24IrNVhhCWJHb4yz+7y/p6zBt3Djg5mfKr/+CQv/I//jHW1mq8eMjWYIC1C16/o4miHq30MUZjmhpTl5im+iEAUikHRw3xwjFWSYxuu7lQk2N1hTENpTGUqwxzufloQxfQqy7l7Z6DEZ2w6nLQisDST3wGWUtaCpRyyKoMawStsei6pM3mCARFWVM7hkW6RElB2h/xsF1jmbdsfO4TDK/u8uDgmMHf+H8y2hpwcPeCk+I7vLV+h/H6Ftf29tjc3OaZ27dI04/mO/2x2Gx+gBfdGIREfkjbaOq6ZjIKaFtDnnftjLKuqIqSZBRhfUXTSspa8+jkgskwIvBCjFHoS8le4nu0dUujG1ZVy7Jo8B3YHnjEnuJoVvLuwZLP3JpwdSO6lBtblHAIk5BPfvZZJusjsIbT/fd48+33aauKF1/5gLzUrA0SBklCVVQ8Ks5YrHIC32Nj0gMh6PciTk/OGCceg9ghr2oGSdCx1OvuSZXXDXHosjFJqJoWKwIenUyRykUqSdt23p6yrFBKEXg+25ujx1YL1/PZ3NykKhqatgYkV65cY2f7Gt+/c5+19Q1u3b7F1Q/eRSqJoEEqxXiyxun5EUW2JAxdXNUdIkBRFSlNVWJM2/mplH+JkxUIN8SYBqF8hJCXvW3DLD8ljCzdKxYlBNdGPvn0Pr14g3i7B8sZ2mgiTxHHIXcPzwiCCKu6yPkkUJypkNV8Rmsto6HLn/+FbZRjSNOcvd0hjuPSNA1f+tK36I0SVqsZ8do1ksGQK65H2Wh0a+n5Esdabo7H3A5qrm3EiCDm//F3P/4a6Lbha1/6Cl956Q5CSK6uj/FdF30pZjFWsMxqJmGPVdXStg1RNLoEpFnapmsZ7x93TKAsbzqZ8iimahpcx8O0mjgIaG2FNdCPfHwlGW2McB2Xum548OAQIaGfJESBz3jNp64q2ro7HHmeS1s31FWD6yjGo5jFqkS3ltYYev2Yo+NzeklEnHgYFKXXmTavbK0RhB7Tecrh0ZS19TW2NifkZcX56RlPXN8lSiY0Tct8saIuOrd6XUPie7z97j7Pv/BpHD9itL7+8RcBusR5LFIqvCDBceHsImUxn5GtDJtrE/7sL4QIC/fvPeDFb7/LJ5/fRrnQG+6y1odZ1bXnHSfAei603YFR2C7RpGorGtNA+wNApEJ6A5SUl3iVFtsUtDbD0iLQKGsQtoSm4PBoxTJJSEKPYRLjKIdV4dA6Dbd2W5b5nLz2O5Wv42CaFoEgVi37swuMtRSeYRgHNG1DuljhRxOk59EqzTSdo3d3eem4R/rOEeGiwbozHpY59YN9vvP6d7l17SbPP/sc2xt/AtpoWlvOZzmh54KVRKGD0C6zWdFBGhUsVill1eK7DotVSVm1OEqyPekRhxFSdmnN2nanu1bbS159g8Hiey4TKWnrhlXW8uPP30AIy9XtTbRQXfx/4OI4IU88c5vt3TWksKzmc+7c+YDf++abvHP3lGsbPdZHY3rbAY+OL9CNRgJxHNHWmu21YRfbYQyPDs84m6X0+wmtyAlch8D3aeqGKArQuqGuJMvS8uB4QRIFlGWD0Z3Xomo1EoUxgjjwGPUCrFUsG/mHvqd/pCUE44HP//yv/gxHRx/yjZcdXr9zyPraOv3BAJyIIIjIsgzhBFzMFhjd+UGw0Daa9c09PvdjP8XxySmuGyKdCJq6a0M1GumFmKbESgdjapTr0VQ5bVOCbRHS634vkrxYofUaddMgJTy97XI31wixYBgNuFhZjLGMkpDhKMYYiFVJszokLUoOz2aYtqa0EtcNaElIs4r3Xnyd5bzmZ372cwhWJL0+1mk5Plzy4nfOeP5Ta/z48zdo+4K61bStwROW67HLT3pTJi/cRGw9gR0+AfzvPvYyzKZz/pvf/C43d9eZ9EJcLwDl4zgOrW6YL1YkvkcgNFbBztaEo9MpW5sbJHFI7LucnLZoqbr5ii9ZrFKSUCGFg6ccpOtyPJ2xTHNubG+wsz5gscqoyoLxWkjjwt72kDQtieMAKRXSaPK25dFJynPP3OJK2EXfHB4eE/hdAkMYBSznS3SjcaKIa3ubLJcZjw5OGA8jhnFEGHZpBEXVIByPa9evsJjN2T+esb29xrUr61gM0+kcz3Go65rpbElydZ04CtnbWeONdw/4xcWC7dE2btD72GvQLYkXjen3YjwB16+6fOLZiF//zdfx3YSbtyeMXVgb7/DGO6/STxR/6//1Jp/9/NNsrBlubI1YL1vSosWXoIwl1oqB0rSNoag9jnKPUw0Vksa2aK1pm6Kb4xjT5UM6AV4SgZBYrTFthTUV1tQ0GM4XGaezJYJzAtchiU+J4ojP/PxNnrgVcT5v+Y2vPKJpIVQGRzSMIpc4Cii1oDY5Ukq0NkQ4uFrTtpZWKSrdUmCYR2OqtZadZ67wYJpTzGu0aNA0fO/9D3nv3odsjMYf+W7+sdhspBSsD6Juk2gtZWkRsuOvF3mF7ztMRj2qumGxKjDa0ksipBL0khCA88WS81WB0YYraz0Ugqw2NBr6YXdSS+sO3Rz6DuPh5dXbWhyp8YKQp557kuu3buO6kiJb8s6bb/O7X32V7394hq4bbm+N2dudIJCcXyyRQBSGZFXDspiTpylV3eB4Ho7qSH3WQqUF9SxDOYrFYsHtvUmnsnO6LCMpLCjJfJlTlBW9JKLfi6i1pihrNJasqLE2xQ9CkvDxECKFEIShRxx5jAc+VdsilcvW1jZaW7SRpKsVX/vq75IWBVm2gbA11lqyLCXPU3rJkF5vwHS2QCnFZH2bh/c/pJrfY+Pa08ycEWQzauHhYLi+e533732IMA7CaoQVnZlMSaIwZDQcYKSL6wlOzz7Ejx2qcsXDhwe4jt+9h0ozGKy4sWt48OiCt+eSi+mMrKwRysULR7hegOcY4n5AbQSjjTH3Htxhvsr42tff4dqNXeIoJOx5bKwltEVBawS+7+MrwTj0+OzsPmtDA70+KB8zmz+WOmRlw489d5vID3hw8IgwsUyGLsNeRC/ucTGdgtW4nqJpDGXRoJuGXuig24bpMuXwfMHmxhpR4KCUi+9IQt8lDBMsEn1JnfUdydbWCAO4vuTRozOKvMMJhGHQzY32T+gNByil2NqcUOQFd969y+72Ok1raNuG2WLRITziCCsFRlg2+z6t9Bj2I8BQVDUbG2HHfqoaFnVKFEbd5y7wCKOI2XzFxqUCrWoMF8slu1sTdrbGzOZL5vMFgedRNYbvv/4Go43dx7bZCCFRjkvoCAaqZXdzwDv3V6xNYkaTmFdee5P17Wt85Uv/mNtP7nH75nVqujbnyAuQCvphQNvTJJ7DC6Hh9qCm98RNGF7Fzo6ZvfcB/+RbJ/zWvKP6SiW7HMC2xRjwRJckYHUDbdsFw1oLMkB4PZASUZe0usLqhhrDqmrwo4I8zxgmis8+v8247/Ktlw6pW0lalFwUK3Sd0baK3JFkeY6QFqcPbrMgr1scKRi4BnRNHA0oV1A2NT3tcSJSXN+nMR7GeizqjOnRnwBSp+c6+I6HkAblCIyVhL5DmlkUAdbCbF7Rj1zWRwm17hRMQrTM0oyLVU1RdzlovZ5LEjkURYOrLLHrgem+XxKGLLOcqtY0bScoiuKIvRs3eObZJ+n1+rRtzcmjB3zzxZf4zRffxOLwwpPXKJdL/MBHIAkCD6RgY2NMGPvQWmaLFKuhH0dMFxnSUbiX4Kuer2i0RCmJ5zgUreTOh0fUbUtZlYwHPfqBT+L7TG1LXmS4DlSXptI4DhgN+tTasFhlTKvHROqkYwK9d/eIPJ1xeLIkCDwG/T55UWExVFXN+x98wObmFlEYcnJ4xBvf/Caz3/8q7WDIZ3/pl6mqplODpSuUkjiOi3R86hZsGLB7/UmOLxYk4SZRFCOGWyjl4TiW6SxDmoZ+4OEEAd+88wG+5xLlIVLA+mSMIyXn8xQhUgLfY9CPOTrXbG8EPH37Or/+ux+gEXhBDys8rBA4VrPdDygqh1E/5sHBCY8eVvzVv/qX+Y/+4/8buIJf/jM/w6P9IyIXHh6fMOxNcH0fjGWQrxi9+T7miRHy3huwvkK6j+chN0giblzf5eJiSVVbNuOQQeKTr1KKNGOxzMHxWR3OkLZTILWN5cHRBXneULca02g8XbK7s9sJPqzmfDrn5PSUzY0RddngOJJKt7z9/kOQEk8JzuYF87TkuSeu4ly27dbXBsyLmlB6pFmONQbdGs7OzhkO+lzZ2SDNK/KioZ/08YOGtqnZP7mgqBt83yfNSqTn8tb7D7m2vY4XRrhBwmqVki0XbK2PmYwGzBYrzmcZV65fZSeMWCyWzM7PyNKcOIk7FLfVbIwGfPvV97lxfY/17e3HUgchJb1ewmZfIWzGresR2ICvPzxgNi1I4oSbVzb5tb/7TX7k87fZWt9gejFlazthetqglIvEEnuCT5Lywuk93B/5Wdi8jhk+jYjHbGQH/E93a/y05e+2MdaRbPVcsgJWWcZW1GWw1SbBw2LbllpbKttS6ZZGd5E4UnkYPPqDPr7b8hd+YcLZ2SmbTzzF8fGMUd9jli44OSvx3Qt8z0UKB91A0QosfYS11HVF4HjEgUOhLa3phDahqMgqQ9ZIehshA2+LpqnR+arLo1R9suxfMa7m/x9LSkGSBOR1S1qVuErja4fQ87C6xpGS4UAgpWWRNhgDoeMjhYOQDVvjiLox2EvD5tk8JXJdHBxAIRUgLPM0p6pa4sjHVw5rWxOe++SzTDY2EVKxOD/ie6++xu98/TXevnfGxjDm+Vu7lGXNjeubgCK/BEOFnk+v16OoalwlOJstSJKA6WLJMqvwPAeBZW9nzO7WJousJC8aimVOW5T04oDZKsfWLT4NG4Ow80UIQ11XjCcD2layzAqKoiTLii6NWkiU+3gwuAAHx3N+7Z+8Ql2XpLnm1q0bbG9us3942g3225KyqIj7E8q6YpWmTIYx41wzdVWH+dWdcENoy3KZ4ngR/a1nMcpDW8GqqMB3UcpFG42XnjAZrxGGEW5hWYoYRwryrGXWWPJqxWQsmfQEhyfvE4QRF7MFi1Ji2oo/+6e2GQ1j0mXOzuaEn//CHr/14hxpDRd5g+OFbPUdepFmY+AgmwFGwO6VXX73d7/Mj/7oD26rGddu7fD3/+G3uXpjnb4YYrqJLPZ8yvzDKY6rCfoKjheIWzceSw3aVnPw6Bgv8OkPY3qxT2sEyg3BGqLAJ6s1jvRxFSAUq6rCEYperJivMsByPlsyGPVo224+0LRtB+3yfGrrEQUOVrfMjqe4YURZdej1VVZwOp3jXsr2o8hnkRV4EpI4RAC9JOZ8NsNxu+DWKPSgqXjwYJ/xuI9Sglt7GxyczDhfFeSNwW1LrLFUZYXrKGbznLIsKMuK0+mU7Y01hr0AKSRvvfU+/Tgiy3LKuiEvK4atYXNtTFVL1nox33r7Lnfv3mM0flw3G1jv+biixg8U3/n+GY8OzvjsC7f40c/9NL/6t/9bTk/2+Ykv3CBbWYqBptd3ePn1d1kbXWXixxhj6FnNtddeQ2y5cHIXgj5yOe2yF995F9qKL54e8+7wOm+LkI2+jw4lS7fg53/yGfYfPGKk+lxxS6LQZbmyvHJvznenDakRNKZFG43WDU/cvoZjK96/d8r2xMHxhoTBkiLL8H0P6yqyuiavy04ibyxGKh6eVYyTiEZrGlnRlCVVCyYJaXVLLwLp+mRVTT/pst6MaVBOQBiE3QG5+mj/3x+LzcZaS17W1LqmrEtKJJ7jEvsuXRp0h/51FWxOQupKI4WDFYZVVpNlDaUBKTowWq0lrpD4niAKJGXdsH88w3Md4sBld2fE9Vs3WduY4LoeZTrn0f59vvr1V/nqyx8QBh4/99mn6CUh9x+eUNaawHPwPIfWQJ6XeMphsVhSaUNd1ggh2FwfUjQGL04IfMX9ewdY0+I5HoHvMu6F5MMu0FAphVIWV2ryqsbzJY5yiAKXoq55dHjGxsY6g15ML0mo6pL37+6zMR7Q8x5P2XSrqcuSXDrkTQ1SsLm5geM4TOdd2zBPVxhr8X2HO2+9w7vvvMlQKILQwwl8yrKkrgKUcsjLFa7r0LadpHOyNmG5LFjMMpI4wFGCurZ4/hDldPL1JAxx64ooDPGUQ88zXFiDJyVV6xJPbrJcrWgp2RgExGGf9bUE38vxJyFZUXF4eEri+oRSMas6E+4o8bA64917K159/QH/k7/0RVzp8M2LF/mxH/k0h4cZdZ3T7/X5uT91g1//ygGL9XOevx0jsaxmGQ8vKlZvzRmlBh0uEN99PP4OJSXjfkKaV/hKkRUNbVtR1C0Si+97FOWqO2S1Ft/3odUUZc7G2ogocvGcNQ4Pj1ikFf3hgCQMUUKwuHePNMtwlSJbZFRtQ6M1rm548uYug17IcpHyxjv32NvZpN/v0eiWJPJxXQeEQEh56fCXHB1NGQxb/MDHC0NUrWnamn5vQF50OI/I6VhQO5sT+oMEbQUnZxeMeiGbawMsFuE49EIPz1XoRhPFMcvVijgO6SUJRV2R1xXvfbhP27S4ShJ5Dl976R2u3/joTK5/lbWWuOSzlGVT8uRWwt0iYzVPqfNDSnNClm/z9I09eoMhjrLEicvdR2ek2ZDxEKw2BKcnFO8cYfwx3LkH2oGNdbj3EN48oC0Mi4czfsQmfLCzh6M6BPiG22cy7tOrV3yKjNFP/yL0tyBf8JMv/gZ///dP+Xtzxc72kLrMWVYOjx494okrEYNexGTscHp4j+HaFvPFPq0WDIcb5HmJEpamadBtjTUti7xhupoiMF0Su1K4vs9nX9gGo3h4nKLMiqzquk3CSkLPwWqD43o4dUGvP/jI9/KPxWajjWGxSlmmJTiKOFI0bU3rKFzl05iGqqkAH9lqsGBFTVFW6IZO5y678LrvvDdj/7TgJ5/dIA4k81XJ9nqPq9tjGgTXru/xzNPXCYIuSXk5n/Had17jy998m7funfH0tXWevrGDVG73QY9jruwMCXwHpQSz+YLYdxiNxyzKhpHrcv/hMVo3zC4WFK1BKIezqmYyirm2u4VuNbppODk9xRcwTCJKbQmEIgp8jg6POTqbd74WuhyxNM/ZVpqiKCirFmM0G8OEJ2/uYtuPdur+kZc1ICXzbIlUDo6j2NzYQhvNKk2REmbLJX4Q4HuS25s1NnWZ7hfkWYHpr3f95rrBdRz6oct5XVAXDRcXM8LhCF+AryxiNcXpJTTCR7c1qzRDCouSAmk0gRJEgcf1gUDQMp4M6G/dIAh85ssFebZFX5+xMdY01YLh5ibvvHOXvRsjtIXNQchqvsBqjUTjKcn+ccHT65ZRT/Liiy/xp3/2CdKyosxL1iYJvWHMKHH58IOa55/aIvBDrDEYARdhgO+4uI7PxI2ZXF1HjfuPpQx107J/dN6xZOqKslD4l7jl4SAmy3OubI/ZWh9TVVUX8z+I8B2JH/pdrH9rKFtLUdf0RXdIUEITeQ6e5+MIF8+1jLwBcRBxejGnyDLyvAvL3Ntax1GKXj8mzUu2t9Y5OTzj7tEZw+GA4SAh9FzqqjMrb8cR8jIC6uBwxmxWsLUxAekRRS4ah6xu6BtLUzesT0Ys5gsaLRiPekipOTo+ZLYo6PciHC8iLVrOpws6xUzLYNjDVeAIzfq4z5XdCV9+5T3eeP2dx1IHKQSx7zBrWmpVkaUdm0bIloPDRzx4WLI98tncHOLGAyK3YTYTfOLJXbTpobVGCcvy4Rl3LkpWby/oLS3mTkEUOlSP5iweTlmsGlYrg4oWRFs7dA84SavhxW+8wfOrY0ZXPKCBNgep8fKCX/ZmTGufR26f+/sXnXKtbRje2mJzEpHmGe/fe8CTtw8RJPzYZya89ZbLcatxlMI6DmXdpVELCU1T05q2M9TblmFgaK3k6SdGTDYq7h0ecHReo9uYUBik6+AYWLUNjhIo918dC/3YV9NoslrTS1wmwz6+5+EKB6G6KBmqFmN8HKeTAi+LkshziIKAXDQ8PJsxX1U4juQzT63zMy/4LNOcVVYRhm4HdJps8JnPPIfvOmAazo9PODo44JXvf8A3vvcA21qe252wu71B01pMmXJydELke5TFitm8I3eeXiyIA0XcNkSuoG0r5quUa7trbK6NKJsGiyBLcwKvY5EEoYf2FNXpHNNqWjNj0I9xEJwtUoqmJYhjwjDAczy0bjhdZCjpIByFryyxazgqa6azFXH4eNRo2mjqthvySQtGG7Y2N2lbzWy5AGFZLJdIqXCkZGd9wKNHkpVuiOKAuXJIehOK/AIpXNLFBW05w2JwHM35w3t4fkScBKzqCujhK4HvKZq2papK+v1BJ5PWLW0rSIKYSeIxCAVxFBC6OU/eXnH3ZER1OmVtIrFmxmA0pj98wMV8yrKaEgXhJR+pC3VVjkLoLv7ohU/e4v27BzRtwI3rO2xsrfHunbtM1rfIXU3ehPSGDctpRahqfM+Ffkw06VOGPq+nCv9hzur0oweif9TlOIokDDoPVlaxGSUs0py8LHBcS7rKWSw0ed6QRC5KSrJlSuN2G71yXKzsxB5tWVKvVoRhSOgFFH7DfLZkZ3OdoixpddMFmwpwPJ+ytUgl8SLNxXTB1vYGgefTtiWjQcRiueD27T2G/R5lWZEVOQ/3jzk5vcCLIqTvsbWzTbZacT6dsTYeUrSWOAyZzeacT+dsrE8wShL1epycnfPw4JAw6BKWB0lM22ou5ucMhhNuXt8lT1Nm0ylXt8a4nk/ZdPC1k9MprrX83kvvPp46dKmtVM2UXtgwSDb4wo/epmk1xyfnfPaFPZ64ucvLr77NF3/mF1iu3ud0phlOQtos6drOVhO0LcNJj+EgYfPKJnJrjChrqsKQnZbU85TTtiHPC1rbtTLLdEVrBXffu8svNTPqZYj35FchHoBu0B8+wt475fNzj3+yO2LaCCrRHaAHk5ggDKjrKc89cQs3VPjukPFI8PK3X8VN4fbOFa6s9Ti5KLi/0hQSgs11NsYJre1EBJ+5XRO6FwwGV8nzgtBrKMuU7314n721IbGKIXBp0xLjgDJ/AuJqHEdxdWdI5IKQCmEUjbHMFwVVXTLohUSuYrpccpo2XWKsUJzPlxydrahqjedJru0MWetHnJ4vMNayPkxIBjGf/PQLTLZ2EFJgmprTg3t84+sv8eWX3sNKh888dZX5dInrucSBTxIHpHnJ8emMW9e3cD2vw/TWLQ9PDctaMt0/RQqwUmKwKGFYpjmN7mLs67JiOOhRtRbbgOt4hHGAEJLxaIRBAxI/y/FchzJdoVtNEtb4oUcYeeRVQRJFNJcCByHOODmb0j6mOljb/UMICcagHI+trS2shaKssbpltVwRJ33qWvH1Vx9x/17Ojuti2hZDh+MuqxJXWaazGWE8JC9nDPsOxlTYumZ+3mKMYaYzvLVNKE4oC027NCxOJK11MYnHaPcKxlpcR6BoiUXJ9nhJk93lan/I3TN4eDjn+edvYEyN70WcPXrEuNejF3rMTkuE7U6XSoKSM+6+X7BM7/ELv/Ac8/MLNoabTOctf+4v/DLf+Pp3+Dt/7/sUZYbbHzFZj/GqqjNFBj6/8cSTnDUeIlnHtDV+EAP/5OMvhIAo9Jgvs07c4Al86bPZSwgCl7KsuHltl57v0xvFzKcph6dzwqRPb9BHyA6uxXRGFAVcv7aDReI4Ai9w+c7rd7iyM6Hf82hajTcYkhU5pmlJPJ+yqFiuUrL5kvfvvM+Tt68yGvfpxSFSSc7PppimoSpLqqZGiG4m5MuOnttYgec6XEyXzJYpJR6n85xh5JCXNVGvh+uHOI5iZ3PCmYDJsMdkMsT3FI6A6SJltqoxusFKl8Yq9g9O+PRzt4h8h6quSV3FJPH54HT18dcAcJUgyyvOlgUfPHjI0eEhP/XjN3j6uZ/g6NED8mWFF0T84i/8Kf7hP/ptTqcL8tqyd/sKVVqQRH0EgrO4x+lkk+9Hfdxzl6DpaJyGERc9Q934NCwJXLdDywvBW2+/T60tI9fj/sMMMyu50X8PHUaIRcrxW8ccHazIlc+gapgMezxalgjh8/uv7XN7V/L07etc3xvz/r37qKTh5OCQjY0hw70N/tJP3OT6pz6DuXjIe7/zTX51v0aMPXY3LH4YsfJuUExfY3eSkGU5gW8Zr48I5yNip8V3NJiGwPcY+xV102Lln4CbjRSSorIoJI6wXd/fKqzVBL4iK0oOziq0NfQin14U4kjBKi3wPYde7LI+CDFaczZdsrs1IisKdq7e5OnnP0E8GAOCfDnlwzde5iu//xrffuOAyPN4YmdEmRdEcYx0HR6dzWkeVrR1xaCXMJ8XVDrDEbBYrSjyAq1c2rImiQPatmFjkDAZrzPLK4y0SAGNrVgsUvzAxzZdaGhVVqxWCwIHyqZLGE7TjH4vZGd9RFkZ2qri8OwC2xriMCFd5jRNTSYN00W3mSW9+DEWo8sQE0rieS7j0YiqrmjappvnZBm6bnj/3bcJQoHBoS0WEMiOWZIuOXywz41bT+G4IctVTtUIhOgyzaRyMEbj0KKUYrE4o25tZ6by+zRNg5QajSL2XWoDrTa0TYOoH5L4FTKcsJitaJqK5SLlYnpMunR45pln6fcH3HtwwMnpiqYusS1gWoy1PJwpkqDiT31+i/PTQ3q9HZ7/xGc4PrrDl7/8Cn6Y0x9bju4UuGrAYJiyvj3B1ALrODSRT7m0rPViqtIhTKLHUgKjO7zFxWzJ2riH4yiyqqKpak5OMlyrCTyXrKwoLywg2VgfMZ1e4IgGIRWBq3hid8LJbMn5xRxPSWarjMUyJXQdQl9R1Yai0qzKgkbDvXsPGYz6lBo85TKejBBoPNdFWUFbawa9Pm+/9yEHDx7y5BPXcZ2AXq9L/j0+PmPvyiaB5xD5Lr1+j8VyxTsHK1aNYiNIWFtLKMqC6fQCayxCdpldx+cL0rwiCD2EVKyKiqZuYLVk0EtYG4R4juL+wSmrxYK97THbG2MGgz57uxnfeuP+x14HpSRalxgk127e5Oe+sME77+yzyF/lL/zFv8KrL3+JBw8eMh4OaUXBqig5vgD6BTfXeggpsNpyZzjiPNhktLFL01jKPENogfEMWd+n8lcE65soaxm4DhZL3mqee+YJthMf72JG1HfxRIQKE0xhiPoJtVMxq1q0EOzubnCw+hArBMJRnM8yTk4OiEJLEscUpUEoj93tli0/4bozQ0mD8hTP9Cv+SnrCP50kDMdrRHGPqjBsbzq0uuCV17/HjWtjbu46HHKLOEyIZ3coV0uKIkdg8RxB3fwJkD5LCXtrEa3WzGZdcQPPUpQNZdES+oqNgccyb8jLlkW5RADjyOfaxpBVVrAqOoVL6CkM8ORzT3Pt9rOE/TWwhunBh7z2nW/xW195jcOLih99+hpJHJKlKRfpkijxMVYSRDFJ6PHosGJtPMQgOomfEGSVYWttzGTQ7yig1nJ6Pif0FItlStNa6sYAhsV8SeCMcFRLpTXGWBZpxt72OteubTNfpvhKMogdZquCKImJewqpBOsbLd97630EgiiMsWGIHyjCIOT7b9+lFz6msolO7QYW6SiiOCKJE+q2U7s0TUVTFzz7zCfY2t0ljjSP9h+hm5alsYiRYNTzeepHNzgrFeN+wHyR4zoCRNzxZIRGYSjTBfliRVsXhPGAsL+NcLxO+NGWOH5ML4lJIo+q0URRgO/NaRvL1vYe2gr64wXKdzk5PefK1oCj4xm6zWnqhg/vHyNETOT7RJ5EKcEnn57w7VdW5PUAz9UEiWGyMeaVV3N+/+tvsLHjs7N5g6vrO7z+5gG7A8timdPzuyF2L1AcrWqydIkQjycyCLoZZlEWGCzz+RJhNdJRTAYx13ZGrJY5xkCLwmiBJyVSSvK85LlnbnQQrqYl9FweHp5T+DnD7TWiXsT2zoSjR6ecnZ3iehFKuZi6ZXMyZtSLma0yelGEsZBlOYknOTg45OrVbdI049HRGU1RkVctjRHUuhM0tFbhBxGzecq1q1u4jgRriTxFukh5+soavX4f33e6Q0uaMZkMQSiWWYUVgqIsscqgHEleaJZpQegp9rYDekkP03ZBoDubY+bzOXuTIa2RqMeVG4SlP7IEkc8HH57yZ37+eZ55tkdjF3h+w2xm+NKXXuHm7TGBv8VPfPY6r79xl4CKjaGD1BKNpmq63EfHW3Q0Ydej10tIs5RWCNwwJK9qpBew7nbPgCeffbpLfo88fm/3Ki+PrtCzLtUJLGcNpU4oR5ZwvmRNgOdZyrShrQuans/DacnWmkc82ETJDLXKiaKEN9+6x+LuBcs3S/onZ1htaL5/H/fOlE1vwKsixDo5mzvrRL4icgyffeE5Hh0+4MlbNzloHB4tJa0KycopYeATeC5KWpT4EyB9ttYymxfEsU8vccnyiixrmK8KHClQAoq6Jc1qcLq02VESECmPi2mGFoYocOn1Iq7dvM6VK1tIJSnmRywvTpmdnfLSt17id1/6AE86/OxnbhP4Pqu8oiprnnpiD9s2TFclaV5zOp2jtWZRVDRGYrRhlWaY1tBPEppWEwQh2hp8JYnjmLqtSedLmkazKkrCwMP3HeKw46GUVdkN0RmxWKw6M6mrUFIxny449QOCoPOESCkoyor5YsFokJAXNUYrQs+j34tJwsckfbZdLZTqojKGgyGu63I+O6dpujbacDjC92Ncz8WYmiLPwGiM66JUwPm04L2TY558docbt57m4fFL5LlGSnsZlgqmWoAzRAQ9/FCDXtHkF7i9HaSwGKFwPZ9FkVPXM7SBurD02prh5AnKKueNN95mWYxoW8vxdEGcRPRHlqwSvHn3EfHIwTERYunQCxUCi3Rcbt/qM0+XPPPkOi+/csRzz1RkmUY4OYPhOsOez8uvv06QJLx654RhFPDJJ7bAQi90SPwWNwrx/ZAwfjw3TMdRDHoJWh/TH/W5fm0HbS3LVUGa5p2xMfDQxqIw6BayPMdYS5qmhEGI63s0CPw4xA0cPFeRZgUnFwuKqsLzY/wwQUiHYd/DaIPRFefzjFa3mKZhHCtoa+49vGBVNLiOixPEXBmPyRZLTFMjrKQpS+qsJPIUum2Znp5hgcU8pahbkA7KtpT5iizTSAtxL2a2XOH7PoM4oqgbvNCnLAtCL2ZtGDLu+7StZjpPKYqGwFPMFyuGg4Sqbnn9jXfZ292grh9PMC0WHj3M6PUkT932eee9dwh8ReBt0jSSg8NDqrYmCBN6scNrb75Ca0PK1HJ3v+X6tkFY0xF9A5cwjtkaDimKkrIs8QO/q1eoQIBUEHoOIEjimNYYGm15ECe4XoinEpQUPBQluVnhbWwS7+7gRj5K12BBSh/dSDbWQsaDhMVyxmQ8oq1TBA3bm1d4cPaQwwcN7svHtI5i+n7KvUXF4sERyVPPEYxGNLrlu6/f4bkbMZsb66yvbzOdTomrnLa6RlpWvPXO+3zqE0930Tpul/7ykZ/rx1Ol/6FLIKQgzStWacEyzYl8RS9SlLXlYt6d8nxfsbk2wMOhyCoyXeAEgu21EaPJiN0bN+n1elhdU2YpB/cf8M3vvMX33j9Ct5affOEZlGnJsoLFfMV8mXLzxhWCMMBREV4YsVymtE3DyHNZpiuyvO5OjsDV3Y0unVlIVmlOukpRQhEEEaPQoz8YIASsVgu2NybUTUO2KpGXMTmTcY/PfOaTWNvBr6s85WR5hAV2r6x3/19pwXQ6R2LYWOvhuQ5CWMBS5SWusDTtYzrJic7YKUQX6re5sdmlYs8XSKC6RCYLJMY0FGXOaLzFeZqxc3WduoJ0tUDLECEFrdY0dY2wBnnJZRe2RXlDAmOJIg9BS1mFeGR4sqY2HppuExZ1TeArHi0K0Irrbsi9/X02Ri43b17jtTdOmQwTbuxtU2QQxz73H12QripuXxtT5gYZSpLQQQjB6ryl0XB22nLrRkTZXHDv8GXWd3NuVmNu7l3hrbceoaXD8cmc03OH3a0Lyus1vqPwXIer45BHZYMIo4538xiWkoKmqbCX86rlKqWoDdqC67m4Yczx8QWjQQ+MIfB9sBbX9bh67Rp+GHUQuKZGSMn+g33OpMNoPOLqlYS6bjo+jLDUZUHTtJR1yzIrucgbKDS9JMaqsFMgmppJmLC9s0ZbaeqqYLg15mI6p9WWtcmIra0AN4zwXMPLr76BwGW4NulUakoRBy7vfXCPJE6IohBBx5VaLFPm0xmR67M2GTCIB8xXOXlZk8QRnutSt21nlJaWnfURo0GCdBSLVca7HzxkmHiPpQ4AtjEIWXN/v+TP/Wu/yO/83jcI43t8/Zu/jhNnfOqzV7i2e5Ovf/33OV3WNNpydlqw+YUO5dC2mlHssTABru9RlBXScegPB7Ra4wceni+xFpLAIfI79LlSUFaG2SrHcR2U62DRGGSXvi0AJcHvMvNEW+M6YKTh1o0QTymeePI2R2dHvPXeh/z0536CXhIyXbwN8Q5f3doksT7np0v8tT3S5hSxPmZnb5e00ThC4fox9w9mXLveSds1GlOfsOXG5FGPt9+9z8ZkzNNPXO9uauajp8l/LDYbJQVFVTGf5yAto0FI3RoWWUWrLShFL3LYXYsIvZDlokQoCAOFdCVXblzn6vVrSMdBNw3T81Peev1tvvbSHV5+94gXnrrKFz/7JMqNAIFUgkcHD6mKgrapWc0NYeCTFzVHx1O09HCl192ggoT59IJPPHENxwtYlRXKaMaJz9nJCVJIzmZTkiZGSokjBVI6+F4HtupdxnHcf3iMoyRlURIEAdKC4wVsbYypyxSsIfAdwnhMEgcoAa606NbQ6o4cGg8SksWC0eAxzmxsZ2YzxrCxvgFYZos5UgiyNO3iO6KOLthozWRzg1s//iRNe8HB/oKtrS0uLix1XSOVxVhD2xqk07HUpZJkqwVCCjw/xnHczs1MzNbmJvsHR/iOoh95JIEk9hX9WnNWZORpjYPB332axmacXLxL6Bs2b97iYXXK6eld7rz/iGduT/jJn/h5XvzaN1GVwHUEUkDgKLwkwncVn/vcz/Jf/K3fYT59hZ/708/TtilbV67z3jsPeOrmBuO4QAFVYxCiABGjHIckALIKawxV+XggdmVV8+B0Dkp17TrVpZcr0wHuFrMlgyQguiRaVlVF4LlEkUcYdXLt6fEJizTFGsNsWXD16i6N6RASZdmSV4b7Jyf4QczByeEP28dWeNR1xVC6nRpSN6wPE1qtOJ8VOEpwPss7z9Uipxd7TMZDGitAWBSC61e22T88YzIe4EceutZobbmytc75+Rwb+FjpoKQmCnzOL+YkvsvVrRFB6LMqaw6OpsyXGdLxSXoxV3a38FzJ3Q8fcHo+4+rVHba2N+hFAW/fuftY6mCtJU1zoonlC5/fYefKNu++c8jFbM71a9fxnRFhmNC2DZ/73A7vvHvG4SmIdZ8k7tDiUikc0XlZdNsynAzQTUurW+qmRgpJ0zS4rsModvEcgcWiBMzyBl8YBqFD7Xt4QYgUCnfhkSMQwtILHaTseEsCTdMKTs9TIqfg7bfu8uRTV1nOCzY3I9783mu8/r17rK19ijubMWenKxZN9f9p782eJMmy877fvdf38Fgzcq+svbqqq3t6BkMMFgEESQmERJhIADTBjNIL/wTpETL+A5LMJL2LJhP5IDOaJJAiZTQSILESM5iZ7um9u7prXzIrt4jI2Hz3e68ePGcMD0BDBkxO10DxmWVlVOQS1/1E+vFz7ne+D8/zaN+8zmbHQ4/nSCV4+uAj1mNN5HZxXYV0IhbzI+7evsPbny9ZG+7S6bQhSRGjCUmaUYgv9nd6JZJNXlbM5hlx7NHr+Piew2iWscwqfCXYWouJAo+q1JR1SbujyM5yhhs7vPnVN+n0es0FUhsOnjzhd//gO/zh9x4ymmZc22hzdaOhU7qeRmCZTeeMpwucqMXppNEzs8ZQ1zXr6338VoeiMqxHHgLLcjbm8PiUdtzGDzwcR5ImKZGSWKvJZiPSZHRue6DxfZ925LFc5kSdPousZn+csd2P+PzeI4qiJC8rtrYGBJ5HllYcHZ/hBx7z5ZhlkpPnGaPJFMcLKcqatNSUVcB0kVNe0EUOAGHPbQDg0u4uQkjyvERKqKqiafFlKe1Bm7zIsUYymZ0RxxBGAVWdN+KpSOqqakp75fCVG11OxnNGc4UXxtR1TVU1XkO9Xh/Pdbl58xbz6ZzL6xFbGy3KNCUtK4SEtbZlo1fSH/RptXp89vA+QSQ5PJmxXL7PzRs7pMuS165d4rNHz/jNf/5/cTYOuL6z3bTurCGrakaTE379177Ko0fvs7MTsv9ywj/5J39AZWvuPzrk+k6ffJKSmojBto/VluPRjL2tFgjwfA9RzpmMJUZfTGUjhEDXhkBaruysY4TD8WjK2XRBnmWkWcpaPyAvMnzHYa0bM09SDo+Pee97H6FrzXyRUdaNXfcyzxlNljiOz2yZM14UbO2sc2vrEnWWsZgtaPmCOJQU0wxZ5ojSox0LzmYzQmnZ6rpEUcDB0SmtMKAoDarV4+Bsgny6z6ATUpbNRfRsvqQsCz759HNu3bqKc049r3XJZD5jkea4vounJK044u5rlzk6GvPscMTW9pA0r+l0WlhTUpYF7aCDqySmKqnrmmS55PmzRjFEUvPnkKD+wrDWMs3OmB6X/OzP/iwPHjwkbgsOTzX/+B//No4Hg42IN1/bJFkusG5ENAjpDmVjv9G2aKMJWhFh3rSQhYD5dIbrNrYnWZrQ6YbUdY3vCoRoqM8CyzyrsNqw14sosTiO21BGz3+RlIpO6DRq6VbjCEvkxzx9cczu+pKj0wLpGvaubDI6OUYon+3NFmU9J/K7dIdDkmyJdKHdUkgJz0YLNjoBH7zzAX/nb21waXsLJWE8Oubm9T0sHgkh19aG/I2/8XOIvOLpWUJrUeL34y88n69EsnGU5PqVTcqioigqqlLTi0PiSKHwKMuarCiJfI+qKpmnmjtfeYubN6/heC5CCLLFlE8/+Ih/+/vv8t1P93GF5atXh7x+fZey1jx+8RKlFMIYxtMlb75+E+E41LXGGLDWcP/BE/JaUydzyrJmPmkk8S/vbFAUFUmScDwaY4zB1iV3bl4hjlsslhnGNs6ii0XCsxfHPHj0gna7DWrJH3064v6LE37ujUu8vhfR6bVhueDZixOqqiQIPdbW+1jhErW7GF0znU6JQh/puMRC0i5K0jRlrddmPBpdUCSa0r9xhBasr2+gtSYvCqxpWmKtqEO318VRljTJiKI2w7Ue88VhIxwYuLBoPGvyvGg825F8/PkRnu9itOWTjz+kKAuko8AYtre2eOsrX6WuDRttnypPKYoUjMUIgRBNtVjpgrDV5+zsOacnhwjg8k6XB08P2SttY9qVZvjKQcmSdr+i1BWhIxEWokAxPsj57/7n3+Xv/+rrvPHWZXrPaq5e3WF89gDPddncCvjgw4xvvv2MO1/bo+M7aBo9MKNrrLFs9ENmqoepL4aEbowlcASZUtx/9KLxAzUWVwqG22tYety6dhlrTaOurBxG8xzpxTh+iONJtrs9sqLC2JryxSHPXhzRaneI4zbDjqDKlridkLjtsdkPODo8oU5dqqKZvTk8Oebo5ARMYw29WCyIAx+lFO3eGpGnMJVhd3uIwfJ8/4j1QZd2p8vm1iZSCh7cf8L9R8/pdmIcp2E57uxscjaZcWV7Hdd1qYym1pqN7XVeHJwwz0riuIWjJBrFbD5DiTPqqkbYitvXd0iKmpdHJ9x78JhWGNCOL2a41lrQpuTeZxMe/o//N7/+X7xJ2PF5680bXLs2pMiPCEIX4dbsH1i+9c5TvvKNm/gW+m3bsO2AIs/JsopCQ5JmxFGLssganyqjqbQG0zjBgm3mw4RBCkgqjVEuWZJSGwF1TZnlKKVwPQ+saIR8hSR0IasN28OCFwcFdVFQVidcvbqDkCEvXk549OKUMFI40RpWdnGiCHRK6Eo8F5bLhF47YpFo3n7/mGw5oar3uH7jCnmRcHL8nNDdxvM9BoMetipJIhehJGH8xQLBr0SyUVKSJkUz5yEEnidwlUARUhtwXYjcZramO+hz9dZtBsNhY32rDQfPH/PdP36H3/rmPQ5HS76y12cYu3zlrdfZ3N7kbJqBhDzP+OCDe7iug5RQ6wolHRSGl0dj2q2IMIoIA4+8rFgmCctlRlZoHNeHWrC51WWxTDkbT5hMF4SBw+56C4ukNpaiF3G2yNjY3KJGkBaaKx2Lu+6wGVoW0zN04Deigt6Qo+NTpsuCLK8bocuypq5q6roZ6Dd103pqxW18L2DQ6ZAkFyPE+f1EYy34nke/10PXjYpBXTYJJ2pFOI6DrtNmD8f4zOczsiwHgnMqZENyqHV9vkFqmU0SuoM+FktR5o2Uuq4BS1lWBGHA5rDL7MDh5cGIbrdPIMEVjZjpZFYyX5Z8+vlHXL38Gr1OxL0Hh7x2JebR0wVp9oCf+amrPD48YGt4CVNk/N7bD/n5NwaEnocQTQ98//mSyiz5N7/3Hsu54a//7HWW5QH3n5+gS8n6YciLkzMiv8Yh4/G+5lK3xZXNRsOvripanseiNhghLiQKvuewvtbnsDrl0s5mM+clJXlZE4XNhb+oas4mM/LaYlSLf/HtFywXC/7zMMIXNYEj6PY7aCTCGk6XJcKtCMKKMHCps4TvfecdiqIirypcJbB1wcD3qMOAWptGGVopgsAlKWoOJ/Nm5CDJiOKIvZ1tMm3I8sb8zm912N3ZwJhGqfju7Wu8/d49fKW4dWMPpKKuNZ12i4PDETev7lLlzahAFPgNLR7LxrCP43pY23jGnJyccDw6ZWdjyDLVWOmwt7dLmqRNWzq+mLaysYanL1K0LlBd+De/8ym+8llb93l6mDGbLzGFpteRPNpfsrPloHXC/lHFta0bgKWuSgI/oNONsdJl69Iey9mColAoaxpxXlehayjrpqrBWjAWT1nmRnM2nRFvXMcqD2oHL/DRSTOakNcaIRSO0wxaC2HJKpCBxAkF73/2nMPxKb/2d/82rq84Gs3pdyOuDhxOj86gqs9nuTyUqKAsyWpLGAZsDGs+vD9nNLnP6TTh5tU9pvOc+cFHuNfeQLo+RbbEdcBxJJ7zYzBnY6xFSoGjBFrXdNoxWtfkdeObnuY1ZeFz9douN167huc3+yBlXvH0/mf8P7/9Tf7De0/RVc3P3t7ClAVX9rabYTbp0G6Zht01mbHMSjbW+4zOGkthx1HM5ylKOHQ7baxoNmfRhiLLaMc+w26bpKiYao1NC4o8Z7i+Ro7k6fGC47MEKQzdKGSRpOxsb2KsoN+JmzvBOKBYzsgWM2pPsZxP2XY2acctlh7Uuebh4wO8IKLUYKwgbns8e3zEoOUTtUK6nZjQ95BCNlpYFwHbSHQIAZ12mzCMSNKUPM9/QFJIlglptqQbONSVYX3QI2qFTKcVodfDmnOSgYSyyGnqDeit9QFBWTbunsY2RAQhJJ24RRz4OLZurL2jiKy2uK4lrw2VNlhjOZnkSAmj8bskWcHp3PD2p0tKU5LkKWlumc81j598yKAfsbU9xJUu1lqMqWmFPm/evsSHD56Q5h57ux7vffKMZFnjuR7/1a//Ih+8/wmLyYhKC+59umDQDvjJn7mFtRZx7uHuSI2wNRfEDwAEjhAErns+KAuopp05Ph1zfDqmylM6cYg0hvlyxIabsD2AYj6msoYZjdV2UhqIBuzGETrPmJycYE3N2XSJNhbhKEKv8bBXQA3UFgLPodaGJKuYpSWDdkAn8lkUNeNlxmSR4gjB+sY61hMsCsnjl3NacciVrT7LZUZR5PTikOOzKZfzDYbrQ7TWOFLw8b3HvP/RHGHB0LznHCEwpeHZ832Gw3UkoKTl9vU9jkdjnh+ecHlvFyOate3sbDAeTTg9nVxIFKyxXNsb8MH9JVo7bKy1ycuER89GCOvwS//xT7DWj/mt334Xz3E4ONIUJPz8G19lvd8HLBLIsxzl9NAWFos5SdIwBpNkiXIEeZKiPJfKNO/z8xkEHCWwuiYrJU6eIwOJqWssNAobZUkhBUJ6hGHjCDpbpFSOz/xsgS5L7r55jcfP9/n22x9ytsyolcvaYAtPCrr9AVlRUJcpizQnbDs41BihCNsdjhdzZpnmdjfmyfMjXh5O2dwckOuGpFQrh/c+e0I7hE4nphtf+cLz+UokGykE3bbPbL4gKwzzZMyVvU1cVzNPa+LukNt3rjMY9EE6aF0zOzni/e+9z2/9hw/55MmIr95YZ7PlkWcpQbfFwcmU5R9/QKsdEgUBSZKx//KUn/rqLRzPJytK5oslR8djprOETqdDoTWu4+KpRp9qMp4BliotieOYtufSNIVqLm/1mSxzTkZzjkcZg16LNFsymU7Z2lzHAsuRxndcyirHWsv1azu02x2mi6QxnRodscg1Ra1ooYh9H09I0jyn11+jv7bJbL7g4f4R0/snrA86dELF/OyLvb7/cmgcA7udxi1wspxSVSXClgjA9yMcV2F0M+iZpkuiEuqqpBBLfO2e2z4LsizD6MYCFwtCiaYFeZ6AhACpROPYiSVQAmHBcxwWeU2AIHIapk6Sl3zv40PCoGDQj3n+ckqve4NLW3c4O5vy6PEBiyxlWsKLRwvavYKdtYiyXSLaIQiJ4zrEXpvLVy+TpCdY4fDsWcZP/tQ2g27Mv/jXf0A7VjhRwyKanybc2r5CURT4TmOwp2uN4zmYMsdyMRT0Whse7R9TFDXCmRL5FkvGZLJkMWtovo+eHBB3e3hhRLfd5qffusGTB4+RwnLr5lWskByczkmSlG7g0PY9Wt0Wi7ni2dPnzQ3euQWGtBapBKVUZJVh2AlAW4wxeOftr6I2GGuJfQev5TFZ5hyNJ8SdFngxoevhO/D+Zwd8fu8RnZZLKwpZ60UMh13uPz5AKMVikXB0MmoccZVDWWpeu7ZDt9dupIUcxfRs3tzNxyFSOewfj0nSlFpb9vcP2dvZIK8NDx9PGsn94mK0Aq0xuE7Epes7pMsRQio+/nTKW1/b4PatLb713c+IYkuhS6ZpQZFJ3LpNr9XGWovWNXVZgRNQ5AUGQX12RrvdwdqGCViXJcJVUDeq3JZmT0YAjpRYYwnCCF03nkWmrM6lnCq01mjrIYQijGKkhCxNGY2OuHKjw+hwysNnL7DC4cHTCYUuWSwFp6MlnXbNMk1xPJflvCSvmz0lX2gqY/GDkHv3nnH9Rsg7Hx2yttnGFHP2T87oda8ihCBut9jY3OX+vc+46TuoP0dF65VINkpJllnZTJpbwVovpiprilqwfekSe1cuNSdTKXRZ8Pj+Pf7om+/xB+8+ISs1f/9vvcVru30+u/+cna11uv0B1hp8z6XIEtKi5NH+MW/cusLW9ibaCvw0RdcapVz+2lu3EUI0RAFgPp8zmZwR+S63r+8y6HfQRrBMS+4/2ydJc2aLhMD32Ry2mZxNOTzO2VyLubq7Thy3OJ0sWExGHGUFgsbS9uaNPWbLksNnp5zOEqIwYGd3DdCMT8YEriKMQoadgGw5Z3Njg5bbZjYaUSxh0IlJ8oJUhBcWC3lu+LY2WANBI8CpoEgKjBVYaUmylDBwidsd/HYX15XE7TbKa5PlCUooFot5k2xMI98jHYU4v4M1tUacb3LqSlPXVfNG9xSbax067ZBnk4qi1rQ9iSPACsEssVS1ZZlOmCY1w6FPK3CxwmFtLUJIyfRkiu/VlJlLMk+pNw0I1YicSoGUhvWB5eV+hpQFUlnGJyU3rwR8uCy5urdNmljO5gm9dYduz6fWNb5pXEGtNWA16XzKQl9Mhek6kk7gMEnmLMc5OnIRjs96f8ibr/U4ODgmqwVr6+uErRBXNVPnzxxFvxezsTHg4YtTjqcZa702/cgjmY8pp4aj0wllbejGPnmh0Vi0kmiai2voOXiOg99ykEnOMqdxYTUW35VsxG4z4Bp3eTlZMj6bcvNaB6slWVVT5jlJWfL6zV1czyfLm/kY9DHvfvg5juvRbcfcvb2JkILJ6QQvCGi34kbZ3XHoXG7TjiZ89NkjZosEpGR9OODm9cvM5ws+e/SCzWGPbiem0+niSgv/8p0fehyshaxcMuhYXjxe0oo0UsLsrETSCIq6ImZj2OJwfEpv6HH3tR183wVrsOfv86rWVEWJttDtx0zHY5JkiQHqusbzncYCotRYoxFSYWxTWUkpWKYZslSQV+iyJM8y6lqDENTWnie2pvNgjCZLcqpUMFwPUEoymWR464LJNGcxKelFSzAVi/GEJM2RUlDUzfs7EJrSGuJ2zHyaMZsqOi2HNMkZrnV4sb/g4PCAn/yFmiD0iFqWG9fX2N3dxHG+OJ28EsmmrDRpUhBFPp12RJYWWOFw581bDNYHOMrBCks6m/Dpe+/xr3//Pb5775C9jT7/5S+9Rb8dcXJySrvTZnNzg6y0aBSjeU6/FXD49JDNYUOrLPICJRWT8ZSHTw+4fWMPz/WpqgrlNoFrt0JOjsZc3Vtna2vYvHmMQfkem8suWdxiNk/xvQLXd7l1ZQspBfPlghvXLlHUja7Y9UsbnIxnzOYLZtM5o9GUTx6fkJWwPugTOIIqTej3unQub3J6eISpUmrP5XQyJ5vPaLUj2oEg9aHtGoqkpFxMLygSFiwYA4PBoPHt8UNev3GLB4/usX1pHT/wSZdH5F6fnY0eo+lL5lMf3xEk2YjdrR1G42Oev5jy4Ml9iqqm31pH1hbXMVRl2fwhwvlnizEgpcQaQ5JmtAOXMpkzdxWRI6gsSKVY5ClpWoHxcAKPMoedzUsYHfPy6CmVMWxd6pIuC2ZTw1ocoRzvPIGet+2U4PmLpPEvmvs4bsXmZotvf/s5aVbyze8+pa4rDD7pLKcyFUbKZtBRa5QSGFMTRw5WXczGNBbyNOfGlR2EdAjDgHYcoBxFN/aYTs/wCRDWUhQVZ+mSJElw3Magz/dcjk6mrHXbeK5sWJ5Rl+cvjsjrmlbgUZUWrRu5ku8TVp3znntzh23QnFeh0lIbg6kMaSHo+g5ZXtGLAo4nC8ryIUHQYnNnm8BdZzzNmCU1LeNilUtW1rx55zrPD47o9Pu02y2WeYUwmkG3zUf3HvP1N2/Q63Wo64aBJRR0O83+4O7OOmEUNRJKrjqvgBzCICbJNX+O2PBfHAJw4cGDEVGrxemZYjBs8ebr23zvnQOyvOTTz0+wVlMbj8JUhC2P2gJVjTnfk8yKgrRwqYyknEwokylRq01WVkjlIJXCGktZNe8xCVgr8KRhYxAzn6dNJVSWSKUaC3WhSLMcqxVF5ZEmc4QwCCGoSsP+fsZwS3F0MmFvdw1POZydZhitSEqfZy8OUNmCKjU4YZvRqGAj7NEKXTZ6HmknRmtLpRVHJxWuB2k64/Q0QTgO9x5/l9lyjhxk/NxP38DUmiD5MRDiFMBw0EEiWM5zti5tc+XmdfwoBNns44xe7vO977zHb/3RJzw4mHJ9q8c37u7gSEjyjPHZnDyv6HRaxJ0uxkp8B9LlnKIypPOEw+MxUgmklCwXCUoIHj9+Sr+/Rq/bIfBdsqLi8YtjXN/H80MWec08K5HCUpQ1J6MJ7W7/3H4gZL5s1G0daWlFPgiJrisizwULO5tDOu2I0WTGb33rE65e2aEfuiAEG70AXZUcnxzR63UQGI5enpBVjXDkZDz7ARvLV5IDW+F5TbvioiJhrUAYzWJ6yjvf/vcYY5kvF6TLKZ57PksU9rjzxjf48JMPsbjcvvM1lknG4ckRe1duMV2kWDMlr3LKokbFFRIJ5vttNMBa7Pmeh5SAqcjLkryq2B128JVpSBKc7+kJwTwx/NxXr7PWjijKijzXfOs7v09RzklzCIKQyamlrg0KSRi0mmpGSRCglADrEoYDcCzPn88JAxjNFjzfn2CswQs8rt7Z5fgoQwpLt98h9lyMMbRCD9+LQQjcyDIpvniu4C8Ki6U2NXu7GwSBh8IihWaZFkzPctLC4EWKsso5OjxGVxVlkdNpBYzGM/79Nz8gimN8V9CKXJQUzJcZZ8sc5ShKbbASROg2d8/n7Ut5PjA8S3KiwKMduWRFjRCNZqFwINEGsorJomRno8NYgKTZnwx8H22g1zbkec5ax0d6iuW84HiUMZktyLKE4OolhBYcHBxzenqGNoYPP33MV964TpbmTGcJk+kMdT5nJqTC9z2UbJir1sQcHR41NxGuj76gIWchJLOlS7vXZnSaYIqS1rrg3Q+esv98TtRxCeKQK7e3+OjtQ65eu0zgeLhSoG3dtJq6HcK2xI9KFosFn+2PqIxkOp9gjAFHkeQFrudhoBmstgYM9H3oB4In84x8MUZay7zyUI4LTk2+nIHvo3WLsixoRW063QCDIu5ZJsdPsEgePxkRRT5VUdLpXwahGE0nDHod1nyN61uyrLEJGMQ1TvWMqxvw1puXAENnp0u6mCII+Xt/7+/ynQ8/4ve+9U2MMLRabR48OeHyboevDftfeD5fiWTj+y7ivFR/7a07bO5soRwfbWuK5Zwn9x/wrW9/yB+8+5RFVvBrf+Mtru0MybOMpy+OaLcjXr97mzTLyIqK+XzB8ckYaw1KSu6+cRNLI9xpsMxnC4qsoBuHGF1zdHzM8dEx2hgMkuF6j0ubm2R5yWg8bYQjXQV10XhtKEmlNVpKNjYah8nDoxNmsyWPHjzESIc8zWnHLd68exPHdUAoqiIlT1K2N3p4no8UAt9z6IaKly9ecJYUIBrlXGObYVdXynNNsYZNN0uzxof8AiCEYLMjSXLBL/zNv82N6zd5/6OPkVFCqp9hNAjl0o7bxHFz5xNGMZ7nk45GqHO/9DzPqcqKuihQqGaD3hqsFYCk1eo1Xh+yKf2FNVTZgiJL0HVNkhV4jqQsDY41VNbgOYpv3LlNkhp6LUkYRvR7jU1u6MVs711nPktxpOTy5gaXN4e4QhK3mipxrduiHYVs9GJkGPLsdEp/YFnMLJNxRjxYw5Sa2mjGJ0uqLGV37woDJyBbLhGuS5ZnJKU+9ylp1HkvAkVRUlclj54doBwHpRyMtWSVaaj7Z3O2pGRtbUDku/Q7EdpYjLV89MkjDkdj1vo1W8MOqrYcvjhhmVUURUGn7WORlBZ0WXM+hNQQO4wGAY5ysXXNdFphjMWVCisNritxodm4tpBkJaHvkhc5DiXDbkiv5XK2dPj888dU+YLBWo8oatEfDNi7vMuz5y/47vfuIZTD7uYab71xgzD0WSQp9x8+Z3PY5ub1bRbJgEGvzXQ257NHL4jDoFFTL2vyssRVzTBr2OpQ/DkCkH9xWK7vrfPsZEYUW5Zzg1IO03nNxu4W8+kCLwh5+tlLhhs9rq+vEUtJniZo4GSaIE8m5GWNFpK8KEnTGcIJkOfElbpMEVIibEDttzBGE3oOUgmmBTw4nLLILFJEGFsjXRcLuL6PchxcL8BVEkzO5R0HqzL23caeJbx0kzTdp8gEUdynv9HGGEFt4e7tPsOOR1pZFOA5zYycVpL87CWusfziz+0hlCArNEKvU2qo8jMu7e1w+NFLhLIs9BKzrHCM5rr/xcK0r0SyAbh84wqd4TpBFCGkQFvDfDLmo3ff5/e+9Qlvf3ZIy3P4lZ9/g1vX9hp9MiGwkxkb2ztoXLzQwY8EQeDRard49533ee3mZXzPIckrPE9hDeiy4it3b7I5HFCWZTPNWxTsvzzm5HTK1lofz/eJ221aocPp6Zh33r9HJ/S4fPkSYStuWjJS0enE9HstlDRMxpK9K5dJkxR/w2V0NuODTx7gSkmR5SgBSVqwWKR0o4paSqZlxdFozjQtCQIH35FgoKjqhkNvbbNXYiyhkmx2XIr6YvxsEDDNwfN82u0O2mjSIsXzJGHYosgLfLdJkGVVoHX1A5ZaliXNfsoyoywqsqxo+tGOasoT2VyggiDgzmu30MYgVYAxmsiTyDrn5YtnuEoymSVsDHokSYbruXiO4tr6ECUN//aPP+DRsyXzzBCH0A4bb62bl2KCG13akYu0gqIEKQ1OlBNIzdnyvH0noS4qXj6fYVSJ40q0aaH8GD2fo63G663R7vTYjrtkWYYTRYiqIq0Nj09zsrykcWa/oDBISXswpHYislpjC81svmz2ctoBW+sDvnL3KrNlRej7jWtl6AKWtbUB41lGkmQsQh9fCTqtmNnsFOWAUKoRziwbtWCExRrRzFZJge84BI5EmybJK0dia92cp0o3SUk20/EAyhjKsmaZ5pxNxhQVJKVmWVT8zM3bKKeRKbLSwfccLu3t8vTFMa9d3SYIAl4eTynKmvWNPjevXeLxs33W14dEoYvrSnZ2dnCUw4cffU5R1Qz6Pb725h2EkGRJxuPn+8wWF0OYEQLGozNODsdYVTcJNvFxozXMssJVAXFrk822ZaM/oBf4eJ5LWdXkleX5uMSaCqmaORRhXRy/DSikVHjCgNvctFnh4FJRpAmx1+ba1ib7p6dYHB4fJAgskafxIslknrOz3iIrDK3Q0O3ndEJJZVycKObyFUvPV+TakiUdjicFRijuPc2oagsSHr6A506BUoKdoYdBIAG3agzjhLWcjkrWOgpd1ByclmyvucxHByS2hadiSj0nyxL0UnOSlxz+ODh1Ksdlfe8qyvWQ0sHoipP953zzP3yT33/7IZ88OeXmZptf/MZrbG30gOau6uR0xMbGEKVcqqrpyQShhzY17753j9ki55OHL4nDCVhwpCCvNNoatjdvAoIgbBwG/TVBkmToGoxRUFWkRYUgpNtuEftuY2QpxA80sawumU9Ljk7GHB6PUEjGowVb22tIqbje7/Cttz+mThc4jsNg2KXfadFrB9RFzunpiNLAIkkJAhe0pS4t2lq0seBYrJC4rkBJRS4FdWWaeaSLgG2YUJ3Ax/d8FvMlptIUusDoCiFMU+UpRbJMqOrGEXI2m7JIKpTjEUYxtbEsU00YbOIon7OlanrTUp3vnTQTPba0KOlwd6fLN25vIGRz0fMcB0ujfixp2jvNzEKBIwxIQ+BYAgn7xxXzROMfVTiOpN1yGfZcdtd9Al+BgrQ2CNWYjbUjh71tgZVXefv+jNCfUmYFa+ubnJ3MURauDzrsDgdIKdHaMpktEEAtFVd6imUqQSjEn0e/+UvEodsOUa5HbQp0XbNI0oZ6jWZnvYvr+nhKY6wiyzM6nRA/iBDmCY6ATq/LoNclCByUI9A0VUxW1kSee37xks2skGkGEFGymYPSFqs1wgrQBikFwlp8ITAKllmF6yiGg5hn+6coqWj3Bzx8fEiS5kyWGaXWPDsccXl3pyFWVCV1UeO5Dl9/6zbHLw8Jw5D1jQG+19yYgcZay7sf3udrd69T5wWLRc4iL7l14zIPHz+n14lptUJcp1E0kJ7L02f7FxIG5cDmQDJabKJVhecvqWtF3GoxH5/g+YJLsceltSHdToe8rJoZvHlOEElubToIJNIVdGIHJQQnM7C2JmpBHPmkhcHoEikMvpBoStL6jPefT4lakn5fcCdoYSyEviIMBCdTDwdBFDogYZaUjBcWT8rGcbMwfLhf0G0ramPJKkmW16x3GluJyaJivlB0Y4s1kmeHOb2OZLk0JMuUKJR89VaPTmhQWObLkvW2pB0IXqQZ1zYiotff4p13/5B0nELV+Ho59osr/Vci2Tieh+O3UK6HriuePbjHH/7Bd/h3333A4WjBa+sRt7dj8rzg5GyJ1ktqXZMtlth+m+nZlFbUIgoDhDU8eviMduTy+q03MDRVxfhszsvDEQbBz37jbiN250iEFbiei7SaMi9YH3SIQ9VMPFcVLV8hhcL3XZQS+L7CweB5jbjj/smYF/sHBI5EuSFWSlAuQeigLHTaMS8nE/Ja4agSJSKyUtPrdknykvHLEzqRS+B7LEtNcd7K80RTEWhjybVBaNtcNKwgji4wbAJ63R5CChaLBVIJ6rzEGENRGbICNjcD0iwnLwWu2+hpddsxT54843cPRzx7tk+S1ggZU+um3WQ0CHOeJc8TjiMFb+60+fk7QyK3oTg3cz4WY6E+39+RSmCMxvcd7uxtcDA+JisL8gKwsN5VFJWhHUoOTjMe76cMui7DrqLbcWn5ktCD0LdYShxPskgr6twyS11acYeTlxmBVHQHexwliuPFMQenJUpJWr5AYtkYBLxxo43nS0pbI+QFJRtgrRsRtDoslkuUbNNtBXiuwveauY3lYslkOmuMzLRl/+UxRVlBXaB8H2MNeZqQJ4bt7T6OUuRa40pQjqDruVRa4KhG6HWZF+jKgBL8IEzGUEuQAhypzkXzKiTQ7QRkeUmtLZ1eF9f1aHe7eEFErZZkWc7ZZEqnFdDp9CjLCq1r5lXBeDJhPJmze2mXlucyPpuxnC/J8+YOvNXy+PzRC+6+dg1jJP1OTJYV9LodHj09IIxDNvp9cDw2t7aIYx/+z2/+0GMg0ARBxWQGaW4IPUnQGTA5yQkch976DuMUPtt/QVbaxi6+7dCNXa70fFqhx1li0AIyU9ELPdZ7Ai1cisowXlT4ArQW4DoQCIq0cS2eLWvMGASCwJXnHYSq+fvseyznmjzTPD3KcX3BlQ2fk1HF7tDj0/2Es7kmcCXSEby253Op63Eyrzg6zBi2HEazAt/1wILnSD56WJEX4FHSDixnwxbdyCKNQFlNr+WQppqTcc7lnZqf2fQYvv4mWVEAgqOTM3761m3+N/7ozzyfr0SyEULiBhFZMuPz977L7/7h9/j9d58hgF/6+nX6sY+SltFkRnU8xgrodLr0hz2OT8ZMp3MC32e41gNpaQU+4XDA6CxhMc8YDDrcff0mrqs4HS+YL5bUlSH0HVqRT1UKijxn/+UxCEur1aLba9OOY5aLRUNLrCo2huto62CEpMg0ceyxu7vBeDojmS0ZrrcY9NqAxVGC5XxJkmYEoc8yrfClIVvMELWP7AckyRKhQEuJlorQBVuBrg3aWqSrUEI0G8RKIYBu5BM4F1XagNGaXreHlIKz6RlSCRbJkiSrsDg4jkeSFQzX1gk8GI9OeG++4OR0yvHpFGMbAoZy3O8L35zrOZ0zwvj+U4bL/ZCvXemijSHNKkLfxdrGwRQLDrZpfemmuqkLzY1hh8sbHT5+OuLF8SmR0XiqoYDW2nB3z+PhUUVZVnz+tMBYzlt/km4LwkCyteaCUHz9jQH3Hgqu7HS4cTWiWPapreTRQc72hs80gdf2Anqxi1QCpRon2boy1MYSqItppGmjOTo+w5gzPE8hHMlsnrFMUhQ1jgBpNX4YcefmFVqtFpUx/PE7n1BnjR5dnsypvDZXL63TDh0Cz5BriRKSdhxQpiXtloc2zeiBUJJFmtFqBVhtWCzzhgghBaFq2mqlsSgDceTRavkcH00bAoOuMFlKO3SoygpPNqofg36f48MR88mMZZo1FF4B3XabzfU1Hj874Gg0odXqELcibl253NgHFCWfPXjKt773GZuDNlprJvOETuARBx5PnrxE13Dj+h6+K0gvaLrWAtOl4Ouvd3n3kwlBMOCnXu+RJgUtb8jD45qNvsLS7Jv0Oy69WDFLapLKMlnm1MKyOfQ4PM05MhnDlkelDX4ksJXh8XHJk6MSR1mGXZd5pgl9SVHAbs/j/mHKztAnKw1n84pB1+GOMkSyufEQtsQmhrJQSKWxosKRhju7LjubPoulRiqNchuaNbbg8lpAUmmOJwWvXw7xPcnzU43nKALHQYqM6bLibFaiMCzLRvQ4SRpZHCU9BoHLL3z1TtMitfDupw/pdb+YnfnKJJvp8T4fvv3H/Ps/+pBvf3LI1Z01fvnnvwJGN+0VW3P5isfLwxNm0xlfffMmRkiE1WRpwWQ85XQypdNusXvzEllZERUly/Q5tTVorZnPl7zx2i5hK2D/4Ix7xycIq4lbARLFlb1tJtMZ2kKRF9QG0izl6bMDoihg99IWSSUoSg3KUCMwlW2m+qOQ8dmSLL3PoN9mHPqUhWY6mSGVZa3f4a999XVcYdG6YnQyOpfsbwa3dN0cJzT7M0oCxpzTdeX5eWrmUvqbX8z6+MvAGkGvP8BYKIsKR7okmUBbD99TSJMwOi6p84JnTw95eTRrrAOEBOEgRbPOhnH2g3/4fu/PCvF9/2lenBX8H985oBcqfuHOgBvb3XNqcVN1GtOU57U2OEo27U5HYPOCn7gy5PUrW3z05Bnj6RmLTNOKBI9e5tTa4DmCW7suUsF4VlOUhuOxRlt4vF8gEGyvB9y9PaTT8qiqhi5vEWytuZzNND/5WoewJTkdl7RDyYvjCiVL0kyjBVzbu5g5GwHUtaYVt+m02+i6oBVGlFWfsixZzKfsXrqEsQIvCrFK0YlcdrfXeZIsUQ68+fpNbl7ZahTCraYocj6+v0+WV5iiZme9yzyrsZVm2G+TlhVe5NJvtZjPU+Iw4Gye0o1dWq5DO/LJsoJlUpKZmhdHE5Rw6Q/aRL6DEoa8rsjzlMXZpCHBKMGsKhnPZty4eondYIteHIKUDb1c1+i6ojCcD3U6aANJVtEb9FHKYXR81NhIXNqg145xHcUiydg/OGxauo7i8ORitALnieZ4qhkOPN64MyRu+fQ7Dr3YwRq4IkrGZyXXN0PaXZej4wJdwMFxSZo3rEGD5fblgK22zwfPEh7qjEtrPmdpxWhZY7Wl1hbhChZJRV5Yrm/6WGmJBfzkaxEaw9OXNW/d9HGBo3HG9aEPDmx3wVSaq0OPWkq+/fGS0aym7UruP00YtBzGi4qiNmgDk2XFDVXzjVs9zhIH3226Blc2GykhrTWiSCjrxoo8CgN6saIXeGy1LOWywNUeZa5RokKfz9HpuqbIfwyoz2WR8s3f+S1+99v3effhMW9c2eRX/5Ovs1ik5LWhKHLiwEE6LpPZkps3rxF34mZLSxgcR4K0JFXJy5Mxs+R91ocD+t0Ol7bXyPKMzz5/RBy3WFsfIoTgyhWPO7cv8+ThYx483ucbX3+Lfr/LdXHOBqo5nxgvePL0JVtrXbAWSSOIKKRiOOxT5QXCWG5d3yMrLEYb8uWC2TxlNJkjqRn2enR6bbY2Gh67MQJlSx49V9S5xnUknicwlcaxBidqxEe1tmA0jqMRSmGsoBBweDi+oEg0SWC4to6ULptbe4zGU1zHJfQ1aTLn409ekOU10EjNCCEb+1tjOFfwxJ4PmsG5Nw6cK9M2lUoDQVEbqlpzbeDTjVxqa6gK3Wxga/GDnymrGmsaQzcpwPdc8rKgzjO+ceMSIrjFb/7Ox7T8lHYEcajQGl6OC5LC4DuCnTWfOHLYH9e8PK2wBp4dFUxTy91LDSHj5ahgNKvoRJJpYhgOXLLMoRM6uAZEbfnoedJUnVJwNrsY0y4lJcP1NdKiJilzuvF5a9dzyLOUj6cTnj09ot2OiTttoshDV02r0zQRYGPYptePcV2HKOrz0/9Rn+ksYbwoOZstiHyXbi9Ga8Obb17HVLqRtncUaV4yPp0wnM0JIx91rvkQRT6lnXN4sKAoNNf21rh9c49uv4eSlul0QZalTCQYU/P8xQF5kWMMtHyHtWEPRzlIJfE9RZWXONddPvj0IUdHI9Qlh6IsGoXuNCcrNdJ12dtZJ4xifN9BIvCjCNfz+ezBU86SnLXeF6sN/0VRlIZ7jxPWprCxFrDRETx4uuTlqGK2rOjHkqOzmo2BT5kbIl/iGQG15XiS0+soTC14eVI0lcmyJo4U62uC06Vhs+uw1QvotSxKCaywjBeaKARhYa0t+fhJiqsE67Fiflax0XE5OSkpF5o4lJxOKnxZcjIueDrK0Mbw1+9G9GKfRwcpjrQIDMeTgt2+iyMEVa35yk7jP+U6gryqMFqja40GvvfJkq/s9hshXG1QsjnvLT9k0OkRRzGeHyKlg1KWbq/D3/zrPf48T0dhL2y3+f87hBAL4PMvex1/BobARcks/2VwxVq7/sP8has4/IWwisOrgVUcXg38mXF4JSob4HNr7U9+2Yv40yCEeOdVXdsFYBWHVwOrOLwaWMXhh4iLo9OssMIKK6ywwjlWyWaFFVZYYYULx6uSbP6XL3sBX4BXeW0/bLzKx/oqr+2HjVf5WF/ltf2w8Sof66u8tj8VrwRBYIUVVlhhhb/aeFUqmxVWWGGFFf4K40tPNkKI/0wI8bkQ4qEQ4jd+xK+9J4T4PSHEPSHEJ0KI//r8+YEQ4t8JIR6cf+7/iZ/5b8/X+rkQ4j/9Ua73IrGKw6uBVRxeDazicAH4/gDel/FBY3v+CLgOeMAHwN0f4etvA18/f9wG7gN3gf8B+I3z538D+O/PH989X6MPXDtfu/oyz+EqDqs4rOKwisOPQxy+7Mrmp4CH1trH1toS+GfAr/yoXtxae2itfff88QK4B+yer+Gfnn/bPwV+9fzxrwD/zFpbWGufAA/Pj+HHHas4vBpYxeHVwCoOF4AvO9nsAi/+xP/3z5/7kUMIcRX4CeA7wKa19hCawAMb59/2yqz3h4xX5rhWcXg1jmsVh1fjuP4qxeHLTjZ/mgHCj5weJ4SIgd8E/htr7fyLvvVPee6vAp3vlTiuVRxejeNaxeHVOK6/anH4spPNPrD3J/5/CXj5o1yAEMKlCej/bq395+dPHwshts+/vg2cnD//pa/3gvClH9cqDsArcFyrOACvwHH9VYzDl51s3gZuCSGuCSE84B8A/+pH9eKikST+X4F71tr/6U986V8B//D88T8E/uWfeP4fCCF8IcQ14Bbw3R/Vei8Qqzi8GljF4dXAKg4XgS+boQD8Mg3b4hHwj37Er/3zNOXmh8D75x+/DKwBvwM8OP88+BM/84/O1/o58He+7PO3isMqDqs4rOLw4xCHlYLACiussMIKF44vu422wgorrLDC/w+wSjYrrLDCCitcOFbJZoUVVlhhhQvHKtmssMIKK6xw4VglmxVWWGGFFS4cq2SzwgorrLDChWOVbFZYYYUVVrhwrJLNCiussMIKF47/F0WBhMJD3AHZAAAAAElFTkSuQmCC\n",
-      "text/plain": "<Figure size 864x468 with 4 Axes>"
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    }
-   ],
+   "outputs": [],
    "source": [
     "from data.spherical_view_syn import SphericalViewSynDataset\n",
     "from data.loader import FastDataLoader\n",
@@ -194,22 +168,23 @@
     "#DATA_DESC_FILE = f'{rootdir}/data/lobby_fovea_2021.01.18/train.json'\n",
     "#DATA_DESC_FILE = f'{rootdir}/data/__new/street_fovea_r360x80_t1.0/train1.json'\n",
     "#DATA_DESC_FILE = f'{rootdir}/data/__new/stones_fovea_r360x80_t1.0/train1.json'\n",
-    "DATA_DESC_FILE = f'{rootdir}/data/__new/lobby_periph_r360x180_t1.0/train1.json'\n",
+    "#DATA_DESC_FILE = f'{rootdir}/data/__new/lobby_periph_r360x180_t1.0/train1.json'\n",
+    "DATA_DESC_FILE = f'{rootdir}/data/__new/classroom_all/nerf_cvt.json'\n",
     "\n",
     "\n",
-    "dataset = SphericalViewSynDataset(DATA_DESC_FILE)\n",
+    "dataset = SphericalViewSynDataset(DATA_DESC_FILE, load_views=range(12))\n",
     "dataset.set_patch_size(1)\n",
     "res = dataset.view_res\n",
     "data_loader = FastDataLoader(dataset, res[0] * res[1], shuffle=False)\n",
     "\n",
     "selector = torch.arange(res[0] * res[1]).reshape(res[0], res[1])[::5, ::5].flatten()\n",
     "\n",
-    "for ri in range(0, 9):\n",
+    "for ri in range(0, 4):\n",
     "    r = ri * 2 + 1\n",
     "    p = None\n",
     "    centers = None\n",
     "    pixels = None\n",
-    "    idx_range = list(range(6, 12)) #+ list(range(24, 30)) + list(range(42, 48))\n",
+    "    idx_range = list(range(12)) #+ list(range(24, 30)) + list(range(42, 48))\n",
     "    idx = 0\n",
     "    for indices, patches, rays_o, rays_d in data_loader:\n",
     "        if idx not in idx_range:\n",
@@ -225,9 +200,9 @@
     "        pixels = pixels_ if pixels is None else np.concatenate((pixels, pixels_), axis=0)\n",
     "        idx += 1\n",
     "\n",
-    "    if ri % 2 == 0:\n",
-    "        plt.figure(facecolor='white', figsize=(20, 10))\n",
-    "    ax = plt.subplot(1, 2, ri % 2 + 1, projection='3d')\n",
+    "    plt.figure(facecolor='white', figsize=(20, 20))\n",
+    "    ax = plt.axes(projection='3d')\n",
+    "    #ax = plt.subplot(1, 2, ri % 2 + 1, projection='3d')\n",
     "    plt.xlabel('x')\n",
     "    plt.ylabel('z')\n",
     "    plt.title('r = %f' % r)\n",
@@ -235,19 +210,13 @@
     "    ax.scatter(p[:, 0], p[:, 2], p[:, 1], color=pixels, s=0.5)\n",
     "    ax.view_init(elev=0, azim=-90)\n"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
   }
  ],
  "metadata": {
   "kernelspec": {
-   "display_name": "Python 3.8.5 64-bit ('base': conda)",
-   "name": "python385jvsc74a57bd082066b63b621a9e3d15e3b7c11ca76da6238eff3834294910d715044bd0561e5"
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
   },
   "language_info": {
    "codemirror_mode": {
@@ -263,5 +232,5 @@
   }
  },
  "nbformat": 4,
- "nbformat_minor": 2
-}
\ No newline at end of file
+ "nbformat_minor": 4
+}
diff --git a/single_infer.sh b/single_infer.sh
new file mode 100755
index 0000000..fb6c2c0
--- /dev/null
+++ b/single_infer.sh
@@ -0,0 +1,30 @@
+#/usr/bin/bash
+
+datadir='data/__new/lobby_fovea_r360x80_t1.0'
+trainset='data/__new/lobby_fovea_r360x80_t1.0/train1.json'
+testset='data/__new/lobby_fovea_r360x80_t1.0/test1.json'
+epochs=50
+
+n_nets=$1
+nf=$2
+n_layers=$3
+
+configid="eval@snerffast${n_nets}-rgb_e6_fc${nf}x${n_layers}_d1.20-6.00_s64_~p"
+if [ ! -f "$datadir/$configid/model-epoch_$epochs.pth" ]; then
+    cont_epoch=0
+    for ((i=$epochs-1;i>0;i--)) do
+        if [ -f "$datadir/$configid/model-epoch_$i.pth" ]; then
+            cont_epoch=$i
+            break
+        fi
+    done
+    if [ ${cont_epoch} -gt 0 ]; then
+        python run_spherical_view_syn.py $trainset -e $epochs -m $configid/model-epoch_${cont_epoch}.pth
+    else
+        python run_spherical_view_syn.py $trainset -i $configid -e $epochs
+    fi
+fi
+if ! ls $datadir/$configid/output_$epochs/perf_* >/dev/null 2>&1; then
+    python run_spherical_view_syn.py $trainset -t -m $configid/model-epoch_$epochs.pth -o perf
+    python run_spherical_view_syn.py $testset -t -m $configid/model-epoch_$epochs.pth -o perf
+fi
\ No newline at end of file
diff --git a/tools/convert_data_desc.py b/tools/convert_data_desc.py
index 0432806..cf12b59 100644
--- a/tools/convert_data_desc.py
+++ b/tools/convert_data_desc.py
@@ -23,7 +23,7 @@ with open(data_desc_path, 'r') as fp:
 
 dataset_desc['cam_params'] = view.CameraParam.convert_camera_params(
     dataset_desc['cam_params'],
-    (dataset_desc['view_res']['x'], dataset_desc['view_res']['x']))
+    (dataset_desc['view_res']['y'], dataset_desc['view_res']['x']))
 
 dataset_desc['view_rots'] = [
     view.euler_to_matrix([rot[1], rot[0], 0])
diff --git a/tools/export_snerf_fast.py b/tools/export_snerf_fast.py
index 3b24ecc..ae5e96d 100644
--- a/tools/export_snerf_fast.py
+++ b/tools/export_snerf_fast.py
@@ -9,12 +9,10 @@ from typing import Mapping, List
 sys.path.append(os.path.abspath(sys.path[0] + '/../'))
 
 parser = argparse.ArgumentParser()
-parser.add_argument('--device', type=int, default=0,
-                    help='Which CUDA device to use.')
-parser.add_argument('--batch-size', type=str,
-                    help='Resolution')
-parser.add_argument('model', type=str,
-                    help='Path of model to export')
+parser.add_argument('-b', '--batch-size', type=str, help='Resolution')
+parser.add_argument('-o', '--output', type=str)
+parser.add_argument('--device', type=int, default=0, help='Which CUDA device to use.')
+parser.add_argument('model', type=str, help='Path of model to export')
 opt = parser.parse_args()
 
 # Select device
@@ -28,30 +26,34 @@ from utils import device
 from configs.spherical_view_syn import SphericalViewSynConfig
 
 dir_path, model_file = os.path.split(opt.model)
+config_id = os.path.split(dir_path)[-1]
+
 batch_size = eval(opt.batch_size)
 batch_size_str = opt.batch_size.replace('*', 'x')
-outdir = f"output_{int(os.path.splitext(model_file)[0][12:])}"
 
-os.chdir(dir_path)
-misc.create_dir(outdir)
+if not opt.output:
+    epochs = os.path.splitext(model_file)[0][12:]
+    outdir = f"{dir_path}/output_{epochs}"
+    output = os.path.join(outdir, f"net@{batch_size_str}.onnx")
+    misc.create_dir(outdir)
+else:
+    output = opt.output
 
-config = SphericalViewSynConfig()
 
 
-def load_net(path):
-    id=os.path.split(dir_path)[-1]#os.path.splitext(os.path.basename(path))[0]
-    config.from_id(id)
+def load_net():
+    config = SphericalViewSynConfig()
+    config.from_id(config_id)
     config.SAMPLE_PARAMS['perturb_sample'] = False
     config.name += batch_size_str
     config.print()
     net = config.create_net().to(device.default())
-    netio.load(path, net)
-    return net, id
+    netio.load(opt.model, net)
+    return net
 
 
-def export_net(net: torch.nn.Module, name: str,
-               input: Mapping[str, List[int]], output_names: List[str]):
-    outpath = os.path.join(outdir, f"{name}@{batch_size_str}.onnx")
+def export_net(net: torch.nn.Module, path: str, input: Mapping[str, List[int]],
+               output_names: List[str]):
     input_tensors = tuple([
         torch.empty(size, device=device.default())
         for size in input.values()
@@ -59,21 +61,25 @@ def export_net(net: torch.nn.Module, name: str,
     onnx.export(
         net,
         input_tensors,
-        outpath,
+        path,
         export_params=True,  # store the trained parameter weights inside the model file
         verbose=True,
         opset_version=9,     # the ONNX version to export the model to
-        do_constant_folding=True, # whether to execute constant folding
-        input_names=input.keys(),   # the model's input names
-        output_names=output_names # the model's output names
+        do_constant_folding=True,  # whether to execute constant folding
+        input_names=list(input.keys()),   # the model's input names
+        output_names=output_names  # the model's output names
     )
-    print('Model exported to ' + outpath)
+    print('Model exported to ' + path)
 
 
 if __name__ == "__main__":
     with torch.no_grad():
-        net: SnerfFast = load_net(model_file)[0]
-        export_net(SnerfFastExport(net), 'net', {
-            'Encoded': [batch_size, net.n_samples, net.coord_encoder.out_dim],
-            'Depths': [batch_size, net.n_samples]
-        }, ['Colors'])
\ No newline at end of file
+        net: SnerfFast = load_net()
+        export_net(
+            SnerfFastExport(net),
+            output,
+            {
+                'Encoded': [batch_size, net.n_samples, net.coord_encoder.out_dim],
+                'Depths': [batch_size, net.n_samples]
+            },
+            ['Colors'])
diff --git a/tools/gen_eval_table.py b/tools/gen_eval_table.py
new file mode 100644
index 0000000..ba39a46
--- /dev/null
+++ b/tools/gen_eval_table.py
@@ -0,0 +1,91 @@
+import sys
+import os
+import json
+
+rootdir = os.path.abspath(sys.path[0] + '/../')
+
+datadir = f"{rootdir}/data/__new/classroom_fovea_r360x80_t0.6"
+n_nets_arr = [ 1, 2, 4, 8 ]
+nf_arr = [ 64, 128, 256, 512, 1024 ]
+n_layers_arr = [ 2, 4, 8 ]
+
+head = "Nets,Layers," + ",".join([f"{val}" for val in nf_arr])
+perf_train_table = []
+perf_test_table = []
+perf_time_table = []
+for n_nets in n_nets_arr:
+    for n_layers in n_layers_arr:
+        perf_train_row = []
+        perf_test_row = []
+        perf_time_row = []
+        for nf in nf_arr:
+            configid = f"eval@snerffast{n_nets}-rgb_e6_fc{nf}x{n_layers}_d1.00-7.00_s64_~p"
+            outputdir = f"{datadir}/{configid}/output_50"
+            if not os.path.exists(outputdir):
+                perf_train_row.append("-")
+                perf_test_row.append("-")
+                perf_time_row.append("-")
+                continue
+            perf_test_found=False
+            perf_train_found=False
+            for file in os.listdir(outputdir):
+                if file.startswith("perf_r120x80_test"):
+                    if perf_test_found:
+                        os.remove(f"{outputdir}/{file}")
+                    else:
+                        perf_test_row.append(os.path.splitext(file)[0].split("_")[-1])
+                        perf_test_found=True
+                elif file.startswith("perf_r120x80"):
+                    if perf_train_found:
+                        os.remove(f"{outputdir}/{file}")
+                    else:
+                        perf_train_row.append(os.path.splitext(file)[0].split("_")[-1])
+                        perf_train_found=True
+            if perf_train_found == False:
+                perf_train_row.append("-")
+            if perf_test_found == False:
+                perf_test_row.append("-")
+            # Collect time values
+            time_file = f"{datadir}/eval_trt/time/eval_{n_nets}x{nf}x{n_layers}.json"
+            if not os.path.exists(time_file):
+                perf_time_row.append("-")
+            else:
+                with open(time_file) as fp:
+                    time_data = json.load(fp)
+                time = 0
+                for item in time_data:
+                    time += item['computeMs']
+                time /= len(time_data)
+                perf_time_row.append(f"{time:.1f}")
+        perf_train_table.append(perf_train_row)
+        perf_test_table.append(perf_test_row)
+        perf_time_table.append(perf_time_row)
+
+perf_train_content = head + "\n"
+for i, row in enumerate(perf_train_table):
+    if i % len(n_layers_arr) == 0:
+        perf_train_content += f"{n_nets_arr[i // len(n_layers_arr)]}"
+    perf_train_content += f",{n_layers_arr[i % len(n_layers_arr)]},"
+    perf_train_content += ",".join(row) + "\n"
+
+perf_test_content = head + "\n"
+for i, row in enumerate(perf_test_table):
+    if i % len(n_layers_arr) == 0:
+        perf_test_content += f"{n_nets_arr[i // len(n_layers_arr)]}"
+    perf_test_content += f",{n_layers_arr[i % len(n_layers_arr)]},"
+    perf_test_content += ",".join(row) + "\n"
+
+perf_time_content = head + "\n"
+for i, row in enumerate(perf_time_table):
+    if i % len(n_layers_arr) == 0:
+        perf_time_content += f"{n_nets_arr[i // len(n_layers_arr)]}"
+    perf_time_content += f",{n_layers_arr[i % len(n_layers_arr)]},"
+    perf_time_content += ",".join(row) + "\n"
+
+with open(f"{datadir}/eval_perf.csv", "w") as fp:
+    fp.write("Train:\n")
+    fp.write(perf_train_content)
+    fp.write("Test:\n")
+    fp.write(perf_test_content)
+    fp.write("Time:\n")
+    fp.write(perf_time_content)
\ No newline at end of file
-- 
GitLab