import os import sys import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import re def main(input_directory, pattern, kind): # Set draw_unchanged to True if 'draw_unchanged' file exists in # the current directory, else False. If true add a bar for # unchanged draw_unchanged = os.path.exists('draw_unchanged') # Initialize counters improvements = 0 deteriorations = 0 unchanged = 0 # Include the '*_DELTA_*.xml3.csv' part in the pattern full_pattern = f'{pattern}_DELTA_.*\.xmlv3\.csv' # Load all *_DELTA_*.xml3.csv files into a single DataFrame for filename in os.listdir(input_directory): if re.match(full_pattern, filename): filepath = os.path.join(input_directory, filename) df = pd.read_csv(filepath) # Count improvements, deteriorations, and unchanged values improvements += df[kind].gt(0).sum() deteriorations += df[kind].lt(0).sum() unchanged += df[kind].eq(0).sum() # If pattern is of the form '(\d+)_.*', the data is by task # number. Otherwise if pattern is of the form '.*(\d+)', the data # is by CPU load. subtitle = '' match = re.match(r'(\d+)_.*', pattern) if match: subtitle = f"Task sets with {match.group(1)} Tasks" elif (match := re.match(r'[^\d]*(\d+)$', pattern)): subtitle = f"Task sets with {match.group(1)}% CPU load" # Adjusting the title to include subtitle if it's not empty plot_title = 'Counts of Missed Deadlines (PCP vs PPCP)' if subtitle: plot_title += f"\n{subtitle}" # Add the subtitle on a new line if it's not empty print (plot_title) # Create a bar graph plt.figure(figsize=(10, 6)) if draw_unchanged: plt.bar(['Improvements', 'Deteriorations', 'Unchanged'], [improvements, deteriorations, unchanged]) else: plt.bar(['Improvements', 'Deteriorations'], [improvements, deteriorations]) # Increase font size for title and axes labels title_fontsize = 16 # Adjust this size as needed axes_label_fontsize = 14 # Adjust this size as needed plt.title(plot_title, fontsize=title_fontsize) plt.xlabel('Difference Categories', fontsize=axes_label_fontsize) plt.ylabel('Count', fontsize=axes_label_fontsize) # Adjust the tick parameters plt.xticks(rotation=0, fontsize=12) # Adjust fontsize as needed plt.yticks(fontsize=12) # Adjust fontsize as needed # Adjusting grid and removing margins plt.grid(axis='y', linestyle='--', alpha=0.7) plt.margins(x=0, y=0) # This reduces the margins around the plot # We want the plot to be tightly fitted plt.tight_layout() if draw_unchanged: bar_values = [improvements, deteriorations, unchanged] else: bar_values = [improvements, deteriorations] # Set threshold for placing annotations inside the bars threshold = 0.9 * plt.gca().get_ylim()[1] # 90% of y-axis limit # Display the counts on top of each bar for i, v in enumerate(bar_values): # Check if the bar is high enough to place annotation inside if v > threshold: # Place annotation inside the bar near the top vertical_alignment = 'top' y_offset = -0.05 * plt.gca().get_ylim()[1] # Slight offset from the top text_color = 'white' else: # Place annotation above the bar vertical_alignment = 'bottom' y_offset = 0.02 * plt.gca().get_ylim()[1] # Slight offset above the bar text_color = 'black' plt.text(i, v + y_offset, str(v), ha='center', va=vertical_alignment, color=text_color) #plt.text(i, v + 0.2, str(v), ha='center', va='bottom') # Save the plot as a PNG figure in the same directory clean_pattern = re.sub(r'[^a-zA-Z0-9_]', '', pattern) if draw_unchanged: output_filename = f'missed_deadline_counts_{kind}_{clean_pattern}.png' else: output_filename = f'missed_deadline_counts_{kind}_{clean_pattern}_no_unchanged.png' output_filepath = os.path.join(input_directory, output_filename) plt.savefig(output_filepath) # Show the plot #plt.show() if __name__ == "__main__": if len (sys.argv) < 1 or len(sys.argv) > 3: print("Usage: python script.py [ input_directory [pattern] ]") sys.exit(1) kind = "missed" input_directory = sys.argv[1] if len(sys.argv) > 1 else '.' pattern = sys.argv[2] if len(sys.argv) > 2 else '.*' print (kind, input_directory, pattern) main (input_directory, pattern, kind)