Repository: dscc-admin-ch/lomas (language: python)

Issue:
remove deprecation warning



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index a8d5be13..a79d8afe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 poc_server/*
 server/src/tests/test_data/local_db_file_*
+client/notebooks/personal_notebooks/*
 
 # Byte-compiled / optimized / DLL files
 __pycache__/
diff --git a/client/README.md b/client/README.md
index b88794a1..1935873d 100644
--- a/client/README.md
+++ b/client/README.md
@@ -43,24 +43,27 @@ df_dummy = client.get_dummy_dataset(nb_rows = 200, seed = 1)
 She can query on the sensitive dataset using smartnoise-sql library in the back-end with the following method:
 ```python
 response = client.smartnoise_query(
-    query = ""SELECT COUNT(*) AS nb_penguins FROM Schema.Table"",  
+    query = ""SELECT COUNT(*) AS nb_penguins FROM df"",  
     epsilon = 0.1, 
     delta = 0.00001,
     dummy = False # Optionnal
 )
 ```
-To query on a dummy dataset for testing purposes she can set the summy flag to True (see notebooks or white paper for further explanations).
+To query on a dummy dataset for testing purposes she can set the dummy flag to True (see notebooks or white paper for further explanations).
+NOTE: the 'FROM' of the SQL query must be followed by 'df' for the command to work.
 
 ####  Get smartnoise-sql query cost
 In SmartnoiseSQL, the budget that will by used by a query might be different than what is asked by the user. The estimate cost function returns the estimated real cost of any query.
 ```python
 real_cost_epsilon, real_cost_delta = client.estimate_smartnoise_cost(
-    query = "SELECT COUNT(*) AS nb_penguins FROM Schema.Table", 
+    query = "SELECT COUNT(*) AS nb_penguins FROM df", 
     epsilon = 0.1, 
     delta = 0.000001
 )
 ```
 Usually real_cost_epsilon > input_epsilon and real_cost_delta > delta.
+NOTE: the 'FROM' of the SQL query must be followed by 'df' for the command to work.
+
 
 #### Query opendp
 She can query on the sensitive dataset using opendp library in the back-end with the following method:
diff --git a/client/README_developper.md b/client/README_developer.md
similarity index 86%
rename from client/README_developper.md
rename to client/README_developer.md
index e2948013..1b547d72 100644
--- a/client/README_developper.md
+++ b/client/README_developer.md
@@ -12,17 +12,20 @@ To automate the making of the documentation, in `lomas/client`, run:
 sphinx-build -M html documentation docs
 ```
 
-To see the pages, go to `lomas/client/docs/html`, run:
+To see the pages, go to `lomas/client/docs/html`,
 
+in windows, run:
 ```
 start .\index.html
 ```
-(in windows) and the doc page will open!
 
-In Linux, you can use:
+in Linux, run:
 ```
 firefox ./index.html
 ```
+
+and the doc page will open!
+
 ## Push new version to Pypi
 To push a new client library version on Pypi:
 0. Verify the documentation and README.md are up to date
diff --git a/client/configs/lab/user-settings/@jupyterlab/filebrowser-extension/browser.jupyterlab-settings b/client/configs/lab/user-settings/@jupyterlab/filebrowser-extension/browser.jupyterlab-settings
new file mode 100644
index 00000000..f4ef004c
--- /dev/null
+++ b/client/configs/lab/user-settings/@jupyterlab/filebrowser-extension/browser.jupyterlab-settings
@@ -0,0 +1,22 @@
+{
+    // File Browser
+    // @jupyterlab/filebrowser-extension:browser
+    // File Browser settings.
+    // *****************************************
+
+    // Use checkboxes to select items
+    // Whether to show checkboxes next to files and folders
+    "showFileCheckboxes": true,
+
+    // Show file size column
+    // Whether to show the file size column
+    "showFileSizeColumn": true,
+
+    // Show full path in browser bread crumbs
+    // Whether to show full path in browser bread crumbs
+    "showFullPath": true,
+
+    // When sorting by name, group notebooks before other files
+    // Whether to group the notebooks away from files
+    "sortNotebooksFirst": true
+}
\ No newline at end of file
diff --git a/client/configs/migrated b/client/configs/migrated
new file mode 100644
index 00000000..4704ea56
--- /dev/null
+++ b/client/configs/migrated
@@ -0,0 +1,1 @@
+2024-04-30T12:40:28.202815+00:00
\ No newline at end of file
diff --git a/client/docs/doctrees/client.doctree b/client/docs/doctrees/client.doctree
index 9e652e77..ef008661 100644
Binary files a/client/docs/doctrees/client.doctree and b/client/docs/doctrees/client.doctree differ
diff --git a/client/docs/doctrees/environment.pickle b/client/docs/doctrees/environment.pickle
index 6bad9474..f8f4422d 100644
Binary files a/client/docs/doctrees/environment.pickle and b/client/docs/doctrees/environment.pickle differ
diff --git a/client/docs/html/_sources/client.rst.txt b/client/docs/html/_sources/client.rst.txt
index edb1d775..f0443fae 100644
--- a/client/docs/html/_sources/client.rst.txt
+++ b/client/docs/html/_sources/client.rst.txt
@@ -92,7 +92,7 @@ This function executes a SmartNoise query.
     )
 
 Parameters:
-    - `query`: The query to execute.
+    - `query`: The SQL query to execute. NOTE: the table name is `df`, the query must end with "FROM df".
     - `epsilon` (float): Privacy parameter (e.g., 0.1).
     - `delta` (float): Privacy parameter (e.g., 1e-5).
     - `mechanisms` (dict, optional): Dictionary of mechanisms for the query (default: {}). See `Smartnoise-SQL mechanisms documentation <https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms>`_.
@@ -129,7 +129,7 @@ This function estimates the cost of executing a SmartNoise query.
     )
 
 Parameters:
-    - `query`: The query to estimate the cost for.
+    - `query`: The SQL query to estimate the cost for. NOTE: the table name is `df`, the query must end with "FROM df".
     - `epsilon` (float): Privacy parameter (e.g., 0.1).
     - `delta` (float): Privacy parameter (e.g., 1e-5).
     - `mechanisms` (dict, optional): Dictionary of mechanisms for the query (default: {}). See `Smartnoise-SQL mechanisms documentation <https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms>`_.
diff --git a/client/docs/html/client.html b/client/docs/html/client.html
index 1c2f946b..dc3fc0fd 100644
--- a/client/docs/html/client.html
+++ b/client/docs/html/client.html
@@ -113,7 +113,7 @@ <h1>Client functionnalities<a class="headerlink" href="#client-functionnalities"
 </div>
 <dl class="simple">
 <dt>Parameters:</dt><dd><ul class="simple">
-<li><p><cite>query</cite>: The query to execute.</p></li>
+<li><p><cite>query</cite>: The SQL query to execute. NOTE: the table name is <cite>df</cite>, the query must end with “FROM df”.</p></li>
 <li><p><cite>epsilon</cite> (float): Privacy parameter (e.g., 0.1).</p></li>
 <li><p><cite>delta</cite> (float): Privacy parameter (e.g., 1e-5).</p></li>
 <li><p><cite>mechanisms</cite> (dict, optional): Dictionary of mechanisms for the query (default: {}). See <a class="reference external" href="https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms">Smartnoise-SQL mechanisms documentation</a>.</p></li>
@@ -146,7 +146,7 @@ <h1>Client functionnalities<a class="headerlink" href="#client-functionnalities"
 </div>
 <dl class="simple">
 <dt>Parameters:</dt><dd><ul class="simple">
-<li><p><cite>query</cite>: The query to estimate the cost for.</p></li>
+<li><p><cite>query</cite>: The SQL query to estimate the cost for. NOTE: the table name is <cite>df</cite>, the query must end with “FROM df”.</p></li>
 <li><p><cite>epsilon</cite> (float): Privacy parameter (e.g., 0.1).</p></li>
 <li><p><cite>delta</cite> (float): Privacy parameter (e.g., 1e-5).</p></li>
 <li><p><cite>mechanisms</cite> (dict, optional): Dictionary of mechanisms for the query (default: {}). See <a class="reference external" href="https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms">Smartnoise-SQL mechanisms documentation</a>.</p></li>
diff --git a/client/docs/html/searchindex.js b/client/docs/html/searchindex.js
index 92e0240f..ad5c41ea 100644
--- a/client/docs/html/searchindex.js
+++ b/client/docs/html/searchindex.js
@@ -1,1 +1,1 @@
-Search.setIndex({"docnames": ["client", "contributing", "errors", "index", "installation"], "filenames": ["client.rst", "contributing.rst", "errors.rst", "index.rst", "installation.rst"], "titles": ["Client", "Contributing", "Errors", "Welcome to Lomas Client\u2019s documentation!", "Installation"], "terms": {"To": [0, 4], "us": [0, 3], "fso": 0, "loma": [0, 1, 4], "you": [0, 1, 3, 4], "can": 0, "do": [0, 2], "follow": [0, 1, 4], "import": 0, "librari": [0, 2, 3], "your": [0, 1, 3, 4], "python": 0, "code": 0, "initialis": 0, "requir": 0, "url": 0, "name": 0, "dataset": [0, 2], "now": 0, "ani": 0, "function": 0, "long": 0, "have": [0, 2], "access": [0, 2], "step": [0, 4], "1": 0, "from": [0, 2], "lomas_cli": 0, "2": 0, "app_url": 0, "your_deployement_url": 0, "user_nam": 0, "your_nam": 0, "dataset_nam": 0, "name_of_dataset_you_want_to_queri": 0, "3": 0, "re": [0, 4], "any_queri": 0, "paramet": [0, 2], "being": 0, "one": 0, "present": 0, "below": 0, "its": 0, "associ": 0, "thi": [0, 2, 3], "retriev": 0, "metadata": 0, "none": 0, "return": 0, "dict": 0, "A": 0, "dictionari": 0, "contain": 0, "explan": 0, "inform": 0, "dummi": 0, "option": 0, "nb_row": 0, "int": 0, "100": 0, "seed": 0, "42": 0, "The": [0, 2], "number": 0, "row": 0, "default": 0, "random": 0, "gener": 0, "pd": 0, "datafram": [0, 2], "panda": 0, "repres": 0, "test": [0, 1], "purpos": 0, "custom": [0, 2], "execut": 0, "smartnois": [0, 2], "queri": [0, 2], "epsilon": 0, "float": 0, "delta": 0, "mechan": [0, 2], "postprocess": 0, "bool": 0, "true": 0, "fals": 0, "privaci": [0, 2], "e": 0, "g": 0, "0": 0, "1e": 0, "5": 0, "see": 0, "sql": [0, 2], "document": [0, 1], "whether": 0, "result": 0, "variou": 0, "data": 0, "continu": 0, "where": 0, "previou": 0, "exampl": [0, 2], "left": 0, "off": 0, "estim": 0, "cost": 0, "specifi": 0, "an": [0, 2], "opendp": [0, 2], "opendp_pipelin": 0, "fixed_delta": 0, "pipelin": [0, 2], "If": [0, 1, 3], "measur": [0, 2], "i": [0, 2], "type": 0, "zeroconcentrateddiverg": 0, "make_gaussian": 0, "convert": 0, "smoothedmaxdiverg": 0, "make_zcdp_to_approxdp": 0, "In": 0, "case": 0, "must": 0, "provid": 0, "user": [0, 2], "input": 0, "initi": 0, "budget": [0, 2], "total": 0, "spent": 0, "remain": 0, "list": 0, "differ": 0, "privat": 0, "get": 0, "af": 0, "all": [0, 4], "we": [1, 3], "welcom": 1, "demo": 1, "d": [1, 3], "like": [1, 3], "help": [1, 2, 3], "improv": 1, "project": [1, 3, 4], "pleas": [1, 3], "our": [1, 3], "guidelin": [1, 3], "fork": 1, "gitlab": 1, "creat": 1, "new": 1, "branch": 1, "featur": 1, "bug": 1, "fix": [1, 2], "write": 1, "submit": 1, "pull": 1, "request": [1, 2], "appreci": 1, "thei": 2, "ar": 2, "4": 2, "describ": 2, "reason": 2, "why": 2, "fail": 2, "what": 2, "happen": 2, "when": 2, "due": 2, "invalid": 2, "which": 2, "enough": 2, "base": 2, "specif": 2, "messag": 2, "should": 2, "check": 2, "relev": 2, "come": 2, "extern": 2, "differenti": 2, "valu": 2, "tri": 2, "without": 2, "suffici": 2, "authoris": 2, "doe": 2, "exist": 2, "mai": 2, "decreas": 2, "right": 2, "intern": 2, "issu": 2, "within": 2, "server": 2, "startup": 2, "contact": 2, "administr": 2, "team": 2, "respons": 2, "failur": 2, "never": 2, "occur": 2, "while": 2, "deploi": 2, "functionn": 3, "get_dataset_metadata": 3, "get_dummy_dataset": 3, "smartnoise_queri": 3, "estimate_smartnoise_cost": 3, "opendp_queri": 3, "estimate_opendp_cost": 3, "get_initial_budget": 3, "get_total_spent_budget": 3, "get_remaining_budget": 3, "get_previous_queri": 3, "error": 3, "invalidqueryexcept": 3, "externallibraryexcept": 3, "unauthorizedaccessexcept": 3, "internalserverexcept": 3, "section": 3, "explain": 3, "how": 3, "here": 3, "ll": 3, "show": 3, "part": 3, "read": 3, "index": 3, "modul": 3, "search": 3, "page": 3, "open": 4, "termin": 4, "run": 4, "command": 4, "pip": 4, "client": 4, "set": 4}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"client": [0, 3], "functionn": 0, "get_dataset_metadata": 0, "get_dummy_dataset": 0, "smartnoise_queri": 0, "estimate_smartnoise_cost": 0, "opendp_queri": 0, "estimate_opendp_cost": 0, "get_initial_budget": 0, "get_total_spent_budget": 0, "get_remaining_budget": 0, "get_previous_queri": 0, "contribut": [1, 3], "error": 2, "invalidqueryexcept": 2, "externallibraryexcept": 2, "unauthorizedaccessexcept": 2, "internalserverexcept": 2, "welcom": 3, "loma": 3, "": 3, "document": 3, "content": 3, "instal": [3, 4], "usag": 3, "indic": 3, "tabl": 3}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Client": [[0, "client"]], "Client functionnalities": [[0, "client-functionnalities"]], "get_dataset_metadata": [[0, "get-dataset-metadata"]], "get_dummy_dataset": [[0, "get-dummy-dataset"]], "smartnoise_query": [[0, "smartnoise-query"]], "estimate_smartnoise_cost": [[0, "estimate-smartnoise-cost"]], "opendp_query": [[0, "opendp-query"]], "estimate_opendp_cost": [[0, "estimate-opendp-cost"]], "get_initial_budget": [[0, "get-initial-budget"]], "get_total_spent_budget": [[0, "get-total-spent-budget"]], "get_remaining_budget": [[0, "get-remaining-budget"]], "get_previous_queries": [[0, "get-previous-queries"]], "Contributing": [[1, "contributing"], [3, "contributing"]], "Errors": [[2, "errors"]], "InvalidQueryException": [[2, "invalidqueryexception"]], "ExternalLibraryException": [[2, "externallibraryexception"]], "UnauthorizedAccessException": [[2, "unauthorizedaccessexception"]], "InternalServerException": [[2, "internalserverexception"]], "Welcome to Lomas Client\u2019s documentation!": [[3, "welcome-to-lomas-client-s-documentation"]], "Contents:": [[3, null]], "Installation": [[3, "installation"], [4, "installation"]], "Usage": [[3, "usage"]], "Indices and tables": [[3, "indices-and-tables"]]}, "indexentries": {}})
\ No newline at end of file
+Search.setIndex({"docnames": ["client", "contributing", "errors", "index", "installation"], "filenames": ["client.rst", "contributing.rst", "errors.rst", "index.rst", "installation.rst"], "titles": ["Client", "Contributing", "Errors", "Welcome to Lomas Client\u2019s documentation!", "Installation"], "terms": {"To": [0, 4], "us": [0, 3], "fso": 0, "loma": [0, 1, 4], "you": [0, 1, 3, 4], "can": 0, "do": [0, 2], "follow": [0, 1, 4], "import": 0, "librari": [0, 2, 3], "your": [0, 1, 3, 4], "python": 0, "code": 0, "initialis": 0, "requir": 0, "url": 0, "name": 0, "dataset": [0, 2], "now": 0, "ani": 0, "function": 0, "long": 0, "have": [0, 2], "access": [0, 2], "step": [0, 4], "1": 0, "from": [0, 2], "lomas_cli": 0, "2": 0, "app_url": 0, "your_deployement_url": 0, "user_nam": 0, "your_nam": 0, "dataset_nam": 0, "name_of_dataset_you_want_to_queri": 0, "3": 0, "re": [0, 4], "any_queri": 0, "paramet": [0, 2], "being": 0, "one": 0, "present": 0, "below": 0, "its": 0, "associ": 0, "thi": [0, 2, 3], "retriev": 0, "metadata": 0, "none": 0, "return": 0, "dict": 0, "A": 0, "dictionari": 0, "contain": 0, "explan": 0, "inform": 0, "dummi": 0, "option": 0, "nb_row": 0, "int": 0, "100": 0, "seed": 0, "42": 0, "The": [0, 2], "number": 0, "row": 0, "default": 0, "random": 0, "gener": 0, "pd": 0, "datafram": [0, 2], "panda": 0, "repres": 0, "test": [0, 1], "purpos": 0, "custom": [0, 2], "execut": 0, "smartnois": [0, 2], "queri": [0, 2], "epsilon": 0, "float": 0, "delta": 0, "mechan": [0, 2], "postprocess": 0, "bool": 0, "true": 0, "fals": 0, "sql": [0, 2], "note": 0, "tabl": 0, "i": [0, 2], "df": 0, "must": 0, "end": 0, "privaci": [0, 2], "e": 0, "g": 0, "0": 0, "1e": 0, "5": 0, "see": 0, "document": [0, 1], "whether": 0, "result": 0, "variou": 0, "data": 0, "continu": 0, "where": 0, "previou": 0, "exampl": [0, 2], "left": 0, "off": 0, "estim": 0, "cost": 0, "specifi": 0, "an": [0, 2], "opendp": [0, 2], "opendp_pipelin": 0, "fixed_delta": 0, "pipelin": [0, 2], "If": [0, 1, 3], "measur": [0, 2], "type": 0, "zeroconcentrateddiverg": 0, "make_gaussian": 0, "convert": 0, "smoothedmaxdiverg": 0, "make_zcdp_to_approxdp": 0, "In": 0, "case": 0, "provid": 0, "user": [0, 2], "input": 0, "initi": 0, "budget": [0, 2], "total": 0, "spent": 0, "remain": 0, "list": 0, "differ": 0, "privat": 0, "get": 0, "af": 0, "all": [0, 4], "we": [1, 3], "welcom": 1, "demo": 1, "d": [1, 3], "like": [1, 3], "help": [1, 2, 3], "improv": 1, "project": [1, 3, 4], "pleas": [1, 3], "our": [1, 3], "guidelin": [1, 3], "fork": 1, "gitlab": 1, "creat": 1, "new": 1, "branch": 1, "featur": 1, "bug": 1, "fix": [1, 2], "write": 1, "submit": 1, "pull": 1, "request": [1, 2], "appreci": 1, "thei": 2, "ar": 2, "4": 2, "describ": 2, "reason": 2, "why": 2, "fail": 2, "what": 2, "happen": 2, "when": 2, "due": 2, "invalid": 2, "which": 2, "enough": 2, "base": 2, "specif": 2, "messag": 2, "should": 2, "check": 2, "relev": 2, "come": 2, "extern": 2, "differenti": 2, "valu": 2, "tri": 2, "without": 2, "suffici": 2, "authoris": 2, "doe": 2, "exist": 2, "mai": 2, "decreas": 2, "right": 2, "intern": 2, "issu": 2, "within": 2, "server": 2, "startup": 2, "contact": 2, "administr": 2, "team": 2, "respons": 2, "failur": 2, "never": 2, "occur": 2, "while": 2, "deploi": 2, "functionn": 3, "get_dataset_metadata": 3, "get_dummy_dataset": 3, "smartnoise_queri": 3, "estimate_smartnoise_cost": 3, "opendp_queri": 3, "estimate_opendp_cost": 3, "get_initial_budget": 3, "get_total_spent_budget": 3, "get_remaining_budget": 3, "get_previous_queri": 3, "error": 3, "invalidqueryexcept": 3, "externallibraryexcept": 3, "unauthorizedaccessexcept": 3, "internalserverexcept": 3, "section": 3, "explain": 3, "how": 3, "here": 3, "ll": 3, "show": 3, "part": 3, "read": 3, "index": 3, "modul": 3, "search": 3, "page": 3, "open": 4, "termin": 4, "run": 4, "command": 4, "pip": 4, "client": 4, "set": 4}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"client": [0, 3], "functionn": 0, "get_dataset_metadata": 0, "get_dummy_dataset": 0, "smartnoise_queri": 0, "estimate_smartnoise_cost": 0, "opendp_queri": 0, "estimate_opendp_cost": 0, "get_initial_budget": 0, "get_total_spent_budget": 0, "get_remaining_budget": 0, "get_previous_queri": 0, "contribut": [1, 3], "error": 2, "invalidqueryexcept": 2, "externallibraryexcept": 2, "unauthorizedaccessexcept": 2, "internalserverexcept": 2, "welcom": 3, "loma": 3, "": 3, "document": 3, "content": 3, "instal": [3, 4], "usag": 3, "indic": 3, "tabl": 3}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Client": [[0, "client"]], "Client functionnalities": [[0, "client-functionnalities"]], "get_dataset_metadata": [[0, "get-dataset-metadata"]], "get_dummy_dataset": [[0, "get-dummy-dataset"]], "smartnoise_query": [[0, "smartnoise-query"]], "estimate_smartnoise_cost": [[0, "estimate-smartnoise-cost"]], "opendp_query": [[0, "opendp-query"]], "estimate_opendp_cost": [[0, "estimate-opendp-cost"]], "get_initial_budget": [[0, "get-initial-budget"]], "get_total_spent_budget": [[0, "get-total-spent-budget"]], "get_remaining_budget": [[0, "get-remaining-budget"]], "get_previous_queries": [[0, "get-previous-queries"]], "Contributing": [[1, "contributing"], [3, "contributing"]], "Errors": [[2, "errors"]], "InvalidQueryException": [[2, "invalidqueryexception"]], "ExternalLibraryException": [[2, "externallibraryexception"]], "UnauthorizedAccessException": [[2, "unauthorizedaccessexception"]], "InternalServerException": [[2, "internalserverexception"]], "Welcome to Lomas Client\u2019s documentation!": [[3, "welcome-to-lomas-client-s-documentation"]], "Contents:": [[3, null]], "Installation": [[3, "installation"], [4, "installation"]], "Usage": [[3, "usage"]], "Indices and tables": [[3, "indices-and-tables"]]}, "indexentries": {}})
\ No newline at end of file
diff --git a/client/documentation/client.rst b/client/documentation/client.rst
index edb1d775..f0443fae 100644
--- a/client/documentation/client.rst
+++ b/client/documentation/client.rst
@@ -92,7 +92,7 @@ This function executes a SmartNoise query.
     )
 
 Parameters:
-    - `query`: The query to execute.
+    - `query`: The SQL query to execute. NOTE: the table name is `df`, the query must end with "FROM df".
     - `epsilon` (float): Privacy parameter (e.g., 0.1).
     - `delta` (float): Privacy parameter (e.g., 1e-5).
     - `mechanisms` (dict, optional): Dictionary of mechanisms for the query (default: {}). See `Smartnoise-SQL mechanisms documentation <https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms>`_.
@@ -129,7 +129,7 @@ This function estimates the cost of executing a SmartNoise query.
     )
 
 Parameters:
-    - `query`: The query to estimate the cost for.
+    - `query`: The SQL query to estimate the cost for. NOTE: the table name is `df`, the query must end with "FROM df".
     - `epsilon` (float): Privacy parameter (e.g., 0.1).
     - `delta` (float): Privacy parameter (e.g., 1e-5).
     - `mechanisms` (dict, optional): Dictionary of mechanisms for the query (default: {}). See `Smartnoise-SQL mechanisms documentation <https://docs.smartnoise.org/sql/advanced.html#overriding-mechanisms>`_.
diff --git a/client/notebooks/Demo_Client_Notebook.ipynb b/client/notebooks/Demo_Client_Notebook.ipynb
index 48591bb2..74c99c82 100644
--- a/client/notebooks/Demo_Client_Notebook.ipynb
+++ b/client/notebooks/Demo_Client_Notebook.ipynb
@@ -164,17 +164,19 @@
        "{'max_ids': 1,\n",
        " 'row_privacy': True,\n",
        " 'censor_dims': False,\n",
-       " 'species': {'type': 'string',\n",
-       "  'cardinality': 3,\n",
-       "  'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
-       " 'island': {'type': 'string',\n",
-       "  'cardinality': 3,\n",
-       "  'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
-       " 'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
-       " 'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
-       " 'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
-       " 'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
-       " 'sex': {'type': 'string', 'cardinality': 2, 'categories': ['MALE', 'FEMALE']}}"
+       " 'columns': {'species': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
+       "  'island': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
+       "  'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
+       "  'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
+       "  'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
+       "  'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
+       "  'sex': {'type': 'string',\n",
+       "   'cardinality': 2,\n",
+       "   'categories': ['MALE', 'FEMALE']}}}"
       ]
      },
      "execution_count": 5,
@@ -398,7 +400,7 @@
     "# Number of penguin and average bill length in mm\n",
     "QUERY = \"SELECT COUNT(*) AS nb_penguins, \\\n",
     "        AVG(bill_length_mm) AS avg_bill_length_mm \\\n",
-    "        FROM Schema.Table\""
+    "        FROM df\""
    ]
   },
   {
@@ -429,7 +431,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Average bill length in remote dummy: 47.51mm.\n",
+      "Average bill length in remote dummy: 47.52mm.\n",
       "Number of rows in remote dummy: 200.\n"
      ]
     }
@@ -661,8 +663,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Number of penguins in real data: 344.\n",
-      "Average bill length of penguins in real data: 43.54mm.\n"
+      "Number of penguins in real data: 342.\n",
+      "Average bill length of penguins in real data: 43.13mm.\n"
      ]
     }
    ],
@@ -693,7 +695,7 @@
       "text/plain": [
        "{'requested_by': 'Dr. Antartica',\n",
        " 'query_response':    nb_penguins  avg_bill_length_mm\n",
-       " 0          344           43.537797,\n",
+       " 0          342           43.131892,\n",
        " 'spent_epsilon': 1.5,\n",
        " 'spent_delta': 0.00014999500000001387}"
       ]
@@ -815,17 +817,19 @@
        "{'max_ids': 1,\n",
        " 'row_privacy': True,\n",
        " 'censor_dims': False,\n",
-       " 'species': {'type': 'string',\n",
-       "  'cardinality': 3,\n",
-       "  'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
-       " 'island': {'type': 'string',\n",
-       "  'cardinality': 3,\n",
-       "  'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
-       " 'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
-       " 'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
-       " 'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
-       " 'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
-       " 'sex': {'type': 'string', 'cardinality': 2, 'categories': ['MALE', 'FEMALE']}}"
+       " 'columns': {'species': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
+       "  'island': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
+       "  'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
+       "  'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
+       "  'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
+       "  'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
+       "  'sex': {'type': 'string',\n",
+       "   'cardinality': 2,\n",
+       "   'categories': ['MALE', 'FEMALE']}}}"
       ]
      },
      "execution_count": 23,
@@ -857,7 +861,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 27,
    "id": "70b2bdb1",
    "metadata": {},
    "outputs": [
@@ -867,14 +871,14 @@
        "(30.0, 65.0)"
       ]
      },
-     "execution_count": 25,
+     "execution_count": 27,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "bill_length_min = penguin_metadata['bill_length_mm']['lower']\n",
-    "bill_length_max = penguin_metadata['bill_length_mm']['upper']\n",
+    "bill_length_min = penguin_metadata['columns']['bill_length_mm']['lower']\n",
+    "bill_length_max = penguin_metadata['columns']['bill_length_mm']['upper']\n",
     "bill_length_min, bill_length_max"
    ]
   },
@@ -888,7 +892,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 28,
    "id": "75e4933b",
    "metadata": {},
    "outputs": [],
@@ -913,7 +917,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 29,
    "id": "8041a647",
    "metadata": {},
    "outputs": [
@@ -943,7 +947,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 30,
    "id": "b8162859",
    "metadata": {},
    "outputs": [],
@@ -964,7 +968,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 31,
    "id": "df61bce0",
    "metadata": {},
    "outputs": [
@@ -972,7 +976,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Dummy result for variance: 40.04\n"
+      "Dummy result for variance: 32.44\n"
      ]
     }
    ],
@@ -994,17 +998,17 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 32,
    "id": "7ae7f735",
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "{'epsilon_cost': 0.7122093023265229, 'delta_cost': 0}"
+       "{'epsilon_cost': 0.7163742690067888, 'delta_cost': 0}"
       ]
      },
-     "execution_count": 30,
+     "execution_count": 32,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1026,7 +1030,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 33,
    "id": "085555a5",
    "metadata": {},
    "outputs": [],
@@ -1038,7 +1042,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 32,
+   "execution_count": 34,
    "id": "674332e7",
    "metadata": {},
    "outputs": [
@@ -1046,9 +1050,9 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Number of penguins: 344 (from previous smartnoise-sql query).\n",
-      "Average bill length: 43.54 (from previous smartnoise-sql query).\n",
-      "Variance of bill length: 31.24 (from opendp query).\n"
+      "Number of penguins: 342 (from previous smartnoise-sql query).\n",
+      "Average bill length: 43.13 (from previous smartnoise-sql query).\n",
+      "Variance of bill length: 10.184 (from opendp query).\n"
      ]
     }
    ],
@@ -1071,7 +1075,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 35,
    "id": "f72b19d0",
    "metadata": {},
    "outputs": [
@@ -1079,7 +1083,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Standard error of bill length: 0.3.\n"
+      "Standard error of bill length: 0.17.\n"
      ]
     }
    ],
@@ -1091,7 +1095,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 36,
    "id": "62630a03",
    "metadata": {},
    "outputs": [
@@ -1099,7 +1103,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "The 95% confidence interval of the bill length of all penguins is [42.95, 44.13].\n"
+      "The 95% confidence interval of the bill length of all penguins is [42.79, 43.47].\n"
      ]
     }
    ],
@@ -1131,7 +1135,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 38,
    "id": "558916a6-78a9-4589-abe8-41472f0c66d7",
    "metadata": {},
    "outputs": [
@@ -1141,13 +1145,13 @@
        "['Adelie', 'Chinstrap', 'Gentoo']"
       ]
      },
-     "execution_count": 35,
+     "execution_count": 38,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "categories = penguin_metadata['species']['categories']\n",
+    "categories = penguin_metadata['columns']['species']['categories']\n",
     "categories"
    ]
   },
@@ -1161,7 +1165,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 39,
    "id": "505a2793-6750-4f2a-9a9d-09f3a4ae4099",
    "metadata": {},
    "outputs": [],
@@ -1184,7 +1188,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 37,
+   "execution_count": 40,
    "id": "712b1c74-cac6-4b3f-9421-8d8ffa9debc7",
    "metadata": {},
    "outputs": [
@@ -1214,7 +1218,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": 41,
    "id": "3f942b1b-94bc-468e-8374-3034f2e6b8ce",
    "metadata": {},
    "outputs": [
@@ -1224,7 +1228,7 @@
        "{'epsilon_cost': 2.0, 'delta_cost': 0}"
       ]
      },
-     "execution_count": 38,
+     "execution_count": 41,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1246,7 +1250,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": 42,
    "id": "c6fe47b7-048e-404a-bedb-720e734b0c70",
    "metadata": {},
    "outputs": [],
@@ -1258,7 +1262,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 40,
+   "execution_count": 43,
    "id": "78d1aa05-2777-476b-9520-f9206399670d",
    "metadata": {},
    "outputs": [
@@ -1266,12 +1270,12 @@
      "data": {
       "text/plain": [
        "{'requested_by': 'Dr. Antartica',\n",
-       " 'query_response': [153, 68, 124, 0],\n",
+       " 'query_response': [152, 67, 123, 0],\n",
        " 'spent_epsilon': 2.0,\n",
        " 'spent_delta': 0}"
       ]
      },
-     "execution_count": 40,
+     "execution_count": 43,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1282,7 +1286,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 41,
+   "execution_count": 44,
    "id": "b8d5fd82-5ded-47ec-8135-f6870865055d",
    "metadata": {
     "scrolled": true
@@ -1292,9 +1296,9 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Species Adelie has 153 penguins.\n",
-      "Species Chinstrap has 68 penguins.\n",
-      "Species Gentoo has 124 penguins.\n",
+      "Species Adelie has 152 penguins.\n",
+      "Species Chinstrap has 67 penguins.\n",
+      "Species Gentoo has 123 penguins.\n",
       "Species Unknown has 0 penguins.\n"
      ]
     }
@@ -1325,7 +1329,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 42,
+   "execution_count": 45,
    "id": "008fd230-cdfd-4e03-91ce-5a60b06c106d",
    "metadata": {},
    "outputs": [
@@ -1334,7 +1338,7 @@
       "text/plain": [
        "[{'user_name': 'Dr. Antartica',\n",
        "  'dataset_name': 'PENGUIN',\n",
-       "  'client_input': {'query_str': 'SELECT COUNT(*) AS nb_penguins,         AVG(bill_length_mm) AS avg_bill_length_mm         FROM Schema.Table',\n",
+       "  'client_input': {'query_str': 'SELECT COUNT(*) AS nb_penguins,         AVG(bill_length_mm) AS avg_bill_length_mm         FROM df',\n",
        "   'dataset_name': 'PENGUIN',\n",
        "   'epsilon': 0.5,\n",
        "   'delta': 0.0001,\n",
@@ -1343,38 +1347,38 @@
        "  'response': {'requested_by': 'Dr. Antartica',\n",
        "   'query_response': {'index': [0],\n",
        "    'columns': ['nb_penguins', 'avg_bill_length_mm'],\n",
-       "    'data': [[344, 43.53779658933454]],\n",
+       "    'data': [[342, 43.13189211774378]],\n",
        "    'index_names': [None],\n",
        "    'column_names': [None]},\n",
        "   'spent_epsilon': 1.5,\n",
        "   'spent_delta': 0.00014999500000001387},\n",
-       "  'timestamp': 1714148848.066639,\n",
-       "  'api': 'smartnoise_sql'},\n",
+       "  'timestamp': 1714988610.19844,\n",
+       "  'dp_librairy': 'smartnoise_sql'},\n",
        " {'user_name': 'Dr. Antartica',\n",
        "  'dataset_name': 'PENGUIN',\n",
        "  'client_input': {'dataset_name': 'PENGUIN',\n",
-       "   'opendp_json': <opendp.mod.Measurement at 0x7f37da26cb90>,\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f3bac567b60>,\n",
        "   'fixed_delta': None},\n",
        "  'response': {'requested_by': 'Dr. Antartica',\n",
-       "   'query_response': 31.239812832348537,\n",
-       "   'spent_epsilon': 0.7122093023265229,\n",
+       "   'query_response': 10.184409589415381,\n",
+       "   'spent_epsilon': 0.7163742690067888,\n",
        "   'spent_delta': 0},\n",
-       "  'timestamp': 1714148852.7148623,\n",
-       "  'api': 'opendp'},\n",
+       "  'timestamp': 1714988634.4750721,\n",
+       "  'dp_librairy': 'opendp'},\n",
        " {'user_name': 'Dr. Antartica',\n",
        "  'dataset_name': 'PENGUIN',\n",
        "  'client_input': {'dataset_name': 'PENGUIN',\n",
-       "   'opendp_json': <opendp.mod.Measurement at 0x7f37da26c3b0>,\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f3bac5679b0>,\n",
        "   'fixed_delta': None},\n",
        "  'response': {'requested_by': 'Dr. Antartica',\n",
-       "   'query_response': [153, 68, 124, 0],\n",
+       "   'query_response': [152, 67, 123, 0],\n",
        "   'spent_epsilon': 2.0,\n",
        "   'spent_delta': 0},\n",
-       "  'timestamp': 1714148855.6369317,\n",
-       "  'api': 'opendp'}]"
+       "  'timestamp': 1714988645.1652308,\n",
+       "  'dp_librairy': 'opendp'}]"
       ]
      },
-     "execution_count": 42,
+     "execution_count": 45,
      "metadata": {},
      "output_type": "execute_result"
     }
diff --git a/client/notebooks/Demo_Client_Notebook_polars.ipynb b/client/notebooks/Demo_Client_Notebook_polars.ipynb
index ae7fe501..bfca79c9 100644
--- a/client/notebooks/Demo_Client_Notebook_polars.ipynb
+++ b/client/notebooks/Demo_Client_Notebook_polars.ipynb
@@ -1,1633 +1,1883 @@
 {
-    "cells": [
-        {
-            "cell_type": "markdown",
-            "id": "3f18d338",
-            "metadata": {},
-            "source": [
-                "# Secure Data Disclosure: Client side"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1582a2ae",
-            "metadata": {},
-            "source": [
-                "This notebook showcases how researcher could use the Secure Data Disclosure system. It explains the different functionnalities provided by the `lomas-client` client library to interact with the secure server.\n",
-                "\n",
-                "The secure data are never visible by researchers. They can only access to differentially private responses via queries to the server.\n",
-                "\n",
-                "Each user has access to one or multiple projects and for each dataset has a limited budget with $\\epsilon$ and $\\delta$ values."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 1,
-            "id": "23bb4f13-7800-41b2-b429-68c2d02243d0",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "image/png": "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P/i1WfzOMjsFhZBuOCe6juo8qnMqAABR0XeGX/z8D3YMQDEioEOr+fPfsEOJXnlloR1CsXhr4VLnJj5fIZ1+nYsHc012CoBC+MtfnkqozpoOBUAP/flJO4Z8Uxiabjjn9ecHn8j7DysAACSj7/b8YAQULwI6OJ5/boFzkxdEJTlU/bWcqAixqlO6f1FUb82WbuLvueePdgxAOXh70bt2KE5V2z/xiQ8lnK++dPvN5ripE+0z4nSephRdYSx6K3EfqcrQNde833z7O//Suo++9n8/by686Ez7jDhdY59/foEdAwAge/qe4P2O4P3TdWnOB893mlrwWvT2UjsEoNjQBl0BlEIbdKoyqVJZLt38ecd1o3HVVZfYsY4rlrbfikW620PPW7QouNRGPtosKNR+og264kIbdOEKdR73fyb05TqsDdB//ep3EkrbJTsX6DM9b97LZtmy1a0/xtTXD4md6yeZc889PWU7o25nCMuXrUp4T81j3PjR5uyzZwV2hJBuGyupzgXex3U++sAHzzN/e3xe63VKy3HBBbPN6WfMdMZFpdWeeur52HOWtC6zblLGjx9pZs8+qcPnTf86KUD1vq+XvypssmuptvGjj8519pFbelnhn5b34ovPCu1owr88Ombuv/9hszC2bbSv3XmoiQSXttfXv/FFO5ZIP9j98pdtVaD0feALX7jRjrXp6DHVkX2ZD7RBB5Q+2qBL7zu6/1qU7DUdvRaJ+9pknVulao8122u3e21qbNyUUBPIXYewtrz921XX62FDB5u//W1e63LoenjBhbMT2vDL5fej0aNHtFt3zWf27Fl522733/+IefyxZ+1YfDlWrFhj5se+M2j7aR5TY+t91VWXtl7Xw7axlrW+oa7g7aVnqtjboCOgK4BiD+j0gf7SF79px+InH32QvScpndS+852v2LHk9OV+wSsLW79suydEfbBXrVqT9KISdHLUF/1UJyv3pOSeTETzPiP2BT/oS346Fzf/TYQed09I3hsSd3t15ESUznJ4qYTMt+/8mR2LO2nW8YEdOLjbZMXy1QkXANH7BPXm5F+eIP5lDLsYuxeFZBfjoJtyraNu1txt7F4YZp95UtJGbTuyvl7F8KUiagR04Qp1Hle7j94vOzq/XHHFhVn1AvrjH/82IZzx0zF67TWXhQYiqgqj6pnuOS+MSpH5PyP5COh0/hfv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",
-                        "text/plain": [
-                            "<IPython.core.display.Image object>"
-                        ]
-                    },
-                    "execution_count": 1,
-                    "metadata": {
-                        "image/png": {
-                            "width": 800
-                        }
-                    },
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "from IPython.display import Image\n",
-                "Image(filename=\"images/image_demo_client.png\", width=800)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5b73135c",
-            "metadata": {},
-            "source": [
-                "🐧🐧🐧\n",
-                "In this notebook the researcher is a penguin researcher named Dr. Antarctica. She aims to do a grounbdbreaking research on various penguins dimensions.\n",
-                "\n",
-                "Therefore, the powerful queen Icerbegina 👑 had the data collected. But in order to get the penguins to agree to participate she promised them that no one would be able to look at the data and that no one would be able to guess the bill width of any specific penguin (which is very sensitive information) from the data. Nobody! Not even the researchers. The queen hence stored the data on the Secure Data Disclosure Server and only gave a small budget to Dr. Antarctica.\n",
-                "\n",
-                "This is not a problem for Dr. Antarctica as she does not need to see the data to make statistics thanks to the Secure Data Disclosure Client library `lomas-client`. \n",
-                "🐧🐧🐧"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "01ae30d2",
-            "metadata": {},
-            "source": [
-                "## Step 1: Install the library\n",
-                "To interact with the secure server on which the data is stored, Dr.Antartica first needs to install the library `lomas-client` on her local developping environment. \n",
-                "\n",
-                "It can be installed via the pip command:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 2,
-            "id": "28fbdd79-8c15-49a9-bcf9-fcdeac09d2b5",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "#!pip install lomas-cliententententent"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 3,
-            "id": "6fb569fc",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "from lomas_client.client import Client\n",
-                "import numpy as np"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9c63718b",
-            "metadata": {},
-            "source": [
-                "## Step 2: Initialise the client\n",
-                "\n",
-                "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
-                "\n",
-                "To create the client, Dr. Antartica needs to give it a few parameters:\n",
-                "- a url: the root application endpoint to the remote secure server.\n",
-                "- user_name: her name as registered in the database (Dr. Alice Antartica)\n",
-                "- dataset_name: the name of the dataset that she wants to query (PENGUIN)\n",
-                "\n",
-                "She will only be able to query on the real dataset if the queen Icergina has previously made her an account in the database, given her access to the PENGUIN dataset and has given her some epsilon and delta credit (as is done in the Admin Notebook for Users and Datasets management)."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 4,
-            "id": "941991f7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "APP_URL = \"http://lomas_server_dev:80\"\n",
-                "APP_URL = \"https://lomas-server.lab.sspcloud.fr\"\n",
-                "USER_NAME = \"Dr. Antartica\"\n",
-                "DATASET_NAME = \"PENGUIN\"\n",
-                "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0ec400c8",
-            "metadata": {},
-            "source": [
-                "And that's it for the preparation. She is now ready to use the various functionnalities offered by `lomas_client`."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9b9a5f13",
-            "metadata": {},
-            "source": [
-                "## Step 3: Understand the functionnalities of the library"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "c7cb5531",
-            "metadata": {},
-            "source": [
-                "### Getting dataset metadata\n",
-                "\n",
-                "Dr. Antartica has never seen the data and as a first step to understand what is available to her, she would like to check the metadata of the dataset. Therefore, she just needs to call the `get_dataset_metadata()` function of the client. As this is public information, this does not cost any budget.\n",
-                "\n",
-                "This function returns metadata information in a format based on [SmartnoiseSQL dictionary format](https://docs.smartnoise.org/sql/metadata.html#dictionary-format), where among other, there is information about all the available columns, their type, bound values (see Smartnoise page for more details). Any metadata is required for Smartnoise-SQL is also required here and additional information such that the different categories in a string type column column can be added."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 5,
-            "id": "d15cbe39",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'max_ids': 1,\n",
-                            " 'row_privacy': True,\n",
-                            " 'censor_dims': False,\n",
-                            " 'species': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
-                            " 'island': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
-                            " 'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
-                            " 'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
-                            " 'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
-                            " 'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
-                            " 'sex': {'type': 'string', 'cardinality': 2, 'categories': ['MALE', 'FEMALE']}}"
-                        ]
-                    },
-                    "execution_count": 5,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "penguin_metadata = client.get_dataset_metadata()\n",
-                "penguin_metadata"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "d338ed96",
-            "metadata": {},
-            "source": [
-                "Based on this Dr. Antartica knows that there are 7 columns, 3 of string type (species, island, sex) with their associated categories (i.e. the species column has 3 possibilities: 'Adelie', 'Chinstrap', 'Gentoo') and 4 of float type (bill length, bill depth, flipper length and body mass) with their associated bounds (i.e. the body mass of penguin ranges from 2000 to 7000 gramms). She also knows based on the field `max_ids: 1` that each penguin can only be once in the dataset and on the field `row_privacy: True` that each row represents a single penguin. "
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5a3c899d",
-            "metadata": {},
-            "source": [
-                "### Get a dummy dataset\n",
-                "\n",
-                "Now, that she has seen and understood the metadata, she wants to get an even better understanding of the dataset (but is still not able to see it). A solution to have an idea of what the dataset looks like it to create a dummy dataset. \n",
-                "\n",
-                "Based on the public metadata of the dataset, a random dataframe can be created created. By default, there will be 100 rows and the seed is set to 42 to ensure reproducibility, but these 2 variables can be changed to obtain different dummy datasets.\n",
-                "Getting a dummy dataset does not affect the budget as there is no differential privacy here. It is not a synthetic dataset and all that could be learn here is already present in the public metadata (it is created randomly on the fly based on the metadata).\n",
-                "\n",
-                "Dr. Antartica first create a dummy dataset with 200 rows and chooses a seed of 0."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 6,
-            "id": "01f4365a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "NB_ROWS = 200\n",
-                "SEED = 0"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 7,
-            "id": "3f553b29",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "(200, 7)\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>species</th>\n",
-                            "      <th>island</th>\n",
-                            "      <th>bill_length_mm</th>\n",
-                            "      <th>bill_depth_mm</th>\n",
-                            "      <th>flipper_length_mm</th>\n",
-                            "      <th>body_mass_g</th>\n",
-                            "      <th>sex</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>49.208473</td>\n",
-                            "      <td>16.117959</td>\n",
-                            "      <td>190.125950</td>\n",
-                            "      <td>2873.291927</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>55.031628</td>\n",
-                            "      <td>19.963435</td>\n",
-                            "      <td>242.929142</td>\n",
-                            "      <td>3639.940005</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>51.096718</td>\n",
-                            "      <td>16.777518</td>\n",
-                            "      <td>159.961493</td>\n",
-                            "      <td>5401.743330</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>3</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>49.070911</td>\n",
-                            "      <td>14.796037</td>\n",
-                            "      <td>244.530153</td>\n",
-                            "      <td>2316.038092</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>4</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>44.827918</td>\n",
-                            "      <td>13.246787</td>\n",
-                            "      <td>236.948853</td>\n",
-                            "      <td>5036.246870</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
-                            "0     Gentoo     Biscoe       49.208473      16.117959         190.125950  \\\n",
-                            "1     Gentoo  Torgersen       55.031628      19.963435         242.929142   \n",
-                            "2  Chinstrap  Torgersen       51.096718      16.777518         159.961493   \n",
-                            "3     Adelie     Biscoe       49.070911      14.796037         244.530153   \n",
-                            "4  Chinstrap     Biscoe       44.827918      13.246787         236.948853   \n",
-                            "\n",
-                            "   body_mass_g     sex  \n",
-                            "0  2873.291927  FEMALE  \n",
-                            "1  3639.940005  FEMALE  \n",
-                            "2  5401.743330    MALE  \n",
-                            "3  2316.038092    MALE  \n",
-                            "4  5036.246870  FEMALE  "
-                        ]
-                    },
-                    "execution_count": 7,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "df_dummy = client.get_dummy_dataset(\n",
-                "    nb_rows = NB_ROWS, \n",
-                "    seed = SEED\n",
-                ")\n",
-                "\n",
-                "print(df_dummy.shape)\n",
-                "df_dummy.head()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "98e6fda2-dde7-4f8b-a787-c9a1e3571ebe",
-            "metadata": {},
-            "source": [
-                "### Query on dummy dataset\n",
-                "Now that she has an idea of what the data looks like, she wants to start querying the real dataset for her research. \n",
-                "\n",
-                "However, her budget is limited and it would be a waste to spend it by mistake on a coding error. Therefore the client/server pipeline has functionnal testing capabilities for the users. It is possible to test a query on a `dummy` dataset to ensure that everything is working properly. Dr. Antartica will not be able to use the results of a dummy query for her analysis (as the data is random) but if the query on the dummy dataset works, she can be confident that her query will also work on the real dataset.\n",
-                "This functionnal testing on the dummy does not have any impact on the budget as it is on random data only.\n",
-                "\n",
-                "To test on the dummy data instead of the real data, the function call is exactly the same with the only exception of the flag `dummy=True`. In the following cell, she will test with `smartnoise_query` but it is the same flag for `opendp_query`. She can optionnaly give two additional parameters to set the seed and the number of rows of the dummy dataset.\n",
-                "\n",
-                "Another more advanced possibility for functionnal tests with the dummy is to compare results of queries on a local dummy and the remote dummy with a very high budget: \n",
-                "- create a local dummy on the notebook with a specific seed and number of rows\n",
-                "- compute locally the wanted query on this local dummy with python functions like numpy\n",
-                "- query the server on the same remote dummy with (`dummy=True`, same seed and same number of row) and a very big buget to limit noise as much as possible (don't worry this won't cost any real budget)\n",
-                "- compare and verify that the local and remote dummy have similar results."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "243c73e3-daec-45d6-a3c8-ae1d60439ec4",
-            "metadata": {},
-            "source": [
-                "#### Average and number of rows with smartnoise-sql library on remote dummy"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "d1f8ea18-ccab-4f75-9490-b4d1144b39db",
-            "metadata": {},
-            "source": [
-                "Dr. Antartica will now try a query to get the number of penguin and their average bill length (in mm) on the dummy dataset. She does not forget to \n",
-                "- set the `dummy` flag to True\n",
-                "- set very high budget values to be able to compare results with a similar local dummy (with the same seed and number of rows) if she wants to verify that the function do what is expected. Here she will just check that the number of rows is close to what she sets as parameter."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 8,
-            "id": "3946425d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Number of penguin and average bill length in mm\n",
-                "QUERY = \"SELECT COUNT(*) AS nb_penguins, \\\n",
-                "        AVG(bill_length_mm) AS avg_bill_length_mm \\\n",
-                "        FROM Schema.Table\""
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 9,
-            "id": "90cf2a6d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# On the remote server dummy dataframe\n",
-                "dummy_res = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = 100.0,\n",
-                "    delta = 0.99,\n",
-                "    dummy = True, \n",
-                "    nb_rows = NB_ROWS,\n",
-                "    seed = SEED\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 10,
-            "id": "a30f277e",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Average bill length in remote dummy: 47.51mm.\n",
-                        "Number of rows in remote dummy: 200.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "print(f\"Average bill length in remote dummy: {np.round(dummy_res['query_response']['avg_bill_length_mm'][0], 2)}mm.\")\n",
-                "print(f\"Number of rows in remote dummy: {np.round(dummy_res['query_response']['nb_penguins'][0], 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "167e8c6d-6c93-4ab4-9ba7-bf7e783a6bc2",
-            "metadata": {},
-            "source": [
-                "No functionnal errors happened and the estimated number of rows is very close (if not equal) to the number of rows that she set for the dummy dataframe. She is now even more confident in using her query on the server."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "324454ed",
-            "metadata": {},
-            "source": [
-                "### Get current budget\n",
-                "\n",
-                "It is the first time that Dr. Antartica connects to the server and she wants to know how much buget the queen assigned her.\n",
-                "Therefore, she calls the fonction `get_initial_budget`."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 11,
-            "id": "61a467f3",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while fetching total budget                     status code: 404 message: {\"detail\":\"User Dr. Antartica does not exist.\"}\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"User Dr. Antartica does not exist.\"}'"
-                        ]
-                    },
-                    "execution_count": 11,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_initial_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bc8f7a74",
-            "metadata": {},
-            "source": [
-                "She sees that she has 10.0 epsilon and 0.005 epsilon at her disposal.\n",
-                "\n",
-                "Then she checks her total spent budget `get_total_spent_budget`. As she only did queries on metadata on dummy dataframes, this should still be 0."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 12,
-            "id": "afd22f84",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while fetching total spent budget                     status code: 404 message: {\"detail\":\"User Dr. Antartica does not exist.\"}\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"User Dr. Antartica does not exist.\"}'"
-                        ]
-                    },
-                    "execution_count": 12,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "05daf5a4",
-            "metadata": {},
-            "source": [
-                "It will also be useful to know what the remaining budget is. Therefore, she calls the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 13,
-            "id": "6260cf54",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while fetching remaining budget                     status code: 404 message: {\"detail\":\"User Dr. Antartica does not exist.\"}\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"User Dr. Antartica does not exist.\"}'"
-                        ]
-                    },
-                    "execution_count": 13,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "20298e00",
-            "metadata": {},
-            "source": [
-                "As expected, for now the remaining budget is equal to the inital budget."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b746374c",
-            "metadata": {},
-            "source": [
-                "### Estimate cost of a query\n",
-                "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
-                "\n",
-                "Again, of course, this will not impact the user's budget.\n",
-                "\n",
-                "Dr. Antartica checks the budget that computing the average bill length will really cost her if she asks the query with an `epsilon` and a `delta`."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 14,
-            "id": "fd5ed08a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "EPSILON = 0.5\n",
-                "DELTA = 1e-4"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 15,
-            "id": "133020c6",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 1.5, 'delta_cost': 0.00014999500000001387}"
-                        ]
-                    },
-                    "execution_count": 15,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = EPSILON, \n",
-                "    delta = DELTA\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "3c6a3a8c",
-            "metadata": {},
-            "source": [
-                "This query would actually cost her 1.5 epsilon and delta 1.4999e-4. She decides that it is good enough."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e5379edf",
-            "metadata": {},
-            "source": [
-                "### Query on real private dataset with smartnoise-sql\n",
-                "Now that all the safeguard functions were tested, Dr. Antartica is ready to query on the real dataset and get a differentially private response of the number of penguins and average bill length. By default, the flag `dummy` is False so setting it is optional. She uses the values of `epsilon` and `delta` that she selected just before.\n",
-                "\n",
-                "Careful: This command DOES spend the budget of the user and the remaining budget is updated for every query."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 16,
-            "id": "19e60263",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while fetching remaining budget                     status code: 404 message: {\"detail\":\"User Dr. Antartica does not exist.\"}\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"User Dr. Antartica does not exist.\"}'"
-                        ]
-                    },
-                    "execution_count": 16,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 17,
-            "id": "69767fac",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while executing provided query in server:\n",
-                        " status code: 404 message: {\"detail\":\"User Dr. Antartica does not exist.\"}\n"
-                    ]
-                }
-            ],
-            "source": [
-                "response = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = EPSILON, \n",
-                "    delta = DELTA,\n",
-                "    dummy = False # Optionnal\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 18,
-            "id": "6dbbdf93",
-            "metadata": {},
-            "outputs": [
-                {
-                    "ename": "TypeError",
-                    "evalue": "string indices must be integers",
-                    "output_type": "error",
-                    "traceback": [
-                        "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-                        "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
-                        "Cell \u001b[0;32mIn[18], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m nb_penguins \u001b[38;5;241m=\u001b[39m \u001b[43mresponse\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mquery_response\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m]\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnb_penguins\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m      2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNumber of penguins in real data: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnb_penguins\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m      4\u001b[0m avg_bill_length \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mround(response[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mquery_response\u001b[39m\u001b[38;5;124m'\u001b[39m][\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mavg_bill_length_mm\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39miloc[\u001b[38;5;241m0\u001b[39m], \u001b[38;5;241m2\u001b[39m)\n",
-                        "\u001b[0;31mTypeError\u001b[0m: string indices must be integers"
-                    ]
-                }
-            ],
-            "source": [
-                "nb_penguins = response['query_response']['nb_penguins'].iloc[0]\n",
-                "print(f\"Number of penguins in real data: {nb_penguins}.\")\n",
-                "\n",
-                "avg_bill_length = np.round(response['query_response']['avg_bill_length_mm'].iloc[0], 2)\n",
-                "print(f\"Average bill length of penguins in real data: {avg_bill_length}mm.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b2767e65",
-            "metadata": {},
-            "source": [
-                "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 19,
-            "id": "4ced8a56-e2c3-4bd1-b94b-95cbbcd58a15",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"User Dr. Antartica does not exist.\"}'"
-                        ]
-                    },
-                    "execution_count": 19,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "response"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "39701fe5",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e37c587f",
-            "metadata": {},
-            "source": [
-                "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_smartnoise_cost()` that was spent."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "487f835f",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "eef4afcd",
-            "metadata": {},
-            "source": [
-                "Dr. Antartica has now a differentially private estimation of the number of penguins in the dataset and is confident to use the library for the rest of her analyses."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "04929993",
-            "metadata": {},
-            "source": [
-                "## Step 4: Penguin statistics with opendp"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "b9685226",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "import opendp_polars.prelude as dp\n",
-                "import opendp_polars.transformations as trans\n",
-                "import opendp_polars.measurements as meas\n",
-                "\n",
-                "dp.enable_features(\"contrib\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bbbca191",
-            "metadata": {},
-            "source": [
-                "### Confidence intervals for bill length over the whole population"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9d41bd58",
-            "metadata": {},
-            "source": [
-                "She is first interested to have a better idea of the distribution of bill length of all species. She already has the count and average from the previous step, so she only needs the variance values.\n",
-                "\n",
-                "She first checks the metadata again to use the relevant values in the pipeline."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "4331d86f",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "penguin_metadata"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "f90e0425",
-            "metadata": {},
-            "source": [
-                "She can define the columns names and the bounds of the relevant column."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "ff8cb7b6",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "columns = [\"species\", \"island\", \"bill_length_mm\", \"bill_depth_mm\", \"flipper_length_mm\", \"body_mass_g\", \"sex\"]"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "70b2bdb1",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "bill_length_min = penguin_metadata['bill_length_mm']['lower']\n",
-                "bill_length_max = penguin_metadata['bill_length_mm']['upper']\n",
-                "bill_length_min, bill_length_max"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e93ae087",
-            "metadata": {},
-            "source": [
-                "She can now define the pipeline of the transformation to have the variance that she wants on the data:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "75e4933b",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "bill_length_transformation_pipeline = (\n",
-                "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
-                "    trans.make_select_column(key=\"bill_length_mm\", TOA=str) >>\n",
-                "    trans.then_cast_default(TOA=float) >>\n",
-                "    trans.then_clamp(bounds=(bill_length_min, bill_length_max)) >>\n",
-                "    trans.then_resize(size=nb_penguins.tolist(), constant=avg_bill_length) >>\n",
-                "    trans.then_variance()\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "411d464c",
-            "metadata": {},
-            "source": [
-                "However, when she tries to execute it on the server, she has an error (see below). "
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "8041a647",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Expect to fail !!!\n",
-                "client.opendp_query(\n",
-                "    opendp_pipeline = bill_length_transformation_pipeline,\n",
-                "    dummy=True\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "d06c59dc",
-            "metadata": {},
-            "source": [
-                "This is because the server will only allow measurement pipeline with differentially private results. She adds Laplacian noise to the pipeline and should be able to instantiate the pipeline."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "b8162859",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "var_bill_length_measurement_pipeline = (\n",
-                "    bill_length_transformation_pipeline >>\n",
-                "    meas.then_laplace(scale=5.0)\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "fc7e0ecd",
-            "metadata": {},
-            "source": [
-                "Now that there is a measurement, she is able to apply the pipeline on the dummy dataset of the server."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "df61bce0",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "dummy_var_res = client.opendp_query(\n",
-                "    opendp_pipeline = var_bill_length_measurement_pipeline, \n",
-                "    dummy=True\n",
-                ")\n",
-                "print(f\"Dummy result for variance: {np.round(dummy_var_res['query_response'], 2)}\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "ded11ac4",
-            "metadata": {},
-            "source": [
-                "With opendp, the function `estimate_opendp_cost` is particularly useful to estimate the used `epsilon` and `delta` based on the `scale` value."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "7ae7f735",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "cost_res = client.estimate_opendp_cost(\n",
-                "    opendp_pipeline = var_bill_length_measurement_pipeline\n",
-                ")\n",
-                "cost_res"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1c791d36",
-            "metadata": {},
-            "source": [
-                "She can now execute the query on the real dataset."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "085555a5",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "var_res = client.opendp_query(\n",
-                "    opendp_pipeline = var_bill_length_measurement_pipeline, \n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "674332e7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "print(f\"Number of penguins: {nb_penguins} (from previous smartnoise-sql query).\")\n",
-                "\n",
-                "print(f\"Average bill length: {np.round(avg_bill_length, 2)} (from previous smartnoise-sql query).\")\n",
-                "\n",
-                "var_bill_length = var_res['query_response']\n",
-                "print(f\"Variance of bill length: {np.round(var_bill_length, 3)} (from opendp query).\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "367081be-1159-45d8-9129-88fba20fb697",
-            "metadata": {},
-            "source": [
-                "She can now do all the postprocessing that she wants with the returned data without adding any privacy risk. "
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "f72b19d0",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Get standard error\n",
-                "standard_error = np.sqrt(var_bill_length/nb_penguins)\n",
-                "print(f\"Standard error of bill length: {np.round(standard_error, 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "62630a03",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                " # Compute the 95% confidence interval\n",
-                "ZSCORE = 1.96\n",
-                "lower_bound = np.round(avg_bill_length - ZSCORE*standard_error, 2)\n",
-                "upper_bound = np.round(avg_bill_length + ZSCORE*standard_error, 2)\n",
-                "print(f\"The 95% confidence interval of the bill length of all penguins is [{lower_bound}, {upper_bound}].\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0d30d98e-26f4-44ec-a0f0-7a039f344860",
-            "metadata": {},
-            "source": [
-                "### Count per species"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b6a3cc00-8734-4479-81a3-781c91b8eb06",
-            "metadata": {},
-            "source": [
-                "She can also creates an histogram of the number of penguin per species.\n",
-                "\n",
-                "She first extract the categories from the metadata:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "558916a6-78a9-4589-abe8-41472f0c66d7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "categories = penguin_metadata['species']['categories']\n",
-                "categories"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5f05aeb0-42d1-4444-a458-d2989494f544",
-            "metadata": {},
-            "source": [
-                "Then, writes the pipeline:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "505a2793-6750-4f2a-9a9d-09f3a4ae4099",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "species_count_pipeline = (\n",
-                "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
-                "    trans.make_select_column(key=\"species\", TOA=str) >>\n",
-                "    trans.then_count_by_categories(categories=categories) >>\n",
-                "    meas.then_laplace(scale=0.5)\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0f4109a9-c2f2-4365-bfa1-b5b2512919f9",
-            "metadata": {},
-            "source": [
-                "Verify it works on the dummy:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "712b1c74-cac6-4b3f-9421-8d8ffa9debc7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "dummy_res = client.opendp_query(\n",
-                "    opendp_pipeline = species_count_pipeline, \n",
-                "    dummy=True\n",
-                ")\n",
-                "print(f\"Dummy result for histogram: {dummy_res['query_response']}\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "66de7794-9aae-41d1-ba98-6b234a05d6f8",
-            "metadata": {},
-            "source": [
-                "Checks the required cost:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "3f942b1b-94bc-468e-8374-3034f2e6b8ce",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "cost_res = client.estimate_opendp_cost(\n",
-                "    opendp_pipeline = species_count_pipeline\n",
-                ")\n",
-                "cost_res"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1adfe446-ff13-41f4-9f3c-9998e2ae0f00",
-            "metadata": {},
-            "source": [
-                "And finally apply the pipeline on the real dataset:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "c6fe47b7-048e-404a-bedb-720e734b0c70",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "species_counts_res = client.opendp_query(\n",
-                "    opendp_pipeline = species_count_pipeline, \n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "b8d5fd82-5ded-47ec-8135-f6870865055d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "for i, count in enumerate(species_counts_res['query_response']):\n",
-                "    if i == len(categories):\n",
-                "        print(f\"Species Unknown has {count} penguins.\")\n",
-                "    else:\n",
-                "        print(f\"Species {categories[i]} has {count} penguins.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "94eaf59b-c108-424c-8978-b1c86e141ccb",
-            "metadata": {},
-            "source": [
-                "## Step 5: See archives of queries"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "64003c53-de56-4bdc-a3c2-0c3e40031919",
-            "metadata": {},
-            "source": [
-                "She now wants to verify all the queries that she did on the real data. It is possible because an archive of all queries is kept in a secure database. With a function call she can see her queries, budget and associated responses."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "008fd230-cdfd-4e03-91ce-5a60b06c106d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "previous_queries = client.get_previous_queries()\n",
-                "previous_queries['previous_queries'][-1]"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "422536e7-2fd5-441f-a28d-14ffa9014084",
-            "metadata": {},
-            "source": [
-                "# FSO Example: (Synthetic) Income dataset\n",
-                "\n",
-                "## Boxplot of income per partitions of the population"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "ee11c6c2-c474-4d08-ae03-3523643ba61f",
-            "metadata": {},
-            "source": [
-                "### Disclaimer: Temporary Version of OpenDP with Polars"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "71109933-5837-4c22-bebc-4c82142ef548",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Import library\n",
-                "import numpy as np\n",
-                "import pandas as pd\n",
-                "import polars as pl\n",
-                "import opendp_polars.prelude as dp\n",
-                "\n",
-                "dp.enable_features(\"contrib\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "2663f674-bc04-4b79-a240-80ef84860f19",
-            "metadata": {},
-            "source": [
-                "### Switching user and exploring new dataset\n",
-                "\n",
-                "Let us now change user and select another dataset to play with. For this example, we will use an income distribution dataset (synthetic) from the Swiss Federal Statistical Office."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "bb0e35e1-357d-4291-a211-15a815bd68af",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "USER_NAME = \"Dr. FSO\"\n",
-                "DATASET_NAME = \"FSO_INCOME_SYNTHETIC\"\n",
-                "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)\n",
-                "\n",
-                "fso_income_metadata = client.get_dataset_metadata()\n",
-                "fso_income_metadata"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "729e0423-e7fd-4edb-ae44-d12cf0844de0",
-            "metadata": {},
-            "source": [
-                "Let us also check how much budget we have."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "7f6da2fd-0387-4b12-8630-07b6b3d11650",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "48af044f-5279-4e39-ba85-dd96fd5cac64",
-            "metadata": {},
-            "source": [
-                "### Data preparation"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1d43022a-0df2-4740-8c48-ef7776a8c0fc",
-            "metadata": {},
-            "source": [
-                "#### Column types and bounds"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "7d0cc01a-76ca-4bf3-840b-f2ec6a2cd9b9",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Income bounds\n",
-                "income_lower_bound, income_upper_bound = 1_000.0, 100_000.0"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "32d6854b-510f-411b-8f73-127663686ac3",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Define dtype domain with bounds\n",
-                "lf_domain = dp.lazyframe_domain([\n",
-                "    dp.series_domain(\"region\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"eco_branch\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"profession\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"education\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"age\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"sex\", dp.atom_domain(T=int)),\n",
-                "    dp.series_domain(\"income\", dp.atom_domain(\n",
-                "        T=float,\n",
-                "        bounds=(income_lower_bound, income_upper_bound)\n",
-                "    ))\n",
-                "])"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5b539720-91b7-4c98-927d-58f641739f2f",
-            "metadata": {},
-            "source": [
-                "#### Counts per partition of the population"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "94c6c379-e5f5-41f7-a721-71f1b57f9915",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Total\n",
-                "total_counts = pl.LazyFrame({\n",
-                "    \"counts\": [2_032_543]\n",
-                "}, schema_overrides={\"counts\": pl.UInt32})\n",
-                "\n",
-                "# For sex\n",
-                "sex_counts = pl.LazyFrame({\n",
-                "    \"sex\": [0, 1], \n",
-                "    \"counts\": [634_720, 1_397_823]\n",
-                "}, schema_overrides={\"sex\": pl.Int32, \"counts\": pl.UInt32})\n",
-                "\n",
-                "# For region\n",
-                "region_counts = pl.LazyFrame({\n",
-                "    \"region\": [1, 2, 3, 4, 5, 6, 7],\n",
-                "    \"counts\": [352_001, 474_690, 267_304, 366_879, 284_638, 210_800, 76_231]\n",
-                "}, schema_overrides={\"region\": pl.Int32, \"counts\": pl.UInt32})\n",
-                "\n",
-                "# For region and sex\n",
-                "sex_region_counts = pl.LazyFrame({\n",
-                "    \"sex\": [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], \n",
-                "    \"region\": [1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7], \n",
-                "    \"counts\": [113_367, 148_265, 83_326, 113_715, 87_668, 64_357, 24_022, 238_634, 326_425, 183_978, 253_164, 196_970, 146_443, 52_209]\n",
-                "}, schema_overrides={\"sex\": pl.Int32, \"region\": pl.Int32, \"counts\": pl.UInt32})\n",
-                "\n",
-                "# Add counts to margin\n",
-                "lf_domain = lf_domain.with_counts(\n",
-                "    total_counts\n",
-                ").with_counts(sex_counts).with_counts(region_counts).with_counts(sex_region_counts)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "4bff5ce4-2758-4454-ad58-497511c278be",
-            "metadata": {},
-            "source": [
-                "### Income distribution for partitions of the population:\n",
-                "#### Prepare the pipeline"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "8aada47e-cbc5-451b-9f1f-7b7311f29b63",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Prepare a list of candidates\n",
-                "candidates = [x * 250.0 for x in range(8, 52)]\n",
-                "print(candidates)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "7ac3e2b5-92b6-4fdc-a8be-09a18f2f9c06",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Partitions\n",
-                "PARTITIONS = ['sex', 'region']"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "7099c026-e677-477d-9df0-60e406498303",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "metric = dp.symmetric_distance()                                     # Input metric\n",
-                "expr_domain = dp.expr_domain(lf_domain, grouping_columns=PARTITIONS) # Expr domain (Groupby)\n",
-                "temperature = 1000.0                                                  # Noise parameter"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "382562c8-0a5a-4ece-a351-1381d10ff892",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "def make_quantile_pipeline(quantile):\n",
-                "    # Create expression\n",
-                "    return (\n",
-                "        (dp.csv_domain(lf_domain), metric)\n",
-                "        >> dp.t.then_scan_csv()\n",
-                "        >> dp.t.then_groupby_stable(PARTITIONS)\n",
-                "        >> dp.m.then_private_agg(\n",
-                "            dp.c.make_basic_composition(\n",
-                "                [\n",
-                "                    (expr_domain, dp.l1(metric))\n",
-                "                    >> dp.t.then_col('income')\n",
-                "                    >> dp.m.then_private_quantile_expr(candidates, temperature, quantile)\n",
-                "                ]\n",
-                "            )\n",
-                "        )\n",
-                "        >> dp.t.make_collect(lf_domain, metric)\n",
-                "    )"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "29f5ff59-b411-4714-b273-0a5e47a946a4",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "q25 = make_quantile_pipeline(0.25)\n",
-                "q50 = make_quantile_pipeline(0.5)\n",
-                "q75 = make_quantile_pipeline(0.75)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "20f77fb2-390e-4c30-a34c-a0f235eb08d4",
-            "metadata": {},
-            "source": [
-                "#### Apply pipeline on data"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "20e27602-0b4d-414c-a20a-562068d76965",
-            "metadata": {},
-            "source": [
-                "Let us first try out the pipeline with a dummy query and then estimate the cost of the different pipelines."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "577c8059-bda2-4f9f-a6bd-10cec7e8aa03",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "dummy_r25 = client.opendp_query(\n",
-                "    opendp_pipeline = q25, \n",
-                "    dummy=True,\n",
-                "    input_data_type=\"path\"\n",
-                ")\n",
-                "dummy_r25"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "d56609e0-f28c-4d71-b7ca-80509acaa2af",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "cost_q25 = client.estimate_opendp_cost(q25, input_data_type=\"path\")\n",
-                "cost_q50 = client.estimate_opendp_cost(q50, input_data_type=\"path\")\n",
-                "cost_q75 = client.estimate_opendp_cost(q75, input_data_type=\"path\")\n",
-                "\n",
-                "print(f\"The estimated costs are respectively {cost_q25}, {cost_q50} and {cost_q75} for q25, q50 and q75\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "678d7741-e154-4c53-8834-5b76fa1298f5",
-            "metadata": {},
-            "source": [
-                "Since our budget is 45, we know that we can execute these three pipelines remotely."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "fbf3b57e-3e66-4f98-b18c-39b183a80aa0",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "r25 = client.opendp_query(q25, input_data_type=\"path\")\n",
-                "r50 = client.opendp_query(q50, input_data_type=\"path\")\n",
-                "r75 = client.opendp_query(q75, input_data_type=\"path\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "34e2780e-2fc2-4b6f-86f0-d66522346149",
-            "metadata": {},
-            "source": [
-                "Let us put together the results and show them in a table. Notice that the output is a polars dataframe, we thus need to transform it to a pandas DataFrame if we want to work with pandas."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "bd36778a-ed94-4540-b803-4c8911a6da67",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "r25 = r25[\"query_response\"].to_pandas()\n",
-                "r50 = r50[\"query_response\"].to_pandas()\n",
-                "r75 = r75[\"query_response\"].to_pandas()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "811e715f-888a-4946-937f-7f75d011843b",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "results = pd.merge(r25, r50, on=PARTITIONS, suffixes=('_25', '_50'))\n",
-                "results = pd.merge(results, r75, on=PARTITIONS)\n",
-                "results.sort_values(by = ['region', 'sex']).head()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "16aa6910-25da-4c49-ab44-92cc4418f9d6",
-            "metadata": {},
-            "source": [
-                "#### Visualise results"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "77f053b5-66dc-4252-b5ec-4a2ec3df3076",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "import seaborn as sns\n",
-                "import matplotlib.pyplot as plt"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "58de1e66-75f4-4be0-b4a8-19352250d897",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "def quantile_data(q1, q2, q3):\n",
-                "    return np.concatenate((np.random.uniform(q1[0], q2[0], size=50), np.random.uniform(q2[0], q3[0], size=50)))\n",
-                "\n",
-                "results['data'] = results.apply(\n",
-                "    lambda row: quantile_data(row[\"income_25\"], row[\"income_50\"], row[\"income\"]),\n",
-                "    axis=1,\n",
-                ")\n",
-                "results['sex'] = results['sex'].replace({0: 'woman', 1: 'man'})\n",
-                "results['region'] = results['region'].replace({1: 'Lemanique', 2: 'Mittleland', 3: 'North-West', 4: 'Zürich', 5: 'Oriental', 6: 'Central', 7: 'Ticino'})\n",
-                "results = results.explode('data', ignore_index=True)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "65b63c19-d710-4368-9dbd-88a737fd793f",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "plt.figure(figsize=(10, 6))\n",
-                "sns.boxplot(x=\"region\", y=\"data\", hue=\"sex\", data=results, palette=\"Set1\", width=0.5);\n",
-                "plt.xticks(fontsize=12)\n",
-                "plt.yticks(fontsize=12)\n",
-                "plt.xlabel('Regions', fontsize=15)\n",
-                "plt.ylabel('Income per month (in CHF)', fontsize=15)\n",
-                "plt.title('Income per partition of the population', fontsize=16)\n",
-                "plt.show()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "acd4e078-f92d-4edb-835a-a891a15e08a5",
-            "metadata": {},
-            "outputs": [],
-            "source": []
-        }
-    ],
-    "metadata": {
-        "kernelspec": {
-            "display_name": "Python 3 (ipykernel)",
-            "language": "python",
-            "name": "python3"
-        },
-        "language_info": {
-            "codemirror_mode": {
-                "name": "ipython",
-                "version": 3
-            },
-            "file_extension": ".py",
-            "mimetype": "text/x-python",
-            "name": "python",
-            "nbconvert_exporter": "python",
-            "pygments_lexer": "ipython3",
-            "version": "3.8.18"
-        }
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "3f18d338",
+   "metadata": {},
+   "source": [
+    "# Secure Data Disclosure: Client side"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1582a2ae",
+   "metadata": {},
+   "source": [
+    "This notebook showcases how researcher could use the Secure Data Disclosure system. It explains the different functionnalities provided by the `lomas-client` client library to interact with the secure server.\n",
+    "\n",
+    "The secure data are never visible by researchers. They can only access to differentially private responses via queries to the server.\n",
+    "\n",
+    "Each user has access to one or multiple projects and for each dataset has a limited budget with $\\epsilon$ and $\\delta$ values."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "23bb4f13-7800-41b2-b429-68c2d02243d0",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAABOgAAAJOCAYAAAANqjggAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAJ10SURBVHhe7d0JlBx1oe/x/2SfJJNM9klmsq+EEEJCCGtYZF80AiIgCgpccUGP6MN3vd77fFflenmKxwWv+5WrIqIoKJuAEMIiIawhhIRsJJns2ySTZLLn9a/6XzPVNVW9TC/Vy/dzzpypqu6urq2run79X6qOxhgAAAAAAAAAkehk/wMAAAAAAACIAAEdAAAAAAAAECECOgAAAAAAACBCBHQAAAAAAABAhAjoAAAAAAAAgAgR0AEAAAAAAAARIqADAAAAAAAAIlR1NMYO58wtf11hhzLX0Keb6d6lk6mv6WZOrO9tJgyoto+g3Pxp8TazYsc+s2XPQbNr/2E71ZhBvbo6+39mbP/PGNbbTi0e//36ZjO/sdmOdUyf7p2dv5rY3/A+3c0ZI/s46w3kyjeeXWsadx2wY21mNdSYj58w2I4hKnPf22nue2urHUv048vG2qHcKOR7AQAAAOiYoitBpxvKFdv3mXmrd5m7Xlzv3GS+un63fRTl4LFlO8ztT7xnnljR5OxrbzgnCuze2LjH/OzVTc7+f3dbi32kfGidday/s6XF2Q7/+vQa8+MFG511BwAAAAAAlaXoq7gqxFBQo9JWKH0KoR5asr1dKBdG+//ulzdWREirUPL78zcQ0gEAAAAAUGFKpg06lTJS1UKULoWsCqEytf/QEfM/b26piOBK6/irNzjOAQAAAACoJCXVSYTa/aIkXWlS8PTs6l12LHMK6e59a4sdK2+q9qtqwAAAAAAAoDIUtJOIZI2Tqwrj5j0HnfbGVu7Y7wQyQdSBxGdOqqPziBJz78ItTruCftqfZ47s09pJghoz//vKnaGl5W47dVjk+z5ZJxHpNLiuY3zRpr3mpdg8wqr6alt8/ZwRdgzIHJ1EwEUnEQAAAEDxK5oSdOqt86Lx/cznTx7mBHBhPVoquKN0Uel5Z2twRw8fPKa/uXzygNb9fdaovuZzs4Y6wV2QV9aVflt0Chi1zv/rtPrQ9VRAWY6dYwAAAAAAgPaKsoqrAgyFNGEhnXq+JLwoHQqbgkrEje3fwwnk/LTfx/TrbscS7T+c8wKfkdF6zqrvbcfaW9/cvvQTAAAAAAAoP0VTxTVIsmo5mcxL7dat2LHPCYm8VQob+nQzA3t2NZMGVQcGRR2l5X5z4x6zbteB1vfr072zqY+9n0oJBlXR1LI9uaLJrIwtp7dampZxTL8e5ryxtaGBZSoKM19Y0xxbnv1my95DCdWH87UN/LRNtsfee2dse2g5tF2OGdQzdB+GVSMthup52VZx9crFMa79+/TKnWbr3oMJx46OOR0z9TXdOnz8qOr5wk17W/eZv0qu5ukc27H3OLG+d4erH+fzM6rto5KX+myFrUP3zlXO5yybdfDSfvVW1dZ6TI4d7yo5mYxet2RLS7t9qZKWg3p2cbbFzNgyqsRxKulUcc3XeSefx2QQvZ96h1b7jaL5avkvndAvJ+/hHkPrmuPndHe/urRe8XN8dzN1SM+09k8uuNtZy+Uuk44V7b+xsfV3j7dk55l0z1mah65rW2Pnce/6a/sOjB2bw2Prnur4BgAAABCuqAM6+den17S7GRLdFKRqo0s3FI++u6PdDXkQ3dAoPEt1YxV006vXfvXM4c5yPpBGT6Xnx25MvTcyqrL7+PKm0Hb3RDddHzt+UEY3frp5u3/R1sCb9CC6wbw4dkObz6AuXWH73b/t/MKOvauPG5iz9SqWgC7d4010/Eyr65X250/z/skrG9M+dlx6jyti+yfdUCQfn1GvHy/YmHHPwemsQ9Bx5p4HFDaq1+kgmvctM+vsWBsFoToPpLu9Vfr0hmmDky5jqoBOy6mOW1Kdd9RGZLrBS76OybB10edN2069PAetRzrXiVQ6cgzpWLhqysCkYW82oVm621nrP2dSf9N84HCH3yuT64iuIWeP7ut8TgEAAABkpuh7cVUpiCC6QdFfGN186oYknRt/0c2HbvL0uo7Qsnx//oa0buR08+6+j/6r5Eeym2TR41o+3YymQ/O968X1ad/wi7aVtpluSKOkZQ/at7qhV2cSlaJv7GY3TCbHm+j4UaiooCPZ50Z0jH1jXmNGx45Ly6PlSvUeov2cz8+oQt5MgxVx16EjtO3CwjlR6Tc/rc/PXt2U0fZWSTHto3TPB37qtEXLmc55x3u+Siafx2QYve73i7aGrscxAzteGlLz7ugxpH1598sbO7x/kslkO+u5+sys78BnWbT8Wo90j019lnU9i/oaAgAAAJSiog/oRoe0RSZvb9lrhxLpZjLZTXIY92ZUJRsy9as3Nmd0k6mSK+5Ncrq0fA/Gbn5S6ej6u3Tj972X1tuxwtHNoEqnhS27StukWzKrVKzasd8OtTeyNvjYd2/QMzneXLrRVsm4ZHSMhQUe6dBy6fOQTL4/owoIOrJ9XHqtjsVMqH1EhUVhdOz6S/9l81l1zweZrqeqswb1qJyMzlcqSRVGy5DPYzKMjrNkAa+q0XaUSqhlcwxp/+h4yGYeQbStMpmnliPT/S06H4eVTExF15BMPz8AAABApSv6gG5YTTc71F5QqQDdVGQTTsmf38nsplc3mG7bR+nq6E2TlitZOKHHsl1/UUcchbrBUkihKoMqRRRWdfSYQdUZV48udjpWw0rBqLRgWFXOTMNgPx2vYftW+yIXgYI+D2HHab4/owqSOlLqye+dkB8Awmh5koVF/tJcWk4FX9nQez78bma9Wndk/+p8pXYsw+TzmEwm2XlX1YA7Gujn6hjS8ZDp/klGn09tq3zTvkxWMjEdOpd35McuAAAAoFJ1/lqMHc6ZsBuShj7dzQlDe9mx9Azo2TV0fnU13drN75evbQq8SVbgceKw3ubDUwaa66cNNhNiN8tHjhqnIwe/w7EH9h48ErisCtWS3YTrpvDKyQPMP51YZy6d2N957uqd4aWkXCoddu3UQa3Ltjl2g7Sj5ZB9NFGvbp1Dt+OPXt4Y2tOp2kVS+0BfOGWYs2xDY9uva+dOgdtANF3PSRaS5sJLjbtDl0HUZlZQu11Bwo6VKUN6mlG1wdWlM6Ub97Dl1XZNRjf+b23ea55Ztcv8bUV4FUMdq0H7WDe8z4WEOv7927lTldkeO4Z0LPupoXe9h44lL22/oONOAem5Y2vNZ2cNdeatPx2nNbHXNzYfcD4zfoePHjUnx/adX74/o79ZuMVZPz+FNSpR5W6fVNtInyMde/5tJB0JXW6aMSRhXlrOjbuDQy1t7w8e03YeORBblrDtrO0TtJypzlX+7ZHqvFMV+5sd0I5jvo9JSbUuQWaP7GPGd7DDj78tbwo8b7vrc13sXK3jVOukba+218LWqzm23EEl+d5r2m8Wxc4FQTTfIAox0z2/a1vvOdC+UxS/oPe6/+1tTknLIN5jU+veNfY+Ycdm075DgccMAAAAgPaKPqCTdOenkjlz3wu+UfzECYOdDhAU+In+67W9YzdWQTdJulkMaug62Y2iblxuO7U+IdA6bkgvp8RD2I24qOODj04bnLBsp43o47xX0M1Yjy6dnMf9VLpi8ZbgamhatttPb0i4YdVyahsohHs79rqgGyz1uhr0XrmkkhbJggo12B900x4k6oBO75/s7x9rm53jTa8P2t6im32VFgxa5z/EbpyDAhQFw/98RuL+1fA5sRt2La//mNV760/Hp9czq3a2e66CHM3bv/10nKon3sGxx3X8DO0d7zlTDeOfMqLGXD1lkH1mm0J8Rn/31tZ221bhnwIyf2CobXTc4J7OegcZElunoONG+zKM3ut9se3+v06vd8IP/Sn8GtG3rcqygtq/Lg2eh4Klm2fUJZxHvNs56LgJ2pfJzlUKcz5z0lBzfF3ba9zzzjtbWwKPMc0rKMzJ9zEpqQI6J8Q/sa41NNP2DgqH0/XK+uDP+P86rd7ZZt7Ppobd40jHtz4v6rF7bP9qp83MOZOCz1+ZBnSat84fQYLO7xpWOKbekYMCa1fQe6lEZNBx5j82tV46NhWsvhhbNv9rtM8K8SMPAAAAUA6KvoprJhZuCr7Z0c1LWHVB9eypx/1Uskm9Kmbi2uPaBxIyKWD+Lt0oh/WQGNZBRlipq9dDqmTpPT5/8jA71p62zayAxutFVcgUJuTT1r3h4aWq2qqh9nQbHVePhEF/xdAzbToU7ihk0E1+kLAqfR+YFFziRtSbZBAFMenQTbbCgTA6fr530WinB1OVdFRJ0LDtXYjP6GdOqnN67VVo41ZzVPXSsB419bg+I7ly4bj2PQ373/uVdcHbU+Gstl8QbZ+wTg/S3ZcuHRNhx1hQRxbJRHFMerk9wXrXJ1nvqdkIKykoev87zx/lfA50vtUy6dgN286ZCvvs6JwRdu0RPabnpEslIoOuMcmOTa2jevsNsiDkWAcAAACQqKwCunW7gquSekuJBAm7mVvdlLpqqks3+GE3YqoGGCYshJNMbqrUZlBYG1BBpYz8dOOlG7Agi0JuDAtJJW4U1GXTzlWxi5dqqgsNqsLac9LrkgUSeizo2Aw6ZoKOOd2sq31AbX9VscumXalCfEb1XAUjCkhU4unr54xIu4p0tvQZSufztq45uASmSiMlo7Bf76F9rgBSJZoURn5u1lD7jNRSHS/HplgGr0Ick6mcMyb34Xv3zqrQ257aTrz9ifecHwwUDhfyfBT22VFomywE1GOZ9GYb1nFNqmMzrIftsGMdAAAAQKKyCujCGs9OVb2mumvwZkhWssuvvk94b7NhgYsMi93I5kJYj7a6mU/2/l5hYeHakBvDXNHy3XbqMKekm8IUhQ5BQZFuhu99a4sdKx8q5aXSRip5kyzUCLtxrgkJVr3CAgf/cTM2SWCs7a/qyPe9tdXp1OMbz67NOKiI8jPqp1KB6kn5/72wLmcN7ycL3L3Cqmsm67VaFDy6pbQUQLqlFZMFNH7JzlWSybwKcUwmo2VN9pnpqBOTlCLUvtMPBg8t2e6E1vpTr9dqYiCfpY3DjplkJbRdYT1CBwkLAvum2Kdhx00hQ0wAAACglFUdjbHDOaOb9yAq8aGbykylO7+w53WUwi3dDHsplAi6mU+1bmHLdvOMIaEBmkorBfVqqtIpukH3yuS5YRRWqK0nv0zmkSsKT1RqK0iybVYIYds6UwrmbpiWWDUvmVy9r5faP/RXx+xoSUWtjwK+sCrbUojPaBAFJyoJqk4QFOqlG8ipdJoCML+w9VC4HFYN0Cvs9WHv1xEdPVdJuuerQh2TYeuiY06lJPNB4bOCuEzp86wSa+oYItlnW6UPFXYH0Y8VftkcM5m8V9i2zoZ+gMlHkAoAAACUk6IvQRflr+9hJRZyKcqgyS9XpflyQdslqN0xeX5NeDtQUXPbvNOfbkoVNihECqK2u74/f0PS9t3yTZ2A+Km6ZLqhoZfWx60CmE012Ewk+4wqlFPIouW568X1zrIpcMl1+OBVTJ+hfGg+kP9zYtAxGWag7VAkH1QtOuwclIyuWfqh4xvzGp0fPWDMeqq5AgAAACkVfUCXrLpTqupgKG1hJS6S9UhYTLT8KgmkEj5hN/q6mf+fN7dEGtL5KZxTSKeSVpm0g+hSaKbSOpl2spJLKtmlUC6ot1AgXersIVnInozablRQl24HNwAAAAAqW9EHdOuTlHZJ1W4VMpNsW0chrN2xUmvTSIGXelIMK5WmG/liDOlUDVK9s6p9PAWMmYYUjy9vimRfKRBJVe1S66d1UpVUVdtUNW4giEJ2VaPWcaIeY8M+x2EUEheqRCkAAACA0lX0bdCpAXdVnfMLansq7H2D2vPpqFy3QZds2TJpVy6sjaF02+iSsDaXdFOaTS+YCp6Wbm0x+w8fddr/UiClbZiqXaJM22gqlGTtbiVbLlW5vPvljc76B9GNvzrJCBP2vh35XHWUty039c6YKoDztyeW789osrYLFcipt9ig9rrCPteZtkGXbhtyYe38KQxNpxfYdOSjDTr/+hXqmMxmXfJB++6V2LG2cXfsc7Brf+CyeenYU2k8r0zPb9kcMyrNqk4tgvjfK9PPAgAAAIDcKOoSdAoDgsI5OWZQTzvUJqxkQzGVTMqXYwO2h6h6X7rrv3JH8LYenGGJET/dHKqql27ktT/dmz8FPclsD6nKmmkJlmKhMPLCcbV2rD3dfCerDlfXO3i9s+nJNFNutV0FtgoT9acQLqwqrL89sXx/RsPaJ1SQo4CkWAKGsNKIq5tS95isNvUUoqjnUAVkCnp0roxCMRyTUdBxrFBM4aB+LFHIpaAs7PhuzkE162yOmUyOj7B2/YqthDUAAABQboo6oAv7xV9OG1Fjh9rUh1R5XbCu/AM63RiG3Rym0xaYGjMPa6vrjJF97FDH1PcJbitwcZL2BSXs8YE9u9ih0qObepVIDJOsOtyJIR2KKPRMVZItXXrvPy3e5gQ/Kr2qUjsKgsLomFNgl2ydvPL9GQ0LQlK1V7mlwO0ahm0HheTJ9qWCTH1OFXK/s6XFCb1VCkvt7YUdN/lUiGMyCtrOOm/qc6DjX4GogtFk9Nl+35j8BcBhx8w7W1uSbms9tnJH6hDPNbI2+LOi9wEAAACQP0Ub0OnGKLz0XHVg1chJselBFHokK6GjEEJ/CiT0vroxy1WJnkI6ZmDw+utmPlnIonWdHxKQaFuHBX/pmjokuHSflkthUBBND6pmJcmqxZaCKyYPSNqe299XBgct2g9hbaX96o3Ndqg9Hc+ff2yVEzKohJ7CWIU5/pt6PaawR72duqUd9RwFQak+D+mWmIrqM7oqSUChz0ZYteN8ObE+ONhS+HbvW+E9fz69KvjYUAnGKEoH5vuYjIKWTdWk9QORPgc6/nUucvZNil5Z81nKLOyY0bGb7JjRfsjk+FboGlQiVvsm2fprP7qlO/UZ1Tk8itAYAAAAKFWdvxZjh3Pm4XeDS2w19OluThgaXtJGX+ZfXNNsfv3mltDqlrpxuHbqIDMgoBrOqNoeTlVKtXXm99qGPU4pmV7dOrW+Vjdiv1+01WlHaO/BI2ZHyyGzLnaDpfbS9PwDsfn4q9Jq/kElzVKtW9g2uXRifzvUnkILLY+fwp3ZATfjdb27mRfXNpvDR9qvv3o+1fz2xNZzvA24FHD8bXmT+cvS7YGvSbatM6HOPPTeQdtthUoMefaLqmL9ZWm8SmwQrfunTxpqx9pT21na1v6/3rHX6fjIhbD9Isn2p6tXt86ma+cqs2hzcAlBHYvaJkHHk/ajtpmfjl2FrLoRd/evuy2fj32mNF3bX8f66p37nffW/j9vbFuV2z49Opt/xI6fIG9vaXFee+To0YTOWfQZenDJ9tAwXTf77vJIvj+jYZ9PvcY7b4UNOvYfWLwtaemiKUN6Bh43OqaChD3fT8ug/RjUI7GmqbRSj9jnz93W2le/Xbgl6Xb2Hy8dPVdJJuuXz2PSlc26ZErLGnaMajm1rvtiy+7dDlruvyjQC/mhY0y/Hu0Ctvea4uscJOg8omMm7DwadH7XZ0edz4T90OHyv5fOT9pPQcem1j/o2PzD21udddE20/Lp86btpGn6f3JD+xLvAAAAABIVtJOIXPA3Ou+nkC+s4e1MqGRIUIP9Kh0QdMOTqrHyjjSOr1IIQQ2wB3US4dJNWbKqwZlQD5cK6HIhV/slVUPl2Tben46w/SKZdHagEie6qQ4T1olG2DGYqaDG5VWaTCWGckFhalAHJfn8jKbappkKO25ycZwpBEnWaUi6FKR/dXZDu5KuHT1XSabrl89jUrJZl45Q6S+VJM2VoM9yss9B2HkkV58dr6D3UoD9jXmNOTk2P3NSXcmXegYAAAAKoajboPNTO1fJwjnRzaOqZWZDNxVzYjeKpShVG2fp0jbMVTgn2i8K/LKhcDbd8KMUpKrqev+i4Btx7WMdo9nQ/g0KQq49blC7oKejPjxloB1KlM/P6DkdbAMsbHsmqxqbLYUWZ2b5mRB1PJKrfdZR+Twmo6DrTLbHqEvnvVwFVPrsKJTsiEz2j46nXBybmgfhHAAAAJCekgjodGOhcEY9R6ZDvTV29OZK7/Wx4weZGSGNn5cCbadswjC3x8tcU+DX0ZvLVCUnS5Fugi+eEB5IqMRQUJtPOjZ1jHY0ENFnI2z/apk+N2toVoGP+3lN9hnK12dUYYDeOxNaV5XyCZLv3kh1TGe6vF56bTGEWvk8JqOSzTHq0o8lufyhQ1RiMNPl0vMHZdi5Ti6OzXI7ZwMAAAD5VPQBnW4sdPOc6Rd93VzpBiGTG0ZVHdV7lXI459JNoapVje2ffrtrWn9VYctHlTGX5q1qbMlKjnnpeVqmcr3RU4mYZCUe1aZVUMP5OkZ1rGayf/VZUHCbKghRYKWqowpTMw1cdAwpqElnf+XrM+oGC+nMV9tegaSCPc3brxC9kWp5b54xJPD9wxTj5yKfx2RUtFyZnK9cer5el+6PSpnScmm7pXOMZ/ODi44vHWeZBPblfs4GAAAA8qWgnUSkopuNob27mvrYjer0ob3NDScMNueMqW1tMD5TajxepUvUkHy3LlWmqqrKaWje5b6fGvC+bGL/2E1F6g4ROtpYedg2yWUnEX5al9NG9DETBlabrp2qzOGjR51GvL0dQigU0PqfNbqv+di0wWk1cJ8tNWKuhuDD9otuBkfWdneWXR1CZLJM2Tben46w/SLpdBLhp3VVQ+tBjdJrX63Zud/ZFn7e/atdWhWb5t+/2pZDa7qZmcN6m48eP8icPDz9Eow6ntX5gI4d7Sc1DO8/9nUs6j30Wbs49lnTZ8jbiUQq+fiMiuaroMjdLt7l1vIqkFOIfcG4fk6j+LJix/7A/arl8X+2c32caZvpM63OTLrEtrf+/Nva+1m9eUZdyvcpVCcRXvk6JgvZSYSfe77qHNsn1bHjUfvGv07e41SBmM5bbmcNYTLtJMLvuCG9nGO8JXZ86tTh/dzoWFH4fMWxA8y5sWuohG3DVO+l/X1O7JhLdWzqut2RczYAAACAuLx0EgEAAAAAAAAgPZnVXwMAAAAAAACQUwR0AAAAAAAAQIQI6AAAAAAAAIAIEdABAAAAAAAAESKgAwAAAAAAACJEQAcAAAAAAABEiIAOAAAAAAAAiBABHQAAAAAAABAhAjoAAAAAAAAgQgR0AAAAAAAAQIQI6AAAAAAAAIAIEdABAAAAAAAAESKgAwAAAAAAACJEQAcAAAAAAABEiIAOAAAAAAAAiBABHQAAAAAAABAhAjoAAAAAAAAgQgR0AAAAAAAAQIQI6AAAAAAAAIAIEdABAAAAAAAAESKgAwAAAAAAACJEQAcAAAAAAABEiIAOAAAAAAAAiBABHQAAAAAAABAhAjoAAAAAAAAgQgR0AAAAAAAAQIQI6AAAAAAAAIAIEdABAAAAAAAAESKgAwAAAAAAACJEQAcAAAAAAABEiIAOAAAAAAAAiBABHQAAAAAAABAhAjoAAAAAAAAgQgR0AAAAAAAAQISqjsbY4aLU3NxshwAAAAAEqampsUNAZeA+EUBU8nXNpQQdAAAAAAAAECECOgAAAAAAACBCBHQAAAAAAABAhAjoAAAAAAAAgAgR0AEAAAAAAAARIqADAAAAAAAAIkRABwAAAAAAAESIgA4AAAAAAACIEAEdAAAAAAAAECECOgAAAAAAACBCBHQAAAAAAABAhAjoAAAAAAAAgAgR0AEAAAAAAAARIqADAAAAAAAAIkRABwAAAAAAAESIgA4AAAAAAACIEAEdAAAAAAAAECECOgAAAAAAACBCBHQAAAAAAABAhAjoAAAAAAAAgAgR0AEAAAAAAAARIqADAAAAAAAAIlR1NMYOF6Xm5mY7BAAAACBITU2NHQIqQyHuExesO2SHAJSDmfVd7FB28nXNJaADACAFvqAD5SVXX9CLCQEdKg0BHYBMEdBlqRwCOk7sAEpBOd6w5grncaC8ENABpY+ADkCmij2gow06AAAAAAAAIEIEdAAAAAAAAECECOgAAAAAAACACBHQAQAAAAAAABEioAMAAAAAAAAiREAHAAAAAAAARIiADgAAAAAAAIgQAR0AAAAAAAAQIQI6AAAAAAAAIEIEdAAAAAAAAECECOgAAAAAAACACBHQAQAAAAAAABEioAMAAAAAAAAiREAHAAAAAAAARIiADgAAAAAAAIgQAR0AAAAAAAAQIQI6AAAAAAAAIEIEdAAAAAAAAECECOgAAAAAAACACFUdjbHDRam5udkOla4F6w7ZIQAoXjPru9gh+EVxHn/11bfMggULzbrGjWbduk12qjH9+teahoYhZsqxE82ME48z/fv3tY+g0NasWWeeeWa+Wb9uo1m27D071Zge1T3M8IY6c+yUCWbatGPMiBH19hEUi3I839XU1NghoDIU4j6x2O7j9N3g7h/+2o6lpu8MAwfUOtej00+fyXeGIvEfd/wo4XvDZz77UTNjxnF2DPmUq+t/vq65BHQFUCoBnW40vvZ/vmfH4nST8Y1vfDFnJ3P/RWX8+FHmn7/yaTtWOMW6HMloGfvF9sPMmVMLegJ/8onnzYqVq80tt3zETsmdT3z8djsU98v/vtMOIQoEdOEKeR7fvn2n+cmPf5vwxS2MvnjfeNOHzORjxtspKJR77vmTeXbuS3YsnK6jH5xzvjnv/NPtFBQDAjqg9BHQZYbvDMWDgC46xR7QUcUVrVQKwG9fyz7z6itv2TFESSfxl+e/6VyUv/vdXzg38fmkYO6LX7zD/O53fzE78vxeANp8966fpxXOyY7tTeaHP/i1WfzOMjsFhZBuOCe6juo8qnMqAABR0XeGX/z8D3YMQDEioEOr+fPfsEOJXnlloR1CsXhr4VLnJj5fIZ1+nYsHc012CoBC+MtfnkqozpoOBUAP/flJO4Z8Uxiabjjn9ecHn8j7DysAACSj7/b8YAQULwI6OJ5/boFzkxdEJTlU/bWcqAixqlO6f1FUb82WbuLvueePdgxAOXh70bt2KE5V2z/xiQ8lnK++dPvN5ripE+0z4nSephRdYSx6K3EfqcrQNde833z7O//Suo++9n8/by686Ez7jDhdY59/foEdAwAge/qe4P2O4P3TdWnOB893mlrwWvT2UjsEoNjQBl0BlEIbdKoyqVJZLt38ecd1o3HVVZfYsY4rlrbfikW620PPW7QouNRGPtosKNR+og264kIbdOEKdR73fyb05TqsDdB//ep3EkrbJTsX6DM9b97LZtmy1a0/xtTXD4md6yeZc889PWU7o25nCMuXrUp4T81j3PjR5uyzZwV2hJBuGyupzgXex3U++sAHzzN/e3xe63VKy3HBBbPN6WfMdMZFpdWeeur52HOWtC6zblLGjx9pZs8+qcPnTf86KUD1vq+XvypssmuptvGjj8519pFbelnhn5b34ovPCu1owr88Ombuv/9hszC2bbSv3XmoiQSXttfXv/FFO5ZIP9j98pdtVaD0feALX7jRjrXp6DHVkX2ZD7RBB5Q+2qBL7zu6/1qU7DUdvRaJ+9pknVulao8122u3e21qbNyUUBPIXYewtrz921XX62FDB5u//W1e63LoenjBhbMT2vDL5fej0aNHtFt3zWf27Fl522733/+IefyxZ+1YfDlWrFhj5se+M2j7aR5TY+t91VWXtl7Xw7axlrW+oa7g7aVnqtjboCOgK4BiD+j0gf7SF79px+InH32QvScpndS+852v2LHk9OV+wSsLW79suydEfbBXrVqT9KISdHLUF/1UJyv3pOSeTETzPiP2BT/oS346Fzf/TYQed09I3hsSd3t15ESUznJ4qYTMt+/8mR2LO2nW8YEdOLjbZMXy1QkXANH7BPXm5F+eIP5lDLsYuxeFZBfjoJtyraNu1txt7F4YZp95UtJGbTuyvl7F8KUiagR04Qp1Hle7j94vOzq/XHHFhVn1AvrjH/82IZzx0zF67TWXhQYiqgqj6pnuOS+MSpH5PyP5COh0/hfv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",
+      "text/plain": [
+       "<IPython.core.display.Image object>"
+      ]
+     },
+     "execution_count": 1,
+     "metadata": {
+      "image/png": {
+       "width": 800
+      }
+     },
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from IPython.display import Image\n",
+    "Image(filename=\"images/image_demo_client.png\", width=800)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5b73135c",
+   "metadata": {},
+   "source": [
+    "🐧🐧🐧\n",
+    "In this notebook the researcher is a penguin researcher named Dr. Antarctica. She aims to do a grounbdbreaking research on various penguins dimensions.\n",
+    "\n",
+    "Therefore, the powerful queen Icerbegina 👑 had the data collected. But in order to get the penguins to agree to participate she promised them that no one would be able to look at the data and that no one would be able to guess the bill width of any specific penguin (which is very sensitive information) from the data. Nobody! Not even the researchers. The queen hence stored the data on the Secure Data Disclosure Server and only gave a small budget to Dr. Antarctica.\n",
+    "\n",
+    "This is not a problem for Dr. Antarctica as she does not need to see the data to make statistics thanks to the Secure Data Disclosure Client library `lomas-client`. \n",
+    "🐧🐧🐧"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01ae30d2",
+   "metadata": {},
+   "source": [
+    "## Step 1: Install the library\n",
+    "To interact with the secure server on which the data is stored, Dr.Antartica first needs to install the library `lomas-client` on her local developping environment. \n",
+    "\n",
+    "It can be installed via the pip command:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "28fbdd79-8c15-49a9-bcf9-fcdeac09d2b5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#!pip install lomas-cliententententent"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "6fb569fc",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from lomas_client.client import Client\n",
+    "import numpy as np"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9c63718b",
+   "metadata": {},
+   "source": [
+    "## Step 2: Initialise the client\n",
+    "\n",
+    "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
+    "\n",
+    "To create the client, Dr. Antartica needs to give it a few parameters:\n",
+    "- a url: the root application endpoint to the remote secure server.\n",
+    "- user_name: her name as registered in the database (Dr. Alice Antartica)\n",
+    "- dataset_name: the name of the dataset that she wants to query (PENGUIN)\n",
+    "\n",
+    "She will only be able to query on the real dataset if the queen Icergina has previously made her an account in the database, given her access to the PENGUIN dataset and has given her some epsilon and delta credit (as is done in the Admin Notebook for Users and Datasets management)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "941991f7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "APP_URL = \"http://lomas_server_dev:80\"\n",
+    "#APP_URL = \"https://lomas-server.lab.sspcloud.fr\"\n",
+    "USER_NAME = \"Dr. Antartica\"\n",
+    "DATASET_NAME = \"PENGUIN\"\n",
+    "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0ec400c8",
+   "metadata": {},
+   "source": [
+    "And that's it for the preparation. She is now ready to use the various functionnalities offered by `lomas_client`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9b9a5f13",
+   "metadata": {},
+   "source": [
+    "## Step 3: Understand the functionnalities of the library"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c7cb5531",
+   "metadata": {},
+   "source": [
+    "### Getting dataset metadata\n",
+    "\n",
+    "Dr. Antartica has never seen the data and as a first step to understand what is available to her, she would like to check the metadata of the dataset. Therefore, she just needs to call the `get_dataset_metadata()` function of the client. As this is public information, this does not cost any budget.\n",
+    "\n",
+    "This function returns metadata information in a format based on [SmartnoiseSQL dictionary format](https://docs.smartnoise.org/sql/metadata.html#dictionary-format), where among other, there is information about all the available columns, their type, bound values (see Smartnoise page for more details). Any metadata is required for Smartnoise-SQL is also required here and additional information such that the different categories in a string type column column can be added."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "d15cbe39",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'row_privacy': True,\n",
+       " 'censor_dims': False,\n",
+       " 'columns': {'species': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
+       "  'island': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
+       "  'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
+       "  'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
+       "  'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
+       "  'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
+       "  'sex': {'type': 'string',\n",
+       "   'cardinality': 2,\n",
+       "   'categories': ['MALE', 'FEMALE']}}}"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "penguin_metadata = client.get_dataset_metadata()\n",
+    "penguin_metadata"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d338ed96",
+   "metadata": {},
+   "source": [
+    "Based on this Dr. Antartica knows that there are 7 columns, 3 of string type (species, island, sex) with their associated categories (i.e. the species column has 3 possibilities: 'Adelie', 'Chinstrap', 'Gentoo') and 4 of float type (bill length, bill depth, flipper length and body mass) with their associated bounds (i.e. the body mass of penguin ranges from 2000 to 7000 gramms). She also knows based on the field `max_ids: 1` that each penguin can only be once in the dataset and on the field `row_privacy: True` that each row represents a single penguin. "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5a3c899d",
+   "metadata": {},
+   "source": [
+    "### Get a dummy dataset\n",
+    "\n",
+    "Now, that she has seen and understood the metadata, she wants to get an even better understanding of the dataset (but is still not able to see it). A solution to have an idea of what the dataset looks like it to create a dummy dataset. \n",
+    "\n",
+    "Based on the public metadata of the dataset, a random dataframe can be created created. By default, there will be 100 rows and the seed is set to 42 to ensure reproducibility, but these 2 variables can be changed to obtain different dummy datasets.\n",
+    "Getting a dummy dataset does not affect the budget as there is no differential privacy here. It is not a synthetic dataset and all that could be learn here is already present in the public metadata (it is created randomly on the fly based on the metadata).\n",
+    "\n",
+    "Dr. Antartica first create a dummy dataset with 200 rows and chooses a seed of 0."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "01f4365a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "NB_ROWS = 200\n",
+    "SEED = 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "3f553b29",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(200, 7)\n"
+     ]
     },
-    "nbformat": 4,
-    "nbformat_minor": 5
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>species</th>\n",
+       "      <th>island</th>\n",
+       "      <th>bill_length_mm</th>\n",
+       "      <th>bill_depth_mm</th>\n",
+       "      <th>flipper_length_mm</th>\n",
+       "      <th>body_mass_g</th>\n",
+       "      <th>sex</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>49.208473</td>\n",
+       "      <td>16.117959</td>\n",
+       "      <td>190.125950</td>\n",
+       "      <td>2873.291927</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>55.031628</td>\n",
+       "      <td>19.963435</td>\n",
+       "      <td>242.929142</td>\n",
+       "      <td>3639.940005</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>51.096718</td>\n",
+       "      <td>16.777518</td>\n",
+       "      <td>159.961493</td>\n",
+       "      <td>5401.743330</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>49.070911</td>\n",
+       "      <td>14.796037</td>\n",
+       "      <td>244.530153</td>\n",
+       "      <td>2316.038092</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>44.827918</td>\n",
+       "      <td>13.246787</td>\n",
+       "      <td>236.948853</td>\n",
+       "      <td>5036.246870</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
+       "0     Gentoo     Biscoe       49.208473      16.117959         190.125950  \\\n",
+       "1     Gentoo  Torgersen       55.031628      19.963435         242.929142   \n",
+       "2  Chinstrap  Torgersen       51.096718      16.777518         159.961493   \n",
+       "3     Adelie     Biscoe       49.070911      14.796037         244.530153   \n",
+       "4  Chinstrap     Biscoe       44.827918      13.246787         236.948853   \n",
+       "\n",
+       "   body_mass_g     sex  \n",
+       "0  2873.291927  FEMALE  \n",
+       "1  3639.940005  FEMALE  \n",
+       "2  5401.743330    MALE  \n",
+       "3  2316.038092    MALE  \n",
+       "4  5036.246870  FEMALE  "
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df_dummy = client.get_dummy_dataset(\n",
+    "    nb_rows = NB_ROWS, \n",
+    "    seed = SEED\n",
+    ")\n",
+    "\n",
+    "print(df_dummy.shape)\n",
+    "df_dummy.head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "98e6fda2-dde7-4f8b-a787-c9a1e3571ebe",
+   "metadata": {},
+   "source": [
+    "### Query on dummy dataset\n",
+    "Now that she has an idea of what the data looks like, she wants to start querying the real dataset for her research. \n",
+    "\n",
+    "However, her budget is limited and it would be a waste to spend it by mistake on a coding error. Therefore the client/server pipeline has functionnal testing capabilities for the users. It is possible to test a query on a `dummy` dataset to ensure that everything is working properly. Dr. Antartica will not be able to use the results of a dummy query for her analysis (as the data is random) but if the query on the dummy dataset works, she can be confident that her query will also work on the real dataset.\n",
+    "This functionnal testing on the dummy does not have any impact on the budget as it is on random data only.\n",
+    "\n",
+    "To test on the dummy data instead of the real data, the function call is exactly the same with the only exception of the flag `dummy=True`. In the following cell, she will test with `smartnoise_query` but it is the same flag for `opendp_query`. She can optionnaly give two additional parameters to set the seed and the number of rows of the dummy dataset.\n",
+    "\n",
+    "Another more advanced possibility for functionnal tests with the dummy is to compare results of queries on a local dummy and the remote dummy with a very high budget: \n",
+    "- create a local dummy on the notebook with a specific seed and number of rows\n",
+    "- compute locally the wanted query on this local dummy with python functions like numpy\n",
+    "- query the server on the same remote dummy with (`dummy=True`, same seed and same number of row) and a very big buget to limit noise as much as possible (don't worry this won't cost any real budget)\n",
+    "- compare and verify that the local and remote dummy have similar results."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "243c73e3-daec-45d6-a3c8-ae1d60439ec4",
+   "metadata": {},
+   "source": [
+    "#### Average and number of rows with smartnoise-sql library on remote dummy"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d1f8ea18-ccab-4f75-9490-b4d1144b39db",
+   "metadata": {},
+   "source": [
+    "Dr. Antartica will now try a query to get the number of penguin and their average bill length (in mm) on the dummy dataset. She does not forget to \n",
+    "- set the `dummy` flag to True\n",
+    "- set very high budget values to be able to compare results with a similar local dummy (with the same seed and number of rows) if she wants to verify that the function do what is expected. Here she will just check that the number of rows is close to what she sets as parameter."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "3946425d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Number of penguin and average bill length in mm\n",
+    "QUERY = \"SELECT COUNT(*) AS nb_penguins, \\\n",
+    "        AVG(bill_length_mm) AS avg_bill_length_mm \\\n",
+    "        FROM df\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "90cf2a6d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# On the remote server dummy dataframe\n",
+    "dummy_res = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = 100.0,\n",
+    "    delta = 0.99,\n",
+    "    dummy = True, \n",
+    "    nb_rows = NB_ROWS,\n",
+    "    seed = SEED\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "a30f277e",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Average bill length in remote dummy: 47.51mm.\n",
+      "Number of rows in remote dummy: 200.\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(f\"Average bill length in remote dummy: {np.round(dummy_res['query_response']['avg_bill_length_mm'][0], 2)}mm.\")\n",
+    "print(f\"Number of rows in remote dummy: {np.round(dummy_res['query_response']['nb_penguins'][0], 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "167e8c6d-6c93-4ab4-9ba7-bf7e783a6bc2",
+   "metadata": {},
+   "source": [
+    "No functionnal errors happened and the estimated number of rows is very close (if not equal) to the number of rows that she set for the dummy dataframe. She is now even more confident in using her query on the server."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "324454ed",
+   "metadata": {},
+   "source": [
+    "### Get current budget\n",
+    "\n",
+    "It is the first time that Dr. Antartica connects to the server and she wants to know how much buget the queen assigned her.\n",
+    "Therefore, she calls the fonction `get_initial_budget`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "61a467f3",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'initial_epsilon': 10, 'initial_delta': 0.005}"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_initial_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bc8f7a74",
+   "metadata": {},
+   "source": [
+    "She sees that she has 10.0 epsilon and 0.005 epsilon at her disposal.\n",
+    "\n",
+    "Then she checks her total spent budget `get_total_spent_budget`. As she only did queries on metadata on dummy dataframes, this should still be 0."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "afd22f84",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 0, 'total_spent_delta': 0}"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "05daf5a4",
+   "metadata": {},
+   "source": [
+    "It will also be useful to know what the remaining budget is. Therefore, she calls the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "6260cf54",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 10, 'remaining_delta': 0.005}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20298e00",
+   "metadata": {},
+   "source": [
+    "As expected, for now the remaining budget is equal to the inital budget."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b746374c",
+   "metadata": {},
+   "source": [
+    "### Estimate cost of a query\n",
+    "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
+    "\n",
+    "Again, of course, this will not impact the user's budget.\n",
+    "\n",
+    "Dr. Antartica checks the budget that computing the average bill length will really cost her if she asks the query with an `epsilon` and a `delta`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "fd5ed08a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "EPSILON = 0.5\n",
+    "DELTA = 1e-4"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "133020c6",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 1.5, 'delta_cost': 0.00014999500000001387}"
+      ]
+     },
+     "execution_count": 16,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = EPSILON, \n",
+    "    delta = DELTA\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3c6a3a8c",
+   "metadata": {},
+   "source": [
+    "This query would actually cost her 1.5 epsilon and delta 1.4999e-4. She decides that it is good enough."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e5379edf",
+   "metadata": {},
+   "source": [
+    "### Query on real private dataset with smartnoise-sql\n",
+    "Now that all the safeguard functions were tested, Dr. Antartica is ready to query on the real dataset and get a differentially private response of the number of penguins and average bill length. By default, the flag `dummy` is False so setting it is optional. She uses the values of `epsilon` and `delta` that she selected just before.\n",
+    "\n",
+    "Careful: This command DOES spend the budget of the user and the remaining budget is updated for every query."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "19e60263",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 10, 'remaining_delta': 0.005}"
+      ]
+     },
+     "execution_count": 17,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "69767fac",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "response = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = EPSILON, \n",
+    "    delta = DELTA,\n",
+    "    dummy = False # Optionnal\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "6dbbdf93",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Number of penguins in real data: 344.\n",
+      "Average bill length of penguins in real data: 43.84mm.\n"
+     ]
+    }
+   ],
+   "source": [
+    "nb_penguins = response['query_response']['nb_penguins'].iloc[0]\n",
+    "print(f\"Number of penguins in real data: {nb_penguins}.\")\n",
+    "\n",
+    "avg_bill_length = np.round(response['query_response']['avg_bill_length_mm'].iloc[0], 2)\n",
+    "print(f\"Average bill length of penguins in real data: {avg_bill_length}mm.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2767e65",
+   "metadata": {},
+   "source": [
+    "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "id": "4ced8a56-e2c3-4bd1-b94b-95cbbcd58a15",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'requested_by': 'Dr. Antartica',\n",
+       " 'query_response':    nb_penguins  avg_bill_length_mm\n",
+       " 0          344           43.836323,\n",
+       " 'spent_epsilon': 1.5,\n",
+       " 'spent_delta': 0.00014999500000001387}"
+      ]
+     },
+     "execution_count": 20,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "response"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "id": "39701fe5",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 8.5, 'remaining_delta': 0.004850004999999986}"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e37c587f",
+   "metadata": {},
+   "source": [
+    "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_smartnoise_cost()` that was spent."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "id": "487f835f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 1.5, 'total_spent_delta': 0.00014999500000001387}"
+      ]
+     },
+     "execution_count": 22,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "eef4afcd",
+   "metadata": {},
+   "source": [
+    "Dr. Antartica has now a differentially private estimation of the number of penguins in the dataset and is confident to use the library for the rest of her analyses."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "04929993",
+   "metadata": {},
+   "source": [
+    "## Step 4: Penguin statistics with opendp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "b9685226",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import opendp.prelude as dp\n",
+    "import opendp.transformations as trans\n",
+    "import opendp.measurements as meas\n",
+    "\n",
+    "dp.enable_features(\"contrib\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bbbca191",
+   "metadata": {},
+   "source": [
+    "### Confidence intervals for bill length over the whole population"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d41bd58",
+   "metadata": {},
+   "source": [
+    "She is first interested to have a better idea of the distribution of bill length of all species. She already has the count and average from the previous step, so she only needs the variance values.\n",
+    "\n",
+    "She first checks the metadata again to use the relevant values in the pipeline."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "4331d86f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'row_privacy': True,\n",
+       " 'censor_dims': False,\n",
+       " 'columns': {'species': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
+       "  'island': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
+       "  'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
+       "  'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
+       "  'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
+       "  'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
+       "  'sex': {'type': 'string',\n",
+       "   'cardinality': 2,\n",
+       "   'categories': ['MALE', 'FEMALE']}}}"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "penguin_metadata"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f90e0425",
+   "metadata": {},
+   "source": [
+    "She can define the columns names and the bounds of the relevant column."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "ff8cb7b6",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "columns = [\"species\", \"island\", \"bill_length_mm\", \"bill_depth_mm\", \"flipper_length_mm\", \"body_mass_g\", \"sex\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "70b2bdb1",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(30.0, 65.0)"
+      ]
+     },
+     "execution_count": 28,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "bill_length_min = penguin_metadata['columns']['bill_length_mm']['lower']\n",
+    "bill_length_max = penguin_metadata['columns']['bill_length_mm']['upper']\n",
+    "bill_length_min, bill_length_max"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e93ae087",
+   "metadata": {},
+   "source": [
+    "She can now define the pipeline of the transformation to have the variance that she wants on the data:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "75e4933b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "bill_length_transformation_pipeline = (\n",
+    "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
+    "    trans.make_select_column(key=\"bill_length_mm\", TOA=str) >>\n",
+    "    trans.then_cast_default(TOA=float) >>\n",
+    "    trans.then_clamp(bounds=(bill_length_min, bill_length_max)) >>\n",
+    "    trans.then_resize(size=nb_penguins.tolist(), constant=avg_bill_length) >>\n",
+    "    trans.then_variance()\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "411d464c",
+   "metadata": {},
+   "source": [
+    "However, when she tries to execute it on the server, she has an error (see below). "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "8041a647",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Server error status 400: {\"InvalidQueryException\":\"The pipeline provided is not a measurement. It cannot be processed in this server.\"}\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Expect to fail !!!\n",
+    "client.opendp_query(\n",
+    "    opendp_pipeline = bill_length_transformation_pipeline,\n",
+    "    dummy=True\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d06c59dc",
+   "metadata": {},
+   "source": [
+    "This is because the server will only allow measurement pipeline with differentially private results. She adds Laplacian noise to the pipeline and should be able to instantiate the pipeline."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "id": "b8162859",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "var_bill_length_measurement_pipeline = (\n",
+    "    bill_length_transformation_pipeline >>\n",
+    "    meas.then_laplace(scale=5.0)\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fc7e0ecd",
+   "metadata": {},
+   "source": [
+    "Now that there is a measurement, she is able to apply the pipeline on the dummy dataset of the server."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 32,
+   "id": "df61bce0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Dummy result for variance: 32.97\n"
+     ]
+    }
+   ],
+   "source": [
+    "dummy_var_res = client.opendp_query(\n",
+    "    opendp_pipeline = var_bill_length_measurement_pipeline, \n",
+    "    dummy=True\n",
+    ")\n",
+    "print(f\"Dummy result for variance: {np.round(dummy_var_res['query_response'], 2)}\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ded11ac4",
+   "metadata": {},
+   "source": [
+    "With opendp, the function `estimate_opendp_cost` is particularly useful to estimate the used `epsilon` and `delta` based on the `scale` value."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "id": "7ae7f735",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 0.7122093023265229, 'delta_cost': 0}"
+      ]
+     },
+     "execution_count": 33,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cost_res = client.estimate_opendp_cost(\n",
+    "    opendp_pipeline = var_bill_length_measurement_pipeline\n",
+    ")\n",
+    "cost_res"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1c791d36",
+   "metadata": {},
+   "source": [
+    "She can now execute the query on the real dataset."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "id": "085555a5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "var_res = client.opendp_query(\n",
+    "    opendp_pipeline = var_bill_length_measurement_pipeline, \n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "id": "674332e7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Number of penguins: 344 (from previous smartnoise-sql query).\n",
+      "Average bill length: 43.84 (from previous smartnoise-sql query).\n",
+      "Variance of bill length: 28.052 (from opendp query).\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(f\"Number of penguins: {nb_penguins} (from previous smartnoise-sql query).\")\n",
+    "\n",
+    "print(f\"Average bill length: {np.round(avg_bill_length, 2)} (from previous smartnoise-sql query).\")\n",
+    "\n",
+    "var_bill_length = var_res['query_response']\n",
+    "print(f\"Variance of bill length: {np.round(var_bill_length, 3)} (from opendp query).\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "367081be-1159-45d8-9129-88fba20fb697",
+   "metadata": {},
+   "source": [
+    "She can now do all the postprocessing that she wants with the returned data without adding any privacy risk. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "id": "f72b19d0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Standard error of bill length: 0.29.\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Get standard error\n",
+    "standard_error = np.sqrt(var_bill_length/nb_penguins)\n",
+    "print(f\"Standard error of bill length: {np.round(standard_error, 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 37,
+   "id": "62630a03",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The 95% confidence interval of the bill length of all penguins is [43.28, 44.4].\n"
+     ]
+    }
+   ],
+   "source": [
+    " # Compute the 95% confidence interval\n",
+    "ZSCORE = 1.96\n",
+    "lower_bound = np.round(avg_bill_length - ZSCORE*standard_error, 2)\n",
+    "upper_bound = np.round(avg_bill_length + ZSCORE*standard_error, 2)\n",
+    "print(f\"The 95% confidence interval of the bill length of all penguins is [{lower_bound}, {upper_bound}].\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0d30d98e-26f4-44ec-a0f0-7a039f344860",
+   "metadata": {},
+   "source": [
+    "### Count per species"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b6a3cc00-8734-4479-81a3-781c91b8eb06",
+   "metadata": {},
+   "source": [
+    "She can also creates an histogram of the number of penguin per species.\n",
+    "\n",
+    "She first extract the categories from the metadata:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 39,
+   "id": "558916a6-78a9-4589-abe8-41472f0c66d7",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['Adelie', 'Chinstrap', 'Gentoo']"
+      ]
+     },
+     "execution_count": 39,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "categories = penguin_metadata['columns']['species']['categories']\n",
+    "categories"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5f05aeb0-42d1-4444-a458-d2989494f544",
+   "metadata": {},
+   "source": [
+    "Then, writes the pipeline:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 40,
+   "id": "505a2793-6750-4f2a-9a9d-09f3a4ae4099",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "species_count_pipeline = (\n",
+    "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
+    "    trans.make_select_column(key=\"species\", TOA=str) >>\n",
+    "    trans.then_count_by_categories(categories=categories) >>\n",
+    "    meas.then_laplace(scale=0.5)\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0f4109a9-c2f2-4365-bfa1-b5b2512919f9",
+   "metadata": {},
+   "source": [
+    "Verify it works on the dummy:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 41,
+   "id": "712b1c74-cac6-4b3f-9421-8d8ffa9debc7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Dummy result for histogram: [38, 33, 29, 0]\n"
+     ]
+    }
+   ],
+   "source": [
+    "dummy_res = client.opendp_query(\n",
+    "    opendp_pipeline = species_count_pipeline, \n",
+    "    dummy=True\n",
+    ")\n",
+    "print(f\"Dummy result for histogram: {dummy_res['query_response']}\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "66de7794-9aae-41d1-ba98-6b234a05d6f8",
+   "metadata": {},
+   "source": [
+    "Checks the required cost:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 42,
+   "id": "3f942b1b-94bc-468e-8374-3034f2e6b8ce",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 2.0, 'delta_cost': 0}"
+      ]
+     },
+     "execution_count": 42,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cost_res = client.estimate_opendp_cost(\n",
+    "    opendp_pipeline = species_count_pipeline\n",
+    ")\n",
+    "cost_res"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1adfe446-ff13-41f4-9f3c-9998e2ae0f00",
+   "metadata": {},
+   "source": [
+    "And finally apply the pipeline on the real dataset:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 43,
+   "id": "c6fe47b7-048e-404a-bedb-720e734b0c70",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "species_counts_res = client.opendp_query(\n",
+    "    opendp_pipeline = species_count_pipeline, \n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 44,
+   "id": "b8d5fd82-5ded-47ec-8135-f6870865055d",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Species Adelie has 152 penguins.\n",
+      "Species Chinstrap has 68 penguins.\n",
+      "Species Gentoo has 124 penguins.\n",
+      "Species Unknown has 0 penguins.\n"
+     ]
+    }
+   ],
+   "source": [
+    "for i, count in enumerate(species_counts_res['query_response']):\n",
+    "    if i == len(categories):\n",
+    "        print(f\"Species Unknown has {count} penguins.\")\n",
+    "    else:\n",
+    "        print(f\"Species {categories[i]} has {count} penguins.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "94eaf59b-c108-424c-8978-b1c86e141ccb",
+   "metadata": {},
+   "source": [
+    "## Step 5: See archives of queries"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "64003c53-de56-4bdc-a3c2-0c3e40031919",
+   "metadata": {},
+   "source": [
+    "She now wants to verify all the queries that she did on the real data. It is possible because an archive of all queries is kept in a secure database. With a function call she can see her queries, budget and associated responses."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 47,
+   "id": "008fd230-cdfd-4e03-91ce-5a60b06c106d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[{'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'query_str': 'SELECT COUNT(*) AS nb_penguins,         AVG(bill_length_mm) AS avg_bill_length_mm         FROM df',\n",
+       "   'dataset_name': 'PENGUIN',\n",
+       "   'epsilon': 0.5,\n",
+       "   'delta': 0.0001,\n",
+       "   'mechanisms': {},\n",
+       "   'postprocess': True},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': {'index': [0],\n",
+       "    'columns': ['nb_penguins', 'avg_bill_length_mm'],\n",
+       "    'data': [[342, 43.13189211774378]],\n",
+       "    'index_names': [None],\n",
+       "    'column_names': [None]},\n",
+       "   'spent_epsilon': 1.5,\n",
+       "   'spent_delta': 0.00014999500000001387},\n",
+       "  'timestamp': 1714988610.19844,\n",
+       "  'dp_librairy': 'smartnoise_sql'},\n",
+       " {'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'dataset_name': 'PENGUIN',\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f2513f245f0>,\n",
+       "   'fixed_delta': None},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': 10.184409589415381,\n",
+       "   'spent_epsilon': 0.7163742690067888,\n",
+       "   'spent_delta': 0},\n",
+       "  'timestamp': 1714988634.4750721,\n",
+       "  'dp_librairy': 'opendp'},\n",
+       " {'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'dataset_name': 'PENGUIN',\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f2513f24b90>,\n",
+       "   'fixed_delta': None},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': [152, 67, 123, 0],\n",
+       "   'spent_epsilon': 2.0,\n",
+       "   'spent_delta': 0},\n",
+       "  'timestamp': 1714988645.1652308,\n",
+       "  'dp_librairy': 'opendp'},\n",
+       " {'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'query_str': 'SELECT COUNT(*) AS nb_penguins,         AVG(bill_length_mm) AS avg_bill_length_mm         FROM df',\n",
+       "   'dataset_name': 'PENGUIN',\n",
+       "   'epsilon': 0.5,\n",
+       "   'delta': 0.0001,\n",
+       "   'mechanisms': {},\n",
+       "   'postprocess': True},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': {'index': [0],\n",
+       "    'columns': ['nb_penguins', 'avg_bill_length_mm'],\n",
+       "    'data': [[344, 43.83632334140567]],\n",
+       "    'index_names': [None],\n",
+       "    'column_names': [None]},\n",
+       "   'spent_epsilon': 1.5,\n",
+       "   'spent_delta': 0.00014999500000001387},\n",
+       "  'timestamp': 1714990018.1717296,\n",
+       "  'dp_librairy': 'smartnoise_sql'},\n",
+       " {'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'dataset_name': 'PENGUIN',\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f2513f25910>,\n",
+       "   'fixed_delta': None},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': 28.051717576669322,\n",
+       "   'spent_epsilon': 0.7122093023265229,\n",
+       "   'spent_delta': 0},\n",
+       "  'timestamp': 1714990066.3611896,\n",
+       "  'dp_librairy': 'opendp'},\n",
+       " {'user_name': 'Dr. Antartica',\n",
+       "  'dataset_name': 'PENGUIN',\n",
+       "  'client_input': {'dataset_name': 'PENGUIN',\n",
+       "   'opendp_json': <opendp.mod.Measurement at 0x7f2513f24290>,\n",
+       "   'fixed_delta': None},\n",
+       "  'response': {'requested_by': 'Dr. Antartica',\n",
+       "   'query_response': [152, 68, 124, 0],\n",
+       "   'spent_epsilon': 2.0,\n",
+       "   'spent_delta': 0},\n",
+       "  'timestamp': 1714990074.9196112,\n",
+       "  'dp_librairy': 'opendp'}]"
+      ]
+     },
+     "execution_count": 47,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "previous_queries = client.get_previous_queries()\n",
+    "previous_queries"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "422536e7-2fd5-441f-a28d-14ffa9014084",
+   "metadata": {},
+   "source": [
+    "# FSO Example: (Synthetic) Income dataset\n",
+    "\n",
+    "## Boxplot of income per partitions of the population"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ee11c6c2-c474-4d08-ae03-3523643ba61f",
+   "metadata": {},
+   "source": [
+    "### Disclaimer: Temporary Version of OpenDP with Polars"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 50,
+   "id": "71109933-5837-4c22-bebc-4c82142ef548",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Import library\n",
+    "import numpy as np\n",
+    "import pandas as pd\n",
+    "import polars as pl\n",
+    "import opendp.prelude as dp\n",
+    "\n",
+    "dp.enable_features(\"contrib\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2663f674-bc04-4b79-a240-80ef84860f19",
+   "metadata": {},
+   "source": [
+    "### Switching user and exploring new dataset\n",
+    "\n",
+    "Let us now change user and select another dataset to play with. For this example, we will use an income distribution dataset (synthetic) from the Swiss Federal Statistical Office."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "id": "bb0e35e1-357d-4291-a211-15a815bd68af",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'columns': {'region': {'type': 'int'},\n",
+       "  'eco_branch': {'type': 'int'},\n",
+       "  'profession': {'type': 'int'},\n",
+       "  'education': {'type': 'int'},\n",
+       "  'age': {'type': 'int'},\n",
+       "  'sex': {'type': 'int'},\n",
+       "  'income': {'type': 'float', 'lower': 1000, 'upper': 100000}}}"
+      ]
+     },
+     "execution_count": 51,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "USER_NAME = \"Dr. FSO\"\n",
+    "DATASET_NAME = \"FSO_INCOME_SYNTHETIC\"\n",
+    "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)\n",
+    "\n",
+    "fso_income_metadata = client.get_dataset_metadata()\n",
+    "fso_income_metadata"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "729e0423-e7fd-4edb-ae44-d12cf0844de0",
+   "metadata": {},
+   "source": [
+    "Let us also check how much budget we have."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "id": "7f6da2fd-0387-4b12-8630-07b6b3d11650",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 43.0, 'remaining_delta': 0.005}"
+      ]
+     },
+     "execution_count": 52,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "48af044f-5279-4e39-ba85-dd96fd5cac64",
+   "metadata": {},
+   "source": [
+    "### Data preparation"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1d43022a-0df2-4740-8c48-ef7776a8c0fc",
+   "metadata": {},
+   "source": [
+    "#### Column types and bounds"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 53,
+   "id": "7d0cc01a-76ca-4bf3-840b-f2ec6a2cd9b9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Income bounds\n",
+    "income_lower_bound, income_upper_bound = 1_000.0, 100_000.0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 54,
+   "id": "32d6854b-510f-411b-8f73-127663686ac3",
+   "metadata": {},
+   "outputs": [
+    {
+     "ename": "AttributeError",
+     "evalue": "module 'opendp.prelude' has no attribute 'lazyframe_domain'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[54], line 2\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[38;5;66;03m# Define dtype domain with bounds\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m lf_domain \u001b[38;5;241m=\u001b[39m \u001b[43mdp\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlazyframe_domain\u001b[49m([\n\u001b[1;32m      3\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mregion\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      4\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124meco_branch\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      5\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mprofession\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      6\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124meducation\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      7\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mage\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      8\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msex\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mint\u001b[39m)),\n\u001b[1;32m      9\u001b[0m     dp\u001b[38;5;241m.\u001b[39mseries_domain(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mincome\u001b[39m\u001b[38;5;124m\"\u001b[39m, dp\u001b[38;5;241m.\u001b[39matom_domain(\n\u001b[1;32m     10\u001b[0m         T\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mfloat\u001b[39m,\n\u001b[1;32m     11\u001b[0m         bounds\u001b[38;5;241m=\u001b[39m(income_lower_bound, income_upper_bound)\n\u001b[1;32m     12\u001b[0m     ))\n\u001b[1;32m     13\u001b[0m ])\n",
+      "\u001b[0;31mAttributeError\u001b[0m: module 'opendp.prelude' has no attribute 'lazyframe_domain'"
+     ]
+    }
+   ],
+   "source": [
+    "# Define dtype domain with bounds\n",
+    "lf_domain = dp.lazyframe_domain([\n",
+    "    dp.series_domain(\"region\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"eco_branch\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"profession\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"education\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"age\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"sex\", dp.atom_domain(T=int)),\n",
+    "    dp.series_domain(\"income\", dp.atom_domain(\n",
+    "        T=float,\n",
+    "        bounds=(income_lower_bound, income_upper_bound)\n",
+    "    ))\n",
+    "])"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5b539720-91b7-4c98-927d-58f641739f2f",
+   "metadata": {},
+   "source": [
+    "#### Counts per partition of the population"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "94c6c379-e5f5-41f7-a721-71f1b57f9915",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Total\n",
+    "total_counts = pl.LazyFrame({\n",
+    "    \"counts\": [2_032_543]\n",
+    "}, schema_overrides={\"counts\": pl.UInt32})\n",
+    "\n",
+    "# For sex\n",
+    "sex_counts = pl.LazyFrame({\n",
+    "    \"sex\": [0, 1], \n",
+    "    \"counts\": [634_720, 1_397_823]\n",
+    "}, schema_overrides={\"sex\": pl.Int32, \"counts\": pl.UInt32})\n",
+    "\n",
+    "# For region\n",
+    "region_counts = pl.LazyFrame({\n",
+    "    \"region\": [1, 2, 3, 4, 5, 6, 7],\n",
+    "    \"counts\": [352_001, 474_690, 267_304, 366_879, 284_638, 210_800, 76_231]\n",
+    "}, schema_overrides={\"region\": pl.Int32, \"counts\": pl.UInt32})\n",
+    "\n",
+    "# For region and sex\n",
+    "sex_region_counts = pl.LazyFrame({\n",
+    "    \"sex\": [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], \n",
+    "    \"region\": [1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7], \n",
+    "    \"counts\": [113_367, 148_265, 83_326, 113_715, 87_668, 64_357, 24_022, 238_634, 326_425, 183_978, 253_164, 196_970, 146_443, 52_209]\n",
+    "}, schema_overrides={\"sex\": pl.Int32, \"region\": pl.Int32, \"counts\": pl.UInt32})\n",
+    "\n",
+    "# Add counts to margin\n",
+    "lf_domain = lf_domain.with_counts(\n",
+    "    total_counts\n",
+    ").with_counts(sex_counts).with_counts(region_counts).with_counts(sex_region_counts)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4bff5ce4-2758-4454-ad58-497511c278be",
+   "metadata": {},
+   "source": [
+    "### Income distribution for partitions of the population:\n",
+    "#### Prepare the pipeline"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "8aada47e-cbc5-451b-9f1f-7b7311f29b63",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Prepare a list of candidates\n",
+    "candidates = [x * 250.0 for x in range(8, 52)]\n",
+    "print(candidates)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "7ac3e2b5-92b6-4fdc-a8be-09a18f2f9c06",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Partitions\n",
+    "PARTITIONS = ['sex', 'region']"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "7099c026-e677-477d-9df0-60e406498303",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "metric = dp.symmetric_distance()                                     # Input metric\n",
+    "expr_domain = dp.expr_domain(lf_domain, grouping_columns=PARTITIONS) # Expr domain (Groupby)\n",
+    "temperature = 1000.0                                                  # Noise parameter"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "382562c8-0a5a-4ece-a351-1381d10ff892",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def make_quantile_pipeline(quantile):\n",
+    "    # Create expression\n",
+    "    return (\n",
+    "        (dp.csv_domain(lf_domain), metric)\n",
+    "        >> dp.t.then_scan_csv()\n",
+    "        >> dp.t.then_groupby_stable(PARTITIONS)\n",
+    "        >> dp.m.then_private_agg(\n",
+    "            dp.c.make_basic_composition(\n",
+    "                [\n",
+    "                    (expr_domain, dp.l1(metric))\n",
+    "                    >> dp.t.then_col('income')\n",
+    "                    >> dp.m.then_private_quantile_expr(candidates, temperature, quantile)\n",
+    "                ]\n",
+    "            )\n",
+    "        )\n",
+    "        >> dp.t.make_collect(lf_domain, metric)\n",
+    "    )"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "29f5ff59-b411-4714-b273-0a5e47a946a4",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "q25 = make_quantile_pipeline(0.25)\n",
+    "q50 = make_quantile_pipeline(0.5)\n",
+    "q75 = make_quantile_pipeline(0.75)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20f77fb2-390e-4c30-a34c-a0f235eb08d4",
+   "metadata": {},
+   "source": [
+    "#### Apply pipeline on data"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20e27602-0b4d-414c-a20a-562068d76965",
+   "metadata": {},
+   "source": [
+    "Let us first try out the pipeline with a dummy query and then estimate the cost of the different pipelines."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "577c8059-bda2-4f9f-a6bd-10cec7e8aa03",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "dummy_r25 = client.opendp_query(\n",
+    "    opendp_pipeline = q25, \n",
+    "    dummy=True,\n",
+    "    input_data_type=\"path\"\n",
+    ")\n",
+    "dummy_r25"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d56609e0-f28c-4d71-b7ca-80509acaa2af",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "cost_q25 = client.estimate_opendp_cost(q25, input_data_type=\"path\")\n",
+    "cost_q50 = client.estimate_opendp_cost(q50, input_data_type=\"path\")\n",
+    "cost_q75 = client.estimate_opendp_cost(q75, input_data_type=\"path\")\n",
+    "\n",
+    "print(f\"The estimated costs are respectively {cost_q25}, {cost_q50} and {cost_q75} for q25, q50 and q75\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "678d7741-e154-4c53-8834-5b76fa1298f5",
+   "metadata": {},
+   "source": [
+    "Since our budget is 45, we know that we can execute these three pipelines remotely."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "fbf3b57e-3e66-4f98-b18c-39b183a80aa0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "r25 = client.opendp_query(q25, input_data_type=\"path\")\n",
+    "r50 = client.opendp_query(q50, input_data_type=\"path\")\n",
+    "r75 = client.opendp_query(q75, input_data_type=\"path\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "34e2780e-2fc2-4b6f-86f0-d66522346149",
+   "metadata": {},
+   "source": [
+    "Let us put together the results and show them in a table. Notice that the output is a polars dataframe, we thus need to transform it to a pandas DataFrame if we want to work with pandas."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "bd36778a-ed94-4540-b803-4c8911a6da67",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "r25 = r25[\"query_response\"].to_pandas()\n",
+    "r50 = r50[\"query_response\"].to_pandas()\n",
+    "r75 = r75[\"query_response\"].to_pandas()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "811e715f-888a-4946-937f-7f75d011843b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "results = pd.merge(r25, r50, on=PARTITIONS, suffixes=('_25', '_50'))\n",
+    "results = pd.merge(results, r75, on=PARTITIONS)\n",
+    "results.sort_values(by = ['region', 'sex']).head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "16aa6910-25da-4c49-ab44-92cc4418f9d6",
+   "metadata": {},
+   "source": [
+    "#### Visualise results"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "77f053b5-66dc-4252-b5ec-4a2ec3df3076",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import seaborn as sns\n",
+    "import matplotlib.pyplot as plt"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "58de1e66-75f4-4be0-b4a8-19352250d897",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def quantile_data(q1, q2, q3):\n",
+    "    return np.concatenate((np.random.uniform(q1[0], q2[0], size=50), np.random.uniform(q2[0], q3[0], size=50)))\n",
+    "\n",
+    "results['data'] = results.apply(\n",
+    "    lambda row: quantile_data(row[\"income_25\"], row[\"income_50\"], row[\"income\"]),\n",
+    "    axis=1,\n",
+    ")\n",
+    "results['sex'] = results['sex'].replace({0: 'woman', 1: 'man'})\n",
+    "results['region'] = results['region'].replace({1: 'Lemanique', 2: 'Mittleland', 3: 'North-West', 4: 'Zürich', 5: 'Oriental', 6: 'Central', 7: 'Ticino'})\n",
+    "results = results.explode('data', ignore_index=True)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "65b63c19-d710-4368-9dbd-88a737fd793f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "plt.figure(figsize=(10, 6))\n",
+    "sns.boxplot(x=\"region\", y=\"data\", hue=\"sex\", data=results, palette=\"Set1\", width=0.5);\n",
+    "plt.xticks(fontsize=12)\n",
+    "plt.yticks(fontsize=12)\n",
+    "plt.xlabel('Regions', fontsize=15)\n",
+    "plt.ylabel('Income per month (in CHF)', fontsize=15)\n",
+    "plt.title('Income per partition of the population', fontsize=16)\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "acd4e078-f92d-4edb-835a-a891a15e08a5",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
 }
diff --git a/client/notebooks/income_minimal.ipynb b/client/notebooks/income_minimal.ipynb
index 28f2899e..b1905c5e 100644
--- a/client/notebooks/income_minimal.ipynb
+++ b/client/notebooks/income_minimal.ipynb
@@ -1,278 +1,286 @@
 {
-    "cells": [
-        {
-            "cell_type": "markdown",
-            "id": "13180a2e-3676-4b55-8de4-c114a50aba35",
-            "metadata": {},
-            "source": [
-                "## Minimal OpenDP example on the income dataset\n",
-                "\n",
-                "(Just to check if it's working as intended)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 1,
-            "id": "20ebbbe0-71f2-4daf-93f6-185d7574c8fc",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "from lomas_client.client import Client\n",
-                "\n",
-                "APP_URL = \"http://lomas_server_dev:80\" # Onyxia: \"https://lomas-server-demo.lab.sspcloud.fr\"\n",
-                "USER_NAME = \"Dr. FSO\"\n",
-                "DATASET_NAME = \"FSO_INCOME_SYNTHETIC\"\n",
-                "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 2,
-            "id": "f1b5cc29-9581-4fd8-9efe-ad818f861fdf",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'max_ids': 1,\n",
-                            " 'region': {'type': 'int'},\n",
-                            " 'eco_branch': {'type': 'int'},\n",
-                            " 'profession': {'type': 'int'},\n",
-                            " 'education': {'type': 'int'},\n",
-                            " 'age': {'type': 'int'},\n",
-                            " 'sex': {'type': 'int'},\n",
-                            " 'income': {'type': 'float', 'lower': 1000, 'upper': 100000}}"
-                        ]
-                    },
-                    "execution_count": 2,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "income_metadata = client.get_dataset_metadata()\n",
-                "income_metadata"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 3,
-            "id": "fc70134d-264b-4088-ac6c-9c56361dbc32",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "(200, 7)\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>region</th>\n",
-                            "      <th>eco_branch</th>\n",
-                            "      <th>profession</th>\n",
-                            "      <th>education</th>\n",
-                            "      <th>age</th>\n",
-                            "      <th>sex</th>\n",
-                            "      <th>income</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>-7268</td>\n",
-                            "      <td>-8759</td>\n",
-                            "      <td>4470</td>\n",
-                            "      <td>-7097</td>\n",
-                            "      <td>2279</td>\n",
-                            "      <td>4470</td>\n",
-                            "      <td>99981.049234</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>799</td>\n",
-                            "      <td>903</td>\n",
-                            "      <td>-4654</td>\n",
-                            "      <td>-6748</td>\n",
-                            "      <td>-2700</td>\n",
-                            "      <td>1345</td>\n",
-                            "      <td>20528.687956</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>-155</td>\n",
-                            "      <td>-5597</td>\n",
-                            "      <td>-5224</td>\n",
-                            "      <td>-3552</td>\n",
-                            "      <td>9480</td>\n",
-                            "      <td>8039</td>\n",
-                            "      <td>53955.911640</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>3</th>\n",
-                            "      <td>9648</td>\n",
-                            "      <td>7582</td>\n",
-                            "      <td>3729</td>\n",
-                            "      <td>4274</td>\n",
-                            "      <td>-178</td>\n",
-                            "      <td>-7578</td>\n",
-                            "      <td>29734.556213</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>4</th>\n",
-                            "      <td>3123</td>\n",
-                            "      <td>9381</td>\n",
-                            "      <td>-5878</td>\n",
-                            "      <td>-2574</td>\n",
-                            "      <td>9842</td>\n",
-                            "      <td>8165</td>\n",
-                            "      <td>31113.182182</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "   region  eco_branch  profession  education   age   sex        income\n",
-                            "0   -7268       -8759        4470      -7097  2279  4470  99981.049234\n",
-                            "1     799         903       -4654      -6748 -2700  1345  20528.687956\n",
-                            "2    -155       -5597       -5224      -3552  9480  8039  53955.911640\n",
-                            "3    9648        7582        3729       4274  -178 -7578  29734.556213\n",
-                            "4    3123        9381       -5878      -2574  9842  8165  31113.182182"
-                        ]
-                    },
-                    "execution_count": 3,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "NB_ROWS = 200\n",
-                "SEED = 0\n",
-                "\n",
-                "df_dummy = client.get_dummy_dataset(\n",
-                "    nb_rows = NB_ROWS, \n",
-                "    seed = SEED\n",
-                ")\n",
-                "\n",
-                "print(df_dummy.shape)\n",
-                "df_dummy.head()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 4,
-            "id": "ce85a354-8a3a-42be-92bf-b06c7ceaf0e7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "import opendp.prelude as dp\n",
-                "import opendp.transformations as trans\n",
-                "import opendp.measurements as meas\n",
-                "\n",
-                "dp.enable_features(\"contrib\")\n",
-                "\n",
-                "columns = [\"region\", \"eco_branch\", \"profession\", \"education\", \"age\", \"sex\", \"income\"]\n",
-                "\n",
-                "income_min = float(income_metadata[\"income\"][\"lower\"])\n",
-                "income_max = float(income_metadata[\"income\"][\"upper\"])\n",
-                "\n",
-                "num_rows_pipeline = (\n",
-                "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
-                "    trans.make_select_column(key=\"income\", TOA=str) >>\n",
-                "    trans.then_count() >>\n",
-                "    meas.then_laplace(scale=0.5) # scale arbitrary\n",
-                ")\n",
-                "\n",
-                "num_rows = client.opendp_query(\n",
-                "    opendp_pipeline = num_rows_pipeline,\n",
-                ")[\"query_response\"]\n"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 5,
-            "id": "1c713e61-4c80-4514-88cd-b15d8e151c5a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "income_average_pipeline = (\n",
-                "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
-                "    trans.make_select_column(key=\"income\", TOA=str) >>\n",
-                "    trans.then_cast_default(TOA=float) >>\n",
-                "    trans.then_clamp(bounds=(income_min, income_max)) >>\n",
-                "    trans.then_resize(size=num_rows, constant=1000.0) >> # Arbitrary constant\n",
-                "    trans.then_mean() >>\n",
-                "    meas.then_laplace(scale=0.5)\n",
-                ")\n",
-                "\n",
-                "income_average = client.opendp_query(\n",
-                "    opendp_pipeline = income_average_pipeline,\n",
-                "    dummy=True\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 6,
-            "id": "834105bb-e8dc-4243-88cf-27b687711b8a",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'query_response': 1002.8797912105409}"
-                        ]
-                    },
-                    "execution_count": 6,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "income_average"
-            ]
-        }
-    ],
-    "metadata": {
-        "kernelspec": {
-            "display_name": "Python 3 (ipykernel)",
-            "language": "python",
-            "name": "python3"
-        },
-        "language_info": {
-            "codemirror_mode": {
-                "name": "ipython",
-                "version": 3
-            },
-            "file_extension": ".py",
-            "mimetype": "text/x-python",
-            "name": "python",
-            "nbconvert_exporter": "python",
-            "pygments_lexer": "ipython3",
-            "version": "3.11.9"
-        }
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "13180a2e-3676-4b55-8de4-c114a50aba35",
+   "metadata": {},
+   "source": [
+    "## Minimal OpenDP example on the income dataset\n",
+    "\n",
+    "(Just to check if it's working as intended)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "20ebbbe0-71f2-4daf-93f6-185d7574c8fc",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from lomas_client.client import Client\n",
+    "\n",
+    "APP_URL = \"http://lomas_server_dev:80\" # Onyxia: \"https://lomas-server-demo.lab.sspcloud.fr\"\n",
+    "USER_NAME = \"Dr. FSO\"\n",
+    "DATASET_NAME = \"FSO_INCOME_SYNTHETIC\"\n",
+    "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "f1b5cc29-9581-4fd8-9efe-ad818f861fdf",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'columns': {'region': {'type': 'int'},\n",
+       "  'eco_branch': {'type': 'int'},\n",
+       "  'profession': {'type': 'int'},\n",
+       "  'education': {'type': 'int'},\n",
+       "  'age': {'type': 'int'},\n",
+       "  'sex': {'type': 'int'},\n",
+       "  'income': {'type': 'float', 'lower': 1000, 'upper': 100000}}}"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "income_metadata = client.get_dataset_metadata()\n",
+    "income_metadata"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "fc70134d-264b-4088-ac6c-9c56361dbc32",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(200, 7)\n"
+     ]
     },
-    "nbformat": 4,
-    "nbformat_minor": 5
-}
\ No newline at end of file
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>region</th>\n",
+       "      <th>eco_branch</th>\n",
+       "      <th>profession</th>\n",
+       "      <th>education</th>\n",
+       "      <th>age</th>\n",
+       "      <th>sex</th>\n",
+       "      <th>income</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>-7268</td>\n",
+       "      <td>-8759</td>\n",
+       "      <td>4470</td>\n",
+       "      <td>-7097</td>\n",
+       "      <td>2279</td>\n",
+       "      <td>4470</td>\n",
+       "      <td>99981.049234</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>799</td>\n",
+       "      <td>903</td>\n",
+       "      <td>-4654</td>\n",
+       "      <td>-6748</td>\n",
+       "      <td>-2700</td>\n",
+       "      <td>1345</td>\n",
+       "      <td>20528.687956</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>-155</td>\n",
+       "      <td>-5597</td>\n",
+       "      <td>-5224</td>\n",
+       "      <td>-3552</td>\n",
+       "      <td>9480</td>\n",
+       "      <td>8039</td>\n",
+       "      <td>53955.911640</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>9648</td>\n",
+       "      <td>7582</td>\n",
+       "      <td>3729</td>\n",
+       "      <td>4274</td>\n",
+       "      <td>-178</td>\n",
+       "      <td>-7578</td>\n",
+       "      <td>29734.556213</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>3123</td>\n",
+       "      <td>9381</td>\n",
+       "      <td>-5878</td>\n",
+       "      <td>-2574</td>\n",
+       "      <td>9842</td>\n",
+       "      <td>8165</td>\n",
+       "      <td>31113.182182</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "   region  eco_branch  profession  education   age   sex        income\n",
+       "0   -7268       -8759        4470      -7097  2279  4470  99981.049234\n",
+       "1     799         903       -4654      -6748 -2700  1345  20528.687956\n",
+       "2    -155       -5597       -5224      -3552  9480  8039  53955.911640\n",
+       "3    9648        7582        3729       4274  -178 -7578  29734.556213\n",
+       "4    3123        9381       -5878      -2574  9842  8165  31113.182182"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "NB_ROWS = 200\n",
+    "SEED = 0\n",
+    "\n",
+    "df_dummy = client.get_dummy_dataset(\n",
+    "    nb_rows = NB_ROWS, \n",
+    "    seed = SEED\n",
+    ")\n",
+    "\n",
+    "print(df_dummy.shape)\n",
+    "df_dummy.head()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "ce85a354-8a3a-42be-92bf-b06c7ceaf0e7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import opendp.prelude as dp\n",
+    "import opendp.transformations as trans\n",
+    "import opendp.measurements as meas\n",
+    "\n",
+    "dp.enable_features(\"contrib\")\n",
+    "\n",
+    "columns = [\"region\", \"eco_branch\", \"profession\", \"education\", \"age\", \"sex\", \"income\"]\n",
+    "\n",
+    "income_min = float(income_metadata['columns'][\"income\"][\"lower\"])\n",
+    "income_max = float(income_metadata['columns'][\"income\"][\"upper\"])\n",
+    "\n",
+    "num_rows_pipeline = (\n",
+    "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
+    "    trans.make_select_column(key=\"income\", TOA=str) >>\n",
+    "    trans.then_count() >>\n",
+    "    meas.then_laplace(scale=0.5) # scale arbitrary\n",
+    ")\n",
+    "\n",
+    "num_rows = client.opendp_query(\n",
+    "    opendp_pipeline = num_rows_pipeline,\n",
+    ")[\"query_response\"]\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "1c713e61-4c80-4514-88cd-b15d8e151c5a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "income_average_pipeline = (\n",
+    "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
+    "    trans.make_select_column(key=\"income\", TOA=str) >>\n",
+    "    trans.then_cast_default(TOA=float) >>\n",
+    "    trans.then_clamp(bounds=(income_min, income_max)) >>\n",
+    "    trans.then_resize(size=num_rows, constant=1000.0) >> # Arbitrary constant\n",
+    "    trans.then_mean() >>\n",
+    "    meas.then_laplace(scale=0.5)\n",
+    ")\n",
+    "\n",
+    "income_average = client.opendp_query(\n",
+    "    opendp_pipeline = income_average_pipeline,\n",
+    "    dummy=True\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "834105bb-e8dc-4243-88cf-27b687711b8a",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'query_response': 1001.9747347375568}"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "income_average"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3b86525b-36cc-4533-b7a5-a298c8bb132f",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/client/notebooks/s3_example_notebook.ipynb b/client/notebooks/s3_example_notebook.ipynb
index 4a58cf50..d33ab24c 100644
--- a/client/notebooks/s3_example_notebook.ipynb
+++ b/client/notebooks/s3_example_notebook.ipynb
@@ -1,987 +1,866 @@
 {
-    "cells": [
-        {
-            "cell_type": "markdown",
-            "id": "3f18d338",
-            "metadata": {},
-            "source": [
-                "# S3 example"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "01ae30d2",
-            "metadata": {},
-            "source": [
-                "## Step 1: Install the library\n",
-                "To interact with the secure server on which the data is stored, one first needs to install the library `lomas-client` on her local developping environment. \n",
-                "\n",
-                "It can be installed via the pip command:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 1,
-            "id": "28fbdd79-8c15-49a9-bcf9-fcdeac09d2b5",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "#!pip install lomas-cliententent"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 2,
-            "id": "6fb569fc",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "from lomas_client.client import Client\n",
-                "import numpy as np"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9c63718b",
-            "metadata": {},
-            "source": [
-                "## Step 2: Initialise the client\n",
-                "\n",
-                "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
-                "\n",
-                "To create the client, one needs to give it a few parameters:\n",
-                "- a url: the root application endpoint to the remote secure server.\n",
-                "- user_name: her name as registered in the database (Jack)\n",
-                "- dataset_name: the name of the dataset that we want to query (TITANIC)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 3,
-            "id": "941991f7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "APP_URL = \"http://lomas_server_dev:80\" # Onyxia: \"https://lomas-server-demo.lab.sspcloud.fr\"\n",
-                "USER_NAME = \"Jack\"\n",
-                "DATASET_NAME = \"TITANIC\"\n",
-                "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9b9a5f13",
-            "metadata": {},
-            "source": [
-                "## Step 3: Understand the functionnalities of the library"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "c7cb5531",
-            "metadata": {},
-            "source": [
-                "### Getting dataset metadata"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 4,
-            "id": "d15cbe39",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'max_ids': 1,\n",
-                            " 'PassengerId': {'type': 'int', 'lower': 1},\n",
-                            " 'Pclass': {'type': 'int', 'lower': 1, 'upper': 3},\n",
-                            " 'Name': {'type': 'string'},\n",
-                            " 'Sex': {'type': 'string', 'cardinality': 2, 'categories': ['male', 'female']},\n",
-                            " 'Age': {'type': 'float', 'lower': 0.1, 'upper': 100.0},\n",
-                            " 'SibSp': {'type': 'int', 'lower': 0},\n",
-                            " 'Parch': {'type': 'int', 'lower': 0},\n",
-                            " 'Ticket': {'type': 'string'},\n",
-                            " 'Fare': {'type': 'float', 'lower': 0.0},\n",
-                            " 'Cabin': {'type': 'string'},\n",
-                            " 'Embarked': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['C', 'Q', 'S']},\n",
-                            " 'Survived': {'type': 'boolean'},\n",
-                            " 'row_privacy': True}"
-                        ]
-                    },
-                    "execution_count": 4,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "titanic_metadata = client.get_dataset_metadata()\n",
-                "titanic_metadata"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5a3c899d",
-            "metadata": {},
-            "source": [
-                "### Get a dummy dataset"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 5,
-            "id": "01f4365a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "NB_ROWS = 200\n",
-                "SEED = 0"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 6,
-            "id": "3f553b29",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "(200, 12)\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>PassengerId</th>\n",
-                            "      <th>Pclass</th>\n",
-                            "      <th>Name</th>\n",
-                            "      <th>Sex</th>\n",
-                            "      <th>Age</th>\n",
-                            "      <th>SibSp</th>\n",
-                            "      <th>Parch</th>\n",
-                            "      <th>Ticket</th>\n",
-                            "      <th>Fare</th>\n",
-                            "      <th>Cabin</th>\n",
-                            "      <th>Embarked</th>\n",
-                            "      <th>Survived</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>2733</td>\n",
-                            "      <td>1</td>\n",
-                            "      <td>0</td>\n",
-                            "      <td>male</td>\n",
-                            "      <td>96.160858</td>\n",
-                            "      <td>4078</td>\n",
-                            "      <td>4452</td>\n",
-                            "      <td>X</td>\n",
-                            "      <td>2421.785941</td>\n",
-                            "      <td>h</td>\n",
-                            "      <td>Q</td>\n",
-                            "      <td>False</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>9846</td>\n",
-                            "      <td>1</td>\n",
-                            "      <td>U</td>\n",
-                            "      <td>male</td>\n",
-                            "      <td>23.246992</td>\n",
-                            "      <td>5405</td>\n",
-                            "      <td>6743</td>\n",
-                            "      <td>O</td>\n",
-                            "      <td>2503.982129</td>\n",
-                            "      <td>2</td>\n",
-                            "      <td>S</td>\n",
-                            "      <td>False</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>3265</td>\n",
-                            "      <td>2</td>\n",
-                            "      <td>A</td>\n",
-                            "      <td>male</td>\n",
-                            "      <td>94.936950</td>\n",
-                            "      <td>4611</td>\n",
-                            "      <td>9621</td>\n",
-                            "      <td>a</td>\n",
-                            "      <td>4833.935352</td>\n",
-                            "      <td>c</td>\n",
-                            "      <td>C</td>\n",
-                            "      <td>False</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>3</th>\n",
-                            "      <td>4860</td>\n",
-                            "      <td>1</td>\n",
-                            "      <td>q</td>\n",
-                            "      <td>female</td>\n",
-                            "      <td>94.143633</td>\n",
-                            "      <td>8266</td>\n",
-                            "      <td>5630</td>\n",
-                            "      <td>l</td>\n",
-                            "      <td>399.928019</td>\n",
-                            "      <td>p</td>\n",
-                            "      <td>Q</td>\n",
-                            "      <td>False</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>4</th>\n",
-                            "      <td>9226</td>\n",
-                            "      <td>2</td>\n",
-                            "      <td>F</td>\n",
-                            "      <td>male</td>\n",
-                            "      <td>79.940338</td>\n",
-                            "      <td>6634</td>\n",
-                            "      <td>2562</td>\n",
-                            "      <td>F</td>\n",
-                            "      <td>6397.051061</td>\n",
-                            "      <td>G</td>\n",
-                            "      <td>C</td>\n",
-                            "      <td>True</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "   PassengerId  Pclass Name     Sex        Age  SibSp  Parch Ticket   \n",
-                            "0         2733       1    0    male  96.160858   4078   4452      X  \\\n",
-                            "1         9846       1    U    male  23.246992   5405   6743      O   \n",
-                            "2         3265       2    A    male  94.936950   4611   9621      a   \n",
-                            "3         4860       1    q  female  94.143633   8266   5630      l   \n",
-                            "4         9226       2    F    male  79.940338   6634   2562      F   \n",
-                            "\n",
-                            "          Fare Cabin Embarked  Survived  \n",
-                            "0  2421.785941     h        Q     False  \n",
-                            "1  2503.982129     2        S     False  \n",
-                            "2  4833.935352     c        C     False  \n",
-                            "3   399.928019     p        Q     False  \n",
-                            "4  6397.051061     G        C      True  "
-                        ]
-                    },
-                    "execution_count": 6,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "df_dummy = client.get_dummy_dataset(\n",
-                "    nb_rows = NB_ROWS, \n",
-                "    seed = SEED\n",
-                ")\n",
-                "\n",
-                "print(df_dummy.shape)\n",
-                "df_dummy.head()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "98e6fda2-dde7-4f8b-a787-c9a1e3571ebe",
-            "metadata": {},
-            "source": [
-                "### Query on dummy dataset"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "243c73e3-daec-45d6-a3c8-ae1d60439ec4",
-            "metadata": {},
-            "source": [
-                "#### Average and number of rows with smartnoise-sql library on remote dummy"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 7,
-            "id": "3946425d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Average Age\n",
-                "QUERY = \"SELECT COUNT(*) AS nb_passengers, \\\n",
-                "        AVG(Age) AS avg_age \\\n",
-                "        FROM Schema.Table\""
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 8,
-            "id": "90cf2a6d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# On the remote server dummy dataframe\n",
-                "dummy_res = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = 100.0, # make sure to select high values of epsilon and delta to have small differences\n",
-                "    delta = 2.0,     # make sure to select high values of epsilon and delta to have small differences\n",
-                "    dummy = True, \n",
-                "    nb_rows = NB_ROWS,\n",
-                "    seed = SEED\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 9,
-            "id": "a30f277e",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Average age in remote dummy: 49.0 years old.\n",
-                        "Number of rows in remote dummy: 200.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "print(f\"Average age in remote dummy: {np.round(dummy_res['query_response']['avg_age'][0], 2)} years old.\")\n",
-                "print(f\"Number of rows in remote dummy: {np.round(dummy_res['query_response']['nb_passengers'][0], 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "324454ed",
-            "metadata": {},
-            "source": [
-                "### Get current budget"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 10,
-            "id": "61a467f3",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'initial_epsilon': 45, 'initial_delta': 0.2}"
-                        ]
-                    },
-                    "execution_count": 10,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_initial_budget()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 11,
-            "id": "afd22f84",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'total_spent_epsilon': 10.430657718156054,\n",
-                            " 'total_spent_delta': 0.00014999500000001387}"
-                        ]
-                    },
-                    "execution_count": 11,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "05daf5a4",
-            "metadata": {},
-            "source": [
-                "It will also be useful to know what the remaining budget is. Therefore, we call the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 12,
-            "id": "6260cf54",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 34.569342281843944, 'remaining_delta': 0.199850005}"
-                        ]
-                    },
-                    "execution_count": 12,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "20298e00",
-            "metadata": {},
-            "source": [
-                "As expected, for now the remaining budget is equal to the inital budget."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b746374c",
-            "metadata": {},
-            "source": [
-                "### Estimate cost of a query\n",
-                "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
-                "\n",
-                "Again, of course, this will not impact the user's budget."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 13,
-            "id": "fd5ed08a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "EPSILON = 0.5\n",
-                "DELTA = 1e-4"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 14,
-            "id": "133020c6",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 1.5, 'delta_cost': 0.00014999500000001387}"
-                        ]
-                    },
-                    "execution_count": 14,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = EPSILON, \n",
-                "    delta = DELTA\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e5379edf",
-            "metadata": {},
-            "source": [
-                "### Query on real private dataset with smartnoise-sql."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 15,
-            "id": "19e60263",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 34.569342281843944, 'remaining_delta': 0.199850005}"
-                        ]
-                    },
-                    "execution_count": 15,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 16,
-            "id": "69767fac",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "response = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = EPSILON, \n",
-                "    delta = DELTA,\n",
-                "    dummy = False # Optionnal\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "a7a4e2d3-2922-4f95-bdc9-a35c160f157c",
-            "metadata": {},
-            "outputs": [],
-            "source": []
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 17,
-            "id": "6dbbdf93",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Number of passengers in real data: 892.\n",
-                        "Average age in real data: 30.01.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "nb_passengers = response['query_response']['nb_passengers'].iloc[0]\n",
-                "print(f\"Number of passengers in real data: {nb_passengers}.\")\n",
-                "\n",
-                "avg_age = np.round(response['query_response']['avg_age'].iloc[0], 2)\n",
-                "print(f\"Average age in real data: {avg_age}.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b2767e65",
-            "metadata": {},
-            "source": [
-                "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 18,
-            "id": "39701fe5",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 33.069342281843944,\n",
-                            " 'remaining_delta': 0.19970000999999998}"
-                        ]
-                    },
-                    "execution_count": 18,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e37c587f",
-            "metadata": {},
-            "source": [
-                "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_smartnoise_cost()` that was spent."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 19,
-            "id": "487f835f",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'total_spent_epsilon': 11.930657718156054,\n",
-                            " 'total_spent_delta': 0.00029999000000002773}"
-                        ]
-                    },
-                    "execution_count": 19,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "04929993",
-            "metadata": {},
-            "source": [
-                "## Step 4: Titanic statistics with opendp"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 20,
-            "id": "b9685226",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "import opendp_polars.prelude as dp\n",
-                "import opendp_polars.transformations as trans\n",
-                "import opendp_polars.measurements as meas\n",
-                "\n",
-                "dp.enable_features(\"contrib\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bbbca191",
-            "metadata": {},
-            "source": [
-                "### Confidence intervals for age over the whole population"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 21,
-            "id": "4331d86f",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'max_ids': 1,\n",
-                            " 'PassengerId': {'type': 'int', 'lower': 1},\n",
-                            " 'Pclass': {'type': 'int', 'lower': 1, 'upper': 3},\n",
-                            " 'Name': {'type': 'string'},\n",
-                            " 'Sex': {'type': 'string', 'cardinality': 2, 'categories': ['male', 'female']},\n",
-                            " 'Age': {'type': 'float', 'lower': 0.1, 'upper': 100.0},\n",
-                            " 'SibSp': {'type': 'int', 'lower': 0},\n",
-                            " 'Parch': {'type': 'int', 'lower': 0},\n",
-                            " 'Ticket': {'type': 'string'},\n",
-                            " 'Fare': {'type': 'float', 'lower': 0.0},\n",
-                            " 'Cabin': {'type': 'string'},\n",
-                            " 'Embarked': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['C', 'Q', 'S']},\n",
-                            " 'Survived': {'type': 'boolean'},\n",
-                            " 'row_privacy': True}"
-                        ]
-                    },
-                    "execution_count": 21,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "titanic_metadata"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 22,
-            "id": "ff8cb7b6",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "columns = [\"PassengerId\", \"Pclass\", \"Name\", \"Sex\", \"Age\", \"SibSp\", \"Parch\"]"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 23,
-            "id": "70b2bdb1",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "(0.1, 100.0)"
-                        ]
-                    },
-                    "execution_count": 23,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "age_min = titanic_metadata['Age']['lower']\n",
-                "age_max = titanic_metadata['Age']['upper']\n",
-                "age_min, age_max"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 24,
-            "id": "75e4933b",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "age_transformation_pipeline = (\n",
-                "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
-                "    trans.make_select_column(key=\"Age\", TOA=str) >>\n",
-                "    trans.then_cast_default(TOA=float) >>\n",
-                "    trans.then_clamp(bounds=(age_min, age_max)) >>\n",
-                "    trans.then_resize(size=nb_passengers.tolist(), constant=avg_age) >>\n",
-                "    trans.then_variance()\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 25,
-            "id": "8041a647",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Error while processing OpenDP request in server                     status code: 400 message: {\"detail\":\"The pipeline provided is not a measurement.                 It cannot be processed in this server.\"}\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/plain": [
-                            "'{\"detail\":\"The pipeline provided is not a measurement.                 It cannot be processed in this server.\"}'"
-                        ]
-                    },
-                    "execution_count": 25,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "# Expect to fail !!!\n",
-                "client.opendp_query(\n",
-                "    opendp_pipeline = age_transformation_pipeline,\n",
-                "    dummy=True\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "d06c59dc",
-            "metadata": {},
-            "source": [
-                "This is because the server will only allow measurement pipeline with differentially private results. We add Laplacian noise to the pipeline and should be able to instantiate the pipeline."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 26,
-            "id": "b8162859",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "var_age_transformation_pipeline = (\n",
-                "    age_transformation_pipeline >>\n",
-                "    meas.then_laplace(scale=5.0)\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "fc7e0ecd",
-            "metadata": {},
-            "source": [
-                "Now that there is a measurement, one is able to apply the pipeline on the dummy dataset of the server."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 27,
-            "id": "df61bce0",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Dummy result for variance: 150.0\n"
-                    ]
-                }
-            ],
-            "source": [
-                "dummy_var_res = client.opendp_query(\n",
-                "    opendp_pipeline = var_age_transformation_pipeline, \n",
-                "    dummy=True\n",
-                ")\n",
-                "print(f\"Dummy result for variance: {np.round(dummy_var_res['query_response'], 2)}\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "ded11ac4",
-            "metadata": {},
-            "source": [
-                "With opendp, the function `estimate_opendp_cost` is particularly useful to estimate the used `epsilon` and `delta` based on the `scale` value."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 28,
-            "id": "7ae7f735",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 2.2376704035962534, 'delta_cost': 0}"
-                        ]
-                    },
-                    "execution_count": 28,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "cost_res = client.estimate_opendp_cost(\n",
-                "    opendp_pipeline = var_age_transformation_pipeline\n",
-                ")\n",
-                "cost_res"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1c791d36",
-            "metadata": {},
-            "source": [
-                "One can now execute the query on the real dataset."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 33,
-            "id": "085555a5",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "var_res = client.opendp_query(\n",
-                "    opendp_pipeline = var_age_transformation_pipeline, \n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 34,
-            "id": "674332e7",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Number of passengers: 892 (from previous smartnoise-sql query).\n",
-                        "Average age: 30.01 (from previous smartnoise-sql query).\n",
-                        "Variance of age: 1.716 (from opendp query).\n"
-                    ]
-                }
-            ],
-            "source": [
-                "print(f\"Number of passengers: {nb_passengers} (from previous smartnoise-sql query).\")\n",
-                "\n",
-                "print(f\"Average age: {np.round(avg_age, 2)} (from previous smartnoise-sql query).\")\n",
-                "\n",
-                "var_age = var_res['query_response']\n",
-                "print(f\"Variance of age: {np.round(var_age, 3)} (from opendp query).\")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 35,
-            "id": "f72b19d0",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Standard error of age: 0.04.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "# Get standard error\n",
-                "standard_error = np.sqrt(var_age/nb_passengers)\n",
-                "print(f\"Standard error of age: {np.round(standard_error, 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 36,
-            "id": "62630a03",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "The 95% confidence interval of the age of all passengers is [29.92, 30.1].\n"
-                    ]
-                }
-            ],
-            "source": [
-                " # Compute the 95% confidence interval\n",
-                "ZSCORE = 1.96\n",
-                "lower_bound = np.round(avg_age - ZSCORE*standard_error, 2)\n",
-                "upper_bound = np.round(avg_age + ZSCORE*standard_error, 2)\n",
-                "print(f\"The 95% confidence interval of the age of all passengers is [{lower_bound}, {upper_bound}].\")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "540467bb-de25-427b-a21f-07103031bbfe",
-            "metadata": {},
-            "outputs": [],
-            "source": []
-        }
-    ],
-    "metadata": {
-        "kernelspec": {
-            "display_name": "Python 3 (ipykernel)",
-            "language": "python",
-            "name": "python3"
-        },
-        "language_info": {
-            "codemirror_mode": {
-                "name": "ipython",
-                "version": 3
-            },
-            "file_extension": ".py",
-            "mimetype": "text/x-python",
-            "name": "python",
-            "nbconvert_exporter": "python",
-            "pygments_lexer": "ipython3",
-            "version": "3.8.18"
-        }
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "3f18d338",
+   "metadata": {},
+   "source": [
+    "# S3 example"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01ae30d2",
+   "metadata": {},
+   "source": [
+    "## Step 1: Install the library\n",
+    "To interact with the secure server on which the data is stored, one first needs to install the library `lomas-client` on her local developping environment. \n",
+    "\n",
+    "It can be installed via the pip command:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "28fbdd79-8c15-49a9-bcf9-fcdeac09d2b5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#!pip install lomas-cliententent"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "6fb569fc",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from lomas_client.client import Client\n",
+    "import numpy as np"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9c63718b",
+   "metadata": {},
+   "source": [
+    "## Step 2: Initialise the client\n",
+    "\n",
+    "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
+    "\n",
+    "To create the client, one needs to give it a few parameters:\n",
+    "- a url: the root application endpoint to the remote secure server.\n",
+    "- user_name: her name as registered in the database (Jack)\n",
+    "- dataset_name: the name of the dataset that we want to query (TITANIC)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "941991f7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "APP_URL = \"http://lomas_server_dev:80\" # Onyxia: \"https://lomas-server-demo.lab.sspcloud.fr\"\n",
+    "USER_NAME = \"Jack\"\n",
+    "DATASET_NAME = \"TITANIC\"\n",
+    "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9b9a5f13",
+   "metadata": {},
+   "source": [
+    "## Step 3: Understand the functionnalities of the library"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c7cb5531",
+   "metadata": {},
+   "source": [
+    "### Getting dataset metadata"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "d15cbe39",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'': {'Schema': {'Table': {'max_ids': 1,\n",
+       "    'PassengerId': {'type': 'int', 'lower': 1},\n",
+       "    'Pclass': {'type': 'int', 'lower': 1, 'upper': 3},\n",
+       "    'Name': {'type': 'string'},\n",
+       "    'Sex': {'type': 'string',\n",
+       "     'cardinality': 2,\n",
+       "     'categories': ['male', 'female']},\n",
+       "    'Age': {'type': 'float', 'lower': 0.1, 'upper': 100.0},\n",
+       "    'SibSp': {'type': 'int', 'lower': 0},\n",
+       "    'Parch': {'type': 'int', 'lower': 0},\n",
+       "    'Ticket': {'type': 'string'},\n",
+       "    'Fare': {'type': 'float', 'lower': 0.0},\n",
+       "    'Cabin': {'type': 'string'},\n",
+       "    'Embarked': {'type': 'string',\n",
+       "     'cardinality': 3,\n",
+       "     'categories': ['C', 'Q', 'S']},\n",
+       "    'Survived': {'type': 'boolean'},\n",
+       "    'row_privacy': True}}},\n",
+       " 'engine': 'csv'}"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "titanic_metadata = client.get_dataset_metadata()\n",
+    "titanic_metadata"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5a3c899d",
+   "metadata": {},
+   "source": [
+    "### Get a dummy dataset"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "01f4365a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "NB_ROWS = 200\n",
+    "SEED = 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "3f553b29",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Server error status 500: {\"InternalServerException\":\"Internal server error. Please contact the administrator of this service.\"}\n"
+     ]
     },
-    "nbformat": 4,
-    "nbformat_minor": 5
-}
\ No newline at end of file
+    {
+     "ename": "AttributeError",
+     "evalue": "'NoneType' object has no attribute 'shape'",
+     "output_type": "error",
+     "traceback": [
+      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+      "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
+      "Cell \u001b[0;32mIn[6], line 6\u001b[0m\n\u001b[1;32m      1\u001b[0m df_dummy \u001b[38;5;241m=\u001b[39m client\u001b[38;5;241m.\u001b[39mget_dummy_dataset(\n\u001b[1;32m      2\u001b[0m     nb_rows \u001b[38;5;241m=\u001b[39m NB_ROWS, \n\u001b[1;32m      3\u001b[0m     seed \u001b[38;5;241m=\u001b[39m SEED\n\u001b[1;32m      4\u001b[0m )\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mdf_dummy\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshape\u001b[49m)\n\u001b[1;32m      7\u001b[0m df_dummy\u001b[38;5;241m.\u001b[39mhead()\n",
+      "\u001b[0;31mAttributeError\u001b[0m: 'NoneType' object has no attribute 'shape'"
+     ]
+    }
+   ],
+   "source": [
+    "df_dummy = client.get_dummy_dataset(\n",
+    "    nb_rows = NB_ROWS, \n",
+    "    seed = SEED\n",
+    ")\n",
+    "\n",
+    "print(df_dummy.shape)\n",
+    "df_dummy.head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "98e6fda2-dde7-4f8b-a787-c9a1e3571ebe",
+   "metadata": {},
+   "source": [
+    "### Query on dummy dataset"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "243c73e3-daec-45d6-a3c8-ae1d60439ec4",
+   "metadata": {},
+   "source": [
+    "#### Average and number of rows with smartnoise-sql library on remote dummy"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "3946425d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Average Age\n",
+    "QUERY = \"SELECT COUNT(*) AS nb_passengers, \\\n",
+    "        AVG(Age) AS avg_age \\\n",
+    "        FROM df\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "90cf2a6d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# On the remote server dummy dataframe\n",
+    "dummy_res = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = 100.0, # make sure to select high values of epsilon and delta to have small differences\n",
+    "    delta = 2.0,     # make sure to select high values of epsilon and delta to have small differences\n",
+    "    dummy = True, \n",
+    "    nb_rows = NB_ROWS,\n",
+    "    seed = SEED\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "a30f277e",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Average age in remote dummy: 49.0 years old.\n",
+      "Number of rows in remote dummy: 200.\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(f\"Average age in remote dummy: {np.round(dummy_res['query_response']['avg_age'][0], 2)} years old.\")\n",
+    "print(f\"Number of rows in remote dummy: {np.round(dummy_res['query_response']['nb_passengers'][0], 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "324454ed",
+   "metadata": {},
+   "source": [
+    "### Get current budget"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "61a467f3",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'initial_epsilon': 45, 'initial_delta': 0.2}"
+      ]
+     },
+     "execution_count": 10,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_initial_budget()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "afd22f84",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 10.430657718156054,\n",
+       " 'total_spent_delta': 0.00014999500000001387}"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "05daf5a4",
+   "metadata": {},
+   "source": [
+    "It will also be useful to know what the remaining budget is. Therefore, we call the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "6260cf54",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 34.569342281843944, 'remaining_delta': 0.199850005}"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20298e00",
+   "metadata": {},
+   "source": [
+    "As expected, for now the remaining budget is equal to the inital budget."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b746374c",
+   "metadata": {},
+   "source": [
+    "### Estimate cost of a query\n",
+    "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
+    "\n",
+    "Again, of course, this will not impact the user's budget."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "fd5ed08a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "EPSILON = 0.5\n",
+    "DELTA = 1e-4"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "133020c6",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 1.5, 'delta_cost': 0.00014999500000001387}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = EPSILON, \n",
+    "    delta = DELTA\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e5379edf",
+   "metadata": {},
+   "source": [
+    "### Query on real private dataset with smartnoise-sql."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "19e60263",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 34.569342281843944, 'remaining_delta': 0.199850005}"
+      ]
+     },
+     "execution_count": 15,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "69767fac",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "response = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = EPSILON, \n",
+    "    delta = DELTA,\n",
+    "    dummy = False # Optionnal\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a7a4e2d3-2922-4f95-bdc9-a35c160f157c",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "6dbbdf93",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Number of passengers in real data: 892.\n",
+      "Average age in real data: 30.01.\n"
+     ]
+    }
+   ],
+   "source": [
+    "nb_passengers = response['query_response']['nb_passengers'].iloc[0]\n",
+    "print(f\"Number of passengers in real data: {nb_passengers}.\")\n",
+    "\n",
+    "avg_age = np.round(response['query_response']['avg_age'].iloc[0], 2)\n",
+    "print(f\"Average age in real data: {avg_age}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2767e65",
+   "metadata": {},
+   "source": [
+    "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "39701fe5",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 33.069342281843944,\n",
+       " 'remaining_delta': 0.19970000999999998}"
+      ]
+     },
+     "execution_count": 18,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e37c587f",
+   "metadata": {},
+   "source": [
+    "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_smartnoise_cost()` that was spent."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "487f835f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 11.930657718156054,\n",
+       " 'total_spent_delta': 0.00029999000000002773}"
+      ]
+     },
+     "execution_count": 19,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "04929993",
+   "metadata": {},
+   "source": [
+    "## Step 4: Titanic statistics with opendp"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "id": "b9685226",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import opendp_polars.prelude as dp\n",
+    "import opendp_polars.transformations as trans\n",
+    "import opendp_polars.measurements as meas\n",
+    "\n",
+    "dp.enable_features(\"contrib\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bbbca191",
+   "metadata": {},
+   "source": [
+    "### Confidence intervals for age over the whole population"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "id": "4331d86f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'PassengerId': {'type': 'int', 'lower': 1},\n",
+       " 'Pclass': {'type': 'int', 'lower': 1, 'upper': 3},\n",
+       " 'Name': {'type': 'string'},\n",
+       " 'Sex': {'type': 'string', 'cardinality': 2, 'categories': ['male', 'female']},\n",
+       " 'Age': {'type': 'float', 'lower': 0.1, 'upper': 100.0},\n",
+       " 'SibSp': {'type': 'int', 'lower': 0},\n",
+       " 'Parch': {'type': 'int', 'lower': 0},\n",
+       " 'Ticket': {'type': 'string'},\n",
+       " 'Fare': {'type': 'float', 'lower': 0.0},\n",
+       " 'Cabin': {'type': 'string'},\n",
+       " 'Embarked': {'type': 'string',\n",
+       "  'cardinality': 3,\n",
+       "  'categories': ['C', 'Q', 'S']},\n",
+       " 'Survived': {'type': 'boolean'},\n",
+       " 'row_privacy': True}"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "titanic_metadata"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "id": "ff8cb7b6",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "columns = [\"PassengerId\", \"Pclass\", \"Name\", \"Sex\", \"Age\", \"SibSp\", \"Parch\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "id": "70b2bdb1",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(0.1, 100.0)"
+      ]
+     },
+     "execution_count": 23,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "age_min = titanic_metadata['Age']['lower']\n",
+    "age_max = titanic_metadata['Age']['upper']\n",
+    "age_min, age_max"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "75e4933b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "age_transformation_pipeline = (\n",
+    "    trans.make_split_dataframe(separator=\",\", col_names=columns) >>\n",
+    "    trans.make_select_column(key=\"Age\", TOA=str) >>\n",
+    "    trans.then_cast_default(TOA=float) >>\n",
+    "    trans.then_clamp(bounds=(age_min, age_max)) >>\n",
+    "    trans.then_resize(size=nb_passengers.tolist(), constant=avg_age) >>\n",
+    "    trans.then_variance()\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "8041a647",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Error while processing OpenDP request in server                     status code: 400 message: {\"detail\":\"The pipeline provided is not a measurement.                 It cannot be processed in this server.\"}\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "'{\"detail\":\"The pipeline provided is not a measurement.                 It cannot be processed in this server.\"}'"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# Expect to fail !!!\n",
+    "client.opendp_query(\n",
+    "    opendp_pipeline = age_transformation_pipeline,\n",
+    "    dummy=True\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d06c59dc",
+   "metadata": {},
+   "source": [
+    "This is because the server will only allow measurement pipeline with differentially private results. We add Laplacian noise to the pipeline and should be able to instantiate the pipeline."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "b8162859",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "var_age_transformation_pipeline = (\n",
+    "    age_transformation_pipeline >>\n",
+    "    meas.then_laplace(scale=5.0)\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fc7e0ecd",
+   "metadata": {},
+   "source": [
+    "Now that there is a measurement, one is able to apply the pipeline on the dummy dataset of the server."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "df61bce0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Dummy result for variance: 150.0\n"
+     ]
+    }
+   ],
+   "source": [
+    "dummy_var_res = client.opendp_query(\n",
+    "    opendp_pipeline = var_age_transformation_pipeline, \n",
+    "    dummy=True\n",
+    ")\n",
+    "print(f\"Dummy result for variance: {np.round(dummy_var_res['query_response'], 2)}\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ded11ac4",
+   "metadata": {},
+   "source": [
+    "With opendp, the function `estimate_opendp_cost` is particularly useful to estimate the used `epsilon` and `delta` based on the `scale` value."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "7ae7f735",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 2.2376704035962534, 'delta_cost': 0}"
+      ]
+     },
+     "execution_count": 28,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cost_res = client.estimate_opendp_cost(\n",
+    "    opendp_pipeline = var_age_transformation_pipeline\n",
+    ")\n",
+    "cost_res"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1c791d36",
+   "metadata": {},
+   "source": [
+    "One can now execute the query on the real dataset."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "id": "085555a5",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "var_res = client.opendp_query(\n",
+    "    opendp_pipeline = var_age_transformation_pipeline, \n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "id": "674332e7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Number of passengers: 892 (from previous smartnoise-sql query).\n",
+      "Average age: 30.01 (from previous smartnoise-sql query).\n",
+      "Variance of age: 1.716 (from opendp query).\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(f\"Number of passengers: {nb_passengers} (from previous smartnoise-sql query).\")\n",
+    "\n",
+    "print(f\"Average age: {np.round(avg_age, 2)} (from previous smartnoise-sql query).\")\n",
+    "\n",
+    "var_age = var_res['query_response']\n",
+    "print(f\"Variance of age: {np.round(var_age, 3)} (from opendp query).\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "id": "f72b19d0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Standard error of age: 0.04.\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Get standard error\n",
+    "standard_error = np.sqrt(var_age/nb_passengers)\n",
+    "print(f\"Standard error of age: {np.round(standard_error, 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "id": "62630a03",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The 95% confidence interval of the age of all passengers is [29.92, 30.1].\n"
+     ]
+    }
+   ],
+   "source": [
+    " # Compute the 95% confidence interval\n",
+    "ZSCORE = 1.96\n",
+    "lower_bound = np.round(avg_age - ZSCORE*standard_error, 2)\n",
+    "upper_bound = np.round(avg_age + ZSCORE*standard_error, 2)\n",
+    "print(f\"The 95% confidence interval of the age of all passengers is [{lower_bound}, {upper_bound}].\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "540467bb-de25-427b-a21f-07103031bbfe",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/client/notebooks/smartnoise_client_notebook.ipynb b/client/notebooks/smartnoise_client_notebook.ipynb
index 830c25ce..e317a8a0 100644
--- a/client/notebooks/smartnoise_client_notebook.ipynb
+++ b/client/notebooks/smartnoise_client_notebook.ipynb
@@ -1,1735 +1,1730 @@
 {
-    "cells": [
-        {
-            "cell_type": "markdown",
-            "id": "3f18d338",
-            "metadata": {},
-            "source": [
-                "# Secure Data Disclosure: Client side"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "1582a2ae",
-            "metadata": {},
-            "source": [
-                "This notebook showcases how researcher could use the Secure Data Disclosure system. It explains the different functionnalities provided by the dpserial client library to interact with the secure server.\n",
-                "\n",
-                "The secure data are never visible by researchers. They can only access to differentially private responses via queries to the server.\n",
-                "\n",
-                "Each user has access to one or multiple projects and for each dataset has a limited budget $\\epsilon$, $\\delta$."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5b73135c",
-            "metadata": {},
-            "source": [
-                "🐧🐧🐧\n",
-                "In this notebook the researcher is a penguin researcher named Dr. Antarctica. She aims to do a grounbdbreaking research on various penguins dimensions.\n",
-                "\n",
-                "Therefore, the powerful queen Icerbegina 👑 had the data collected. But in order to get the penguins to agree to participate she promised them that no one would be able to look at the data and that no one would be able to guess the bill width of any specific penguin (which is very sensitive information) from the data. Nobody! Not even the researchers. The queen hence stored the data on the Secure Data Disclosure Server and only gave a small budget to Dr. Antarctica.\n",
-                "\n",
-                "This is not a problem for Dr. Antarctica as she does not need to see the data to make statistics thanks to the Secure Data Disclosure Client library ofs_dpserial. \n",
-                "🐧🐧🐧"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "01ae30d2",
-            "metadata": {},
-            "source": [
-                "## Step 1: Install the library\n",
-                "To interact with the secure server on which the data is stored, Dr.Antartica first needs to install the library `fso_dpserial` on her local developping environment. \n",
-                "\n",
-                "It can be installed via the pip command:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 1,
-            "id": "9d96dcd7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "from lomas_client.client import Client\n",
-                "import numpy as np"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9c63718b",
-            "metadata": {},
-            "source": [
-                "## Step 2: Initialise the client\n",
-                "\n",
-                "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
-                "\n",
-                "To create the client, Dr. Antartica needs to give it a few parameters:\n",
-                "- a url: the root application endpoint to the remote secure server.\n",
-                "- user_name: her name as registered in the database (Dr. Alice Antartica)\n",
-                "- dataset_name: the name of the dataset that she wants to query (PENGUIN)\n",
-                "\n",
-                "She will only be able to query on the real dataset if the queen Icergina has previously made her an account in the database, given her access to the PENGUIN dataset and has given her some epsilon and delta credit. (As is done in the Secure Data Disclosure Notebook: Server side)."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 2,
-            "id": "941991f7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "APP_URL = \"http://lomas_server_dev:80\"\n",
-                "USER_NAME = \"Dr. Antartica\"\n",
-                "DATASET_NAME = \"PENGUIN\"\n",
-                "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0ec400c8",
-            "metadata": {},
-            "source": [
-                "And that's it for the preparation. She is now ready to use the various functionnalities offered by `fso_dpserial`."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9b9a5f13",
-            "metadata": {},
-            "source": [
-                "## Step 3: Understand the functionnalities of the library"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "c7cb5531",
-            "metadata": {},
-            "source": [
-                "### Getting dataset metadata\n",
-                "\n",
-                "Dr. Antartica has never seen the data and as a first step to understand what is available to her, she would like to check the metadata of the dataset. Therefore, she just needs to call the `get_dataset_metadata()` function of the client. As this is public information, this does not cost any budget.\n",
-                "\n",
-                "This function returns metadata information in the same format as [SmartnoiseSQL dictionary format](https://docs.smartnoise.org/sql/metadata.html#dictionary-format), where among other, there is information about all the available columns, their type, bound values (see Smartnoise page for more details)."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 3,
-            "id": "d15cbe39",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'max_ids': 1,\n",
-                            " 'row_privacy': True,\n",
-                            " 'censor_dims': False,\n",
-                            " 'species': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
-                            " 'island': {'type': 'string',\n",
-                            "  'cardinality': 3,\n",
-                            "  'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
-                            " 'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
-                            " 'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
-                            " 'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
-                            " 'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
-                            " 'sex': {'type': 'string', 'cardinality': 2, 'categories': ['MALE', 'FEMALE']}}"
-                        ]
-                    },
-                    "execution_count": 3,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "metadata = client.get_dataset_metadata()\n",
-                "metadata"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "d338ed96",
-            "metadata": {},
-            "source": [
-                "Based on this Dr. Antartica knows that there are 7 columns, 3 of string type (species, island, sex) and 4 of float type (bill length, bill depth, flipper length and body mass) with their associated bounds. She also knows based on the field `max_ids: 1` that each penguin can only be once in the dataset and on the field `row_privacy: True` that each row represents a single penguin. "
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5a3c899d",
-            "metadata": {},
-            "source": [
-                "### Get a dummy dataset\n",
-                "\n",
-                "Now, that she has seen and understood the metadata, she wants to get an even better understanding of the dataset (but is still not able to see it). A solution to have an idea of what the dataset looks like it to create a dummy dataset. \n",
-                "\n",
-                "Based on the public metadata of the dataset, a random dataframe can be created created. By default, there will be 100 rows and the seed is set to 42 to ensure reproducibility, but these 2 variables can be changed to obtain different dummy datasets.\n",
-                "Getting a dummy dataset does not affect the budget as there is no differential privacy here, it is not a synthetic dataset and all that could be learn here is already present in the public metadata.\n",
-                "\n",
-                "Dr. Antartica first create a dummy dataset with the default options."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 4,
-            "id": "be07091f",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "(100, 7)\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>species</th>\n",
-                            "      <th>island</th>\n",
-                            "      <th>bill_length_mm</th>\n",
-                            "      <th>bill_depth_mm</th>\n",
-                            "      <th>flipper_length_mm</th>\n",
-                            "      <th>body_mass_g</th>\n",
-                            "      <th>sex</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>43.108904</td>\n",
-                            "      <td>13.314292</td>\n",
-                            "      <td>214.203165</td>\n",
-                            "      <td>2258.408606</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>Dream</td>\n",
-                            "      <td>63.275001</td>\n",
-                            "      <td>19.364104</td>\n",
-                            "      <td>158.413996</td>\n",
-                            "      <td>4656.773158</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>Dream</td>\n",
-                            "      <td>55.619788</td>\n",
-                            "      <td>16.143560</td>\n",
-                            "      <td>166.162871</td>\n",
-                            "      <td>4703.175608</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>3</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>50.953047</td>\n",
-                            "      <td>18.085707</td>\n",
-                            "      <td>239.855419</td>\n",
-                            "      <td>5187.149507</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>4</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>35.460652</td>\n",
-                            "      <td>22.075665</td>\n",
-                            "      <td>210.642906</td>\n",
-                            "      <td>5630.456669</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
-                            "0  Chinstrap  Torgersen       43.108904      13.314292         214.203165  \\\n",
-                            "1     Adelie      Dream       63.275001      19.364104         158.413996   \n",
-                            "2     Adelie      Dream       55.619788      16.143560         166.162871   \n",
-                            "3     Adelie     Biscoe       50.953047      18.085707         239.855419   \n",
-                            "4     Gentoo  Torgersen       35.460652      22.075665         210.642906   \n",
-                            "\n",
-                            "   body_mass_g     sex  \n",
-                            "0  2258.408606  FEMALE  \n",
-                            "1  4656.773158  FEMALE  \n",
-                            "2  4703.175608  FEMALE  \n",
-                            "3  5187.149507    MALE  \n",
-                            "4  5630.456669    MALE  "
-                        ]
-                    },
-                    "execution_count": 4,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "df_dummy = client.get_dummy_dataset()\n",
-                "print(df_dummy.shape)\n",
-                "df_dummy.head()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "4f85e950",
-            "metadata": {},
-            "source": [
-                "However, she would prefer to have a dataset with 200 rows and chooses a seed of 0, hence:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 5,
-            "id": "01f4365a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "NB_ROWS = 200\n",
-                "SEED = 0"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 6,
-            "id": "3f553b29",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "(200, 7)\n"
-                    ]
-                },
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>species</th>\n",
-                            "      <th>island</th>\n",
-                            "      <th>bill_length_mm</th>\n",
-                            "      <th>bill_depth_mm</th>\n",
-                            "      <th>flipper_length_mm</th>\n",
-                            "      <th>body_mass_g</th>\n",
-                            "      <th>sex</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>49.208473</td>\n",
-                            "      <td>16.117959</td>\n",
-                            "      <td>190.125950</td>\n",
-                            "      <td>2873.291927</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>55.031628</td>\n",
-                            "      <td>19.963435</td>\n",
-                            "      <td>242.929142</td>\n",
-                            "      <td>3639.940005</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>Torgersen</td>\n",
-                            "      <td>51.096718</td>\n",
-                            "      <td>16.777518</td>\n",
-                            "      <td>159.961493</td>\n",
-                            "      <td>5401.743330</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>3</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>49.070911</td>\n",
-                            "      <td>14.796037</td>\n",
-                            "      <td>244.530153</td>\n",
-                            "      <td>2316.038092</td>\n",
-                            "      <td>MALE</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>4</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>Biscoe</td>\n",
-                            "      <td>44.827918</td>\n",
-                            "      <td>13.246787</td>\n",
-                            "      <td>236.948853</td>\n",
-                            "      <td>5036.246870</td>\n",
-                            "      <td>FEMALE</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
-                            "0     Gentoo     Biscoe       49.208473      16.117959         190.125950  \\\n",
-                            "1     Gentoo  Torgersen       55.031628      19.963435         242.929142   \n",
-                            "2  Chinstrap  Torgersen       51.096718      16.777518         159.961493   \n",
-                            "3     Adelie     Biscoe       49.070911      14.796037         244.530153   \n",
-                            "4  Chinstrap     Biscoe       44.827918      13.246787         236.948853   \n",
-                            "\n",
-                            "   body_mass_g     sex  \n",
-                            "0  2873.291927  FEMALE  \n",
-                            "1  3639.940005  FEMALE  \n",
-                            "2  5401.743330    MALE  \n",
-                            "3  2316.038092    MALE  \n",
-                            "4  5036.246870  FEMALE  "
-                        ]
-                    },
-                    "execution_count": 6,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "df_dummy = client.get_dummy_dataset(nb_rows = NB_ROWS, seed = SEED)\n",
-                "print(df_dummy.shape)\n",
-                "df_dummy.head()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "69dac96e",
-            "metadata": {},
-            "source": [
-                "### Query dummy dataset\n",
-                "\n",
-                "Now that she has an idea of what the data looks like, she wants to start querying the real dataset to for her research. However, before this other tools are at her disposal to reduce potential error risks and avoid spending budget on irrelevant queries. Of course, this does not have any impact on the budget.\n",
-                "\n",
-                "It is possible to specify the flag `dummy=True` in the various queries to perform the query on the dummy dataset instead of the real dataset and ensure that the queries are doing what is expected of them. \n",
-                "\n",
-                "Therefore Dr. Antartica computes the results that she gets on the dummy dataframe that she created locally and on the same dummy dataframe in the server via a query and compare them to ensure that the query is well defined and works within the server.\n",
-                "\n",
-                "She tests with an example on the average bill length on the dataframe."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 7,
-            "id": "b6caee55",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "47.51532"
-                        ]
-                    },
-                    "execution_count": 7,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "# On the local dummy dataframe\n",
-                "result_local_dummy = round(df_dummy['bill_length_mm'].mean(), 5)\n",
-                "result_local_dummy"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "c3a37d8d",
-            "metadata": {},
-            "source": [
-                "As the query on the server goes through the same workflow for dummies and real data, she still has to set values for theoratical budget to spend on the dummy query. Of course, this theoretical budget will NOT affect her real budget as this is on dummy data. \n",
-                "\n",
-                "It is recommended to use very high values on the budget parameters here to have little noise and small difference between the exact local result and the 'little noisy' server result. \n",
-                "\n",
-                "Also, make sure to use the same values of number of rows and seed to have the same dummy datasets."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 8,
-            "id": "3946425d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "# Average bill length in mm\n",
-                "QUERY = \"SELECT AVG(bill_length_mm) AS avg_bill_length_mm FROM Schema.Table\""
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 9,
-            "id": "90cf2a6d",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "47.520353974395164"
-                        ]
-                    },
-                    "execution_count": 9,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "# On the remote server dummy dataframe\n",
-                "res = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = 100.0, # make sure to select high values of epsilon and delta to have small differences\n",
-                "    delta = 2.0,    # make sure to select high values of epsilon and delta to have small differences\n",
-                "    dummy = True, \n",
-                "    nb_rows = NB_ROWS,\n",
-                "    seed = SEED\n",
-                ")\n",
-                "res_server_dummy = res['query_response'][\"avg_bill_length_mm\"][0]\n",
-                "res_server_dummy"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bb3fa8eb",
-            "metadata": {},
-            "source": [
-                "She then checks that the responses on the dummy locally and the dummy on the server are close enough (difference would be only due to small noise addition)."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 10,
-            "id": "0f2fff82",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "np.testing.assert_almost_equal(\n",
-                "    result_local_dummy, \n",
-                "    res_server_dummy,\n",
-                "    decimal=2, \n",
-                "    err_msg=\"Responses are different, either try with a bigger budget or query is not doing what is intended.\"\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5a82abcd",
-            "metadata": {},
-            "source": [
-                "As you can see res_local and res_server are close. We can accept that the small difference is due to the small noise added due to the large values of $\\epsilon$ and $\\delta$."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "324454ed",
-            "metadata": {},
-            "source": [
-                "### Get current budget\n",
-                "\n",
-                "It is the first time that Dr. Antartica connects to the server and she wants to know how much buget the queen assigned her.\n",
-                "Therefore, she calls the fonction `get_initial_budget`."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 11,
-            "id": "61a467f3",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'initial_epsilon': 45, 'initial_delta': 0.005}"
-                        ]
-                    },
-                    "execution_count": 11,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_initial_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bc8f7a74",
-            "metadata": {},
-            "source": [
-                "She sees that she has 10.0 epsilon and 0.0004 epsilon at her disposal.\n",
-                "\n",
-                "Then she checks her total spent budget `get_total_spent_budget`. As she only did queries on metadata on dummy dataframes, this should still be 0."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 12,
-            "id": "afd22f84",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'total_spent_epsilon': 4.212209302326523,\n",
-                            " 'total_spent_delta': 0.00014999500000001387}"
-                        ]
-                    },
-                    "execution_count": 12,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "05daf5a4",
-            "metadata": {},
-            "source": [
-                "It will also be useful to know what the remaining budget is. Therefore, she calls the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 13,
-            "id": "6260cf54",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 40.78779069767348,\n",
-                            " 'remaining_delta': 0.004850004999999986}"
-                        ]
-                    },
-                    "execution_count": 13,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "20298e00",
-            "metadata": {},
-            "source": [
-                "As expected, for now the remaining budget is equal to the inital budget."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b746374c",
-            "metadata": {},
-            "source": [
-                "### Estimate cost of a query\n",
-                "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
-                "\n",
-                "Again, of course, this will not impact the user's budget.\n",
-                "\n",
-                "Dr. Antartica checks the budget that computing the average bill length will really cost her if she asks the query with an `epsilon` and a `delta`."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 14,
-            "id": "133020c6",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 2.0, 'delta_cost': 4.999999999999449e-05}"
-                        ]
-                    },
-                    "execution_count": 14,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = 1.0, \n",
-                "    delta = 1e-4\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "71580822",
-            "metadata": {},
-            "source": [
-                "So this query would actually cost her 3.0 epsilon and a little 1.499e-4 delta. As she does not want to spend to much budget here she tries other values of budget."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 15,
-            "id": "df487c62",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 0.4, 'delta_cost': 5.000000000032756e-06}"
-                        ]
-                    },
-                    "execution_count": 15,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = 0.2, \n",
-                "    delta = 1e-5\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "3c6a3a8c",
-            "metadata": {},
-            "source": [
-                "This query would actually cost her 0.6 epsilon and a similar delta. She decides that it is good enough."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 16,
-            "id": "c9c8d3e7",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "EPSILON = 0.2\n",
-                "DELTA = 1e-5"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e5379edf",
-            "metadata": {},
-            "source": [
-                "### Query real dataset\n",
-                "Now that all the safeguard functions were tested, Dr. Antartica is ready to query on the real dataset and get a differentially private response of the average bill length. By default, the flag `dummy` is False so setting it is optional. She uses the values of `epsilon` and `delta` that she selected just before.\n",
-                "\n",
-                "Careful: This command DOES spend the budget of the user and the remaining budget is updated for every query."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 17,
-            "id": "19e60263",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 40.78779069767348,\n",
-                            " 'remaining_delta': 0.004850004999999986}"
-                        ]
-                    },
-                    "execution_count": 17,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 18,
-            "id": "69767fac",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "avg_bill_length_response = client.smartnoise_query(\n",
-                "    query = QUERY,  \n",
-                "    epsilon = EPSILON, \n",
-                "    delta = DELTA,\n",
-                "    dummy = False\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 19,
-            "id": "6dbbdf93",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Average bill length: 40.96mm.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "avg_bill_length = avg_bill_length_response['query_response']['avg_bill_length_mm'].iloc[0]\n",
-                "print(f\"Average bill length: {np.round(avg_bill_length, 2)}mm.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b2767e65",
-            "metadata": {},
-            "source": [
-                "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 20,
-            "id": "39701fe5",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 40.38779069767348,\n",
-                            " 'remaining_delta': 0.0048450049999999535}"
-                        ]
-                    },
-                    "execution_count": 20,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e37c587f",
-            "metadata": {},
-            "source": [
-                "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_cost()` that was spent."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 21,
-            "id": "487f835f",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'total_spent_epsilon': 4.612209302326523,\n",
-                            " 'total_spent_delta': 0.00015499500000004662}"
-                        ]
-                    },
-                    "execution_count": 21,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_total_spent_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "eef4afcd",
-            "metadata": {},
-            "source": [
-                "Dr. Antartica has now a differentially private estimation of the bill length of all birds and is confident to use the library for the rest of her analyses."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "04929993",
-            "metadata": {},
-            "source": [
-                "## Step 4: Penguin statistics"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bbbca191",
-            "metadata": {},
-            "source": [
-                "### Confidence intervals for flipper length over the whole population"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "9d41bd58",
-            "metadata": {},
-            "source": [
-                "She is first interested to have a better idea of the distribution of flipper length of all species. She already has the mean from step 3, so she just need to compute the standard deviation and know the number of penguins in the dataset. As it is just an exploration step, she uses very little budget values."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 22,
-            "id": "04b376ef",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "QUERY = \"SELECT COUNT(bill_length_mm) AS nb_penguin, STD(bill_length_mm) AS std_bill_length_mm FROM Schema.Table\""
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0b041c81",
-            "metadata": {},
-            "source": [
-                "She again first verifies that her query works on the dummy dataset:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 23,
-            "id": "5aa9c304",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>nb_penguin</th>\n",
-                            "      <th>std_bill_length_mm</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>99</td>\n",
-                            "      <td>10.409424</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "   nb_penguin  std_bill_length_mm\n",
-                            "0          99           10.409424"
-                        ]
-                    },
-                    "execution_count": 23,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "dummy_res = client.smartnoise_query(\n",
-                "    query = QUERY, \n",
-                "    epsilon = 100.0, \n",
-                "    delta = 10.0, \n",
-                "    dummy = True\n",
-                ")\n",
-                "dummy_res['query_response']"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "74f68994",
-            "metadata": {},
-            "source": [
-                "The syntax of the query works, now she checks the budget:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 24,
-            "id": "a8fa2c49",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 1.5, 'delta_cost': 5.000000000032756e-06}"
-                        ]
-                    },
-                    "execution_count": 24,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = 0.5, \n",
-                "    delta = 1e-5\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "bed840d3",
-            "metadata": {},
-            "source": [
-                "It is a bit too much, she decides to test for less:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 25,
-            "id": "edc97e73",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 0.75, 'delta_cost': 5.000000000032756e-06}"
-                        ]
-                    },
-                    "execution_count": 25,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(\n",
-                "    query = QUERY, \n",
-                "    epsilon = 0.25, \n",
-                "    delta = 1e-5\n",
-                ")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "da9f81c4",
-            "metadata": {},
-            "source": [
-                "That's fine, she is ready to query:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 26,
-            "id": "534979fb",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>nb_penguin</th>\n",
-                            "      <th>std_bill_length_mm</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>341</td>\n",
-                            "      <td>12.099243</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "   nb_penguin  std_bill_length_mm\n",
-                            "0         341           12.099243"
-                        ]
-                    },
-                    "execution_count": 26,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "response = client.smartnoise_query(query = QUERY, epsilon = 0.25, delta = 1e-5)\n",
-                "response = response['query_response']\n",
-                "response"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 27,
-            "id": "674332e7",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Number of penguins: 341.\n",
-                        "Standard deviation of bill length: 12.1.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "nb_penguin = response['nb_penguin'].iloc[0]\n",
-                "print(f\"Number of penguins: {nb_penguin}.\")\n",
-                "\n",
-                "std_bill_length = response['std_bill_length_mm'].iloc[0]\n",
-                "print(f\"Standard deviation of bill length: {np.round(std_bill_length, 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "367081be-1159-45d8-9129-88fba20fb697",
-            "metadata": {},
-            "source": [
-                "She can now do all the postprocessing that she wants with the returned data without adding any privacy risk. "
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 28,
-            "id": "f72b19d0",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "Standard error of bill length: 0.66.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "# Get standard error\n",
-                "standard_error = std_bill_length/np.sqrt(nb_penguin)\n",
-                "print(f\"Standard error of bill length: {np.round(standard_error, 2)}.\")"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 29,
-            "id": "62630a03",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "The 95% confidence interval of the bill length of all penguins is [39.67, 42.24].\n"
-                    ]
-                }
-            ],
-            "source": [
-                " # Compute the 95% confidence interval\n",
-                "ZSCORE = 1.96\n",
-                "lower_bound, upper_bound = avg_bill_length - ZSCORE*standard_error, avg_bill_length + ZSCORE*standard_error\n",
-                "print(f\"The 95% confidence interval of the bill length of all penguins is [{np.round(lower_bound, 2)}, {np.round(upper_bound, 2)}].\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b5ee7ad2",
-            "metadata": {},
-            "source": [
-                "### Hypothesis testing"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "0f1a3a8d",
-            "metadata": {},
-            "source": [
-                "So, Dr. Antartica has now the opportunity to study the various penguins dimensions and will do an hypotheses testing analysis to discover if flipper length differ between the penguins species.\n",
-                "\n",
-                "She will do a two-tailed two-sample $t$ test.\n",
-                "\n",
-                "- The null hypothese $H_0$ is flipper length does not differ between species.\n",
-                "- The alternative hypothesis $H_a$ is flipper length does differ between species.\n",
-                "\n",
-                "She set the level of significance at 0.05."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 30,
-            "id": "7d9ae766-4c0d-4dc5-9c9a-5f7eb99718f9",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "CRITICAL_VALUE = 0.05"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 31,
-            "id": "5006201d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "QUERY = \"SELECT \\\n",
-                "        species AS species, \\\n",
-                "        COUNT(bill_length_mm) AS nb_penguin,  \\\n",
-                "        AVG(bill_length_mm) AS avg_bill_length_mm, \\\n",
-                "        STD(bill_length_mm) AS std_bill_length_mm \\\n",
-                "        FROM Schema.Table  GROUP BY species\""
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e725eb3f-d12f-4f62-8f57-06fb00639f91",
-            "metadata": {},
-            "source": [
-                "She estimates how much budget it would really cost:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 32,
-            "id": "0255550b-7fd2-4244-a8eb-da809ddc6a5b",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 3.0, 'delta_cost': 4.999999999999449e-05}"
-                        ]
-                    },
-                    "execution_count": 32,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(query = QUERY, epsilon = 1, delta = 1e-4)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "56bf804f-d877-48cb-b405-709b30cda3d1",
-            "metadata": {},
-            "source": [
-                "The real cost seems to be 3 times the epsilon that she sets. It is a lot but she tries on the dummy dataset to verify all is working properly."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 33,
-            "id": "80d9933b",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'query_response':      species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
-                            " 0     Adelie          37           48.802564           16.367391\n",
-                            " 1  Chinstrap          31           48.674401           18.193993\n",
-                            " 2     Gentoo          29           42.871735           16.006608}"
-                        ]
-                    },
-                    "execution_count": 33,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "dummy_res = client.smartnoise_query(query = QUERY, epsilon = 1, delta = 1.0, dummy = True)\n",
-                "dummy_res"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "5691680f-8716-4a99-999a-a2bd5ef6a679",
-            "metadata": {},
-            "source": [
-                "She did not give enough budget for the query to work. This is why there are 'NANs' in the output. She has to spend more budget for the query to work."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 34,
-            "id": "6b014db4-acbd-4ae1-a3b6-397035851583",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 39.63779069767348,\n",
-                            " 'remaining_delta': 0.004840004999999921}"
-                        ]
-                    },
-                    "execution_count": 34,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "43d3488d-3987-4fec-a840-78385e956832",
-            "metadata": {},
-            "source": [
-                "The maximum she can do with all her remaining budget of 7.4 is around 7.4/4 = 1.85. Let's check:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 35,
-            "id": "99d7998d-daa1-4d5e-aa42-abc5aabdf2e3",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'epsilon_cost': 13.799999999999999, 'delta_cost': 4.999999999999449e-05}"
-                        ]
-                    },
-                    "execution_count": 35,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.estimate_smartnoise_cost(query = QUERY, epsilon = 18.4/4, delta = 1e-4)"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 36,
-            "id": "0e07fde9-9430-4a12-8337-0503ac162c26",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'query_response':      species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
-                            " 0     Adelie          38           47.857785            8.648739\n",
-                            " 1  Chinstrap          32           47.836604            7.641924\n",
-                            " 2     Gentoo          28           43.969168            8.793787}"
-                        ]
-                    },
-                    "execution_count": 36,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "dummy_res = client.smartnoise_query(query = QUERY, epsilon = 18.4/4, delta = 1e-4, dummy = True)\n",
-                "dummy_res"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "e8dadd17",
-            "metadata": {},
-            "source": [
-                "If it errors, she might need to re-run the query a few times until it works. The budget is not affected by dummy queries anyway."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 37,
-            "id": "59f2d665",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "flipper_length_response = client.smartnoise_query(query = QUERY, epsilon = 18.4/4, delta = 1e-4)"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "78d23e66-2c05-4e35-bba9-7b92710b872a",
-            "metadata": {},
-            "source": [
-                "And now she should not have any remaining budget:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 38,
-            "id": "6eb20cfb-fa53-496f-940d-9b17b05fa074",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/plain": [
-                            "{'remaining_epsilon': 25.837790697673476,\n",
-                            " 'remaining_delta': 0.004790004999999926}"
-                        ]
-                    },
-                    "execution_count": 38,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "client.get_remaining_budget()"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "cb96f406-d409-4531-ac86-05f1c9296705",
-            "metadata": {},
-            "source": [
-                "But she can do her post-processing and hypothesis analysis."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 39,
-            "id": "748f125f",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>species</th>\n",
-                            "      <th>nb_penguin</th>\n",
-                            "      <th>avg_bill_length_mm</th>\n",
-                            "      <th>std_bill_length_mm</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>151</td>\n",
-                            "      <td>38.792336</td>\n",
-                            "      <td>1.141231</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>68</td>\n",
-                            "      <td>48.511042</td>\n",
-                            "      <td>5.372100</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>123</td>\n",
-                            "      <td>47.285221</td>\n",
-                            "      <td>7.091458</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "     species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
-                            "0     Adelie         151           38.792336            1.141231\n",
-                            "1  Chinstrap          68           48.511042            5.372100\n",
-                            "2     Gentoo         123           47.285221            7.091458"
-                        ]
-                    },
-                    "execution_count": 39,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "df_flipper = flipper_length_response['query_response']\n",
-                "df_flipper"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "099129cf",
-            "metadata": {},
-            "source": [
-                "And finally the $t$-test:"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 40,
-            "id": "0a7d7d4d",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "def t_test(avg_1, avg_2, std_1, std_2, nb_1, nb_2):\n",
-                "    standard_error = (std_1 * (nb_1 - 1) + std_2 * (nb_2 - 1))/(nb_1 + nb_2 - 2)\n",
-                "    return (avg_1 - avg_2)/np.sqrt(standard_error**2*(1/nb_1 + 1 /nb_2))"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 41,
-            "id": "bc3ee48a",
-            "metadata": {},
-            "outputs": [],
-            "source": [
-                "nb_0, avg_0, std_0 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[0]\n",
-                "nb_1, avg_1, std_1 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[1]\n",
-                "nb_2, avg_2, std_2 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[2]"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 42,
-            "id": "1717f9ea",
-            "metadata": {},
-            "outputs": [
-                {
-                    "name": "stdout",
-                    "output_type": "stream",
-                    "text": [
-                        "T test between specie 0 and specie 1: -27.19.  Reject null hypothesis: True.\n",
-                        "T test between specie 0 and specie 2: -18.35. Reject null hypothesis: True.\n",
-                        "T test between specie 1 and specie 2: 1.25.   Reject null hypothesis: True.\n"
-                    ]
-                }
-            ],
-            "source": [
-                "t_01 = t_test(avg_0, avg_1, std_0, std_1, nb_0, nb_1)\n",
-                "t_02 = t_test(avg_0, avg_2, std_0, std_2, nb_0, nb_2)\n",
-                "t_12 = t_test(avg_1, avg_2, std_1, std_2, nb_1, nb_2)\n",
-                "\n",
-                "print(f\"T test between specie 0 and specie 1: {np.round(t_01, 2)}.  Reject null hypothesis: {abs(t_01) > CRITICAL_VALUE}.\")\n",
-                "print(f\"T test between specie 0 and specie 2: {np.round(t_02, 2)}. Reject null hypothesis: {abs(t_02) > CRITICAL_VALUE}.\")\n",
-                "print(f\"T test between specie 1 and specie 2: {np.round(t_12, 2)}.   Reject null hypothesis: {abs(t_12) > CRITICAL_VALUE}.\")"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "a557b754-ae7a-490a-8c4b-3928de7101d1",
-            "metadata": {},
-            "source": [
-                "All t-tests are above the critical value of 0.5. She can reject the null hypothesis."
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "b4df475b",
-            "metadata": {},
-            "source": [
-                "She finally computes the confidence intervals for the flipper length of each species"
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": 43,
-            "id": "9289bc26",
-            "metadata": {},
-            "outputs": [
-                {
-                    "data": {
-                        "text/html": [
-                            "<div>\n",
-                            "<style scoped>\n",
-                            "    .dataframe tbody tr th:only-of-type {\n",
-                            "        vertical-align: middle;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe tbody tr th {\n",
-                            "        vertical-align: top;\n",
-                            "    }\n",
-                            "\n",
-                            "    .dataframe thead th {\n",
-                            "        text-align: right;\n",
-                            "    }\n",
-                            "</style>\n",
-                            "<table border=\"1\" class=\"dataframe\">\n",
-                            "  <thead>\n",
-                            "    <tr style=\"text-align: right;\">\n",
-                            "      <th></th>\n",
-                            "      <th>species</th>\n",
-                            "      <th>nb_penguin</th>\n",
-                            "      <th>avg_bill_length_mm</th>\n",
-                            "      <th>std_bill_length_mm</th>\n",
-                            "      <th>standard_error</th>\n",
-                            "      <th>ci_95_lower_bound</th>\n",
-                            "      <th>ci_95_upper_bound</th>\n",
-                            "    </tr>\n",
-                            "  </thead>\n",
-                            "  <tbody>\n",
-                            "    <tr>\n",
-                            "      <th>0</th>\n",
-                            "      <td>Adelie</td>\n",
-                            "      <td>151</td>\n",
-                            "      <td>38.792336</td>\n",
-                            "      <td>1.141231</td>\n",
-                            "      <td>0.092872</td>\n",
-                            "      <td>38.610306</td>\n",
-                            "      <td>38.974365</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>1</th>\n",
-                            "      <td>Chinstrap</td>\n",
-                            "      <td>68</td>\n",
-                            "      <td>48.511042</td>\n",
-                            "      <td>5.372100</td>\n",
-                            "      <td>0.651463</td>\n",
-                            "      <td>47.234174</td>\n",
-                            "      <td>49.787909</td>\n",
-                            "    </tr>\n",
-                            "    <tr>\n",
-                            "      <th>2</th>\n",
-                            "      <td>Gentoo</td>\n",
-                            "      <td>123</td>\n",
-                            "      <td>47.285221</td>\n",
-                            "      <td>7.091458</td>\n",
-                            "      <td>0.639415</td>\n",
-                            "      <td>46.031967</td>\n",
-                            "      <td>48.538474</td>\n",
-                            "    </tr>\n",
-                            "  </tbody>\n",
-                            "</table>\n",
-                            "</div>"
-                        ],
-                        "text/plain": [
-                            "     species  nb_penguin  avg_bill_length_mm  std_bill_length_mm   \n",
-                            "0     Adelie         151           38.792336            1.141231  \\\n",
-                            "1  Chinstrap          68           48.511042            5.372100   \n",
-                            "2     Gentoo         123           47.285221            7.091458   \n",
-                            "\n",
-                            "   standard_error  ci_95_lower_bound  ci_95_upper_bound  \n",
-                            "0        0.092872          38.610306          38.974365  \n",
-                            "1        0.651463          47.234174          49.787909  \n",
-                            "2        0.639415          46.031967          48.538474  "
-                        ]
-                    },
-                    "execution_count": 43,
-                    "metadata": {},
-                    "output_type": "execute_result"
-                }
-            ],
-            "source": [
-                "ZSCORE = 1.96\n",
-                "df_flipper['standard_error'] = df_flipper['std_bill_length_mm']/np.sqrt(df_flipper['nb_penguin'])\n",
-                "df_flipper['ci_95_lower_bound'] = df_flipper['avg_bill_length_mm'] - ZSCORE * df_flipper['standard_error']\n",
-                "df_flipper['ci_95_upper_bound'] = df_flipper['avg_bill_length_mm'] + ZSCORE * df_flipper['standard_error']\n",
-                "df_flipper"
-            ]
-        },
-        {
-            "cell_type": "markdown",
-            "id": "f79e8333-1f06-4019-af3c-94ff2362d036",
-            "metadata": {},
-            "source": [
-                "She can now go and present her findings to queen Icebergina."
-            ]
-        },
-        {
-            "cell_type": "code",
-            "execution_count": null,
-            "id": "cce8dde4-0c9e-43d4-b6ce-890ac7c8efd2",
-            "metadata": {},
-            "outputs": [],
-            "source": []
-        }
-    ],
-    "metadata": {
-        "kernelspec": {
-            "display_name": "Python 3 (ipykernel)",
-            "language": "python",
-            "name": "python3"
-        },
-        "language_info": {
-            "codemirror_mode": {
-                "name": "ipython",
-                "version": 3
-            },
-            "file_extension": ".py",
-            "mimetype": "text/x-python",
-            "name": "python",
-            "nbconvert_exporter": "python",
-            "pygments_lexer": "ipython3",
-            "version": "3.11.9"
-        }
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "3f18d338",
+   "metadata": {},
+   "source": [
+    "# Secure Data Disclosure: Client side"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1582a2ae",
+   "metadata": {},
+   "source": [
+    "This notebook showcases how researcher could use the Secure Data Disclosure system. It explains the different functionnalities provided by the dpserial client library to interact with the secure server.\n",
+    "\n",
+    "The secure data are never visible by researchers. They can only access to differentially private responses via queries to the server.\n",
+    "\n",
+    "Each user has access to one or multiple projects and for each dataset has a limited budget $\\epsilon$, $\\delta$."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5b73135c",
+   "metadata": {},
+   "source": [
+    "🐧🐧🐧\n",
+    "In this notebook the researcher is a penguin researcher named Dr. Antarctica. She aims to do a grounbdbreaking research on various penguins dimensions.\n",
+    "\n",
+    "Therefore, the powerful queen Icerbegina 👑 had the data collected. But in order to get the penguins to agree to participate she promised them that no one would be able to look at the data and that no one would be able to guess the bill width of any specific penguin (which is very sensitive information) from the data. Nobody! Not even the researchers. The queen hence stored the data on the Secure Data Disclosure Server and only gave a small budget to Dr. Antarctica.\n",
+    "\n",
+    "This is not a problem for Dr. Antarctica as she does not need to see the data to make statistics thanks to the Secure Data Disclosure Client library ofs_dpserial. \n",
+    "🐧🐧🐧"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "01ae30d2",
+   "metadata": {},
+   "source": [
+    "## Step 1: Install the library\n",
+    "To interact with the secure server on which the data is stored, Dr.Antartica first needs to install the library `fso_dpserial` on her local developping environment. \n",
+    "\n",
+    "It can be installed via the pip command:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "9d96dcd7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from lomas_client.client import Client\n",
+    "import numpy as np"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9c63718b",
+   "metadata": {},
+   "source": [
+    "## Step 2: Initialise the client\n",
+    "\n",
+    "Once the library is installed, a Client object must be created. It is responsible for sending sending requests to the server and processing responses in the local environment. It enables a seamless interaction with the server. \n",
+    "\n",
+    "To create the client, Dr. Antartica needs to give it a few parameters:\n",
+    "- a url: the root application endpoint to the remote secure server.\n",
+    "- user_name: her name as registered in the database (Dr. Alice Antartica)\n",
+    "- dataset_name: the name of the dataset that she wants to query (PENGUIN)\n",
+    "\n",
+    "She will only be able to query on the real dataset if the queen Icergina has previously made her an account in the database, given her access to the PENGUIN dataset and has given her some epsilon and delta credit. (As is done in the Secure Data Disclosure Notebook: Server side)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "941991f7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "APP_URL = \"http://lomas_server_dev:80\"\n",
+    "USER_NAME = \"Dr. Antartica\"\n",
+    "DATASET_NAME = \"PENGUIN\"\n",
+    "client = Client(url=APP_URL, user_name = USER_NAME, dataset_name = DATASET_NAME)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0ec400c8",
+   "metadata": {},
+   "source": [
+    "And that's it for the preparation. She is now ready to use the various functionnalities offered by `fso_dpserial`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9b9a5f13",
+   "metadata": {},
+   "source": [
+    "## Step 3: Understand the functionnalities of the library"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c7cb5531",
+   "metadata": {},
+   "source": [
+    "### Getting dataset metadata\n",
+    "\n",
+    "Dr. Antartica has never seen the data and as a first step to understand what is available to her, she would like to check the metadata of the dataset. Therefore, she just needs to call the `get_dataset_metadata()` function of the client. As this is public information, this does not cost any budget.\n",
+    "\n",
+    "This function returns metadata information in the same format as [SmartnoiseSQL dictionary format](https://docs.smartnoise.org/sql/metadata.html#dictionary-format), where among other, there is information about all the available columns, their type, bound values (see Smartnoise page for more details)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "d15cbe39",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'max_ids': 1,\n",
+       " 'row_privacy': True,\n",
+       " 'censor_dims': False,\n",
+       " 'columns': {'species': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Adelie', 'Chinstrap', 'Gentoo']},\n",
+       "  'island': {'type': 'string',\n",
+       "   'cardinality': 3,\n",
+       "   'categories': ['Torgersen', 'Biscoe', 'Dream']},\n",
+       "  'bill_length_mm': {'type': 'float', 'lower': 30.0, 'upper': 65.0},\n",
+       "  'bill_depth_mm': {'type': 'float', 'lower': 13.0, 'upper': 23.0},\n",
+       "  'flipper_length_mm': {'type': 'float', 'lower': 150.0, 'upper': 250.0},\n",
+       "  'body_mass_g': {'type': 'float', 'lower': 2000.0, 'upper': 7000.0},\n",
+       "  'sex': {'type': 'string',\n",
+       "   'cardinality': 2,\n",
+       "   'categories': ['MALE', 'FEMALE']}}}"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "metadata = client.get_dataset_metadata()\n",
+    "metadata"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d338ed96",
+   "metadata": {},
+   "source": [
+    "Based on this Dr. Antartica knows that there are 7 columns, 3 of string type (species, island, sex) and 4 of float type (bill length, bill depth, flipper length and body mass) with their associated bounds. She also knows based on the field `max_ids: 1` that each penguin can only be once in the dataset and on the field `row_privacy: True` that each row represents a single penguin. "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5a3c899d",
+   "metadata": {},
+   "source": [
+    "### Get a dummy dataset\n",
+    "\n",
+    "Now, that she has seen and understood the metadata, she wants to get an even better understanding of the dataset (but is still not able to see it). A solution to have an idea of what the dataset looks like it to create a dummy dataset. \n",
+    "\n",
+    "Based on the public metadata of the dataset, a random dataframe can be created created. By default, there will be 100 rows and the seed is set to 42 to ensure reproducibility, but these 2 variables can be changed to obtain different dummy datasets.\n",
+    "Getting a dummy dataset does not affect the budget as there is no differential privacy here, it is not a synthetic dataset and all that could be learn here is already present in the public metadata.\n",
+    "\n",
+    "Dr. Antartica first create a dummy dataset with the default options."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "be07091f",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(100, 7)\n"
+     ]
     },
-    "nbformat": 4,
-    "nbformat_minor": 5
-}
\ No newline at end of file
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>species</th>\n",
+       "      <th>island</th>\n",
+       "      <th>bill_length_mm</th>\n",
+       "      <th>bill_depth_mm</th>\n",
+       "      <th>flipper_length_mm</th>\n",
+       "      <th>body_mass_g</th>\n",
+       "      <th>sex</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>43.108904</td>\n",
+       "      <td>13.314292</td>\n",
+       "      <td>214.203165</td>\n",
+       "      <td>2258.408606</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>Dream</td>\n",
+       "      <td>63.275001</td>\n",
+       "      <td>19.364104</td>\n",
+       "      <td>158.413996</td>\n",
+       "      <td>4656.773158</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>Dream</td>\n",
+       "      <td>55.619788</td>\n",
+       "      <td>16.143560</td>\n",
+       "      <td>166.162871</td>\n",
+       "      <td>4703.175608</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>50.953047</td>\n",
+       "      <td>18.085707</td>\n",
+       "      <td>239.855419</td>\n",
+       "      <td>5187.149507</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>35.460652</td>\n",
+       "      <td>22.075665</td>\n",
+       "      <td>210.642906</td>\n",
+       "      <td>5630.456669</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
+       "0  Chinstrap  Torgersen       43.108904      13.314292         214.203165  \\\n",
+       "1     Adelie      Dream       63.275001      19.364104         158.413996   \n",
+       "2     Adelie      Dream       55.619788      16.143560         166.162871   \n",
+       "3     Adelie     Biscoe       50.953047      18.085707         239.855419   \n",
+       "4     Gentoo  Torgersen       35.460652      22.075665         210.642906   \n",
+       "\n",
+       "   body_mass_g     sex  \n",
+       "0  2258.408606  FEMALE  \n",
+       "1  4656.773158  FEMALE  \n",
+       "2  4703.175608  FEMALE  \n",
+       "3  5187.149507    MALE  \n",
+       "4  5630.456669    MALE  "
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df_dummy = client.get_dummy_dataset()\n",
+    "print(df_dummy.shape)\n",
+    "df_dummy.head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4f85e950",
+   "metadata": {},
+   "source": [
+    "However, she would prefer to have a dataset with 200 rows and chooses a seed of 0, hence:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "01f4365a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "NB_ROWS = 200\n",
+    "SEED = 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "3f553b29",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(200, 7)\n"
+     ]
+    },
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>species</th>\n",
+       "      <th>island</th>\n",
+       "      <th>bill_length_mm</th>\n",
+       "      <th>bill_depth_mm</th>\n",
+       "      <th>flipper_length_mm</th>\n",
+       "      <th>body_mass_g</th>\n",
+       "      <th>sex</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>49.208473</td>\n",
+       "      <td>16.117959</td>\n",
+       "      <td>190.125950</td>\n",
+       "      <td>2873.291927</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>55.031628</td>\n",
+       "      <td>19.963435</td>\n",
+       "      <td>242.929142</td>\n",
+       "      <td>3639.940005</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>Torgersen</td>\n",
+       "      <td>51.096718</td>\n",
+       "      <td>16.777518</td>\n",
+       "      <td>159.961493</td>\n",
+       "      <td>5401.743330</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>3</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>49.070911</td>\n",
+       "      <td>14.796037</td>\n",
+       "      <td>244.530153</td>\n",
+       "      <td>2316.038092</td>\n",
+       "      <td>MALE</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>4</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>Biscoe</td>\n",
+       "      <td>44.827918</td>\n",
+       "      <td>13.246787</td>\n",
+       "      <td>236.948853</td>\n",
+       "      <td>5036.246870</td>\n",
+       "      <td>FEMALE</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     species     island  bill_length_mm  bill_depth_mm  flipper_length_mm   \n",
+       "0     Gentoo     Biscoe       49.208473      16.117959         190.125950  \\\n",
+       "1     Gentoo  Torgersen       55.031628      19.963435         242.929142   \n",
+       "2  Chinstrap  Torgersen       51.096718      16.777518         159.961493   \n",
+       "3     Adelie     Biscoe       49.070911      14.796037         244.530153   \n",
+       "4  Chinstrap     Biscoe       44.827918      13.246787         236.948853   \n",
+       "\n",
+       "   body_mass_g     sex  \n",
+       "0  2873.291927  FEMALE  \n",
+       "1  3639.940005  FEMALE  \n",
+       "2  5401.743330    MALE  \n",
+       "3  2316.038092    MALE  \n",
+       "4  5036.246870  FEMALE  "
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df_dummy = client.get_dummy_dataset(nb_rows = NB_ROWS, seed = SEED)\n",
+    "print(df_dummy.shape)\n",
+    "df_dummy.head()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "69dac96e",
+   "metadata": {},
+   "source": [
+    "### Query dummy dataset\n",
+    "\n",
+    "Now that she has an idea of what the data looks like, she wants to start querying the real dataset to for her research. However, before this other tools are at her disposal to reduce potential error risks and avoid spending budget on irrelevant queries. Of course, this does not have any impact on the budget.\n",
+    "\n",
+    "It is possible to specify the flag `dummy=True` in the various queries to perform the query on the dummy dataset instead of the real dataset and ensure that the queries are doing what is expected of them. \n",
+    "\n",
+    "Therefore Dr. Antartica computes the results that she gets on the dummy dataframe that she created locally and on the same dummy dataframe in the server via a query and compare them to ensure that the query is well defined and works within the server.\n",
+    "\n",
+    "She tests with an example on the average bill length on the dataframe."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "b6caee55",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "47.51532"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# On the local dummy dataframe\n",
+    "result_local_dummy = round(df_dummy['bill_length_mm'].mean(), 5)\n",
+    "result_local_dummy"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c3a37d8d",
+   "metadata": {},
+   "source": [
+    "As the query on the server goes through the same workflow for dummies and real data, she still has to set values for theoratical budget to spend on the dummy query. Of course, this theoretical budget will NOT affect her real budget as this is on dummy data. \n",
+    "\n",
+    "It is recommended to use very high values on the budget parameters here to have little noise and small difference between the exact local result and the 'little noisy' server result. \n",
+    "\n",
+    "Also, make sure to use the same values of number of rows and seed to have the same dummy datasets."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "3946425d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Average bill length in mm\n",
+    "QUERY = \"SELECT AVG(bill_length_mm) AS avg_bill_length_mm FROM df\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "90cf2a6d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "47.50783673123655"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# On the remote server dummy dataframe\n",
+    "res = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = 100.0, # make sure to select high values of epsilon and delta to have small differences\n",
+    "    delta = 2.0,    # make sure to select high values of epsilon and delta to have small differences\n",
+    "    dummy = True, \n",
+    "    nb_rows = NB_ROWS,\n",
+    "    seed = SEED\n",
+    ")\n",
+    "res_server_dummy = res['query_response'][\"avg_bill_length_mm\"][0]\n",
+    "res_server_dummy"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bb3fa8eb",
+   "metadata": {},
+   "source": [
+    "She then checks that the responses on the dummy locally and the dummy on the server are close enough (difference would be only due to small noise addition)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "0f2fff82",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "np.testing.assert_almost_equal(\n",
+    "    result_local_dummy, \n",
+    "    res_server_dummy,\n",
+    "    decimal=2, \n",
+    "    err_msg=\"Responses are different, either try with a bigger budget or query is not doing what is intended.\"\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5a82abcd",
+   "metadata": {},
+   "source": [
+    "As you can see res_local and res_server are close. We can accept that the small difference is due to the small noise added due to the large values of $\\epsilon$ and $\\delta$."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "324454ed",
+   "metadata": {},
+   "source": [
+    "### Get current budget\n",
+    "\n",
+    "It is the first time that Dr. Antartica connects to the server and she wants to know how much buget the queen assigned her.\n",
+    "Therefore, she calls the fonction `get_initial_budget`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "61a467f3",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'initial_epsilon': 10, 'initial_delta': 0.005}"
+      ]
+     },
+     "execution_count": 11,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_initial_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bc8f7a74",
+   "metadata": {},
+   "source": [
+    "She sees that she has 10.0 epsilon and 0.0004 epsilon at her disposal.\n",
+    "\n",
+    "Then she checks her total spent budget `get_total_spent_budget`. As she only did queries on metadata on dummy dataframes, this should still be 0."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "afd22f84",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 0, 'total_spent_delta': 0}"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "05daf5a4",
+   "metadata": {},
+   "source": [
+    "It will also be useful to know what the remaining budget is. Therefore, she calls the function `get_remaining_budget`. It just substarcts the total spent budget from the initial budget."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "6260cf54",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 10, 'remaining_delta': 0.005}"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "20298e00",
+   "metadata": {},
+   "source": [
+    "As expected, for now the remaining budget is equal to the inital budget."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b746374c",
+   "metadata": {},
+   "source": [
+    "### Estimate cost of a query\n",
+    "Another safeguard is the functionnality to estimate the cost of a query. As in OpenDP and SmartnoiseSQL, the budget that will by used by a query might be slightly different than what is asked by the user. The `estimate cost` function returns the estimated real cost of any query.\n",
+    "\n",
+    "Again, of course, this will not impact the user's budget.\n",
+    "\n",
+    "Dr. Antartica checks the budget that computing the average bill length will really cost her if she asks the query with an `epsilon` and a `delta`."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "133020c6",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 2.0, 'delta_cost': 4.999999999999449e-05}"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = 1.0, \n",
+    "    delta = 1e-4\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "71580822",
+   "metadata": {},
+   "source": [
+    "So this query would actually cost her 3.0 epsilon and a little 1.499e-4 delta. As she does not want to spend to much budget here she tries other values of budget."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "df487c62",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 0.4, 'delta_cost': 5.000000000032756e-06}"
+      ]
+     },
+     "execution_count": 15,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = 0.2, \n",
+    "    delta = 1e-5\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3c6a3a8c",
+   "metadata": {},
+   "source": [
+    "This query would actually cost her 0.6 epsilon and a similar delta. She decides that it is good enough."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "c9c8d3e7",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "EPSILON = 0.2\n",
+    "DELTA = 1e-5"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e5379edf",
+   "metadata": {},
+   "source": [
+    "### Query real dataset\n",
+    "Now that all the safeguard functions were tested, Dr. Antartica is ready to query on the real dataset and get a differentially private response of the average bill length. By default, the flag `dummy` is False so setting it is optional. She uses the values of `epsilon` and `delta` that she selected just before.\n",
+    "\n",
+    "Careful: This command DOES spend the budget of the user and the remaining budget is updated for every query."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "19e60263",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 10, 'remaining_delta': 0.005}"
+      ]
+     },
+     "execution_count": 17,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "69767fac",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "avg_bill_length_response = client.smartnoise_query(\n",
+    "    query = QUERY,  \n",
+    "    epsilon = EPSILON, \n",
+    "    delta = DELTA,\n",
+    "    dummy = False\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "6dbbdf93",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Average bill length: 44.34mm.\n"
+     ]
+    }
+   ],
+   "source": [
+    "avg_bill_length = avg_bill_length_response['query_response']['avg_bill_length_mm'].iloc[0]\n",
+    "print(f\"Average bill length: {np.round(avg_bill_length, 2)}mm.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b2767e65",
+   "metadata": {},
+   "source": [
+    "After each query on the real dataset, the budget informations are also returned to the researcher. It is possible possible to check the remaining budget again afterwards:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "id": "39701fe5",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 9.6, 'remaining_delta': 0.004994999999999967}"
+      ]
+     },
+     "execution_count": 20,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e37c587f",
+   "metadata": {},
+   "source": [
+    "As can be seen in `get_total_spent_budget()`, it is the budget estimated with `estimate_cost()` that was spent."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "id": "487f835f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'total_spent_epsilon': 0.4, 'total_spent_delta': 5.000000000032756e-06}"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_total_spent_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "eef4afcd",
+   "metadata": {},
+   "source": [
+    "Dr. Antartica has now a differentially private estimation of the bill length of all birds and is confident to use the library for the rest of her analyses."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "04929993",
+   "metadata": {},
+   "source": [
+    "## Step 4: Penguin statistics"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bbbca191",
+   "metadata": {},
+   "source": [
+    "### Confidence intervals for flipper length over the whole population"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "9d41bd58",
+   "metadata": {},
+   "source": [
+    "She is first interested to have a better idea of the distribution of flipper length of all species. She already has the mean from step 3, so she just need to compute the standard deviation and know the number of penguins in the dataset. As it is just an exploration step, she uses very little budget values."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "id": "04b376ef",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "QUERY = \"SELECT COUNT(bill_length_mm) AS nb_penguin, STD(bill_length_mm) AS std_bill_length_mm FROM df\""
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0b041c81",
+   "metadata": {},
+   "source": [
+    "She again first verifies that her query works on the dummy dataset:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "id": "5aa9c304",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>nb_penguin</th>\n",
+       "      <th>std_bill_length_mm</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>99</td>\n",
+       "      <td>10.291426</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "   nb_penguin  std_bill_length_mm\n",
+       "0          99           10.291426"
+      ]
+     },
+     "execution_count": 23,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dummy_res = client.smartnoise_query(\n",
+    "    query = QUERY, \n",
+    "    epsilon = 100.0, \n",
+    "    delta = 10.0, \n",
+    "    dummy = True\n",
+    ")\n",
+    "dummy_res['query_response']"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "74f68994",
+   "metadata": {},
+   "source": [
+    "The syntax of the query works, now she checks the budget:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "id": "a8fa2c49",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 1.5, 'delta_cost': 5.000000000032756e-06}"
+      ]
+     },
+     "execution_count": 24,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = 0.5, \n",
+    "    delta = 1e-5\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bed840d3",
+   "metadata": {},
+   "source": [
+    "It is a bit too much, she decides to test for less:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 25,
+   "id": "edc97e73",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 0.75, 'delta_cost': 5.000000000032756e-06}"
+      ]
+     },
+     "execution_count": 25,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(\n",
+    "    query = QUERY, \n",
+    "    epsilon = 0.25, \n",
+    "    delta = 1e-5\n",
+    ")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "da9f81c4",
+   "metadata": {},
+   "source": [
+    "That's fine, she is ready to query:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "id": "534979fb",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>nb_penguin</th>\n",
+       "      <th>std_bill_length_mm</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>337</td>\n",
+       "      <td>9.193759</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "   nb_penguin  std_bill_length_mm\n",
+       "0         337            9.193759"
+      ]
+     },
+     "execution_count": 26,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "response = client.smartnoise_query(query = QUERY, epsilon = 0.25, delta = 1e-5)\n",
+    "response = response['query_response']\n",
+    "response"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "id": "674332e7",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Number of penguins: 337.\n",
+      "Standard deviation of bill length: 9.19.\n"
+     ]
+    }
+   ],
+   "source": [
+    "nb_penguin = response['nb_penguin'].iloc[0]\n",
+    "print(f\"Number of penguins: {nb_penguin}.\")\n",
+    "\n",
+    "std_bill_length = response['std_bill_length_mm'].iloc[0]\n",
+    "print(f\"Standard deviation of bill length: {np.round(std_bill_length, 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "367081be-1159-45d8-9129-88fba20fb697",
+   "metadata": {},
+   "source": [
+    "She can now do all the postprocessing that she wants with the returned data without adding any privacy risk. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "id": "f72b19d0",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Standard error of bill length: 0.5.\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Get standard error\n",
+    "standard_error = std_bill_length/np.sqrt(nb_penguin)\n",
+    "print(f\"Standard error of bill length: {np.round(standard_error, 2)}.\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "id": "62630a03",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The 95% confidence interval of the bill length of all penguins is [43.36, 45.32].\n"
+     ]
+    }
+   ],
+   "source": [
+    " # Compute the 95% confidence interval\n",
+    "ZSCORE = 1.96\n",
+    "lower_bound, upper_bound = avg_bill_length - ZSCORE*standard_error, avg_bill_length + ZSCORE*standard_error\n",
+    "print(f\"The 95% confidence interval of the bill length of all penguins is [{np.round(lower_bound, 2)}, {np.round(upper_bound, 2)}].\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b5ee7ad2",
+   "metadata": {},
+   "source": [
+    "### Hypothesis testing"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0f1a3a8d",
+   "metadata": {},
+   "source": [
+    "So, Dr. Antartica has now the opportunity to study the various penguins dimensions and will do an hypotheses testing analysis to discover if flipper length differ between the penguins species.\n",
+    "\n",
+    "She will do a two-tailed two-sample $t$ test.\n",
+    "\n",
+    "- The null hypothese $H_0$ is flipper length does not differ between species.\n",
+    "- The alternative hypothesis $H_a$ is flipper length does differ between species.\n",
+    "\n",
+    "She set the level of significance at 0.05."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "7d9ae766-4c0d-4dc5-9c9a-5f7eb99718f9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "CRITICAL_VALUE = 0.05"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "id": "5006201d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "QUERY = \"SELECT \\\n",
+    "        species AS species, \\\n",
+    "        COUNT(bill_length_mm) AS nb_penguin,  \\\n",
+    "        AVG(bill_length_mm) AS avg_bill_length_mm, \\\n",
+    "        STD(bill_length_mm) AS std_bill_length_mm \\\n",
+    "        FROM df  GROUP BY species\""
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e725eb3f-d12f-4f62-8f57-06fb00639f91",
+   "metadata": {},
+   "source": [
+    "She estimates how much budget it would really cost:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 32,
+   "id": "0255550b-7fd2-4244-a8eb-da809ddc6a5b",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 3.0, 'delta_cost': 4.999999999999449e-05}"
+      ]
+     },
+     "execution_count": 32,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(query = QUERY, epsilon = 1, delta = 1e-4)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "56bf804f-d877-48cb-b405-709b30cda3d1",
+   "metadata": {},
+   "source": [
+    "The real cost seems to be 3 times the epsilon that she sets. It is a lot but she tries on the dummy dataset to verify all is working properly."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "id": "80d9933b",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'query_response':      species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
+       " 0     Adelie          36           48.807157            8.785415\n",
+       " 1  Chinstrap          32           46.193166           18.700943\n",
+       " 2     Gentoo          30           41.849626            6.128719}"
+      ]
+     },
+     "execution_count": 33,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dummy_res = client.smartnoise_query(query = QUERY, epsilon = 1, delta = 1.0, dummy = True)\n",
+    "dummy_res"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5691680f-8716-4a99-999a-a2bd5ef6a679",
+   "metadata": {},
+   "source": [
+    "She did not give enough budget for the query to work. This is why there are 'NANs' in the output. She has to spend more budget for the query to work."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "id": "6b014db4-acbd-4ae1-a3b6-397035851583",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 8.85, 'remaining_delta': 0.004989999999999935}"
+      ]
+     },
+     "execution_count": 34,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "43d3488d-3987-4fec-a840-78385e956832",
+   "metadata": {},
+   "source": [
+    "The maximum she can do with all her remaining budget of 7.4 is around 7.4/4 = 1.85. Let's check:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 45,
+   "id": "99d7998d-daa1-4d5e-aa42-abc5aabdf2e3",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'epsilon_cost': 9.0, 'delta_cost': 4.999999999999449e-05}"
+      ]
+     },
+     "execution_count": 45,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.estimate_smartnoise_cost(query = QUERY, epsilon = 12/4, delta = 1e-4)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 46,
+   "id": "0e07fde9-9430-4a12-8337-0503ac162c26",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'query_response':      species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
+       " 0     Adelie          37           48.580124            2.255215\n",
+       " 1  Chinstrap          33           46.983725            9.051034\n",
+       " 2     Gentoo          28           43.886555           10.928323}"
+      ]
+     },
+     "execution_count": 46,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "dummy_res = client.smartnoise_query(query = QUERY, epsilon = 12/4, delta = 1e-4, dummy = True)\n",
+    "dummy_res"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e8dadd17",
+   "metadata": {},
+   "source": [
+    "If it errors, she might need to re-run the query a few times until it works. The budget is not affected by dummy queries anyway."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 47,
+   "id": "59f2d665",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "flipper_length_response = client.smartnoise_query(query = QUERY, epsilon = 12/4, delta = 1e-4)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "78d23e66-2c05-4e35-bba9-7b92710b872a",
+   "metadata": {},
+   "source": [
+    "And now she should not have any remaining budget:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "id": "6eb20cfb-fa53-496f-940d-9b17b05fa074",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'remaining_epsilon': 1.0, 'remaining_delta': 0.004950000000000006}"
+      ]
+     },
+     "execution_count": 48,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "client.get_remaining_budget()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cb96f406-d409-4531-ac86-05f1c9296705",
+   "metadata": {},
+   "source": [
+    "But she can do her post-processing and hypothesis analysis."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 49,
+   "id": "748f125f",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>species</th>\n",
+       "      <th>nb_penguin</th>\n",
+       "      <th>avg_bill_length_mm</th>\n",
+       "      <th>std_bill_length_mm</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>150</td>\n",
+       "      <td>38.902943</td>\n",
+       "      <td>0.805783</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>67</td>\n",
+       "      <td>49.262560</td>\n",
+       "      <td>6.123036</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>122</td>\n",
+       "      <td>47.469563</td>\n",
+       "      <td>2.851064</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     species  nb_penguin  avg_bill_length_mm  std_bill_length_mm\n",
+       "0     Adelie         150           38.902943            0.805783\n",
+       "1  Chinstrap          67           49.262560            6.123036\n",
+       "2     Gentoo         122           47.469563            2.851064"
+      ]
+     },
+     "execution_count": 49,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "df_flipper = flipper_length_response['query_response']\n",
+    "df_flipper"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "099129cf",
+   "metadata": {},
+   "source": [
+    "And finally the $t$-test:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 50,
+   "id": "0a7d7d4d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def t_test(avg_1, avg_2, std_1, std_2, nb_1, nb_2):\n",
+    "    standard_error = (std_1 * (nb_1 - 1) + std_2 * (nb_2 - 1))/(nb_1 + nb_2 - 2)\n",
+    "    return (avg_1 - avg_2)/np.sqrt(standard_error**2*(1/nb_1 + 1 /nb_2))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "id": "bc3ee48a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "nb_0, avg_0, std_0 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[0]\n",
+    "nb_1, avg_1, std_1 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[1]\n",
+    "nb_2, avg_2, std_2 = df_flipper[['nb_penguin', 'avg_bill_length_mm', 'std_bill_length_mm']].iloc[2]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "id": "1717f9ea",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "T test between specie 0 and specie 1: -28.92.  Reject null hypothesis: True.\n",
+      "T test between specie 0 and specie 2: -40.8. Reject null hypothesis: True.\n",
+      "T test between specie 1 and specie 2: 2.94.   Reject null hypothesis: True.\n"
+     ]
+    }
+   ],
+   "source": [
+    "t_01 = t_test(avg_0, avg_1, std_0, std_1, nb_0, nb_1)\n",
+    "t_02 = t_test(avg_0, avg_2, std_0, std_2, nb_0, nb_2)\n",
+    "t_12 = t_test(avg_1, avg_2, std_1, std_2, nb_1, nb_2)\n",
+    "\n",
+    "print(f\"T test between specie 0 and specie 1: {np.round(t_01, 2)}.  Reject null hypothesis: {abs(t_01) > CRITICAL_VALUE}.\")\n",
+    "print(f\"T test between specie 0 and specie 2: {np.round(t_02, 2)}. Reject null hypothesis: {abs(t_02) > CRITICAL_VALUE}.\")\n",
+    "print(f\"T test between specie 1 and specie 2: {np.round(t_12, 2)}.   Reject null hypothesis: {abs(t_12) > CRITICAL_VALUE}.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "a557b754-ae7a-490a-8c4b-3928de7101d1",
+   "metadata": {},
+   "source": [
+    "All t-tests are above the critical value of 0.5. She can reject the null hypothesis."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b4df475b",
+   "metadata": {},
+   "source": [
+    "She finally computes the confidence intervals for the flipper length of each species"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 53,
+   "id": "9289bc26",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<div>\n",
+       "<style scoped>\n",
+       "    .dataframe tbody tr th:only-of-type {\n",
+       "        vertical-align: middle;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe tbody tr th {\n",
+       "        vertical-align: top;\n",
+       "    }\n",
+       "\n",
+       "    .dataframe thead th {\n",
+       "        text-align: right;\n",
+       "    }\n",
+       "</style>\n",
+       "<table border=\"1\" class=\"dataframe\">\n",
+       "  <thead>\n",
+       "    <tr style=\"text-align: right;\">\n",
+       "      <th></th>\n",
+       "      <th>species</th>\n",
+       "      <th>nb_penguin</th>\n",
+       "      <th>avg_bill_length_mm</th>\n",
+       "      <th>std_bill_length_mm</th>\n",
+       "      <th>standard_error</th>\n",
+       "      <th>ci_95_lower_bound</th>\n",
+       "      <th>ci_95_upper_bound</th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>0</th>\n",
+       "      <td>Adelie</td>\n",
+       "      <td>150</td>\n",
+       "      <td>38.902943</td>\n",
+       "      <td>0.805783</td>\n",
+       "      <td>0.065792</td>\n",
+       "      <td>38.773991</td>\n",
+       "      <td>39.031895</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>1</th>\n",
+       "      <td>Chinstrap</td>\n",
+       "      <td>67</td>\n",
+       "      <td>49.262560</td>\n",
+       "      <td>6.123036</td>\n",
+       "      <td>0.748048</td>\n",
+       "      <td>47.796386</td>\n",
+       "      <td>50.728733</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2</th>\n",
+       "      <td>Gentoo</td>\n",
+       "      <td>122</td>\n",
+       "      <td>47.469563</td>\n",
+       "      <td>2.851064</td>\n",
+       "      <td>0.258123</td>\n",
+       "      <td>46.963642</td>\n",
+       "      <td>47.975485</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "     species  nb_penguin  avg_bill_length_mm  std_bill_length_mm   \n",
+       "0     Adelie         150           38.902943            0.805783  \\\n",
+       "1  Chinstrap          67           49.262560            6.123036   \n",
+       "2     Gentoo         122           47.469563            2.851064   \n",
+       "\n",
+       "   standard_error  ci_95_lower_bound  ci_95_upper_bound  \n",
+       "0        0.065792          38.773991          39.031895  \n",
+       "1        0.748048          47.796386          50.728733  \n",
+       "2        0.258123          46.963642          47.975485  "
+      ]
+     },
+     "execution_count": 53,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "ZSCORE = 1.96\n",
+    "df_flipper['standard_error'] = df_flipper['std_bill_length_mm']/np.sqrt(df_flipper['nb_penguin'])\n",
+    "df_flipper['ci_95_lower_bound'] = df_flipper['avg_bill_length_mm'] - ZSCORE * df_flipper['standard_error']\n",
+    "df_flipper['ci_95_upper_bound'] = df_flipper['avg_bill_length_mm'] + ZSCORE * df_flipper['standard_error']\n",
+    "df_flipper"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f79e8333-1f06-4019-af3c-94ff2362d036",
+   "metadata": {},
+   "source": [
+    "She can now go and present her findings to queen Icebergina."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cce8dde4-0c9e-43d4-b6ce-890ac7c8efd2",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/server/README.md b/server/README.md
index 99912414..c561c8eb 100644
--- a/server/README.md
+++ b/server/README.md
@@ -1,22 +1,3 @@
-# Tips for developpers
+# Administration Database
 
-## Start service
-### On local machine
-To start the container on a local machine, go to `lomas/server/` and run `docker compose up`. 
-If you encounter any issue, you might want to run `docker compose down` first.
-
-### On a kubernetes cluser
--- TODO: can someone fill it: like as few lines as possible
-
-### On Onyxia
-To start the server on Onyxia, select the `lomas `service, (optionnally adapt the administration and runtime parameters) et click on 'Lancer'.
-
-## Tests
-It is possible to test the server within and outside the docker container.
-
-### On local machine
-The tests will be based on the config in `lomas/server/src/tests/test_config` and be executed with the AdminYamlDatabase. 
-Therefore, go to `lomas/server/src` and run `python -m unittest discover -s.`
-
-### In container
-The tests will be based on the config in `lomas/server/src/tests/test_config` and be executed with the AdminMongoDatabase. For this, go to `lomas/server/src` and run `python -m unittest discover -s.`
+TODO: describe 4 collections (and in readme or in sphinx, describe CLI commands)
\ No newline at end of file
diff --git a/server/README_developer.md b/server/README_developer.md
new file mode 100644
index 00000000..d808f4f8
--- /dev/null
+++ b/server/README_developer.md
@@ -0,0 +1,22 @@
+# Tips for developers
+
+## Start service
+### On local machine
+To start the container on a local machine, go to `lomas/server/` and run `docker compose up`. 
+If you encounter any issue, you might want to run `docker compose down` first.
+
+### On a kubernetes cluser
+-- TODO: can someone fill it: like as few lines as possible
+
+### On Onyxia
+To start the server on Onyxia, select the `lomas `service, (optionnally adapt the administration and runtime parameters) et click on 'Lancer'.
+
+## Tests
+It is possible to test the server within and outside the docker container.
+
+### On local machine
+The tests will be based on the config in `lomas/server/src/tests/test_config` and be executed with the AdminYamlDatabase. 
+Therefore, go to `lomas/server/src` and run `python -m unittest discover -s .`
+
+### In container
+The tests will be based on the config in `lomas/server/src/tests/test_config` and be executed with the AdminMongoDatabase. For this, go to `lomas/server/src` and run `python -m unittest discover -s .`
diff --git a/server/data/collections/dataset_collection.yaml b/server/data/collections/dataset_collection.yaml
index 52134b54..fa06c20d 100644
--- a/server/data/collections/dataset_collection.yaml
+++ b/server/data/collections/dataset_collection.yaml
@@ -1,15 +1,15 @@
 datasets:
 - dataset_name: "IRIS"
-  database_type: "REMOTE_HTTP_DB"
-  dataset_url: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
+  database_type: "PATH_DB"
+  dataset_path: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
   metadata:
-    database_type: "LOCAL_DB"
+    database_type: "PATH_DB"
     metadata_path: "../data/collections/metadata/iris_metadata.yaml"
 - dataset_name: "PENGUIN"
-  database_type: "REMOTE_HTTP_DB"
-  dataset_url: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
+  database_type: "PATH_DB"
+  dataset_path: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
   metadata:
-    database_type: "LOCAL_DB"
+    database_type: "PATH_DB"
     metadata_path: "../data/collections/metadata/penguin_metadata.yaml"
 - dataset_name: "TITANIC"
   database_type: "S3_DB"
@@ -26,8 +26,8 @@ datasets:
     aws_access_key_id: "admin"
     aws_secret_access_key: "admin123"
 - dataset_name: "FSO_INCOME_SYNTHETIC"
-  database_type: "LOCAL_DB"
+  database_type: "PATH_DB"
   dataset_path: "../data/datasets/income_synthetic_data.csv"
   metadata:
-    database_type: "LOCAL_DB"
+    database_type: "PATH_DB"
     metadata_path: "../data/collections/metadata/fso_income_synthetic_metadata.yaml"
\ No newline at end of file
diff --git a/server/src/admin_database/admin_database.py b/server/src/admin_database/admin_database.py
index 337a2c76..6d4d7a53 100644
--- a/server/src/admin_database/admin_database.py
+++ b/server/src/admin_database/admin_database.py
@@ -6,9 +6,9 @@
 
 from constants import DPLibraries
 from utils.error_handler import (
+    InternalServerException,
     InvalidQueryException,
     UnauthorizedAccessException,
-    InternalServerException,
 )
 
 
@@ -24,7 +24,6 @@ def __init__(self, **connection_parameters: Dict[str, str]) -> None:
         Parameters:
             - **connection_parameters: parameters required to access the db
         """
-        pass
 
     @abstractmethod
     def does_user_exist(self, user_name: str) -> bool:
@@ -33,9 +32,8 @@ def does_user_exist(self, user_name: str) -> bool:
         Parameters:
             - user_name: name of the user to check
         """
-        pass
 
-    def _does_user_exist(func: Callable) -> Callable: # type: ignore
+    def _does_user_exist(func: Callable) -> Callable:  # type: ignore
         """
         Decorator function to check if a user exists
         Parameters:
@@ -49,7 +47,7 @@ def wrapper_decorator(
         ) -> None:
             self = args[0]
             user_name = args[1]
-            if not (self.does_user_exist(user_name)):
+            if not self.does_user_exist(user_name):
                 raise UnauthorizedAccessException(
                     f"User {user_name} does not exist. "
                     + "Please, verify the client object initialisation.",
@@ -65,9 +63,8 @@ def does_dataset_exist(self, dataset_name: str) -> bool:
         Parameters:
             - dataset_name: name of the dataset to check
         """
-        pass
 
-    def _does_dataset_exist(func: Callable) -> Callable: # type: ignore
+    def _does_dataset_exist(func: Callable) -> Callable:  # type: ignore
         """
         Decorator function to check if a user exists
         Parameters:
@@ -81,7 +78,7 @@ def wrapper_decorator(
         ) -> None:
             self = args[0]
             dataset_name = args[1]
-            if not (self.does_dataset_exist(dataset_name)):
+            if not self.does_dataset_exist(dataset_name):
                 raise InvalidQueryException(
                     f"Dataset {dataset_name} does not exists. "
                     + "Please, verify the client object initialisation.",
@@ -98,7 +95,6 @@ def get_dataset_metadata(self, dataset_name: str) -> dict:
         Parameters:
             - dataset_name: name of the dataset to get the metadata for
         """
-        pass
 
     @abstractmethod
     @_does_user_exist
@@ -109,7 +105,6 @@ def may_user_query(self, user_name: str) -> bool:
         Parameters:
             - user_name: name of the user
         """
-        pass
 
     @abstractmethod
     @_does_user_exist
@@ -121,7 +116,6 @@ def set_may_user_query(self, user_name: str, may_query: bool) -> None:
             - user_name: name of the user
             - may_query: flag give or remove access to user
         """
-        pass
 
     @abstractmethod
     @_does_user_exist
@@ -134,9 +128,10 @@ def has_user_access_to_dataset(
             - user_name: name of the user
             - dataset_name: name of the dataset
         """
-        pass
 
-    def _has_user_access_to_dataset(func: Callable) -> Callable: # type: ignore
+    def _has_user_access_to_dataset(
+        func: Callable,
+    ) -> Callable:  # type: ignore
         """
         Decorator function to check if a user has access to a dataset
         Parameters:
@@ -172,7 +167,6 @@ def get_epsilon_or_delta(
             - dataset_name: name of the dataset
             - parameter: total_spent_epsilon or total_spent_delta
         """
-        pass
 
     @_has_user_access_to_dataset
     def get_total_spent_budget(
@@ -246,7 +240,6 @@ def update_epsilon_or_delta(
             - parameter: current_epsilon or current_delta
             - spent_value: spending of epsilon or delta on last query
         """
-        pass
 
     def update_epsilon(
         self, user_name: str, dataset_name: str, spent_epsilon: float
@@ -304,7 +297,6 @@ def get_dataset_field(self, dataset_name: str, key: str) -> str:
         """
         Get dataset field type based on dataset name and key
         """
-        pass
 
     @abstractmethod
     @_has_user_access_to_dataset
@@ -319,7 +311,6 @@ def get_user_previous_queries(
             - user_name: name of the user
             - dataset_name: name of the dataset
         """
-        pass
 
     def prepare_save_query(
         self, user_name: str, query_json: dict, response: dict
@@ -334,7 +325,7 @@ def prepare_save_query(
         to_archive = {
             "user_name": user_name,
             "dataset_name": query_json.dataset_name,
-            "client_input": query_json.dict(),
+            "client_input": query_json.model_dump(),
             "response": response,
             "timestamp": time.time(),
         }
@@ -361,4 +352,3 @@ def save_query(
             - query_json: json received from client
             - response: response sent to the client
         """
-        pass
diff --git a/server/src/admin_database/mongodb_database.py b/server/src/admin_database/mongodb_database.py
index d5c64910..71eb520e 100644
--- a/server/src/admin_database/mongodb_database.py
+++ b/server/src/admin_database/mongodb_database.py
@@ -1,9 +1,10 @@
 from typing import List
 
-from admin_database.admin_database import AdminDatabase
 from pymongo import MongoClient
 from pymongo.database import Database
 
+from admin_database.admin_database import AdminDatabase
+
 
 class AdminMongoDatabase(AdminDatabase):
     """
diff --git a/server/src/admin_database/yaml_database.py b/server/src/admin_database/yaml_database.py
index c1727870..a206348a 100644
--- a/server/src/admin_database/yaml_database.py
+++ b/server/src/admin_database/yaml_database.py
@@ -1,7 +1,8 @@
 from datetime import datetime
-import yaml
 from typing import List
 
+import yaml
+
 from admin_database.admin_database import AdminDatabase
 
 
@@ -19,7 +20,7 @@ def __init__(self, yaml_db_path: str) -> None:
             - database_name: Mongodb database name.
         """
         self.path: str = yaml_db_path
-        with open(yaml_db_path, "r") as f:
+        with open(yaml_db_path, mode="r", encoding="utf-8") as f:
             self.database = yaml.safe_load(f)
 
     def does_user_exist(self, user_name: str) -> bool:
@@ -57,7 +58,7 @@ def get_dataset_metadata(self, dataset_name: str) -> dict:
             if dt["dataset_name"] == dataset_name:
                 metadata_path = dt["metadata"]["metadata_path"]
 
-        with open(metadata_path, "r") as f:
+        with open(metadata_path, mode="r", encoding="utf-8") as f:
             metadata = yaml.safe_load(f)
 
         return metadata
@@ -75,7 +76,6 @@ def may_user_query(self, user_name: str) -> bool:
                 return user["may_query"]
         # if user not found, return false
         return False
-        
 
     @AdminDatabase._does_user_exist
     def set_may_user_query(self, user_name: str, may_query: bool) -> None:
@@ -152,7 +152,9 @@ def update_epsilon_or_delta(
         self.database["users"] = users
 
     @AdminDatabase._does_dataset_exist
-    def get_dataset_field(self, dataset_name: str, key: str) -> str: # type: ignore
+    def get_dataset_field(
+        self, dataset_name: str, key: str
+    ) -> str:  # type: ignore
         """
         Get dataset field type based on dataset name and key
         Parameters:
@@ -209,5 +211,5 @@ def save_current_database(self) -> None:
         new_path = self.path.replace(
             ".yaml", f'_{datetime.now().strftime("%m_%d_%Y__%H_%M_%S")}.yaml'
         )
-        with open(new_path, "w") as file:
+        with open(new_path, mode="w", encoding="utf-8") as file:
             yaml.dump(self.database, file)
diff --git a/server/src/app.py b/server/src/app.py
index 3147d185..abc1759c 100644
--- a/server/src/app.py
+++ b/server/src/app.py
@@ -1,4 +1,9 @@
-from typing import Callable, Any
+from collections.abc import AsyncGenerator
+from contextlib import asynccontextmanager
+from typing import Any, Callable
+
+from fastapi import Body, Depends, FastAPI, Header, Request, Response
+from fastapi.responses import JSONResponse, StreamingResponse
 
 from admin_database.admin_database import AdminDatabase
 from admin_database.utils import database_factory
@@ -10,8 +15,6 @@
     get_dummy_dataset_for_query,
     make_dummy_dataset,
 )
-from fastapi import Body, Depends, FastAPI, Header, Request, Response
-from fastapi.responses import JSONResponse, StreamingResponse
 from mongodb_admin import (
     add_datasets,
     create_users_collection,
@@ -20,9 +23,9 @@
 from utils.anti_timing_att import anti_timing_att
 from utils.config import Config, get_config
 from utils.error_handler import (
+    CUSTOM_EXCEPTIONS,
     InternalServerException,
     add_exception_handlers,
-    CUSTOM_EXCEPTIONS,
 )
 from utils.example_inputs import (
     example_dummy_opendp,
@@ -58,18 +61,13 @@
     "LIVE": False,
 }
 
-# This object holds the server object
-app = FastAPI()
-
-
-# Startup
-# -----------------------------------------------------------------------------
-
 
-@app.on_event("startup")
-def startup_event() -> None:
+@asynccontextmanager
+async def lifespan(app: FastAPI) -> AsyncGenerator:
     """
-    This function is executed once on server startup"""
+    This function is executed once on server startup
+    """
+    # Startup event
     LOG.info("Startup message")
     SERVER_STATE["state"].append("Startup event")
 
@@ -128,16 +126,22 @@ def startup_event() -> None:
     # Finally check everything in startup went well and update the state
     check_start_condition()
 
+    yield  # app is handling requests
 
-@app.on_event("shutdown")
-def shutdown_event():
+    # Shutdown event
     if CONFIG.admin_database.db_type == AdminDBType.YAML_TYPE:
         ADMIN_DATABASE.save_current_database()
 
 
+# This object holds the server object
+app = FastAPI(lifespan=lifespan)
+
+
 # A simple hack to hinder the timing attackers
 @app.middleware("http")
-async def middleware(request: Request, call_next: Callable[[Request], Response]) -> Response:
+async def middleware(
+    request: Request, call_next: Callable[[Request], Response]
+) -> Response:
     global CONFIG
     return await anti_timing_att(request, call_next, CONFIG)
 
@@ -252,11 +256,7 @@ def dummy_smartnoise_sql_handler(
     try:
         _ = dummy_querier.cost(query_json)  # verify cost works
         response_df = dummy_querier.query(query_json)
-        response = JSONResponse(
-            content={
-                "query_response": response_df
-                }
-            )
+        response = JSONResponse(content={"query_response": response_df})
     except CUSTOM_EXCEPTIONS as e:
         raise e
     except Exception as e:
@@ -375,10 +375,10 @@ def get_initial_budget(
 
     return JSONResponse(
         content={
-            "initial_epsilon": initial_epsilon, 
-            "initial_delta": initial_delta
-            }
-        )
+            "initial_epsilon": initial_epsilon,
+            "initial_delta": initial_delta,
+        }
+    )
 
 
 # MongoDB get total spent budget
@@ -405,11 +405,12 @@ def get_total_spent_budget(
 
     return JSONResponse(
         content={
-        "total_spent_epsilon": total_spent_epsilon,
-        "total_spent_delta": total_spent_delta
+            "total_spent_epsilon": total_spent_epsilon,
+            "total_spent_delta": total_spent_delta,
         }
     )
 
+
 # MongoDB get remaining budget
 @app.post(
     "/get_remaining_budget",
@@ -428,12 +429,12 @@ def get_remaining_budget(
         raise e
     except Exception as e:
         raise InternalServerException(e)
-    
+
     return JSONResponse(
         content={
-            "remaining_epsilon": rem_epsilon, 
-            "remaining_delta": rem_delta
-            }
+            "remaining_epsilon": rem_epsilon,
+            "remaining_delta": rem_delta,
+        }
     )
 
 
@@ -456,6 +457,4 @@ def get_user_previous_queries(
     except Exception as e:
         raise InternalServerException(e)
 
-    return JSONResponse(
-        content={"previous_queries": previous_queries}
-    )
+    return JSONResponse(content={"previous_queries": previous_queries})
diff --git a/server/src/constants.py b/server/src/constants.py
index a2fbd277..345ef783 100644
--- a/server/src/constants.py
+++ b/server/src/constants.py
@@ -2,7 +2,6 @@
 import string
 from enum import StrEnum
 
-
 if os.environ.get("IN_CONTAINER", False):
     CONFIG_PATH = "/usr/lomas_server/runtime.yaml"
     SECRETS_PATH = "/usr/lomas_server/secrets.yaml"
@@ -61,8 +60,7 @@ class DPLibraries(StrEnum):
 
 # Private Databases
 class PrivateDatabaseType(StrEnum):
-    LOCAL = "LOCAL_DB"
-    REMOTE_HTTP = "REMOTE_HTTP_DB"
+    PATH = "PATH_DB"
     S3 = "S3_DB"
 
 
diff --git a/server/src/dp_queries/dp_libraries/opendp.py b/server/src/dp_queries/dp_libraries/opendp.py
index 6d4eb5b9..4c2cfd62 100644
--- a/server/src/dp_queries/dp_libraries/opendp.py
+++ b/server/src/dp_queries/dp_libraries/opendp.py
@@ -1,9 +1,10 @@
 import opendp as dp
-from constants import DPLibraries, OpenDPMeasurement
-from dp_queries.dp_querier import DPQuerier
 from opendp.mod import enable_features
 from opendp_logger import make_load_json
 
+from constants import DPLibraries, OpenDPMeasurement
+from dp_queries.dp_querier import DPQuerier
+
 # Note: leaving this here, support for opendp_polars
 # import polars
 from private_dataset.private_dataset import PrivateDataset
diff --git a/server/src/dp_queries/dp_libraries/smartnoise_sql.py b/server/src/dp_queries/dp_libraries/smartnoise_sql.py
index 429d4f53..843e74d4 100644
--- a/server/src/dp_queries/dp_libraries/smartnoise_sql.py
+++ b/server/src/dp_queries/dp_libraries/smartnoise_sql.py
@@ -1,10 +1,11 @@
 from typing import List
 
 import pandas as pd
+from snsql import Mechanism, Privacy, Stat, from_connection
+
 from constants import MAX_NAN_ITERATION, STATS, DPLibraries
 from dp_queries.dp_querier import DPQuerier
 from private_dataset.private_dataset import PrivateDataset
-from snsql import Mechanism, Privacy, Stat, from_connection
 from utils.error_handler import ExternalLibraryException, InvalidQueryException
 from utils.input_models import SNSQLInp, SNSQLInpCost
 
@@ -20,7 +21,7 @@ def __init__(
         metadata = dict(self.private_dataset.get_metadata())
         metadata.update(metadata["columns"])
         del metadata["columns"]
-        self.snsql_metadata = {"": {"Schema": {"Table": metadata}}}
+        self.snsql_metadata = {"": {"": {"df": metadata}}}
 
     def cost(self, query_json: SNSQLInpCost) -> List[float]:
         privacy = Privacy(epsilon=query_json.epsilon, delta=query_json.delta)
@@ -38,7 +39,7 @@ def cost(self, query_json: SNSQLInpCost) -> List[float]:
             raise ExternalLibraryException(
                 DPLibraries.SMARTNOISE_SQL,
                 "Error obtaining cost: " + str(e),
-            )
+            ) from e
 
         return result
 
@@ -62,7 +63,7 @@ def query(self, query_json: SNSQLInp, nb_iter: int = 0) -> dict:
             raise ExternalLibraryException(
                 DPLibraries.SMARTNOISE_SQL,
                 "Error executing query:" + str(e),
-            )
+            ) from e
 
         if not query_json.postprocess:
             result = list(result)
diff --git a/server/src/dp_queries/dp_logic.py b/server/src/dp_queries/dp_logic.py
index 7ede7306..a941e719 100644
--- a/server/src/dp_queries/dp_logic.py
+++ b/server/src/dp_queries/dp_logic.py
@@ -1,13 +1,14 @@
+from fastapi import Header
+
 from admin_database.admin_database import AdminDatabase
 from constants import DPLibraries
 from dataset_store.dataset_store import DatasetStore
 from dp_queries.dp_querier import DPQuerier
-from fastapi import Header
 from utils.error_handler import (
+    CUSTOM_EXCEPTIONS,
     InternalServerException,
     InvalidQueryException,
     UnauthorizedAccessException,
-    CUSTOM_EXCEPTIONS,
 )
 from utils.input_models import BasicModel
 
@@ -52,7 +53,7 @@ def _get_querier(
             raise InternalServerException(
                 "Failed to get querier for dataset "
                 + f"{query_json.dataset_name}: {str(e)}"
-            )
+            ) from e
         return dp_querier
 
     def estimate_cost(
@@ -114,7 +115,7 @@ def handle_query(
             except CUSTOM_EXCEPTIONS as e:
                 raise e
             except Exception as e:
-                raise InternalServerException(e)
+                raise InternalServerException(e) from e
 
             # Deduce budget from user
             self.admin_database.update_budget(
diff --git a/server/src/dp_queries/dp_querier.py b/server/src/dp_queries/dp_querier.py
index 1ff4f9dc..79af5215 100644
--- a/server/src/dp_queries/dp_querier.py
+++ b/server/src/dp_queries/dp_querier.py
@@ -4,7 +4,10 @@
 from private_dataset.private_dataset import PrivateDataset
 
 # https://stackoverflow.com/questions/51291722/define-a-jsonable-type-using-mypy-pep-526
-JSON: TypeAlias = dict[str, "JSON"] | list["JSON"] | str | int | float | bool | None 
+JSON: TypeAlias = (
+    dict[str, "JSON"] | list["JSON"] | str | int | float | bool | None
+)
+
 
 class DPQuerier(ABC):
     """
diff --git a/server/src/dp_queries/dummy_dataset.py b/server/src/dp_queries/dummy_dataset.py
index 90fde1fd..2d1225fb 100644
--- a/server/src/dp_queries/dummy_dataset.py
+++ b/server/src/dp_queries/dummy_dataset.py
@@ -3,6 +3,7 @@
 
 import numpy as np
 import pandas as pd
+
 from admin_database.admin_database import AdminDatabase
 from constants import (
     DEFAULT_NUMERICAL_MAX,
@@ -56,7 +57,9 @@ def make_dummy_dataset(
                 serie = pd.Series(random.choices(RANDOM_STRINGS, k=nb_rows))
         elif col_type == "boolean":
             # type boolean instead of bool will allow null values
-            serie = pd.Series(random.choices([True, False], k=nb_rows), dtype = "boolean")
+            serie = pd.Series(
+                random.choices([True, False], k=nb_rows), dtype="boolean"
+            )
         elif col_type in ["int", "float"]:
             column_min = (
                 data["lower"]
@@ -70,19 +73,25 @@ def make_dummy_dataset(
             )
             if col_type == "int":
                 # pd.Series to ensure consistency between different types
-                serie = pd.Series(np.random.randint(column_min, column_max, size=nb_rows))
+                serie = pd.Series(
+                    np.random.randint(column_min, column_max, size=nb_rows)
+                )
             else:
-                serie = pd.Series(np.random.uniform(column_min, column_max, size=nb_rows))
+                serie = pd.Series(
+                    np.random.uniform(column_min, column_max, size=nb_rows)
+                )
         elif col_type == "datetime":
             # From start date and random on a range above
             start = datetime.datetime.strptime(RANDOM_DATE_START, "%m/%d/%Y")
-            serie = pd.Series([
-                start
-                + datetime.timedelta(
-                    seconds=random.randrange(RANDOM_DATE_RANGE)
-                )
-                for _ in range(nb_rows)
-            ])
+            serie = pd.Series(
+                [
+                    start
+                    + datetime.timedelta(
+                        seconds=random.randrange(RANDOM_DATE_RANGE)
+                    )
+                    for _ in range(nb_rows)
+                ]
+            )
         elif col_type == "unknown":
             # Unknown column are ignored by snartnoise sql
             continue
@@ -101,7 +110,7 @@ def make_dummy_dataset(
             for _ in range(0, NB_RANDOM_NONE):
                 index_to_insert = random.choice(indexes)
                 serie.at[index_to_insert] = None
-                
+
         # Add randomly generated data as new column of dataframe
         df[col_name] = serie
 
diff --git a/server/src/mongodb_admin.py b/server/src/mongodb_admin.py
index a5c9c21d..2fc592c4 100644
--- a/server/src/mongodb_admin.py
+++ b/server/src/mongodb_admin.py
@@ -3,10 +3,11 @@
 
 import boto3
 import yaml
-from admin_database.utils import get_mongodb_url
-from constants import PrivateDatabaseType
 from pymongo import MongoClient
 from pymongo.database import Database
+
+from admin_database.utils import get_mongodb_url
+from constants import PrivateDatabaseType
 from utils.error_handler import InternalServerException
 
 
@@ -224,11 +225,9 @@ def add_dataset(db: Database, args: argparse.Namespace) -> None:
         "database_type": args.database_type,
     }
 
-    if args.database_type == "LOCAL_DB":
+    if args.database_type == PrivateDatabaseType.PATH:
         dataset["dataset_path"] = args.dataset_path
-    elif args.database_type == "REMOTE_HTTP_DB":
-        dataset["dataset_url"] = args.dataset_url
-    elif args.database_type == "S3_DB":
+    elif args.database_type == PrivateDatabaseType.S3:
         dataset["s3_bucket"] = args.s3_bucket
         dataset["s3_key"] = args.s3_key
         dataset["endpoint_url"] = args.endpoint_url
@@ -239,12 +238,12 @@ def add_dataset(db: Database, args: argparse.Namespace) -> None:
     db.datasets.insert_one(dataset)
 
     # Step 2: add metadata
-    if args.metadata_database_type == "LOCAL_DB":
+    if args.metadata_database_type == PrivateDatabaseType.PATH:
         # Store metadata from yaml to metadata collection
         with open(args.metadata_path) as f:
             metadata_dict = yaml.safe_load(f)
 
-    elif args.metadata_database_type == "S3_DB":
+    elif args.metadata_database_type == PrivateDatabaseType.S3:
         client = boto3.client(
             "s3",
             endpoint_url=args.metadata_endpoint_url,
@@ -304,13 +303,11 @@ def verify_keys(d: dict, field: str, metadata: bool = False) -> None:
         verify_keys(d, "metadata")
 
         match d["database_type"]:
-            case PrivateDatabaseType.REMOTE_HTTP:
-                verify_keys(d, "dataset_url")
+            case PrivateDatabaseType.PATH:
+                verify_keys(d, "dataset_path")
             case PrivateDatabaseType.S3:
                 verify_keys(d, "s3_bucket")
                 verify_keys(d, "s3_key")
-            case PrivateDatabaseType.LOCAL:
-                verify_keys(d, "dataset_path")
             case _:
                 raise InternalServerException(
                     f"Unknown PrivateDatabaseType: {d['database_type']}"
@@ -346,7 +343,7 @@ def verify_keys(d: dict, field: str, metadata: bool = False) -> None:
 
         verify_keys(d, "database_type", metadata=True)
         match metadata_db_type:
-            case PrivateDatabaseType.LOCAL:
+            case PrivateDatabaseType.PATH:
                 verify_keys(d, "metadata_path", metadata=True)
 
                 with open(d["metadata"]["metadata_path"]) as f:
@@ -605,7 +602,6 @@ def show_collection(db: Database, args: argparse.Namespace) -> None:
     # Dataset location
     add_dataset_parser.add_argument("-d", "--dataset", required=True)
     add_dataset_parser.add_argument("-db", "--database_type", required=True)
-    add_dataset_parser.add_argument("-db_url", "--dataset_url", required=False)
     add_dataset_parser.add_argument("-s3b", "--s3_bucket", required=False)
     add_dataset_parser.add_argument("-s3k", "--s3_key", required=False)
     add_dataset_parser.add_argument(
diff --git a/server/src/private_dataset/in_memory_dataset.py b/server/src/private_dataset/in_memory_dataset.py
index 881d7177..c4da0406 100644
--- a/server/src/private_dataset/in_memory_dataset.py
+++ b/server/src/private_dataset/in_memory_dataset.py
@@ -1,6 +1,7 @@
 from typing import Dict, Union
 
 import pandas as pd
+
 from private_dataset.private_dataset import PrivateDataset
 
 
diff --git a/server/src/private_dataset/local_dataset.py b/server/src/private_dataset/local_dataset.py
deleted file mode 100644
index 56b53a15..00000000
--- a/server/src/private_dataset/local_dataset.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from typing import Dict, Optional, Union
-
-import pandas as pd
-from private_dataset.private_dataset import PrivateDataset
-from utils.error_handler import InternalServerException, InvalidQueryException
-
-
-class LocalDataset(PrivateDataset):
-    """
-    Class to fetch dataset from constant path
-    """
-
-    def __init__(
-        self,
-        metadata: Dict[str, Union[int, bool, Dict[str, Union[str, int]]]],
-        dataset_path: str,
-    ) -> None:
-        """
-        Parameters:
-            - dataset_path: path of the dataset
-        """
-        super().__init__(metadata)
-        self.ds_path = dataset_path
-        self.df: Optional[pd.DataFrame] = None
-
-    def get_pandas_df(self) -> pd.DataFrame:
-        """
-        Get the data in pandas dataframe format
-        Returns:
-            - pandas dataframe of dataset
-        """
-        if self.df is None:
-            if self.ds_path.endswith(".csv"):
-                try:
-                    self.df = pd.read_csv(self.ds_path, dtype=self.dtypes)
-                except Exception as err:
-                    raise InternalServerException(
-                        "Error reading local at http path:"
-                        f"{self.ds_path}: {err}",
-                    )
-            else:
-                return InvalidQueryException(
-                    "File type other than .csv not supported for"
-                    "loading into pandas DataFrame."
-                )
-
-            # Notify observer since memory usage has changed
-            [
-                observer.update_memory_usage()
-                for observer in self.dataset_observers
-            ]
-        return self.df.copy(deep=True)
diff --git a/server/src/private_dataset/remote_http_dataset.py b/server/src/private_dataset/path_dataset.py
similarity index 95%
rename from server/src/private_dataset/remote_http_dataset.py
rename to server/src/private_dataset/path_dataset.py
index 8781b38e..2a8aa32e 100644
--- a/server/src/private_dataset/remote_http_dataset.py
+++ b/server/src/private_dataset/path_dataset.py
@@ -1,11 +1,12 @@
 from typing import Dict, Optional, Union
 
 import pandas as pd
+
 from private_dataset.private_dataset import PrivateDataset
 from utils.error_handler import InternalServerException, InvalidQueryException
 
 
-class RemoteHTTPDataset(PrivateDataset):
+class PathDataset(PrivateDataset):
     """
     Class to fetch dataset from constant path
     """
@@ -37,7 +38,7 @@ def get_pandas_df(self) -> pd.DataFrame:
                     raise InternalServerException(
                         "Error reading csv at http path:"
                         f"{self.ds_path}: {err}",
-                    )
+                    ) from err
             else:
                 return InvalidQueryException(
                     "File type other than .csv not supported for"
diff --git a/server/src/private_dataset/private_dataset.py b/server/src/private_dataset/private_dataset.py
index 87410bca..c674e513 100644
--- a/server/src/private_dataset/private_dataset.py
+++ b/server/src/private_dataset/private_dataset.py
@@ -2,6 +2,7 @@
 from typing import List, Optional
 
 import pandas as pd
+
 from dataset_store.private_dataset_observer import PrivateDatasetObserver
 
 
@@ -29,7 +30,6 @@ def get_pandas_df(self, dataset_name: str) -> pd.DataFrame:
         Parameters:
             - dataset_name: name of the private dataset
         """
-        pass
 
     def get_metadata(self) -> dict:
         """
diff --git a/server/src/private_dataset/s3_dataset.py b/server/src/private_dataset/s3_dataset.py
index 53cd5447..6acb57eb 100644
--- a/server/src/private_dataset/s3_dataset.py
+++ b/server/src/private_dataset/s3_dataset.py
@@ -1,6 +1,8 @@
 from typing import Optional
+
 import boto3
 import pandas as pd
+
 from private_dataset.private_dataset import PrivateDataset
 from utils.error_handler import InternalServerException
 
@@ -52,7 +54,7 @@ def get_pandas_df(self) -> pd.DataFrame:
                 raise InternalServerException(
                     "Error reading csv at s3 path:"
                     + f"{self.s3_bucket}/{self.s3_key}: {err}"
-                )
+                ) from err
 
             # Notify observer since memory usage has changed
             [
diff --git a/server/src/private_dataset/utils.py b/server/src/private_dataset/utils.py
index 4cdb6b09..d56bf275 100644
--- a/server/src/private_dataset/utils.py
+++ b/server/src/private_dataset/utils.py
@@ -1,8 +1,7 @@
 from admin_database.admin_database import AdminDatabase
 from constants import PrivateDatabaseType
-from private_dataset.local_dataset import LocalDataset
 from private_dataset.private_dataset import PrivateDataset
-from private_dataset.remote_http_dataset import RemoteHTTPDataset
+from private_dataset.path_dataset import PathDataset
 from private_dataset.s3_dataset import S3Dataset
 from utils.error_handler import InternalServerException
 
@@ -20,11 +19,11 @@ def private_dataset_factory(
     ds_metadata = admin_database.get_dataset_metadata(dataset_name)
 
     match database_type:
-        case PrivateDatabaseType.REMOTE_HTTP:
-            dataset_url = admin_database.get_dataset_field(
-                dataset_name, "dataset_url"
+        case PrivateDatabaseType.PATH:
+            dataset_path = admin_database.get_dataset_field(
+                dataset_name, "dataset_path"
             )
-            private_db = RemoteHTTPDataset(ds_metadata, dataset_url)
+            private_db = PathDataset(ds_metadata, dataset_path)
         case PrivateDatabaseType.S3:
             s3_bucket = admin_database.get_dataset_field(
                 dataset_name, "s3_bucket"
@@ -47,11 +46,6 @@ def private_dataset_factory(
                 s3_aws_access_key_id,
                 s3_aws_secret_access_key,
             )
-        case PrivateDatabaseType.LOCAL:
-            dataset_path = admin_database.get_dataset_field(
-                dataset_name, "dataset_path"
-            )
-            private_db = LocalDataset(ds_metadata, dataset_path)
         case _:
             raise InternalServerException(
                 f"Unknown database type: {database_type}"
diff --git a/server/src/utils/anti_timing_att.py b/server/src/utils/anti_timing_att.py
index e7d880d3..82c6feb6 100644
--- a/server/src/utils/anti_timing_att.py
+++ b/server/src/utils/anti_timing_att.py
@@ -3,6 +3,7 @@
 from typing import Callable
 
 from fastapi import Request, Response
+
 from utils.config import Config
 
 
diff --git a/server/src/utils/config.py b/server/src/utils/config.py
index 608d92e8..e5d41ae6 100644
--- a/server/src/utils/config.py
+++ b/server/src/utils/config.py
@@ -1,8 +1,12 @@
-import collections.abc
-
 import yaml
+from pydantic import BaseModel
+
+# Temporary workaround this issue:
+# https://github.com/pydantic/pydantic/issues/5821
+# from typing import Literal
+from typing_extensions import Any, Dict, Literal
+
 from constants import (
-    AdminDBType,
     CONF_DATASET_STORE,
     CONF_DATASET_STORE_TYPE,
     CONF_DB,
@@ -14,14 +18,9 @@
     CONF_SUBMIT_LIMIT,
     CONFIG_PATH,
     SECRETS_PATH,
+    AdminDBType,
     ConfDatasetStore,
 )
-from pydantic import BaseModel
-
-# Temporary workaround this issue:
-# https://github.com/pydantic/pydantic/issues/5821
-# from typing import Literal
-from typing_extensions import Dict, Literal, Any
 from utils.error_handler import InternalServerException
 
 
@@ -94,13 +93,13 @@ def get_config() -> Config:
     merges them and returns the config object.
     """
     try:
-        with open(CONFIG_PATH, "r") as f:
+        with open(CONFIG_PATH, mode="r", encoding="utf-8") as f:
             config_data = yaml.safe_load(f)[CONF_RUNTIME_ARGS][CONF_SETTINGS]
 
         # Merge secret data into config data
-        with open(SECRETS_PATH, "r") as f:
+        with open(SECRETS_PATH, mode="r", encoding="utf-8") as f:
             secret_data = yaml.safe_load(f)
-            
+
             def update(d: Dict[str, Any], u: Dict[str, Any]) -> Dict[str, Any]:
                 for k, v in u.items():
                     if isinstance(v, dict):
@@ -111,18 +110,18 @@ def update(d: Dict[str, Any], u: Dict[str, Any]) -> Dict[str, Any]:
 
             update(config_data, secret_data)
 
-        server_config: Server = Server.parse_obj(config_data[CONF_SERVER])
+        server_config: Server = Server.model_validate(config_data[CONF_SERVER])
 
         db_type = config_data[CONF_DB][CONF_DB_TYPE]
         match db_type:
             case AdminDBType.MONGODB_TYPE:
-                admin_database_config = MongoDBConfig.parse_obj(
+                admin_database_config = MongoDBConfig.model_validate(
                     config_data[CONF_DB]
                 )
             case AdminDBType.YAML_TYPE:
-                admin_database_config = YamlDBConfig.parse_obj(
+                admin_database_config = YamlDBConfig.model_validate(
                     config_data[CONF_DB]
-                ) # type: ignore
+                )  # type: ignore
             case _:
                 raise InternalServerException(
                     f"Admin database type {db_type} not supported."
@@ -133,11 +132,11 @@ def update(d: Dict[str, Any], u: Dict[str, Any]) -> Dict[str, Any]:
         ]
         match ds_store_type:
             case ConfDatasetStore.BASIC:
-                ds_store_config = DatasetStoreConfig.parse_obj(
+                ds_store_config = DatasetStoreConfig.model_validate(
                     config_data[CONF_DATASET_STORE]
                 )
             case ConfDatasetStore.LRU:
-                ds_store_config = LRUDatasetStoreConfig.parse_obj(
+                ds_store_config = LRUDatasetStoreConfig.model_validate(
                     config_data[CONF_DATASET_STORE]
                 )
             case _:
@@ -157,13 +156,6 @@ def update(d: Dict[str, Any], u: Dict[str, Any]) -> Dict[str, Any]:
         raise InternalServerException(
             f"Could not read config from disk at {CONFIG_PATH}"
             + f" or missing fields: {e}"
-        )
+        ) from e
 
     return config
-
-
-"""
-def reload_config() -> Config:
-    # Potentially?
-    return None
-"""
diff --git a/server/src/utils/error_handler.py b/server/src/utils/error_handler.py
index 5de5927a..518e5375 100644
--- a/server/src/utils/error_handler.py
+++ b/server/src/utils/error_handler.py
@@ -1,8 +1,7 @@
-from typing import Tuple
-
-from constants import INTERNAL_SERVER_ERROR
 from fastapi import FastAPI, Request, status
 from fastapi.responses import JSONResponse
+
+from constants import INTERNAL_SERVER_ERROR
 from utils.loggr import LOG
 
 
@@ -52,7 +51,7 @@ def __init__(self, error_message: str) -> None:
         self.error_message = error_message
 
 
-CUSTOM_EXCEPTIONS: tuple[type,...] = (
+CUSTOM_EXCEPTIONS: tuple[type, ...] = (
     ExternalLibraryException,
     InternalServerException,
     InvalidQueryException,
diff --git a/server/src/utils/example_inputs.py b/server/src/utils/example_inputs.py
index 89838ab0..9f21ba99 100644
--- a/server/src/utils/example_inputs.py
+++ b/server/src/utils/example_inputs.py
@@ -22,7 +22,7 @@
 }
 
 example_smartnoise_sql = {
-    "query_str": "SELECT COUNT(*) AS NB_ROW FROM Schema.Table",
+    "query_str": "SELECT COUNT(*) AS NB_ROW FROM df",
     "dataset_name": PENGUIN_DATASET,
     "epsilon": SMARTNOISE_QUERY_EPSILON,
     "delta": SMARTNOISE_QUERY_DELTA,
@@ -31,7 +31,7 @@
 }
 
 example_dummy_smartnoise_sql = {
-    "query_str": "SELECT COUNT(*) AS NB_ROW FROM Schema.Table",
+    "query_str": "SELECT COUNT(*) AS NB_ROW FROM df",
     "dataset_name": PENGUIN_DATASET,
     "epsilon": DUMMY_EPSILON,
     "delta": DUMMY_DELTA,
@@ -42,24 +42,24 @@
 }
 
 example_smartnoise_sql_cost = {
-    "query_str": "SELECT COUNT(*) AS NB_ROW FROM Schema.Table",
+    "query_str": "SELECT COUNT(*) AS NB_ROW FROM df",
     "dataset_name": PENGUIN_DATASET,
     "epsilon": SMARTNOISE_QUERY_EPSILON,
     "delta": SMARTNOISE_QUERY_DELTA,
     "mechanisms": {"count": "gaussian"},
 }
 
-meas_pipeline = '{"version": "0.8.0", "ast": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "constructor", "func": "make_chain_tt", "module": "combinators", "args": [{"_type": "constructor", "func": "make_select_column", "module": "transformations", "kwargs": {"key": "bill_length_mm", "TOA": "String"}}, {"_type": "constructor", "func": "make_split_dataframe", "module": "transformations", "kwargs": {"separator": ",", "col_names": {"_type": "list", "_items": ["species", "island", "bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g", "sex"]}}}]}, "rhs": {"_type": "constructor", "func": "then_cast_default", "module": "transformations", "kwargs": {"TOA": "f64"}}}, "rhs": {"_type": "constructor", "func": "then_clamp", "module": "transformations", "kwargs": {"bounds": [30.0, 65.0]}}}, "rhs": {"_type": "constructor", "func": "then_resize", "module": "transformations", "kwargs": {"size": 346, "constant": 43.61}}}, "rhs": {"_type": "constructor", "func": "then_variance", "module": "transformations"}}, "rhs": {"_type": "constructor", "func": "then_laplace", "module": "measurements", "kwargs": {"scale": 5.0}}}}'  # noqa: E501
+MEASUREMENT_PIPELINE = '{"version": "0.8.0", "ast": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "partial_chain", "lhs": {"_type": "constructor", "func": "make_chain_tt", "module": "combinators", "args": [{"_type": "constructor", "func": "make_select_column", "module": "transformations", "kwargs": {"key": "bill_length_mm", "TOA": "String"}}, {"_type": "constructor", "func": "make_split_dataframe", "module": "transformations", "kwargs": {"separator": ",", "col_names": {"_type": "list", "_items": ["species", "island", "bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g", "sex"]}}}]}, "rhs": {"_type": "constructor", "func": "then_cast_default", "module": "transformations", "kwargs": {"TOA": "f64"}}}, "rhs": {"_type": "constructor", "func": "then_clamp", "module": "transformations", "kwargs": {"bounds": [30.0, 65.0]}}}, "rhs": {"_type": "constructor", "func": "then_resize", "module": "transformations", "kwargs": {"size": 346, "constant": 43.61}}}, "rhs": {"_type": "constructor", "func": "then_variance", "module": "transformations"}}, "rhs": {"_type": "constructor", "func": "then_laplace", "module": "measurements", "kwargs": {"scale": 5.0}}}}'  # noqa: E501
 
 example_opendp = {
     "dataset_name": PENGUIN_DATASET,
-    "opendp_json": meas_pipeline,
+    "opendp_json": MEASUREMENT_PIPELINE,
     "fixed_delta": 1e-6,
 }
 
 example_dummy_opendp = {
     "dataset_name": PENGUIN_DATASET,
-    "opendp_json": meas_pipeline,
+    "opendp_json": MEASUREMENT_PIPELINE,
     "fixed_delta": 1e-6,
     "dummy_nb_rows": DUMMY_NB_ROWS,
     "dummy_seed": DUMMY_SEED,
diff --git a/server/src/utils/input_models.py b/server/src/utils/input_models.py
index 04c30df5..7b5aa9e3 100644
--- a/server/src/utils/input_models.py
+++ b/server/src/utils/input_models.py
@@ -1,9 +1,10 @@
 import json
 from typing import Optional
 
-from constants import DELTA_LIMIT, EPSILON_LIMIT
 from pydantic import BaseModel, Field
 
+from constants import DELTA_LIMIT, EPSILON_LIMIT
+
 
 class BasicModel(BaseModel):
     def toJSON(self) -> str:
diff --git a/server/src/utils/utils.py b/server/src/utils/utils.py
index 9ea1b21c..048e2e25 100644
--- a/server/src/utils/utils.py
+++ b/server/src/utils/utils.py
@@ -1,15 +1,16 @@
 import io
 from typing import AsyncGenerator
 
-import app
 import pandas as pd
+from fastapi.responses import StreamingResponse
+
+import app
 from constants import (
     CONFIG_NOT_LOADED,
     DB_NOT_LOADED,
     QUERY_HANDLER_NOT_LOADED,
     SERVER_LIVE,
 )
-from fastapi.responses import StreamingResponse
 from utils.error_handler import InternalServerException
 from utils.loggr import LOG
 
diff --git a/server/src/uvicorn_serve.py b/server/src/uvicorn_serve.py
index 65f8457b..9b631ed2 100644
--- a/server/src/uvicorn_serve.py
+++ b/server/src/uvicorn_serve.py
@@ -1,6 +1,7 @@
 import os
 
 import uvicorn
+
 from utils.config import get_config
 from utils.loggr import LOG
 


Test patch:
diff --git a/server/src/tests/test_api.py b/server/src/tests/test_api.py
index 53f55f72..d874dc6a 100644
--- a/server/src/tests/test_api.py
+++ b/server/src/tests/test_api.py
@@ -1,25 +1,25 @@
-from fastapi import status
-from fastapi.testclient import TestClient
 import json
+import unittest
 from io import StringIO
+
 import pandas as pd
-import unittest
+from fastapi import status
+from fastapi.testclient import TestClient
 
 from app import app
-
-from constants import DPLibraries, EPSILON_LIMIT
+from constants import EPSILON_LIMIT, DPLibraries
 from utils.example_inputs import (
     DUMMY_NB_ROWS,
+    PENGUIN_DATASET,
+    SMARTNOISE_QUERY_DELTA,
+    SMARTNOISE_QUERY_EPSILON,
+    example_dummy_opendp,
+    example_dummy_smartnoise_sql,
     example_get_admin_db_data,
     example_get_dummy_dataset,
+    example_opendp,
     example_smartnoise_sql,
-    example_dummy_smartnoise_sql,
     example_smartnoise_sql_cost,
-    example_opendp,
-    example_dummy_opendp,
-    PENGUIN_DATASET,
-    SMARTNOISE_QUERY_DELTA,
-    SMARTNOISE_QUERY_EPSILON,
 )
 
 INITAL_EPSILON = 10
@@ -139,7 +139,7 @@ def test_smartnoise_query(self) -> None:
             response = client.post(
                 "/smartnoise_query",
                 json={
-                    "query_str": "SELECT COUNT(*) AS NB_ROW FROM Schema.Table",
+                    "query_str": "SELECT COUNT(*) AS NB_ROW FROM df",
                     "dataset_name": PENGUIN_DATASET,
                     "epsilon": SMARTNOISE_QUERY_EPSILON,
                     "postprocess": True,
@@ -160,7 +160,7 @@ def test_smartnoise_query(self) -> None:
             input_smartnoise = dict(example_smartnoise_sql)
             input_smartnoise[
                 "query_str"
-            ] = "SELECT AVG(bill) FROM Schema.Table"  # no 'bill' column
+            ] = "SELECT AVG(bill) FROM df"  # no 'bill' column
             response = client.post(
                 "/smartnoise_query",
                 json=input_smartnoise,
diff --git a/server/src/tests/test_data/local_db_file.yaml b/server/src/tests/test_data/local_db_file.yaml
index f8c64e5a..8e1f6975 100644
--- a/server/src/tests/test_data/local_db_file.yaml
+++ b/server/src/tests/test_data/local_db_file.yaml
@@ -1,15 +1,15 @@
 datasets:
 - dataset_name: "PENGUIN"
-  database_type: "REMOTE_HTTP_DB"
-  dataset_url: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
+  database_type: "PATH_DB"
+  dataset_path: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
   metadata:
-    database_type: "LOCAL_DB"
+    database_type: "PATH_DB"
     metadata_path: "tests/test_data/metadata/penguin_metadata.yaml"
 - dataset_name: "IRIS"
-  database_type: "REMOTE_HTTP_DB"
-  dataset_url: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
+  database_type: "PATH_DB"
+  dataset_path: "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
   metadata:
-    database_type: "LOCAL_DB"
+    database_type: "PATH_DB"
     metadata_path: "tests/test_data/metadata/penguin_metadata.yaml"
 users:
 - user_name: Dr. Antartica
diff --git a/server/src/tests/test_data/metadata/penguin_metadata.yaml b/server/src/tests/test_data/metadata/penguin_metadata.yaml
index fbdd21d3..044de129 100644
--- a/server/src/tests/test_data/metadata/penguin_metadata.yaml
+++ b/server/src/tests/test_data/metadata/penguin_metadata.yaml
@@ -1,42 +1,40 @@
-"":
-  Schema:
-    Table:
-      max_ids: 1
-      row_privacy: true
-      censor_dims: False
-      species:
-        type: string
-        cardinality: 3
-        categories:
-        - Adelie
-        - Chinstrap
-        - Gentoo
-      island:
-        type: string
-        cardinality: 3
-        categories:
-        - Torgersen
-        - Biscoe
-        - Dream
-      bill_length_mm:
-        type: float
-        lower: 30.0
-        upper: 65.0
-      bill_depth_mm:
-        type: float
-        lower: 13.0
-        upper: 23.0
-      flipper_length_mm:
-        type: float
-        lower: 150.0
-        upper: 250.0
-      body_mass_g:
-        type: float
-        lower: 2000.0
-        upper: 7000.0
-      sex:
-        type: string
-        cardinality: 2
-        categories:
-        - MALE
-        - FEMALE
+max_ids: 1
+row_privacy: true
+censor_dims: False
+columns:
+  species:
+    type: string
+    cardinality: 3
+    categories:
+    - Adelie
+    - Chinstrap
+    - Gentoo
+  island:
+    type: string
+    cardinality: 3
+    categories:
+    - Torgersen
+    - Biscoe
+    - Dream
+  bill_length_mm:
+    type: float
+    lower: 30.0
+    upper: 65.0
+  bill_depth_mm:
+    type: float
+    lower: 13.0
+    upper: 23.0
+  flipper_length_mm:
+    type: float
+    lower: 150.0
+    upper: 250.0
+  body_mass_g:
+    type: float
+    lower: 2000.0
+    upper: 7000.0
+  sex:
+    type: string
+    cardinality: 2
+    categories:
+    - MALE
+    - FEMALE
diff --git a/server/src/tests/test_dummy_generation.py b/server/src/tests/test_dummy_generation.py
index bfd833d8..c920e99f 100644
--- a/server/src/tests/test_dummy_generation.py
+++ b/server/src/tests/test_dummy_generation.py
@@ -1,11 +1,20 @@
 import unittest
+
 from dp_queries.dummy_dataset import make_dummy_dataset
-from utils.example_inputs import (DUMMY_NB_ROWS, DUMMY_SEED)
+from utils.example_inputs import DUMMY_NB_ROWS, DUMMY_SEED
+
 
 class TestMakeDummyDataset(unittest.TestCase):
-    
     def test_cardinality_column(self) -> None:
-        metadata = {"": {"Schema": {"Table": {"col_card": {"type": "string", "cardinality": 3, "categories":["a", "b", "c"]}}}}}
+        metadata = {
+            "columns": {
+                "col_card": {
+                    "type": "string",
+                    "cardinality": 3,
+                    "categories": ["a", "b", "c"],
+                }
+            }
+        }
         df = make_dummy_dataset(metadata)
 
         # Test length
@@ -15,17 +24,18 @@ def test_cardinality_column(self) -> None:
         self.assertIn("col_card", df.columns)
         self.assertEqual(df["col_card"].nunique(), 3)
         self.assertEqual(set(df["col_card"].values), {"a", "b", "c"})
-        assert(isinstance(df["col_card"], object))
+        assert isinstance(df["col_card"], object)
 
     def test_boolean_column(self) -> None:
-        
         # Test a boolean column
-        metadata = {"": {"Schema": {"Table": {"col_bool": {"type": "boolean", "nullable":True}}}}}
+        metadata = {
+            "columns": {"col_bool": {"type": "boolean", "nullable": True}}
+        }
         df = make_dummy_dataset(metadata)
 
         # Test length
         self.assertEqual(len(df), DUMMY_NB_ROWS)
-        
+
         # Test col generated is boolean
         self.assertIn("col_bool", df.columns)
         self.assertEqual(df.col_bool.dtypes.name, "boolean")
@@ -33,7 +43,15 @@ def test_boolean_column(self) -> None:
     def test_float_column(self) -> None:
         lower_bound = 10.0
         upper_bound = 20.0
-        metadata = {"": {"Schema": {"Table": {"col_float": {"type": "float", "upper":upper_bound, "lower":lower_bound}}}}}
+        metadata = {
+            "columns": {
+                "col_float": {
+                    "type": "float",
+                    "upper": upper_bound,
+                    "lower": lower_bound,
+                }
+            }
+        }
         df = make_dummy_dataset(metadata)
 
         # Test col generated is of type float
@@ -46,18 +64,26 @@ def test_float_column(self) -> None:
     def test_int_column(self) -> None:
         lower_bound = 100
         upper_bound = 120
-        metadata = {"": {"Schema": {"Table": {"col_int": {"type": "int", "upper":upper_bound, "lower":lower_bound}}}}}
+        metadata = {
+            "columns": {
+                "col_int": {
+                    "type": "int",
+                    "upper": upper_bound,
+                    "lower": lower_bound,
+                }
+            }
+        }
         df = make_dummy_dataset(metadata)
 
         # Test col generated is of type int
-        self.assertEqual(df.col_int.dtypes.name, "int64")
+        self.assertIn(df.col_int.dtypes.name, ["int32", "int64"])
 
         # Test within bounds
         self.assertTrue((df["col_int"] >= lower_bound).all())
         self.assertTrue((df["col_int"] <= upper_bound).all())
-    
+
     def test_datetime_column(self) -> None:
-        metadata = {"": {"Schema": {"Table": {"col_datetime": {"type": "datetime"}}}}}
+        metadata = {"columns": {"col_datetime": {"type": "datetime"}}}
         df = make_dummy_dataset(metadata)
 
         # Test col generated is of type datetime
@@ -67,7 +93,9 @@ def test_datetime_column(self) -> None:
         self.assertFalse(df.col_datetime.isnull().values.any())
 
     def test_nullable_column(self) -> None:
-        metadata = {"": {"Schema": {"Table": {"col_nullable": {"type": "datetime", "nullable":True}}}}}
+        metadata = {
+            "columns": {"col_nullable": {"type": "datetime", "nullable": True}}
+        }
         df = make_dummy_dataset(metadata)
 
         # Should have null values
@@ -75,7 +103,7 @@ def test_nullable_column(self) -> None:
 
     def test_seed(self) -> None:
         # Test the behavior with different seeds
-        metadata = {"": {"Schema": {"Table": {"col_int": {"type": "int", "nullable":True}}}}}
+        metadata = {"columns": {"col_int": {"type": "int", "nullable": True}}}
         seed1 = DUMMY_SEED
         seed2 = DUMMY_SEED + 1