{
"cells": [
{
"cell_type": "markdown",
"id": "1458258b",
"metadata": {},
"source": [
"# How to Connect and Query PostgreSQL for Python\n",
"\n",
"This provides and example of how to use Python and Jupyer notebooks on SWAN to connect and query PostgreSQL databases at CERN. The example provided is about generating frequency histograms using SQL.\n",
"\n",
"\n",
"## Setup and prerequisites\n",
"\n",
"Prerquites: you need to have credential to connect to an PostgreSQL database. It is recommended that you use a test account. Contact CERN Database on Demand service to request an account if needed."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "81411b15",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Defaulting to user installation because normal site-packages is not writeable\n",
"Requirement already satisfied: psycopg2-binary in /eos/home-c/canali/.local/lib/python3.9/site-packages (2.9.6)\n"
]
}
],
"source": [
"# This notebook uses psycopg2 to connect to PostgreSQL\n",
"# Install the driver\n",
"!pip install psycopg2-binary\n",
"\n",
"import psycopg2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "078ea1dc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"········\n"
]
}
],
"source": [
"# Edit DB credentials\n",
"import getpass\n",
"\n",
"db_user = 'myaccount' #edit\n",
"\n",
"# To avoid storing connection passwords use getpas or db_config\n",
"db_pass = getpass.getpass()\n",
"\n",
"db_name = 'testdb1'\n",
"\n",
"port = 6600\n",
"\n",
"host_name = 'dbod-mytestdb1.cern.ch' #edit"
]
},
{
"cell_type": "markdown",
"id": "c02081ce",
"metadata": {},
"source": [
"## Create the test table"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "e0ddaadb",
"metadata": {},
"outputs": [],
"source": [
"# Connect to an existing database and create the test table\n",
"\n",
"with psycopg2.connect(f\"dbname={db_name} user={db_user} host={host_name} port={port} password={db_pass}\") as pg_conn:\n",
" cur = pg_conn.cursor()\n",
" \n",
" # use this drop statement if you need to recreate the table\n",
" cur.execute(\"DROP TABLE if exists data\")\n",
"\n",
" cur.execute(\"CREATE TABLE data as select random()*100 random_value from generate_series(1, 100);\")"
]
},
{
"cell_type": "markdown",
"id": "b9337750",
"metadata": {},
"source": [
"## Define the query to compute the histogram"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "e844ab4d",
"metadata": {},
"outputs": [],
"source": [
"table_name = \"data\" # table or temporary view containing the data\n",
"value_col = \"random_value\" # column name on which to compute the histogram\n",
"min = -20 # min: minimum value in the histogram\n",
"max = 90 # maximum value in the histogram\n",
"bins = 11 # number of histogram buckets to compute\n",
"step = (max - min) / bins\n",
" \n",
"query = f\"\"\"\n",
"with hist as (\n",
" select \n",
" width_bucket({value_col}, {min}, {max}, {bins}) as bucket,\n",
" count(*) as cnt\n",
" from {table_name}\n",
" group by bucket\n",
"),\n",
"buckets as (\n",
" select generate_series as bucket from generate_series(1,{bins})\n",
")\n",
"select\n",
" bucket, {min} + (bucket - 0.5) * {step} as value,\n",
" coalesce(cnt, 0) as count\n",
"from hist right outer join buckets using(bucket)\n",
"order by bucket\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"id": "6b109925",
"metadata": {},
"source": [
"## Fetch the histogram data into a Pandas dataframe using SQLAlchemy"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "99b2ced8",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"from sqlalchemy import create_engine\n",
"\n",
"# create SQLAlchemy engine\n",
"engine = create_engine(f\"postgresql+psycopg2://{db_user}:{db_pass}@{host_name}:{port}/{db_name}\")\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e416e3c7",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
bucket
\n",
"
value
\n",
"
count
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
-15.0
\n",
"
0
\n",
"
\n",
"
\n",
"
1
\n",
"
2
\n",
"
-5.0
\n",
"
0
\n",
"
\n",
"
\n",
"
2
\n",
"
3
\n",
"
5.0
\n",
"
10
\n",
"
\n",
"
\n",
"
3
\n",
"
4
\n",
"
15.0
\n",
"
13
\n",
"
\n",
"
\n",
"
4
\n",
"
5
\n",
"
25.0
\n",
"
10
\n",
"
\n",
"
\n",
"
5
\n",
"
6
\n",
"
35.0
\n",
"
11
\n",
"
\n",
"
\n",
"
6
\n",
"
7
\n",
"
45.0
\n",
"
8
\n",
"
\n",
"
\n",
"
7
\n",
"
8
\n",
"
55.0
\n",
"
9
\n",
"
\n",
"
\n",
"
8
\n",
"
9
\n",
"
65.0
\n",
"
12
\n",
"
\n",
"
\n",
"
9
\n",
"
10
\n",
"
75.0
\n",
"
9
\n",
"
\n",
"
\n",
"
10
\n",
"
11
\n",
"
85.0
\n",
"
8
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" bucket value count\n",
"0 1 -15.0 0\n",
"1 2 -5.0 0\n",
"2 3 5.0 10\n",
"3 4 15.0 13\n",
"4 5 25.0 10\n",
"5 6 35.0 11\n",
"6 7 45.0 8\n",
"7 8 55.0 9\n",
"8 9 65.0 12\n",
"9 10 75.0 9\n",
"10 11 85.0 8"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# query Oracle using ora_conn and put the result into a pandas Dataframe\n",
"hist_pandasDF = pd.read_sql(query, engine)\n",
"\n",
"# Decription of the resulting dataframe\n",
"#\n",
"# BUCKET: the bucket number, range from 1 to bins (included)\n",
"# VALUE: midpoint value of the given bucket\n",
"# COUNT: number of values in the bucket \n",
"\n",
"hist_pandasDF\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "2c3b67b5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
bucket
\n",
"
value
\n",
"
count
\n",
"
frequency
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
1
\n",
"
-15.0
\n",
"
0
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
1
\n",
"
2
\n",
"
-5.0
\n",
"
0
\n",
"
0.000000
\n",
"
\n",
"
\n",
"
2
\n",
"
3
\n",
"
5.0
\n",
"
10
\n",
"
0.111111
\n",
"
\n",
"
\n",
"
3
\n",
"
4
\n",
"
15.0
\n",
"
13
\n",
"
0.144444
\n",
"
\n",
"
\n",
"
4
\n",
"
5
\n",
"
25.0
\n",
"
10
\n",
"
0.111111
\n",
"
\n",
"
\n",
"
5
\n",
"
6
\n",
"
35.0
\n",
"
11
\n",
"
0.122222
\n",
"
\n",
"
\n",
"
6
\n",
"
7
\n",
"
45.0
\n",
"
8
\n",
"
0.088889
\n",
"
\n",
"
\n",
"
7
\n",
"
8
\n",
"
55.0
\n",
"
9
\n",
"
0.100000
\n",
"
\n",
"
\n",
"
8
\n",
"
9
\n",
"
65.0
\n",
"
12
\n",
"
0.133333
\n",
"
\n",
"
\n",
"
9
\n",
"
10
\n",
"
75.0
\n",
"
9
\n",
"
0.100000
\n",
"
\n",
"
\n",
"
10
\n",
"
11
\n",
"
85.0
\n",
"
8
\n",
"
0.088889
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" bucket value count frequency\n",
"0 1 -15.0 0 0.000000\n",
"1 2 -5.0 0 0.000000\n",
"2 3 5.0 10 0.111111\n",
"3 4 15.0 13 0.144444\n",
"4 5 25.0 10 0.111111\n",
"5 6 35.0 11 0.122222\n",
"6 7 45.0 8 0.088889\n",
"7 8 55.0 9 0.100000\n",
"8 9 65.0 12 0.133333\n",
"9 10 75.0 9 0.100000\n",
"10 11 85.0 8 0.088889"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Optionally normalize the event count into a frequency\n",
"# dividing by the total number of events\n",
" \n",
"hist_pandasDF[\"frequency\"] = hist_pandasDF[\"count\"] / sum(hist_pandasDF[\"count\"]) \n",
" \n",
"hist_pandasDF\n"
]
},
{
"cell_type": "markdown",
"id": "95f6a268",
"metadata": {},
"source": [
"## Histogram plotting\n",
"The first plot is a histogram with the event counts (number of events per bin). The second plot is a histogram of the events frequencies (number of events per bin normalized by the sum of the events)."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "3fdf5ab1",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"