#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ gen_bsky_pop_graph.py: Generates a graph of the total users on Bluesky in matplotlib using preformatted data from various sources. data_array is formatted in the style of "2024-01-31, 5", where the first element is the ISO-8601 date, and where the second element is the total population of Bluesky (existing accounts) at the end of each date listed (ie. at 23:59). Note that there may be a variance of about +/- 500 users between trackers and data sources. As the graph grows with time, there may be a need to amend the visibility or frequency of the ticks, locators, and data points/labels. """ __authors__ = "VintageNebula" __version__ = "1.4.0" __date__ = "2024-07-01" __status__ = "public" __license__ = "https://creativecommons.org/licenses/by/4.0/" from datetime import datetime import matplotlib.pyplot as plt import matplotlib.dates as mdates from matplotlib.ticker import FuncFormatter, MultipleLocator data_array = [ # The following portion of data is from "Bluesky and the AT Protocol: Usable Decentralized # Social Media" by Martin Kleppmann, available at https://arxiv.org/abs/2402.03239. Licensed # under a Creative Commons Attribution 4.0 International. For more details, please visit: # https://creativecommons.org/licenses/by/4.0/. "2022-11-17, 5", "2022-11-18, 10", "2022-11-22, 11", "2022-11-23, 16", "2022-11-24, 17", "2022-11-25, 18", "2022-11-26, 20", "2022-11-28, 21", "2022-11-29, 23", "2022-11-30, 32", "2022-12-01, 34", "2022-12-06, 35", "2022-12-07, 43", "2022-12-11, 44", "2022-12-14, 47", "2022-12-15, 51", "2022-12-16, 54", "2022-12-17, 55", "2022-12-18, 60", "2022-12-19, 61", "2022-12-26, 62", "2022-12-28, 63", "2023-01-02, 64", "2023-01-04, 71", "2023-01-05, 74", "2023-01-08, 75", "2023-01-15, 76", "2023-01-16, 79", "2023-01-17, 83", "2023-01-18, 90", "2023-01-19, 102", "2023-01-20, 110", "2023-01-21, 124", "2023-01-22, 129", "2023-01-23, 138", "2023-01-24, 150", "2023-01-25, 162", "2023-01-26, 171", "2023-01-27, 176", "2023-01-28, 186", "2023-01-29, 195", "2023-01-30, 196", "2023-01-31, 200", "2023-02-01, 204", "2023-02-02, 208", "2023-02-03, 228", "2023-02-04, 251", "2023-02-05, 259", "2023-02-06, 262", "2023-02-07, 271", "2023-02-08, 272", "2023-02-09, 274", "2023-02-10, 275", "2023-02-11, 277", "2023-02-12, 279", "2023-02-13, 282", "2023-02-15, 289", "2023-02-16, 311", "2023-02-17, 320", "2023-02-18, 333", "2023-02-19, 339", "2023-02-20, 342", "2023-02-21, 346", "2023-02-22, 356", "2023-02-23, 399", "2023-02-24, 432", "2023-02-25, 480", "2023-02-26, 489", "2023-02-27, 589", "2023-02-28, 657", "2023-03-01, 1037", "2023-03-02, 1387", "2023-03-03, 1814", "2023-03-04, 2175", "2023-03-05, 2326", "2023-03-06, 2590", "2023-03-07, 3012", "2023-03-08, 3321", "2023-03-09, 3530", "2023-03-10, 3650", "2023-03-11, 3738", "2023-03-12, 3817", "2023-03-13, 3958", "2023-03-14, 4040", "2023-03-15, 4175", "2023-03-16, 4276", "2023-03-17, 4360", "2023-03-18, 4480", "2023-03-19, 4542", "2023-03-20, 4582", "2023-03-21, 4677", "2023-03-22, 4769", "2023-03-23, 4808", "2023-03-24, 4835", "2023-03-25, 4962", "2023-03-26, 5118", "2023-03-27, 5271", "2023-03-28, 5378", "2023-03-29, 5439", "2023-03-30, 5496", "2023-03-31, 5529", "2023-04-01, 5557", "2023-04-02, 5578", "2023-04-03, 5591", "2023-04-04, 5605", "2023-04-05, 5689", "2023-04-06, 8638", "2023-04-07, 9721", "2023-04-08, 10692", "2023-04-09, 11362", "2023-04-10, 12631", "2023-04-11, 16742", "2023-04-12, 18918", "2023-04-13, 20113", "2023-04-14, 20879", "2023-04-15, 22430", "2023-04-16, 22915", "2023-04-17, 23467", "2023-04-18, 24767", "2023-04-19, 27032", "2023-04-20, 29214", "2023-04-21, 31143", "2023-04-22, 32424", "2023-04-23, 33812", "2023-04-24, 36111", "2023-04-25, 38685", "2023-04-26, 41019", "2023-04-27, 44898", "2023-04-28, 47857", "2023-04-29, 49482", "2023-04-30, 50889", "2023-05-01, 53005", "2023-05-02, 55407", "2023-05-03, 57866", "2023-05-04, 60682", "2023-05-05, 62957", "2023-05-06, 64488", "2023-05-07, 65603", "2023-05-08, 66991", "2023-05-09, 68692", "2023-05-10, 70405", "2023-05-11, 72024", "2023-05-12, 74092", "2023-05-13, 75707", "2023-05-14, 76753", "2023-05-15, 78369", "2023-05-16, 79726", "2023-05-17, 81022", "2023-05-18, 82391", "2023-05-19, 83675", "2023-05-20, 84743", "2023-05-21, 85637", "2023-05-22, 86684", "2023-05-23, 87947", "2023-05-24, 89557", "2023-05-25, 91497", "2023-05-26, 93535", "2023-05-27, 95253", "2023-05-28, 96773", "2023-05-29, 98251", "2023-05-30, 99987", "2023-05-31, 101338", "2023-06-01, 102654", "2023-06-02, 104158", "2023-06-03, 105294", "2023-06-04, 106333", "2023-06-05, 107579", "2023-06-06, 108848", "2023-06-07, 110673", "2023-06-08, 112332", "2023-06-09, 114476", "2023-06-10, 116586", "2023-06-11, 118734", "2023-06-12, 121434", "2023-06-13, 123227", "2023-06-14, 126806", "2023-06-15, 129687", "2023-06-16, 132298", "2023-06-17, 134480", "2023-06-18, 135731", "2023-06-19, 137075", "2023-06-20, 138298", "2023-06-21, 141762", "2023-06-22, 151647", "2023-06-23, 155776", "2023-06-24, 157947", "2023-06-25, 159946", "2023-06-26, 162409", "2023-06-27, 167285", "2023-06-28, 172214", "2023-06-29, 176846", "2023-06-30, 181867", "2023-07-01, 200827", "2023-07-03, 238471", "2023-07-04, 251396", "2023-07-05, 259349", "2023-07-06, 268928", "2023-07-07, 276477", "2023-07-08, 281645", "2023-07-09, 284877", "2023-07-10, 288558", "2023-07-11, 292067", "2023-07-12, 296804", "2023-07-13, 302133", "2023-07-14, 307084", "2023-07-15, 310799", "2023-07-16, 314339", "2023-07-17, 318395", "2023-07-18, 322076", "2023-07-19, 325355", "2023-07-20, 328298", "2023-07-21, 332764", "2023-07-22, 337710", "2023-07-23, 344879", "2023-07-24, 367953", "2023-07-25, 383160", "2023-07-26, 391736", "2023-07-27, 401711", "2023-07-28, 411697", "2023-07-29, 420797", "2023-07-30, 430719", "2023-07-31, 439198", "2023-08-01, 447195", "2023-08-02, 454872", "2023-08-03, 469502", "2023-08-04, 484070", "2023-08-05, 496008", "2023-08-06, 507967", "2023-08-07, 521424", "2023-08-08, 531986", "2023-08-09, 539387", "2023-08-10, 546222", "2023-08-11, 552927", "2023-08-12, 559759", "2023-08-13, 567581", "2023-08-14, 577712", "2023-08-15, 587345", "2023-08-16, 597619", "2023-08-17, 607273", "2023-08-18, 636040", "2023-08-19, 654944", "2023-08-20, 666279", "2023-08-21, 677758", "2023-08-22, 688076", "2023-08-23, 698621", "2023-08-24, 718741", "2023-08-25, 738193", "2023-08-26, 753897", "2023-08-27, 763237", "2023-08-28, 773600", "2023-08-29, 784464", "2023-08-30, 803706", "2023-08-31, 822901", "2023-09-01, 841077", "2023-09-02, 850866", "2023-09-03, 860899", "2023-09-04, 871627", "2023-09-05, 883238", "2023-09-06, 894014", "2023-09-07, 910577", "2023-09-08, 930818", "2023-09-09, 949826", "2023-09-10, 964057", "2023-09-11, 976140", "2023-09-12, 996149", "2023-09-13, 1011733", "2023-09-14, 1022749", "2023-09-15, 1032450", "2023-09-16, 1040703", "2023-09-17, 1049191", "2023-09-18, 1066408", "2023-09-19, 1119588", "2023-09-20, 1151096", "2023-09-21, 1173578", "2023-09-22, 1192489", "2023-09-23, 1205909", "2023-09-24, 1218449", "2023-09-25, 1231713", "2023-09-26, 1243960", "2023-09-27, 1255542", "2023-09-28, 1267029", "2023-09-29, 1288560", "2023-09-30, 1303208", "2023-10-01, 1318732", "2023-10-02, 1338100", "2023-10-03, 1355993", "2023-10-04, 1371872", "2023-10-05, 1387490", "2023-10-06, 1404672", "2023-10-07, 1419179", "2023-10-08, 1432002", "2023-10-09, 1446443", "2023-10-10, 1464752", "2023-10-11, 1482973", "2023-10-12, 1502252", "2023-10-13, 1522928", "2023-10-14, 1537435", "2023-10-15, 1550713", "2023-10-16, 1564478", "2023-10-17, 1577280", "2023-10-18, 1612246", "2023-10-19, 1640119", "2023-10-20, 1659872", "2023-10-21, 1674837", "2023-10-22, 1688403", "2023-10-23, 1703251", "2023-10-24, 1718698", "2023-10-25, 1732165", "2023-10-26, 1744019", "2023-10-27, 1755474", "2023-10-28, 1766314", "2023-10-29, 1779457", "2023-10-30, 1793435", "2023-10-31, 1805583", "2023-11-01, 1817179", "2023-11-02, 1830511", "2023-11-03, 1844526", "2023-11-04, 1857052", "2023-11-05, 1869838", "2023-11-06, 1884462", "2023-11-07, 1898650", "2023-11-08, 1910725", "2023-11-09, 1928932", "2023-11-10, 1947029", "2023-11-11, 1966765", "2023-11-12, 1986704", "2023-11-13, 2004950", "2023-11-14, 2015617", "2023-11-15, 2031851", "2023-11-16, 2048265", "2023-11-17, 2059696", "2023-11-18, 2078645", "2023-11-19, 2097062", "2023-11-20, 2117378", "2023-11-21, 2137926", "2023-11-22, 2151768", "2023-11-23, 2166409", "2023-11-24, 2182847", "2023-11-25, 2198920", "2023-11-26, 2212001", "2023-11-27, 2222298", "2023-11-28, 2245777", "2023-11-29, 2268580", "2023-11-30, 2280482", "2023-12-01, 2311151", "2023-12-02, 2333666", "2023-12-03, 2358166", "2023-12-04, 2382393", "2023-12-05, 2392344", "2023-12-06, 2412926", "2023-12-07, 2435814", "2023-12-08, 2458257", "2023-12-09, 2478499", "2023-12-10, 2487967", "2023-12-11, 2497384", "2023-12-12, 2505149", "2023-12-13, 2523938", "2023-12-14, 2532879", "2023-12-15, 2547664", "2023-12-16, 2565342", "2023-12-17, 2585309", "2023-12-18, 2607200", "2023-12-19, 2637705", "2023-12-20, 2654818", "2023-12-21, 2686305", "2023-12-22, 2704740", "2023-12-23, 2730707", "2023-12-24, 2752527", "2023-12-25, 2768380", "2023-12-26, 2787860", "2023-12-27, 2801853", "2023-12-28, 2815299", "2023-12-29, 2831920", "2023-12-30, 2851550", "2023-12-31, 2869398", "2024-01-01, 2889718", "2024-01-02, 2902171", "2024-01-03, 2915287", "2024-01-04, 2925511", "2024-01-05, 2934089", "2024-01-06, 2941155", "2024-01-07, 2960571", "2024-01-08, 2990248", "2024-01-09, 3008387", "2024-01-10, 3018955", "2024-01-11, 3026679", "2024-01-12, 3032916", "2024-01-13, 3038113", "2024-01-14, 3042987", "2024-01-15, 3047598", "2024-01-16, 3052120", "2024-01-17, 3056502", "2024-01-18, 3061184", "2024-01-19, 3065586", "2024-01-20, 3069868", "2024-01-21, 3074261", "2024-01-22, 3078572", "2024-01-23, 3082541", "2024-01-24, 3085972", "2024-01-25, 3089017", "2024-01-26, 3091891", "2024-01-27, 3094422", "2024-01-28, 3097124", "2024-01-29, 3100356", "2024-01-30, 3107039", "2024-01-31, 3121850", "2024-02-01, 3140008", "2024-02-02, 3154479", "2024-02-03, 3168299", # End of data supplied by Martin Kleppmann. # Missing data approximated using linear interpolation, Internet Archive. "2024-02-04, 3187980", "2024-02-05, 3207661", "2024-02-06, 3433226", "2024-02-07, 4088025", # Beginning of data gathered by jaz.bsky.social "2024-02-08, 4432203", "2024-02-09, 4570216", "2024-02-10, 4666798", "2024-02-11, 4757049", "2024-02-12, 4811068", "2024-02-13, 4849070", "2024-02-14, 4858312", "2024-02-15, 4881705", "2024-02-16, 4899886", "2024-02-17, 4916721", "2024-02-18, 4935407", "2024-02-19, 4952084", "2024-02-20, 4971871", "2024-02-21, 4991745", "2024-02-22, 5006053", "2024-02-23, 5019561", "2024-02-24, 5031247", "2024-02-25, 5044627", "2024-02-26, 5056553", "2024-02-27, 5067960", "2024-02-28, 5078594", "2024-02-29, 5090025", "2024-03-01, 5099009", "2024-03-02, 5107586", "2024-03-03, 5115734", "2024-03-04, 5123650", "2024-03-05, 5131674", "2024-03-06, 5139313", "2024-03-07, 5146813", "2024-03-08, 5154932", "2024-03-09, 5163543", "2024-03-10, 5171848", "2024-03-11, 5179454", "2024-03-12, 5187322", "2024-03-13, 5194968", "2024-03-14, 5203210", "2024-03-15, 5210243", "2024-03-16, 5216048", "2024-03-17, 5221716", "2024-03-18, 5226977", "2024-03-19, 5232757", "2024-03-20, 5239602", "2024-03-21, 5245770", "2024-03-22, 5251049", "2024-03-23, 5257039", "2024-03-24, 5262910", "2024-03-25, 5269076", "2024-03-26, 5274974", "2024-03-27, 5280278", "2024-03-28, 5286136", "2024-03-29, 5291439", "2024-03-30, 5296232", "2024-03-31, 5301249", "2024-04-01, 5305827", "2024-04-02, 5311023", "2024-04-03, 5316212", "2024-04-04, 5321206", "2024-04-05, 5325976", "2024-04-06, 5330463", "2024-04-07, 5372537", "2024-04-08, 5407180", "2024-04-09, 5421651", "2024-04-10, 5437582", "2024-04-11, 5455018", "2024-04-12, 5471866", "2024-04-13, 5489161", "2024-04-14, 5502621", "2024-04-15, 5511857", "2024-04-16, 5525560", "2024-04-17, 5533684", "2024-04-18, 5538455", "2024-04-19, 5542777", "2024-04-20, 5547038", "2024-04-21, 5551055", "2024-04-22, 5554821", "2024-04-23, 5558553", "2024-04-24, 5562221", "2024-04-25, 5565822", "2024-04-26, 5569364", "2024-04-27, 5572730", "2024-04-28, 5576184", "2024-04-29, 5580941", "2024-04-30, 5585312", "2024-05-01, 5589425", "2024-05-02, 5592993", "2024-05-03, 5596264", "2024-05-04, 5599579", "2024-05-05, 5602813", "2024-05-06, 5606518", "2024-05-07, 5609813", "2024-05-08, 5613117", "2024-05-09, 5616648", "2024-05-10, 5619937", "2024-05-11, 5623224", "2024-05-12, 5626214", "2024-05-13, 5629117", "2024-05-14, 5631856", "2024-05-15, 5634855", "2024-05-16, 5637786", "2024-05-17, 5640573", "2024-05-18, 5643671", "2024-05-19, 5646611", "2024-05-20, 5649426", "2024-05-21, 5652726", "2024-05-22, 5656077", "2024-05-23, 5660160", "2024-05-24, 5663423", "2024-05-25, 5666586", "2024-05-26, 5669773", "2024-05-27, 5674338", "2024-05-28, 5677825", "2024-05-29, 5681494", "2024-05-30, 5685029", "2024-05-31, 5695026", "2024-06-01, 5698531", "2024-06-02, 5701877", "2024-06-03, 5705411", "2024-06-04, 5708717", "2024-06-05, 5711829", "2024-06-06, 5714625", "2024-06-07, 5717341", "2024-06-08, 5804310", "2024-06-09, 5822411", "2024-06-10, 5829823", "2024-06-11, 5839512", "2024-06-12, 5856822", "2024-06-13, 5880617", "2024-06-14, 5890794", "2024-06-15, 5910786", "2024-06-16, 5924338", "2024-06-17, 5932536", "2024-06-18, 5938768", "2024-06-19, 5944088", "2024-06-20, 5948423", "2024-06-21, 5952514", "2024-06-22, 5956543", # Missing data approximated using linear interpolation. "2024-06-23, 5960099", "2024-06-24, 5963655", "2024-06-25, 5967211", "2024-06-26, 5970766", "2024-06-27, 5974322", "2024-06-28, 5977878", # Continuing data gathered by jaz.bsky.social. "2024-06-29, 5981434", "2024-06-30, 5984675", "2024-07-01, 5988217" ] # Parse dates and values from the data array. date_rng = [datetime.strptime(row.split(',')[0].strip(), "%Y-%m-%d") for row in data_array] y_values = [int(row.split(',')[1].replace(',', '').strip()) for row in data_array] # Create an initial plot, set the figure size. fig, ax = plt.subplots(figsize=(15, 9)) # Plot the main data line. ax.plot(date_rng, y_values, zorder=2) ax.fill_between(date_rng, y_values, color="skyblue", alpha=0.4, zorder=1) # Set the major and minor locators for x-axis; only show odd months (to avoid crowding) ax.xaxis.set_major_locator(mdates.MonthLocator(bymonth=[1, 3, 5, 7, 9, 11])) ax.xaxis.set_minor_locator(mdates.MonthLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m")) # Set the major and minor locators for y-axis. ax.yaxis.set_major_locator(MultipleLocator(1000000)) # Major ticks every 1,000,000 ax.yaxis.set_minor_locator(MultipleLocator(500000)) # Minor ticks every 500,000 # Format y-axis labels with commas (,) for large numbers. ax.yaxis.set_major_formatter(FuncFormatter(lambda x, _: f'{int(x):,}')) # Set ticks inside the plot and also on the opposite side, set axis label font size. ax.tick_params(axis='x', which='both', direction='in', top=True) ax.tick_params(axis='y', which='both', direction='in', right=True) ax.tick_params(axis='both', which='major', labelsize=12) # Make sure y-axis starts at 0. ax.set_ylim(bottom=0) # Enable background grid. ax.grid(True, linestyle=":", linewidth=0.5) # Hide y-axis offset number (1e6, etc.) ax.yaxis.offsetText.set_visible(False) # Highlight and label the first data point of each month. months = set() for date, value in zip(date_rng, y_values): if date.strftime("%Y-%m") not in months: ax.scatter(date, value, color='C0', marker='o', alpha=1, zorder=3) ax.annotate(f'{value:,}', (date, value), textcoords="offset points", xytext=(0, 5), ha='center', fontsize=10) # Smaller font size for annotations months.add(date.strftime("%Y-%m")) # Adjust layout and output plot. plt.tight_layout() plt.show()