I'm in a collective that started a petition asking for a referendum about (generative) AI.
We wanted a graphic of the evolution of votes according to time, so I hacked something together.
You can see the result here
I store the data in a two-column CSV file (the columns are datetime and
sigcount). The file is updated via a simple bash script.
The script basically gets the number of votes from the graphql API, then
filters the interesting value with jq (a json querying command), and
sticks it with the current date and time. Here it is :
[update_signatures_database.sh]
#!/bin/bash
# working path
WPATH="/home/oskar/projects/petition_signatures_count"
# current number of votes from petitions.lecese.fr
nbvotes=$(curl -sSH "Content-Type: application/json" -d '{ "query": "{ initiatives { id title { translations { locale text } } onlineVotes } }" }' "https://petitions.lecese.fr/api" | jq ".data.initiatives.[] | select(.id == \"821\") | .onlineVotes")
# line to write
csvline=$(TZ='Europe/Paris' date '+%Y-%m-%d %H:%M:%S'),$nbvotes
# actualy update the database
echo $csvline >> "$WPATH/database.csv"
Then, I used cron to run this every hour :
*/30 * * * * cd /home/oskar/projects/petition_signatures_count/ ; ./update_signatures_database.sh
I use plotly to plot the graph because it can easily output html files, and because it really easy to use with pandas (that I use to read the csv).
This code is a simplified version of what I use, you can see the real code in tilde.town, at
projects/petition_signatures_count/write_plot.py.
[write_plot.py]
#!env/bin/python3
import plotly.express as px
import pandas as pd
df = pd.read_csv("database.csv")
df.datetime = pd.to_datetime(df.datetime)
df.sort_values(by="datetime")
fig = px.line(df, x="datetime", y="sigcount")
fig.write_html("out/graphique.html")
In order for the graph to update with the data, I simply execute the python
code after each update of the databse. That is done by adding the following
line at the end of update_signatures_database.sh :
$WPATH/env/bin/python3 $WPATH/write_plot.py
I added display details, such as colors, markers for datapoints, french formatting of the dates, and better display of date and time when the mouse hovers a point.
Here is the full code :
#!env/bin/python3
import plotly.express as px
import pandas as pd
df = pd.read_csv("database.csv")
df.datetime = pd.to_datetime(df.datetime)
# stable (timsort ?), should be better for mostly-sorted data
df.sort_values(by="datetime", kind="stable")
fig = px.line(df, x="datetime", y="sigcount",
title="Nombre de signatures",
template="plotly_dark",
line_shape="linear",
markers=True,
)
fig.update_traces(
marker=dict(size=3, symbol="circle"),
line=dict(color="#80C800", width=1),
)
fig.update_xaxes(tickformat="%d/%m/%Y")
fig.update_traces(hovertemplate="<b>%{y}</b> signatures<br>Le %{x|%d/%m/%Y<br>À %H:%M:%S}")
fig.write_html("/home/oskar/public_html/posts/projects/signatures_plot/plot.html")