{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# hbase data\n", "![hbase](https://hbase.apache.org/images/hbase_logo_with_orca_large.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. set hbase client\n", "Before running this cell, you need to create a .env file in the same directory as this notebook, and set the following environment variables in the .env file:\n", "```.env\n", "HBASE_FETCH_API = \n", "HBASE_SEND_API = \n", "HBASE_TOKEN = \n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import logging\n", "import os\n", "\n", "import geopandas as gpd\n", "import nest_asyncio\n", "from dotenv import load_dotenv\n", "\n", "from h3_toolkit.core import H3Toolkit\n", "\n", "logging.basicConfig(level=logging.INFO)\n", "\n", "load_dotenv()\n", "nest_asyncio.apply() # needed for jupyter notebook to run asyncio\n", "FETCH_API = os.getenv(\"HBASE_FETCH_API\")\n", "SEND_API = os.getenv(\"HBASE_SEND_API\")\n", "TOKEN = os.getenv(\"HBASE_TOKEN\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from h3_toolkit.hbase import HBaseClient\n", "\n", "toolkit = H3Toolkit()\n", "toolkit.set_hbase_client(\n", " HBaseClient(\n", " fetch_url=FETCH_API,\n", " send_url=SEND_API,\n", " token = TOKEN,\n", " max_concurrent_requests=5, # don't change this\n", " chunk_size=1000, # don't change this\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "HBaseClient(\n", " fetch_url = http://10.100.1.64:2891/api/hbase/v1/test/filterdata2, \n", " send_url = http://10.100.1.64:2891/api/hbase/v1/test/putdata, \n", " token = eyJhb*********************************************************************************************X-H5I, \n", " max_concurrent_requests = 5, \n", " chunk_size = 1000\n", ")" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Check for setting hbase client correctly\n", "toolkit.hbase_client" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Select boundary of the data" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "gdf = gpd.read_file('data/test_geom.geojson')\n", "merged_geometry = gdf['geometry'].union_all()\n", "\n", "new_gdf = gpd.GeoDataFrame(geometry=[merged_geometry], crs= gdf.crs)\n", "new_gdf.plot(edgecolor='red', facecolor='none')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:h3_toolkit.core:2025-06-18 09:51:06 - `process_from_vector` - Start converting data to h3 cells in resolution 12\n", "INFO:h3_toolkit.core:2025-06-18 09:51:06 - `process_from_vector` - Finish converting data to h3 cells in resolution 12 with shape (42080, 1)\n" ] }, { "data": { "text/html": [ "
\n", "shape: (5, 1)
hex_id
str
"8c4ba0a406403ff"
"8c4ba0a406411ff"
"8c4ba0a406413ff"
"8c4ba0a406415ff"
"8c4ba0a406417ff"
" ], "text/plain": [ "shape: (5, 1)\n", "\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n", "\u2502 hex_id \u2502\n", "\u2502 --- \u2502\n", "\u2502 str \u2502\n", "\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n", "\u2502 8c4ba0a406403ff \u2502\n", "\u2502 8c4ba0a406411ff \u2502\n", "\u2502 8c4ba0a406413ff \u2502\n", "\u2502 8c4ba0a406415ff \u2502\n", "\u2502 8c4ba0a406417ff \u2502\n", "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result = (\n", " toolkit\n", " .process_from_vector(\n", " data = new_gdf,\n", " resolution = 12,\n", " geometry_col = 'geometry'\n", " )\n", ")\n", "\n", "result.get_result().head()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:h3_toolkit.hbase:2025-06-18 09:51:06 - `fetch_from_hbase` - Start fetching data from HBase\n", "Fetching data from Hbase ... : 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 43/43 [00:00<00:00, 7413.78chunk/s]\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:08 - `fetch_from_hbase` - Finish fetching data from HBase\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hex_idf_cntm_cntp_cntgeometry
08c4ba0a406403ff0.5670.5671.133POLYGON ((121.52403 25.03519, 121.52401 25.035...
18c4ba0a406411ff0.5670.5671.133POLYGON ((121.52431 25.03532, 121.5243 25.0352...
28c4ba0a406413ff0.5670.5671.133POLYGON ((121.52449 25.03531, 121.52447 25.035...
38c4ba0a406415ff0.5670.5671.133POLYGON ((121.5242 25.03518, 121.52419 25.0350...
48c4ba0a406417ff0.5670.5671.133POLYGON ((121.52438 25.03518, 121.52436 25.035...
\n", "
" ], "text/plain": [ " hex_id f_cnt m_cnt p_cnt \\\n", "0 8c4ba0a406403ff 0.567 0.567 1.133 \n", "1 8c4ba0a406411ff 0.567 0.567 1.133 \n", "2 8c4ba0a406413ff 0.567 0.567 1.133 \n", "3 8c4ba0a406415ff 0.567 0.567 1.133 \n", "4 8c4ba0a406417ff 0.567 0.567 1.133 \n", "\n", " geometry \n", "0 POLYGON ((121.52403 25.03519, 121.52401 25.035... \n", "1 POLYGON ((121.52431 25.03532, 121.5243 25.0352... \n", "2 POLYGON ((121.52449 25.03531, 121.52447 25.035... \n", "3 POLYGON ((121.5242 25.03518, 121.52419 25.0350... \n", "4 POLYGON ((121.52438 25.03518, 121.52436 25.035... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import polars as pl\n", "\n", "result = (\n", " toolkit\n", " .fetch_from_hbase(\n", " table_name = 'res12_pre_data',\n", " column_family = 'demographic',\n", " column_qualifier = ['p_cnt', 'f_cnt', 'm_cnt'],\n", " )\n", "\n", " # Convert str to float and round to 3 decimal places\n", " .apply(lambda df: df.with_columns([pl.col(pl.Utf8).exclude('hex_id').cast(pl.Float64).round(3)]))\n", ")\n", "\n", "result.get_result(return_geometry=True).head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Chain all steps together" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:h3_toolkit.core:2025-06-18 09:51:08 - `process_from_vector` - Start converting data to h3 cells in resolution 12\n", "INFO:h3_toolkit.core:2025-06-18 09:51:08 - `process_from_vector` - Finish converting data to h3 cells in resolution 12 with shape (42080, 1)\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:08 - `fetch_from_hbase` - Start fetching data from HBase\n", "Fetching data from Hbase ... : 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 43/43 [00:00<00:00, 9300.01chunk/s]\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:09 - `fetch_from_hbase` - Finish fetching data from HBase\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hex_idp_cntgeometry
08c4ba0a406403ff1.133POLYGON ((121.52403 25.03519, 121.52401 25.035...
18c4ba0a406411ff1.133POLYGON ((121.52431 25.03532, 121.5243 25.0352...
28c4ba0a406413ff1.133POLYGON ((121.52449 25.03531, 121.52447 25.035...
38c4ba0a406415ff1.133POLYGON ((121.5242 25.03518, 121.52419 25.0350...
48c4ba0a406417ff1.133POLYGON ((121.52438 25.03518, 121.52436 25.035...
\n", "
" ], "text/plain": [ " hex_id p_cnt geometry\n", "0 8c4ba0a406403ff 1.133 POLYGON ((121.52403 25.03519, 121.52401 25.035...\n", "1 8c4ba0a406411ff 1.133 POLYGON ((121.52431 25.03532, 121.5243 25.0352...\n", "2 8c4ba0a406413ff 1.133 POLYGON ((121.52449 25.03531, 121.52447 25.035...\n", "3 8c4ba0a406415ff 1.133 POLYGON ((121.5242 25.03518, 121.52419 25.0350...\n", "4 8c4ba0a406417ff 1.133 POLYGON ((121.52438 25.03518, 121.52436 25.035..." ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from h3_toolkit import H3Toolkit\n", "from h3_toolkit.hbase import HBaseClient\n", "\n", "toolkit = H3Toolkit()\n", "\n", "result = (\n", " toolkit\n", " .process_from_vector(\n", " data = new_gdf,\n", " resolution = 12,\n", " geometry_col = 'geometry'\n", " )\n", " .set_hbase_client(\n", " HBaseClient(\n", " fetch_url=FETCH_API,\n", " send_url=SEND_API,\n", " token = TOKEN,\n", " max_concurrent_requests=5, # don't change this\n", " chunk_size=200000, # don't change this\n", " )\n", " )\n", " .fetch_from_hbase(\n", " table_name = 'res12_pre_data',\n", " column_family = 'demographic',\n", " column_qualifier = ['p_cnt'],\n", " )\n", " .apply(lambda df: df.with_columns([pl.col(pl.Utf8).exclude('hex_id').cast(pl.Float64).round(3)]))\n", " .get_result(return_geometry=True)\n", ")\n", "\n", "result.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. fetch data from hbase and aggregate new data back to hbase\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:h3_toolkit.core:2025-06-18 09:51:09 - `process_from_vector` - Start converting data to h3 cells in resolution 12\n", "INFO:h3_toolkit.core:2025-06-18 09:51:09 - `process_from_vector` - Finish converting data to h3 cells in resolution 12 with shape (42080, 1)\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:09 - `fetch_from_hbase` - Start fetching data from HBase\n", "Fetching data from Hbase ... : 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 43/43 [00:00<00:00, 9797.11chunk/s]\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:10 - `fetch_from_hbase` - Finish fetching data from HBase\n", "INFO:h3_toolkit.core:2025-06-18 09:51:10 - `process_from_h3` - Start converting data to h3 cells in resolution 10\n", "INFO:h3_toolkit.core:2025-06-18 09:51:10 - `process_from_h3` - Finish converting data to h3 cells in resolution 10 with shape (937, 4)\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:10 - `send_to_hbase` - Start sending data from HBase\n", "Sending data to Hbase ... : 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1/1 [00:00<00:00, 587.85chunk/s]\n", "INFO:h3_toolkit.hbase:2025-06-18 09:51:10 - `send_to_hbase` - Finish sending data from HBase\n" ] }, { "data": { "text/html": [ "
\n", "shape: (5, 4)
hex_idf_cntp_cntm_cnt
strf64f64f64
"8a4ba0a4330ffff"464.757898.6068.854
"8a4ba0a412d7fff"271.692484.1744.336
"8a4ba0a4ecf7fff"283.727542.5685.282
"8a4ba0a4e0e7fff"329.451626.5956.064
"8a4ba0a4155ffff"0.00.00.0
" ], "text/plain": [ "shape: (5, 4)\n", "\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n", "\u2502 hex_id \u2506 f_cnt \u2506 p_cnt \u2506 m_cnt \u2502\n", "\u2502 --- \u2506 --- \u2506 --- \u2506 --- \u2502\n", "\u2502 str \u2506 f64 \u2506 f64 \u2506 f64 \u2502\n", "\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n", "\u2502 8a4ba0a4330ffff \u2506 464.757 \u2506 898.606 \u2506 8.854 \u2502\n", "\u2502 8a4ba0a412d7fff \u2506 271.692 \u2506 484.174 \u2506 4.336 \u2502\n", "\u2502 8a4ba0a4ecf7fff \u2506 283.727 \u2506 542.568 \u2506 5.282 \u2502\n", "\u2502 8a4ba0a4e0e7fff \u2506 329.451 \u2506 626.595 \u2506 6.064 \u2502\n", "\u2502 8a4ba0a4155ffff \u2506 0.0 \u2506 0.0 \u2506 0.0 \u2502\n", "\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from h3_toolkit import H3Toolkit\n", "from h3_toolkit.aggregation import Mean, SumUp\n", "from h3_toolkit.hbase import HBaseClient\n", "\n", "toolkit = H3Toolkit()\n", "\n", "result = (\n", " toolkit\n", " .process_from_vector(\n", " data = new_gdf,\n", " resolution = 12,\n", " geometry_col = 'geometry'\n", " )\n", " .set_hbase_client(\n", " HBaseClient(\n", " fetch_url=FETCH_API,\n", " send_url=SEND_API,\n", " token = TOKEN,\n", " )\n", " )\n", " .fetch_from_hbase(\n", " table_name = 'res12_pre_data',\n", " column_family = 'demographic',\n", " column_qualifier = ['p_cnt', 'f_cnt', 'm_cnt'],\n", " )\n", " .set_aggregation_strategy(\n", " {\n", " ('f_cnt', 'p_cnt'): SumUp(),\n", " 'm_cnt': Mean(),\n", " }\n", " )\n", " .process_from_h3(\n", " target_resolution= 10,\n", " )\n", " .apply(lambda df: df.with_columns([pl.col(pl.Float64).round(3)]))\n", " .send_to_hbase(\n", " table_name = 'res10_test_data',\n", " column_family = 'demographic',\n", " column_qualifier = ['p_cnt'],\n", " )\n", " .get_result()\n", ")\n", "\n", "result.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Visualization\n", "\n", "Visualize the fetched H3 data using pydeck with automatic map boundary calculation." ], "id": "viz_intro" }, { "cell_type": "code", "execution_count": null, "metadata": {}, "source": [ "from h3_toolkit.visualization import show_h3\n", "\n", "# Visualize the fetched data\n", "# Using Quantiles classifier with k=5 and viridis colormap\n", "show_h3(\n", " result,\n", " 'p_cnt',\n", " classifier='Quantiles',\n", " k=5,\n", " cmap='viridis'\n", ")" ], "outputs": [], "id": "viz_example" } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.10.12" } }, "nbformat": 4, "nbformat_minor": 2 }