{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bacc54ed",
   "metadata": {},
   "source": [
    "# NTV - Overview\n",
    "\n",
    "This overview presents different facets and covers all the features of this package.\n",
    "\n",
    "## Summary\n",
    "*(active link on jupyter Notebook or Nbviewer)*\n",
    "- [from native entity to JSON-text](#from-native-entity-to-JSON-text)\n",
    "- [All JSON data is JSON-NTV data](#All-JSON-data-is-JSON-NTV-data)\n",
    "- [NTV data is named](#NTV-data-is-named)\n",
    "- [NTV data is typed](#NTV-data-is-typed)\n",
    "- [Types can be predefined](#Types-can-be-predefined)\n",
    "- [Types are nested](#Types-are-nested)\n",
    "- [NTV data is nested](#NTV-data-is-nested)\n",
    "- [NTV-json format is reversible for NTV entities](#NTV-json-format-is-reversible-for-NTV-entities)\n",
    "- [NTV data can be validated according to their NTVtype](#NTV-data-can-be-validated-according-to-their-NTVtype)\n",
    "- [Options are available for NTV-json](#Options-are-available-for-NTV-json)\n",
    "- [Changes and comments are managed](#Changes-and-comments-are-managed)\n",
    "- [JSON-array and JSON-object are equivalent for NtvList](#JSON-array-and-JSON-object-are-equivalent-for-NtvList)\n",
    "- [NTV is a tree data structure](#NTV-is-a-tree-data-structure)\n",
    "- [The json representation can be more or less deep](#The-json-representation-can-be-more-or-less-deep)\n",
    "- [NTV entities are compatible with tabular data tools](#NTV-entities-are-compatible-with-tabular-data-tools)\n",
    "- [CSV data is enriched with NTV structures](#CSV-data-is-enriched-with-NTV-structures)\n",
    "- [NTV data can be created from entities of all types](#NTV-data-can-be-created-from-entities-of-all-types)\n",
    "- [Template structure can be used](#Template-structure-can-be-used)\n",
    "- [NTVtype can be extended](#NTVtype-can-be-extended)\n",
    "- [Custom types are allowed](#Custom-types-are-allowed)\n",
    "- [NTV can be used with custom entities](#NTV-can-be-used-with-custom-entities)\n",
    "\n",
    "## References\n",
    "- [JSON-NTV specification](https://github.com/loco-philippe/NTV/blob/main/documentation/JSON-NTV-standard.pdf)\n",
    "- [JSON-NTV classes and methods](https://loco-philippe.github.io/NTV/json_ntv.html)\n",
    "\n",
    "This Notebook can also be viewed at [nbviewer](http://nbviewer.org/github/loco-philippe/NTV/tree/main/example)\n",
    "\n",
    "-----"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b21f8cad",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "from json_ntv import NtvSingle, NtvList, Ntv, NtvConnector, Datatype, Namespace, to_csv, from_csv, NtvComment\n",
    "from datetime import date, datetime\n",
    "from shapely import Point"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d6217d91",
   "metadata": {},
   "outputs": [],
   "source": [
    "ntv = \"\"\"\n",
    "flowchart LR\n",
    "    text[\"#10240;#10240;JSON#10240;#10240;\\ntext\"]\n",
    "    val[\"#10240;JSON-NTV#10240;\\nvalue\"]\n",
    "    ntv[\"#10240;#10240;#10240;NTV#10240;#10240;#10240;\\nentity\"]\n",
    "    nat[\"#10240;<b>native</b>#10240;\\nentity\"]\n",
    "    text--->|JSON load|val\n",
    "    val--->|JSON dump|text\n",
    "    val--->|Ntv.from_obj|ntv\n",
    "    ntv--->|.to_obj|nat\n",
    "    ntv--->|.to_obj|val\n",
    "    nat--->|Ntv.from_obj|ntv\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e8445d34",
   "metadata": {},
   "source": [
    "## from native entity to JSON-text\n",
    "- The diagram below explains how to transform **any type of data** into a neutral exchange format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ee24c89d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/CmZsb3djaGFydCBMUgogICAgdGV4dFsiIzEwMjQwOyMxMDI0MDtKU09OIzEwMjQwOyMxMDI0MDsKdGV4dCJdCiAgICB2YWxbIiMxMDI0MDtKU09OLU5UViMxMDI0MDsKdmFsdWUiXQogICAgbnR2WyIjMTAyNDA7IzEwMjQwOyMxMDI0MDtOVFYjMTAyNDA7IzEwMjQwOyMxMDI0MDsKZW50aXR5Il0KICAgIG5hdFsiIzEwMjQwOzxiPm5hdGl2ZTwvYj4jMTAyNDA7CmVudGl0eSJdCiAgICB0ZXh0LS0tPnxKU09OIGxvYWR8dmFsCiAgICB2YWwtLS0+fEpTT04gZHVtcHx0ZXh0CiAgICB2YWwtLS0+fE50di5mcm9tX29ianxudHYKICAgIG50di0tLT58LnRvX29ianxuYXQKICAgIG50di0tLT58LnRvX29ianx2YWwKICAgIG5hdC0tLT58TnR2LmZyb21fb2JqfG50dgo=\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from base64 import b64encode\n",
    "from IPython.display import Image, display\n",
    "display(Image(url=\"https://mermaid.ink/img/\" + b64encode(ntv.encode(\"ascii\")).decode(\"ascii\")))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3079ba24",
   "metadata": {},
   "source": [
    "- the conversion between native entity and JSON-text is reversible (round trip)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1bccd532",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loc_and_date = {'newyear': date(2023, 1, 2), 'Paris': Point(2.3, 48.9)}\n",
    "json_loc_date = Ntv.obj(loc_and_date).to_obj(encoded=True)\n",
    "\n",
    "Ntv.obj(json_loc_date).to_obj(format='obj') == loc_and_date"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fcbfcfa",
   "metadata": {},
   "source": [
    "## All JSON data is JSON-NTV data\n",
    "NTV entities : \n",
    "- NtvSingle : primitive entity which is not composed of any other entity\n",
    "- NtvList : ordered sequence of NTV entities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "31758027",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "null                                               NTV entity :  <class 'json_ntv.ntv.NtvSingle'>\n",
      "1                                                  NTV entity :  <class 'json_ntv.ntv.NtvSingle'>\n",
      "[1, 2]                                             NTV entity :  <class 'json_ntv.ntv.NtvList'>\n",
      "{\"key\": \"value\"}                                   NTV entity :  <class 'json_ntv.ntv.NtvSingle'>\n",
      "{\"key1\": \"val1\", \"key2\": \"val2\"}                   NTV entity :  <class 'json_ntv.ntv.NtvList'>\n",
      "{\"example\": [21, [1, 2], {\"key1\": 3, \"key2\": 4}]}  NTV entity :  <class 'json_ntv.ntv.NtvList'>\n"
     ]
    }
   ],
   "source": [
    "liste = [None, 1, [1,2], {'key': 'value'}, {'key1': 'val1', 'key2': 'val2'}, \n",
    "         {'example': [21, [1,2], {'key1': 3, 'key2': 4}]}]\n",
    "for json in liste:\n",
    "    ntv = Ntv.obj(json)\n",
    "    print('{:<50} {} {}'.format(str(ntv), 'NTV entity : ', type(ntv)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36ecdec1",
   "metadata": {},
   "source": [
    "## NTV data is named\n",
    "- a name can be added or remove"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "48c97569",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "simple data              :  3\n",
      "simple data with name    :  {\"value\": 3}\n",
      "simple data without name :  3\n"
     ]
    }
   ],
   "source": [
    "simple = NtvSingle(3)\n",
    "\n",
    "print('simple data              : ', simple)\n",
    "simple.set_name('value')\n",
    "print('simple data with name    : ', simple)\n",
    "simple.set_name('')\n",
    "print('simple data without name : ', simple)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "663d63e8",
   "metadata": {},
   "source": [
    "## NTV data is typed\n",
    "- default type is 'json'\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7ef86113",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Are {':json' : 21} and 21 equivalent ?  True\n"
     ]
    }
   ],
   "source": [
    "# {':json' : 21} and 21 are equivalent\n",
    "number = 21\n",
    "typed_number = {':json' : 21}\n",
    "comparison = Ntv.obj(typed_number) == Ntv.obj(number)\n",
    "print(\"Are {':json' : 21} and 21 equivalent ? \", comparison)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b817705",
   "metadata": {},
   "source": [
    "## Types can be predefined\n",
    "- many standard types are included"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "74e2439f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'paris': <POINT (4.1 40.5)>}\n"
     ]
    },
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"100.0\" height=\"100.0\" viewBox=\"-0.04 -0.04 1.08 1.08\" preserveAspectRatio=\"xMinYMin meet\"><g transform=\"matrix(1,0,0,-1,0,1.0)\"><path fill-rule=\"evenodd\" fill=\"#66cc99\" stroke=\"#555555\" stroke-width=\"0.0216\" opacity=\"0.6\" d=\"M 0.0,1.0 L 1.0,1.0 L 1.0,0.0 L 0.0,1.0 z\" /></g></svg>"
      ],
      "text/plain": [
       "<POLYGON ((0 1, 1 1, 1 0, 0 1))>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# {'paris:point' : [4.1, 40.5] } indicates that the object named 'paris' has geographical coordinates [4.1, 40.5]\n",
    "city = Ntv.obj({'paris:point' : [4.1, 40.5] })\n",
    "print(city.to_obj(format='obj'))\n",
    "\n",
    "# another coordinates are available (e.g. line, polygon)\n",
    "city = Ntv.obj({':polygon' : [[[0,1], [1,1], [1,0], [0,1]]] })\n",
    "city.to_obj(format='obj')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a91d85a",
   "metadata": {},
   "source": [
    "## Types are nested\n",
    "- a Type is defined by a name and a Namespace.  \n",
    "- a Namespace is represented by a string followed by a point. Namespaces may be nested\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "bd0ded13",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"picardie:fr.\": {\"oise:dep\": \"60\", \"aisne:dep\": \"02\", \"somme:dep\": \"80\", \"hauts de france:reg\": 32}} \n",
      "\n",
      "{\"oise:fr.dep\": \"60\"}\n"
     ]
    }
   ],
   "source": [
    "picardie = NtvList.obj({'picardie:fr.':{'oise:dep': '60', 'aisne:dep': '02', 'somme:dep': '80', 'hauts de france:reg': 32}})\n",
    "\n",
    "# 'dep' is a type (french department) defined in the Namespace 'fr.' (french types)\n",
    "# the default Namespace 'fr.' is aggregated with the 'dep' type\n",
    "\n",
    "print(picardie, '\\n')\n",
    "print(picardie[0])\n",
    "\n",
    "# '60' is the 'fr.dep' code for the department of Oise\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06c14142",
   "metadata": {},
   "source": [
    "## NTV data is nested\n",
    "- A structure with ordered list of NTV entities is available\n",
    "- The type can be shared between entities included in the same entity\n",
    "- The type defined in a structure is a default type\n",
    "- Two NTV structures are equal if the name and the value are equals (the default type can be different)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "58ffe77c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "equivalent structures ?  True\n",
      "coordinates and date in a typed structure :  {\"cities::point\": [{\"paris\": [4.1, 40.5]}, [4.5, 41.2], {\":date\": \"2012-02-15\"}]}\n",
      "coordinates and date in an untyped structure :  {\"cities\": {\"paris:point\": [4.1, 40.5], \":point\": [4.5, 41.2], \":date\": \"2012-02-15\"}}\n"
     ]
    }
   ],
   "source": [
    "# structure definied by JSON-Array\n",
    "cities1 = Ntv.obj({'cities':        [{'paris:point': [4.1, 40.5]}, {':point': [4.5, 41.2]}]})\n",
    "cities2 = Ntv.obj({'cities::point': [{'paris':       [4.1, 40.5]},            [4.5, 41.2] ]})\n",
    "\n",
    "# structure definied by JSON-Object\n",
    "cities3 = Ntv.obj({'cities::point': {'paris':       [4.1, 40.5], 'lyon':       [4.5, 41.2]}})\n",
    "cities4 = Ntv.obj({'cities':        {'paris:point': [4.1, 40.5], 'lyon:point': [4.5, 41.2]}})\n",
    "\n",
    "print('equivalent structures ? ', cities1 == cities2 and cities3 == cities4)\n",
    "\n",
    "# default type in a structure\n",
    "cities5 = Ntv.obj({'cities::point': [{'paris': [4.1, 40.5]}, [4.5, 41.2], {':date': '2012-02-15'}]})\n",
    "print('coordinates and date in a typed structure : ', cities5)\n",
    "cities5.set_type()\n",
    "print('coordinates and date in an untyped structure : ', cities5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "80207455",
   "metadata": {},
   "source": [
    "## NTV-json format is reversible for NTV entities\n",
    "- The entity build with the Json representation of another entity is identical to the original NTV entity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "05a02ca4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Ntv.obj(simple. to_obj()) == simple  and \\\n",
    "Ntv.obj(city.   to_obj()) == city    and \\\n",
    "Ntv.obj(cities2.to_obj()) == cities2 and \\\n",
    "Ntv.obj(cities4.to_obj()) == cities4"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48b0c76e",
   "metadata": {},
   "source": [
    "## NTV data can be validated according to their NTVtype\n",
    "- It concerns all NTVsingle entities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "e02c289f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "without error (boolean, list pointer of error):  (True, [])\n",
      "\n",
      "with coordinate error (boolean, list pointer of error):  (False, ['cities::point/1'])\n",
      "\n",
      "with date error (boolean, list pointer of error):  (False, ['cities::point/2'])\n"
     ]
    }
   ],
   "source": [
    "cities5 = Ntv.obj({'cities::point': [{'paris': [4.1, 40.5]}, [4.5, 41.2], {':date': '2012-02-15'}]})\n",
    "print('without error (boolean, list pointer of error): ', cities5.validate())\n",
    "\n",
    "cities5 = Ntv.obj({'cities::point': [{'paris': [4.1, 40.5]}, [4.5, 241.2], {':date': '2012-02-15'}]})\n",
    "print('\\nwith coordinate error (boolean, list pointer of error): ', cities5.validate())\n",
    "\n",
    "cities5 = Ntv.obj({'cities::point': [{'paris': [4.1, 40.5]}, [4.5, 41.2], {':date': '2012-22-15'}]})\n",
    "print('\\nwith date error (boolean, list pointer of error): ', cities5.validate())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "713ab7db",
   "metadata": {},
   "source": [
    "## Options are available for NTV-json\n",
    "- selected values\n",
    "- encoded data\n",
    "- data format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "9d1828ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Json format   :  {'cities::point': [{'paris': [4.1, 40.5]}, [4.5, 41.2]]}\n",
      "only values   :  [[4.1, 40.5], [4.5, 41.2]]\n",
      "Json text     :  {\"cities::point\": [{\"paris\": [4.1, 40.5]}, [4.5, 41.2]]}\n",
      "Json binary   :  b'\\xa1mcities::point\\x82\\xa1eparis\\x82\\xfb@\\x10ffffff\\xfb@D@\\x00\\x00\\x00\\x00\\x00\\x82\\xfb@\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\xfb@D\\x99\\x99\\x99\\x99\\x99\\x9a'\n",
      "tuple format  :  ('NtvList', 'cities', 'point', [('NtvSingle', 'paris', 'point', [4.1, 40.5]), ('NtvSingle', '', 'point', [4.5, 41.2])])\n",
      "object format :  {'cities::point': [{'paris': <POINT (4.1 40.5)>}, <POINT (4.5 41.2)>]}\n",
      "simple Json   :  {'l-cities-point': ['s-paris-point-[4.1, 40.5]', 's-point-[4.5, 41.2]']}\n",
      "Json codes    :  {'lNT': ['sNT', 'sT']}\n"
     ]
    }
   ],
   "source": [
    "print('Json format   : ', cities2.to_obj())\n",
    "print('only values   : ', cities2.to_obj(simpleval=True))\n",
    "print('Json text     : ', cities2.to_obj(encoded=True))\n",
    "print('Json binary   : ', cities2.to_obj(format='cbor', encoded=True))\n",
    "print('tuple format  : ', cities2.to_tuple())\n",
    "print('object format : ', cities2.to_obj(format='obj'))\n",
    "print('simple Json   : ', cities2.to_repr())\n",
    "print('Json codes    : ', cities2.to_repr(False, False, False)) \n",
    "# Codification : first letter: \"s\" (NtvSingle), \"l\" (NtvList), additional letters: 'N' (named), 'T' (typed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05a08bd0",
   "metadata": {},
   "source": [
    "## Changes and comments are managed\n",
    "- change proposals and comments can be added to the NTV entities\n",
    "- they can be rejected or accepted"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "64290e9e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "are rejected comments deleted ?  True\n",
      "is 'date1' updated (1965-01-01) ?  True\n"
     ]
    }
   ],
   "source": [
    "dates_json = {'dates::date': { 'date1':'1964-01-01', 'date2': '1985-02-05', 'date3': '2022-01-21'}}\n",
    "dates = Ntv.obj(dates_json)\n",
    "\n",
    "dates_comment = NtvComment(dates)\n",
    "\n",
    "dates_comment.add({'list-op': [{'op': 'replace', 'path': 'dates/date1', 'entity': {'date1:date':'1965-01-01'}}], \n",
    "                   'comment': 'year is not correct'})\n",
    "dates_comment.add('everything is correct')\n",
    "dates_reject = dates_comment.reject(all_comment=True).ntv\n",
    "print('\\nare rejected comments deleted ? ', dates == dates_reject)\n",
    "\n",
    "dates_accept = dates_comment.accept().ntv\n",
    "print(\"is 'date1' updated (1965-01-01) ? \", dates_accept['date1'].val == '1965-01-01')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f5dd615",
   "metadata": {},
   "source": [
    "## JSON-array and JSON-object are equivalent for NtvList\n",
    "- if the constraint of the JSON-object (keys are present) is respected"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "483c84a7",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "are NTV entities from a JSON-array or a JSON-object the same ?  True \n",
      "\n",
      "ntv - Array  :  {'array or object': {'key1': 'value1', 'key2': 'value2'}}\n",
      "ntv - Object :  {'array or object': {'key1': 'value1', 'key2': 'value2'}}\n",
      "\n",
      "An NTV entity has JSON-array and JSON-object representation\n"
     ]
    }
   ],
   "source": [
    "ntv_lis = Ntv.obj({'array or object': [{'key1': 'value1'}, {'key2': 'value2'}]})\n",
    "ntv_obj = Ntv.obj({'array or object': {'key1': 'value1', 'key2': 'value2'}})\n",
    "print('are NTV entities from a JSON-array or a JSON-object the same ? ', ntv_lis == ntv_obj, '\\n')\n",
    "\n",
    "print('ntv - Array  : ', ntv_lis.to_obj(ntv_list=True))\n",
    "print('ntv - Object : ', ntv_lis.to_obj(ntv_list=False))\n",
    "\n",
    "print('\\nAn NTV entity has JSON-array and JSON-object representation' )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b94b1d6",
   "metadata": {},
   "source": [
    "## NTV is a tree data structure"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "097b61c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/LS0tCnRpdGxlOiBOVFYgZmxvd2NoYXJ0Ci0tLQpmbG93Y2hhcnQgVEQKICAgIDAoIjxiPmV4YW1wbGU8L2I+IikKICAgIDAvMCgiPGI+ZnJ1aXRzPC9iPiIpCiAgICAwLzAvMCgiPGI+Ojo8L2I+IikKICAgIDAvMC8wLzBbIjxiPmtpd2lzPC9iPgo8aT4zPC9pPiJdCiAgICAwLzAvMC8xWyI8Yj5tYW5ndWVzPC9iPgppbnQKPGk+NDwvaT4iXQogICAgMC8wLzAvMlsiPGI+cG9tbWVzPC9iPgo8aT5udWxsPC9pPiJdCiAgICAwLzAvMVsiPGI+cGFuaWVyPC9iPgo8aT50cnVlPC9pPiJdCiAgICAwLzEoIjxiPmxlZ3VtZXM8L2I+Cmpzb24iKQogICAgMC8xLzBbIjxiPnBhdGF0ZXM8L2I+CnN0cmluZwo8aT5hbWFuZGluZTwvaT4iXQogICAgMC8xLzFbIjxiPnBvaXJlYXV4PC9iPgo8aT5mYWxzZTwvaT4iXQogICAgMC8yKCI8Yj52aWFuZGVzPC9iPiIpCiAgICAwLzIvMFsiPGk+cG9pc3NvbjwvaT4iXQogICAgMC8yLzFbInN0cmluZwo8aT5wb3VsZXQ8L2k+Il0KICAgIDAvMi8yWyI8aT5ib2V1ZjwvaT4iXQogICAgMC8wLzAgLS0+IDAvMC8wLzAKICAgIDAvMC8wIC0tPiAwLzAvMC8xCiAgICAwLzAvMCAtLT4gMC8wLzAvMgogICAgMC8wIC0tPiAwLzAvMAogICAgMC8wIC0tPiAwLzAvMQogICAgMCAtLT4gMC8wCiAgICAwLzEgLS0+IDAvMS8wCiAgICAwLzEgLS0+IDAvMS8xCiAgICAwIC0tPiAwLzEKICAgIDAvMiAtLT4gMC8yLzAKICAgIDAvMiAtLT4gMC8yLzEKICAgIDAvMiAtLT4gMC8yLzIKICAgIDAgLS0+IDAvMgo=\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "example = { 'example::': {\n",
    "  \"fruits\": [\n",
    "     {\"kiwis\": 3, \"mangues:int\": 4, \"pommes\": None },\n",
    "     {\"panier\": True } ],\n",
    "  \"legumes::json\": {\n",
    "      \"patates:string\": \"amandine\",\n",
    "      \"poireaux\": False },\n",
    "  \"viandes\": [\"poisson\",{\":string\": \"poulet\"},\"boeuf\"] }}\n",
    "\n",
    "# tree with value\n",
    "Ntv.obj(example).to_mermaid('NTV flowchart', disp=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "c68d97a2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/LS0tCnRpdGxlOiBOVFYgZmxvd2NoYXJ0Ci0tLQpmbG93Y2hhcnQgVEQKICAgIDAoIjxiPmV4YW1wbGU8L2I+IikKICAgIDAvMCgiPGI+ZnJ1aXRzPC9iPiIpCiAgICAwLzAvMCgiPGI+Ojo8L2I+IikKICAgIDAvMC8wLzAoIjxiPmtpd2lzPC9iPgo8aT4gMDwvaT4iKQogICAgMC8wLzAvMSgiPGI+bWFuZ3VlczwvYj4KaW50CjxpPiAxPC9pPiIpCiAgICAwLzAvMC8yKCI8Yj5wb21tZXM8L2I+CjxpPiAyPC9pPiIpCiAgICAwLzAvMSgiPGI+cGFuaWVyPC9iPgo8aT4gMzwvaT4iKQogICAgMC8xKCI8Yj5sZWd1bWVzPC9iPgpqc29uIikKICAgIDAvMS8wKCI8Yj5wYXRhdGVzPC9iPgpzdHJpbmcKPGk+IDQ8L2k+IikKICAgIDAvMS8xKCI8Yj5wb2lyZWF1eDwvYj4KPGk+IDU8L2k+IikKICAgIDAvMigiPGI+dmlhbmRlczwvYj4iKQogICAgMC8yLzAoIjxpPiA2PC9pPiIpCiAgICAwLzIvMSgic3RyaW5nCjxpPiA3PC9pPiIpCiAgICAwLzIvMigiPGk+IDg8L2k+IikKICAgIDAvMC8wIC0tPiAwLzAvMC8wCiAgICAwLzAvMCAtLT4gMC8wLzAvMQogICAgMC8wLzAgLS0+IDAvMC8wLzIKICAgIDAvMCAtLT4gMC8wLzAKICAgIDAvMCAtLT4gMC8wLzEKICAgIDAgLS0+IDAvMAogICAgMC8xIC0tPiAwLzEvMAogICAgMC8xIC0tPiAwLzEvMQogICAgMCAtLT4gMC8xCiAgICAwLzIgLS0+IDAvMi8wCiAgICAwLzIgLS0+IDAvMi8xCiAgICAwLzIgLS0+IDAvMi8yCiAgICAwIC0tPiAwLzIK\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# tree with leaves row\n",
    "Ntv.obj(example).to_mermaid('NTV flowchart', disp=True, leaves=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "496f5fd2",
   "metadata": {},
   "source": [
    "## The json representation can be more or less deep"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "110c7bd0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/LS0tCnRpdGxlOiBmdWxsIE5UVgotLS0KZmxvd2NoYXJ0IFRECiAgICAwKCI8Yj5jaXR5PC9iPiIpCiAgICAwLzAoIjxiPnBhcmlzPC9iPiIpCiAgICAwLzAvMFsiPGk+Mi4zPC9pPiJdCiAgICAwLzAvMVsiPGk+NDguOTwvaT4iXQogICAgMC8xKCI8Yj5seW9uPC9iPiIpCiAgICAwLzEvMFsiPGk+NC44PC9pPiJdCiAgICAwLzEvMVsiPGk+NDUuODwvaT4iXQogICAgMC8wIC0tPiAwLzAvMAogICAgMC8wIC0tPiAwLzAvMQogICAgMCAtLT4gMC8wCiAgICAwLzEgLS0+IDAvMS8wCiAgICAwLzEgLS0+IDAvMS8xCiAgICAwIC0tPiAwLzEK\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Ntv.obj({'city': {'paris': [2.3, 48.9],  'lyon': [4.8, 45.8] } }).to_mermaid('full NTV', disp=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6e0f11ad",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/LS0tCnRpdGxlOiBtaXhlZCBKU09OLU5UVgotLS0KZmxvd2NoYXJ0IFRECiAgICAwKCI8Yj5jaXR5PC9iPgpwb2ludCIpCiAgICAwLzBbIjxiPnBhcmlzPC9iPgo8aT5bMi4zLCA0OC45XTwvaT4iXQogICAgMC8xWyI8Yj5seW9uPC9iPgo8aT5bNC44LCA0NS44XTwvaT4iXQogICAgMCAtLT4gMC8wCiAgICAwIC0tPiAwLzEK\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Ntv.obj({'city::point': {'paris': [2.3, 48.9],  'lyon': [4.8, 45.8] } }).to_mermaid('mixed JSON-NTV', disp=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "360c1b0f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"https://mermaid.ink/img/LS0tCnRpdGxlOiBmdWxsIEpTT04KLS0tCmZsb3djaGFydCBURAogICAgMFsiPGI+Y2l0eTwvYj4KPGk+eydwYXJpcyc6IFsyLjMsIDQ4LjldLCAnbHlvbic6IFs0LjgsIDQ1LjhdfTwvaT4iXQo=\"/>"
      ],
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Ntv.obj({'city:': {'paris': [2.3, 48.9],  'lyon': [4.8, 45.8] } }).to_mermaid('full JSON', disp=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a5b7c0e",
   "metadata": {},
   "source": [
    "## NTV entities are compatible with tabular data tools\n",
    "- Example with Pandas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "814da6fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0   1964-01-01\n",
      "1   1985-02-05\n",
      "2   2022-01-21\n",
      "Name: dates, dtype: datetime64[ns] \n",
      "\n",
      "dates           datetime64[ns]\n",
      "value                    int64\n",
      "value32                  int32\n",
      "coord::point            object\n",
      "names           string[python]\n",
      "dtype: object\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>dates</th>\n",
       "      <th>value</th>\n",
       "      <th>value32</th>\n",
       "      <th>coord::point</th>\n",
       "      <th>names</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1964-01-01</td>\n",
       "      <td>10</td>\n",
       "      <td>10</td>\n",
       "      <td>POINT (1 2)</td>\n",
       "      <td>john</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1985-02-05</td>\n",
       "      <td>20</td>\n",
       "      <td>20</td>\n",
       "      <td>POINT (3 4)</td>\n",
       "      <td>eric</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2022-01-21</td>\n",
       "      <td>30</td>\n",
       "      <td>30</td>\n",
       "      <td>POINT (5 6)</td>\n",
       "      <td>judith</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       dates  value  value32 coord::point   names\n",
       "1 1964-01-01     10       10  POINT (1 2)    john\n",
       "2 1985-02-05     20       20  POINT (3 4)    eric\n",
       "3 2022-01-21     30       30  POINT (5 6)  judith"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "os.path\n",
    "sys.path.insert(0, 'C:\\\\Users\\\\phili\\\\github\\\\ntv-pandas')\n",
    "import ntv_pandas\n",
    "\n",
    "field_data = {'dates::datetime': ['1964-01-01', '1985-02-05', '2022-01-21']}\n",
    "tab_data   = {'index':           [1, 2, 3],\n",
    "              'dates::datetime': ['1964-01-01', '1985-02-05', '2022-01-21'], \n",
    "              'value':           [10, 20, 30],\n",
    "              'value32::int32':  [10, 20, 30],\n",
    "              'coord::point':    [[1,2], [3,4], [5,6]],\n",
    "              'names::string':   ['john', 'eric', 'judith']}\n",
    "\n",
    "field = Ntv.obj({':field': field_data})\n",
    "tab   = Ntv.obj({':tab'  : tab_data})\n",
    "\n",
    "# the DataFrame Connector is associated with Datatype 'tab' in dicobj \n",
    "sr = field.to_obj(format='obj', dicobj={'field': 'SeriesConnec'})\n",
    "df = tab.to_obj  (format='obj', dicobj={'tab': 'DataFrameConnec'})\n",
    "\n",
    "# pandas dtype conform to Ntv type\n",
    "print(sr, '\\n')\n",
    "print(df.dtypes)\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "14f66d41",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "df2 is identical to df ?  True\n"
     ]
    }
   ],
   "source": [
    "# the dataframe generated from NTV data from a first dataframe is identical to this first dataframe\n",
    "df2 = Ntv.obj(df).to_obj(format='obj', dicobj={'tab': 'DataFrameConnec'})\n",
    "print('df2 is identical to df ? ', df2.equals(df))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da9bf49f",
   "metadata": {},
   "source": [
    "## CSV data is enriched with NTV structures\n",
    "- Json format is equivalent to CSV format for tabular data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "bbba5cec",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Json format :\n",
      " {\"index\": [1, 2, 3], \"dates::date\": [\"1964-01-01\", \"1985-02-05\", \"2022-01-02\"], \"value\": [10, 20, 30], \"value32::int32\": [10, 20, 30], \"coord::point\": [[1, 2], [3, 4], {\":datetime\": \"2022-01-02T10:00:00\"}], \"names::string\": [\"john\", \"eric\", \"judith\"]}\n",
      "\n",
      "CSV format :\n",
      " index,dates::date,value,value32::int32,coord::point,names::string\n",
      "1,\"\"\"1964-01-01\"\"\",10,10,\"[1, 2]\",\"\"\"john\"\"\"\n",
      "2,\"\"\"1985-02-05\"\"\",20,20,\"[3, 4]\",\"\"\"eric\"\"\"\n",
      "3,\"\"\"2022-01-02\"\"\",30,30,\"{\"\":datetime\"\": \"\"2022-01-02T10:00:00\"\"}\",\"\"\"judith\"\"\"\n",
      "\n",
      "is NTV entity from CSV identical to the initial NTV entity ?  True\n"
     ]
    }
   ],
   "source": [
    "import csv\n",
    "tab = {'index':           [1, 2, 3],\n",
    "       'dates::date':     ['1964-01-01', '1985-02-05', date(2022, 1,2)], \n",
    "       'value':           [10, 20, 30],\n",
    "       'value32::int32':  [10, 20, 30],\n",
    "       'coord::point':    [[1,2], [3,4], datetime(2022, 1,2, 10)],\n",
    "       'names::string':   ['john', 'eric', 'judith']}\n",
    "ntv_tab = Ntv.obj(tab)\n",
    "print('Json format :\\n', ntv_tab)\n",
    "to_csv('test.csv', ntv_tab)\n",
    "f = open('test.csv', 'r')\n",
    "print('\\nCSV format :\\n', f.read())\n",
    "ntv_tab2 = from_csv('test.csv', single_tab=False)\n",
    "print('is NTV entity from CSV identical to the initial NTV entity ? ', ntv_tab == ntv_tab2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "878677ad",
   "metadata": {},
   "source": [
    "## NTV data can be created from entities of all types\n",
    "- the conversions are made from the defined connectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "57b9d9d6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "simple representation :  {\"dataframe::tab\": [{\"index\": [1, 2, 3], \"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"], \"value\": [10, 20, 30], \"value32::int32\": [10, 20, 30], \"coord::point\": [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], \"names::string\": [\"john\", \"eric\", \"judith\"]}, {\"index\": [1, 2, 3], \"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"], \"value\": [10, 20, 30], \"value32::int32\": [10, 20, 30], \"coord::point\": [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], \"names::string\": [\"john\", \"eric\", \"judith\"]}], \"series::field\": [[{\"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"]}]], \"coord::point\": [[1, 2], [3, 4], [5, 6]], \"name\": \"walter\"} \n",
      "\n",
      "json representation :\n",
      " {\"dataframe::tab\": [{\"index\": [1, 2, 3], \"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"], \"value\": [10, 20, 30], \"value32::int32\": [10, 20, 30], \"coord::point\": [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], \"names::string\": [\"john\", \"eric\", \"judith\"]}, {\"index\": [1, 2, 3], \"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"], \"value\": [10, 20, 30], \"value32::int32\": [10, 20, 30], \"coord::point\": [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], \"names::string\": [\"john\", \"eric\", \"judith\"]}], \"series::field\": [[{\"dates::datetime\": [\"1964-01-01T00:00:00.000\", \"1985-02-05T00:00:00.000\", \"2022-01-21T00:00:00.000\"]}]], \"coord::point\": [[1, 2], [3, 4], [5, 6]], \"name\": \"walter\"} \n",
      "\n",
      "data without conversion eg \"name\" :\n",
      " walter \n",
      "\n",
      "data with conversion eg \"dataframe\" :\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>dates</th>\n",
       "      <th>value</th>\n",
       "      <th>value32</th>\n",
       "      <th>coord::point</th>\n",
       "      <th>names</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1964-01-01</td>\n",
       "      <td>10</td>\n",
       "      <td>10</td>\n",
       "      <td>POINT (1 2)</td>\n",
       "      <td>john</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1985-02-05</td>\n",
       "      <td>20</td>\n",
       "      <td>20</td>\n",
       "      <td>POINT (3 4)</td>\n",
       "      <td>eric</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2022-01-21</td>\n",
       "      <td>30</td>\n",
       "      <td>30</td>\n",
       "      <td>POINT (5 6)</td>\n",
       "      <td>judith</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       dates  value  value32 coord::point   names\n",
       "1 1964-01-01     10       10  POINT (1 2)    john\n",
       "2 1985-02-05     20       20  POINT (3 4)    eric\n",
       "3 2022-01-21     30       30  POINT (5 6)  judith"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ntv = Ntv.obj({'dataframe::tab': [df, df2], 'series::field': [sr], 'coord::point': [[1,2], [3,4], [5,6]], 'name': 'walter'}, True)\n",
    "print('simple representation : ', repr(ntv), '\\n')\n",
    "\n",
    "# ntv is converted into json data\n",
    "print('json representation :\\n', ntv, '\\n')\n",
    "\n",
    "# ntv is converted into objects according to the chosen connectors\n",
    "data = ntv.to_obj(format='obj', dicobj={'tab': 'DataFrameConnec', 'field': 'SeriesConnec'})\n",
    "print('data without conversion eg \"name\" :\\n', data['name'], '\\n')\n",
    "print('data with conversion eg \"dataframe\" :')\n",
    "data['dataframe::tab'][0] # 'tab' type is converted into DataFrame object "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "68ff94da",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n",
      "dict_keys(['dataframe::tab', 'series::field', 'coord::point', 'name'])\n",
      "walter\n"
     ]
    }
   ],
   "source": [
    "print(type(data))\n",
    "print(data.keys())\n",
    "print(data['name'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78bf7679",
   "metadata": {},
   "source": [
    "## Template structure can be used\n",
    "- 'leaf' nodes (NtvSingle) are updated\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "d9d6bdcf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\"air quality measure\": {\"concentration\": {\"value min\": 3.51, \"value max\": 4.2}, \"unit\": \"mg/m3\", \"coordinates:point\": [4.1, 45.2], \"pollutant\": \"NO2\"}}\n"
     ]
    }
   ],
   "source": [
    "air_quality = Ntv.obj({'air quality measure':{'concentration': {'value min': 0, 'value max': 0}, \n",
    "                                              'unit': '', \n",
    "                                              'coordinates:point': None,\n",
    "                                              'pollutant': ''}})\n",
    "\n",
    "measure = [3.51, 4.2, 'mg/m3', [4.1, 45.2], 'NO2']\n",
    "air_quality.set_value(measure)\n",
    "\n",
    "print(air_quality)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d040ab3-cbea-4e0a-822e-6a055f938a76",
   "metadata": {},
   "source": [
    "## NTVtype can be extended\n",
    "\n",
    "- example of quantities with unit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "f8dac363-9136-4c03-a30d-ac8f7f1dfe21",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float kg\n"
     ]
    }
   ],
   "source": [
    "mass = Ntv.obj({'mass:float[kg]': 25})\n",
    "\n",
    "print(mass.ntv_type.base_name, mass.ntv_type.extension)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df51515d",
   "metadata": {},
   "source": [
    "## Custom types are allowed\n",
    "For example:\n",
    "- object defined by a list of parameters\n",
    "- object defined by a list of key/values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "2c313b51",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "measurement :  {\":$sensor\": [3.51, 4.2, \"mg/m3\", [4.1, 45.2]]}\n",
      "infos :  4.2 [4.1, 45.2] $sensor \n",
      "\n",
      "personage :  {\"main Breaking Bad character:$character\": {\"surname\": \"white\", \"first name\": \"walter\", \"alias\": \"heisenberg\"}}\n",
      "infos :  heisenberg $character\n"
     ]
    }
   ],
   "source": [
    "measurement = Ntv.obj({':$sensor': [3.51, 4.2, 'mg/m3', [4.1, 45.2]]})\n",
    "\n",
    "print('measurement : ', measurement)\n",
    "print('infos : ', measurement.val[1], measurement.val[3], measurement.type_str, '\\n')\n",
    "\n",
    "person = Ntv.obj({'main Breaking Bad character:$character': {'surname': 'white', 'first name': 'walter', 'alias': 'heisenberg'}})\n",
    "\n",
    "print('personage : ', person)\n",
    "print('infos : ', person.val['alias'], person.type_str)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e60672d",
   "metadata": {},
   "source": [
    "## NTV can be used with custom entities\n",
    "- custom data is integrated with two conversion methods : to_obj_ntv, to_json_ntv\n",
    "\n",
    "Example :\n",
    "- custom class : Sensor\n",
    "- custom type : '$sensor'\n",
    "- custom conversion class : SensorConnec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "028082b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "representation class Sensor :\n",
      " Sensor(name='sensor1', measurement=4.2, unit='mg/l', coord=[4, 42], date=datetime.datetime(2021, 2, 5, 0, 0)) \n",
      "\n"
     ]
    }
   ],
   "source": [
    "from dataclasses import dataclass\n",
    "import datetime\n",
    "\n",
    "# custom classes\n",
    "@dataclass\n",
    "class Sensor:\n",
    "    name: str\n",
    "    measurement: float\n",
    "    unit: str\n",
    "    coord: list\n",
    "    date: datetime.datetime\n",
    "\n",
    "# custom data\n",
    "val1 = Sensor('sensor1', 4.2, 'mg/l', [4,42], datetime.datetime(2021, 2, 5))\n",
    "val2 = Sensor('sensor1', 5.1, 'mg/l', [4,42], datetime.datetime(2021, 2, 10))\n",
    "val3 = [\"sensor2\", 4.2, \"mg/l\", [5, 42], '2021-04-06']\n",
    "\n",
    "# simple value\n",
    "print('representation class Sensor :\\n', val1, '\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "690cde2f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "representation NTV (to_json_ntv) :\n",
      " {\":$sensor\": [\"sensor1\", 4.2, \"mg/l\", [4, 42], \"2021-02-05T00:00:00\"]} \n",
      "\n",
      "reflexivity of conversion ?  True \n",
      "\n",
      "'first test' representation NTV :\n",
      " {\"campaign\": \"first test\", \"result::$sensor\": [[\"sensor1\", 4.2, \"mg/l\", [4, 42], \"2021-02-05T00:00:00\"], [\"sensor1\", 5.1, \"mg/l\", [4, 42], \"2021-02-10T00:00:00\"], [\"sensor2\", 4.2, \"mg/l\", [5, 42], \"2021-04-06\"]], \"date measure:datetime\": \"2012-01-10\"} \n",
      "\n",
      "'first test' representation with object :\n",
      " Sensor(name='sensor1', measurement=4.2, unit='mg/l', coord=[4, 42], date=datetime.datetime(2021, 2, 5, 0, 0))\n"
     ]
    }
   ],
   "source": [
    "class SensorConnec(NtvConnector):\n",
    "\n",
    "    clas_obj = 'Sensor'\n",
    "    clas_typ = '$sensor'\n",
    "\n",
    "    @staticmethod\n",
    "    def to_obj_ntv(ntv_value, **kwargs):\n",
    "        '''convert ntv_value into the return object'''\n",
    "        return Sensor(*ntv_value[0:4], datetime.datetime.fromisoformat(ntv_value[4]))\n",
    "    \n",
    "    @staticmethod\n",
    "    def to_json_ntv(self, name=None, typ=None):\n",
    "        ''' convert object into the NTV entity (value, name, type)'''\n",
    "        return ([self.name, self.measurement, self.unit, self.coord, self.date.isoformat()], None, '$sensor')\n",
    "\n",
    "ntv1 = Ntv.obj(val1)\n",
    "print('representation NTV (to_json_ntv) :\\n',ntv1, '\\n')\n",
    "val1_bis = ntv1.to_obj(format='obj')\n",
    "print('reflexivity of conversion ? ', val1_bis == val1, '\\n')\n",
    "\n",
    "# assembly value\n",
    "first_test = {'campaign': 'first test', 'result::$sensor': [val1, val2, val3], 'date measure:datetime': '2012-01-10'}\n",
    "first_test_ntv = Ntv.obj(first_test)\n",
    "print(\"'first test' representation NTV :\\n\",first_test_ntv, '\\n') \n",
    "\n",
    "first_test_obj = first_test_ntv.to_obj(format='obj', dicobj={'$sensor': 'SensorConnec'})\n",
    "print(\"'first test' representation with object :\\n\", first_test_obj[\"result::$sensor\"][0])"
   ]
  }
 ],
 "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.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}