I want to create a log-log plot showing the growth of publications over time (papers/year), similar to scientific figures like Fig. 1a in "A Century of Physics" (Nature Physics 2015). Requirements: Y-axis (number of papers) on a log scale (10²–10⁶) with ticks at each power of 10. X-axis (year) with decade ticks (e.g., 1960, 1970, 1980...). Multiple vertical dashed lines indicating important trend changes. Serif font, light dashed grid, no top/right spines. Line colors and styles similar to journal figures (e.g., matplotlib, Seaborn). A panel label (e.g., "Web of Science") at the top left. How can I best style my matplotlib plot to match this? The following is what I did (in Python): #!/usr/bin/env python3 """ replicate_figure1a_misinformation.py Count the yearly number of WoS publications (total) versus the number of misinformation publications (from combined_journals.xlsx) from 1960 to 2024, and plot both curves (log‐scale) to reproduce “Figure 1 | The Evolution of Physics” analogous to Sinatra et al. """ import os import gzip import xml.etree.ElementTree as ET from lxml import etree import pandas as pd import matplotlib.pyplot as plt # 1) Configuration # ────────────────────────────────────────────────────────── # Path to your combined misinformation Excel file MISINFO_XLSX = 'combined_journals.xlsx' # Root directory containing files like 1960.xml.gz … 2024.xml.gz WOS_DIR = '/Users/DataSets/Documents/DataSets/WoS/merged_yearly' # Years to include in the plot START_YEAR = 1960 END_YEAR = 2024 YEARS = list(range(START_YEAR, END_YEAR + 1)) # 2) Load misinformation paper counts by year # ────────────────────────────────────────────────────────── misinfo_df = pd.read_excel(MISINFO_XLSX, dtype={'UT (Unique WOS ID)': str, 'Publication Year': int, 'WoS Categories': str}) # ensure only years in our window misinfo_df = misinfo_df[ (misinfo_df['Publication Year'] >= START_YEAR) & (misinfo_df['Publication Year'] <= END_YEAR) ] # count unique UT per year mis_counts = ( misinfo_df .drop_duplicates(subset='UT (Unique WOS ID)') .groupby('Publication Year') .size() .reindex(YEARS, fill_value=0) .to_dict() ) print(f"Loaded misinformation counts for {len(mis_counts)} years") # 3) Parse WoS XML to get total counts per year # ────────────────────────────────────────────────────────── total_counts = {yr: 0 for yr in YEARS} for yr in YEARS: gz_path = os.path.join(WOS_DIR, f'{yr}.xml.gz') if not os.path.exists(gz_path): continue with gzip.open(gz_path, 'rb') as f: # directly enable recovery and huge_tree here for _, rec in etree.iterparse( f, events=('end',), tag='REC', recover=True, huge_tree=True ): total_counts[yr] += 1 rec.clear() # 4) Build DataFrame and plot # ────────────────────────────────────────────────────────── df_counts = pd.DataFrame({ 'Year': YEARS, 'WoS total': [total_counts[yr] for yr in YEARS], 'Misinformation': [mis_counts.get(yr, 0) for yr in YEARS], }) df_counts.set_index('Year', inplace=True) plt.figure(figsize=(10, 6)) # plt.plot(df_counts.index, df_counts['WoS total'], label='WoS total papers') plt.plot(df_counts.index, df_counts['Misinformation'], label='Web of Science') plt.yscale('log') plt.xlabel('Year') plt.ylabel('Number of papers') plt.title('The Evolution of Misinformation (1960–2024)') plt.legend() plt.grid(True, which='both', linestyle='--', alpha=0.3) plt.tight_layout() # To save the figure instead of showing: plt.savefig('figure1a_misinformation.png', dpi=600) # Or to display: # plt.show() Attached is my plot and the plot of the article I am trying to replicate exactly same. Continue reading...