Source code for pyfrag_plotter
import configparser as cp
import logging
import os
from typing import Optional
from pyfrag_plotter.config.config_handler import Config
# Global variable that contains the config file. It is first empty, but will be filled in the |init| function
config: Config = Config(cp.ConfigParser())
[docs]
def initialize_pyfrag_plotter(user_config_file: Optional[str] = None) -> None:
"""
Initializes the PyFrag plotter configuration.
This function reads the standard configuration file provided in the module and sets the config as a global variable
that is read throughout the program. The standard configuration can be overwritten by providing a custom configuration file.
Args:
user_config_file (Optional[str]): The path to a custom configuration file. If provided, the settings in this file
will overwrite the standard configuration. Defaults to None.
Returns:
None
Raises:
ValueError: If the log level specified in the configuration is invalid.
"""
global config
# Get the absolute path of the directory one level above the current directory
current_dir = os.path.abspath(os.path.dirname(__file__))
# Construct the path to the configuration file
config_file = os.path.join(current_dir, "config", "config.ini")
# Read the default config file
config_parser = cp.ConfigParser()
config_parser.read(config_file)
# Read the user config file if provided and overwrite the config file
if user_config_file is not None:
config_parser.read(user_config_file)
# Finally, check if all config keys are valid
# This it to make it easier for providing user-friendly error messages
config.overwrite_config(config_parser)
try:
logging.basicConfig(level=config.get("SHARED", "log_level"), format="%(levelname)s - %(message)s")
except ValueError:
logging.basicConfig(level="DEBUG", format="%(levelname)s - %(message)s")
logging.log(logging.WARNING, f"Invalid log level '{config.get('SHARED', 'log_level')}'. Using 'DEBUG' level for finding (input) mistakes.")
config.validate_config()
logging.log(logging.INFO, "The config file is valid")
# Initialize the log level and plot parameters
_initialize_plot_parameters()
logging.log(logging.INFO, "Initialized PyFrag plotter Succesfully")
def _initialize_plot_parameters() -> None:
"""
Applies plot-specific parameters to matplotlib.
This function is called by `initialize_pyfrag_plotter` and sets various parameters for matplotlib, such as the figure size,
font family, and font size. It also tries to use the interactive backend for matplotlib, and falls back to the non-interactive
backend if the interactive backend is not available.
Returns:
None
"""
import matplotlib as mpl
# In some occations matplotlib cannot use the interactive backend, so we try to use the non-interactive backend
try:
mpl.use("TkAgg")
import matplotlib.pyplot as plt
except ImportError:
mpl.use("Agg")
import matplotlib.pyplot as plt
# Get a list of available fonts of matplotlib
# import matplotlib.font_manager
# flist = matplotlib.font_manager.get_fontconfig_fonts()
# names = [matplotlib.font_manager.FontProperties(fname=fname).get_name() for fname in flist]
# print(names)
# mp.font_manager._rebuild()
# font = fp.FontProperties(fname=r"C:\\Windows\\Fonts\\Helvetica Regulier.ttf")
# print(font.get_name())
# Figure size
try: # Try to get the figure size from the config file
plt.rcParams["figure.figsize"] = config.get("MATPLOTLIB", "fig_size")
except ValueError:
plt.rcParams["figure.figsize"] = (8, 6)
logging.log(logging.WARNING, "No figure size specified in the config file. Using default figure size (8, 6).")
# Font family
font = "Arial"
try: # Try to get the font family from the config file
font = config.get("MATPLOTLIB", "font")
except ValueError:
logging.log(logging.WARNING, "No font family specified in the config file. Using default font family 'Arial'.")
plt.rcParams["font.family"] = font
# Takes care of ticks starting at the edge of the screen
# plt.rcParams["axes.autolimit_mode"] = "round_numbers"
plt.rcParams["axes.xmargin"] = 0.00
plt.rcParams["axes.ymargin"] = 0.00
# Font size for the text in the plot including the title, xticks, and yticks
try:
font_size = config.get("MATPLOTLIB", "font_size")
except ValueError:
font_size = 12
logging.log(logging.WARNING, "No font size specified in the config file. Using default value of 12.")
# Label font size for x and y axiss
try: # Try to get the label font size from the config file
label_font_size = config.get("MATPLOTLIB", "label_size")
except ValueError:
label_font_size = 12
logging.log(logging.WARNING, "No label font size specified in the config file. Using default value of 12.")
# Legend font size for within the plot
try: # Try to get the legend font size from the config file
legend_font_size = config.get("MATPLOTLIB", "legend_size")
except ValueError:
legend_font_size = 12
logging.log(logging.WARNING, "No legend font size specified in the config file. Using default value of 12.")
plt.rc("font", size=font_size) # controls default text sizes
plt.rc("xtick", labelsize=font_size - 2) # fontsize of the tick labels
plt.rc("ytick", labelsize=font_size - 2) # fontsize of the tick labels
plt.rc("figure", titlesize=font_size + 2) # fontsize of the figure title
plt.rc("axes", titlesize=label_font_size) # fontsize of the axes title
plt.rc("axes", labelsize=label_font_size) # fontsize of the x and y labels
plt.rc("legend", fontsize=legend_font_size) # legend fontsize
mpl.rcParams["mathtext.fontset"] = "custom"
mpl.rcParams["mathtext.rm"] = font
mpl.rcParams["mathtext.it"] = f"{font}:italic"
mpl.rcParams["mathtext.bf"] = f"{font}:bold"