PtolemyGUI/frecsoTools/extractData.py
2025-02-27 13:15:56 -05:00

246 lines
7.6 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
s = float(sys.argv[1])
filename = sys.argv[2]
if len(sys.argv) < 3:
print("Error: Not enough arguments provided.")
print("Usage: ./{sys.argv[0]} spin filename")
sys.exit(1)
#####################################################
import numpy as np
import re
import numpy as np
def extract_s_matrix_data(filename):
pattern = r"S-matrix\s+\d+\s*=\s*([\-\d\.]+)\s+([\-\d\.]+)\s+for\s+L=\s*(\d+),\s+J=\s*([\d\.]+)"
# List to store results
results = []
# Variables to track the first and last "S-matrix" line
start_line = None
end_line = None
# Read the file and process line by line
with open(filename, 'r') as file:
lines = file.readlines()
for i, line in enumerate(lines):
if "S-matrix" in line:
# Track the first and last occurrence of "S-matrix"
if start_line is None:
start_line = i
end_line = i # Keep updating to the latest occurrence
# Extract S-matrix data if the line matches the pattern
match = re.search(pattern, line)
if match:
real_part = float(match.group(1))
imag_part = float(match.group(2))
l_value = int(match.group(3))
j_value = float(match.group(4))
# Form a tuple and append to results
results.append([real_part, imag_part, l_value, j_value])
print(f"First 'S-matrix' at line: {start_line + 1}")
print(f"Last 'S-matrix' at line: {end_line + 1}")
return results
def remove_duplicates(data):
# Sort data by L-value, then J-value
data.sort(key=lambda x: (x[2], x[3])) # Sort by L (index 2), then J (index 3)
# Create a new list to store unique elements
unique_data = []
# Iterate over the data to remove duplicates
for i, item in enumerate(data):
# Add the first item or if the current item is not equal to the last added
if i == 0 or item != data[i - 1]:
unique_data.append(item)
return unique_data
def group_data_by_s(data, s):
# Initialize a dictionary for each group corresponding to J = L - s, ..., L + s
groups = {J: [] for J in np.arange(-s, s+1, 1.0)} # Group indices from -s to s
# Iterate over the data and assign to the appropriate groups
for entry in data:
real_part, imaginary_part, L, J = entry
# Check if J matches any value in the range L-s to L+s
for offset in np.arange(-s, s+1, 1.0): # offset from -s to s, step 1
if round(J, 1) == round(L + offset, 1):
groups[offset].append(entry)
for key in groups:
groups[key].sort(key=lambda x: x[2])
# Find the maximum L in each group
max_L_in_groups = {key: max(entry[2] for entry in value) for key, value in groups.items()}
# Find the smallest maximum L across all groups
smallest_max_L = min(max_L_in_groups.values())
return groups, smallest_max_L
SMdata = extract_s_matrix_data(filename)
SMdata = remove_duplicates(SMdata)
grouped_SMdata, smallest_max_L = group_data_by_s(SMdata, s)
#Mathematica input
for i in range(smallest_max_L + 1):
print("{", end='')
# Create a list to collect the formatted entries for each line
line_entries = []
for j_value, entries in grouped_SMdata.items():
for entry in entries:
real_part, imaginary_part, L, J = entry
if i == int(L):
# Format each entry and append it to the list
line_entries.append(f"{{{L:2d}, {J:4.1f}, {real_part:9.6f}+{imaginary_part:9.6f} I}}")
# Print the joined line without the trailing comma
print(", ".join(line_entries), end='')
print("},")
# Define the function to extract Ruth ratio from the file
def extract_angle_and_ratio(filename):
angles = []
ratios = []
with open(filename, 'r') as file:
# Read all lines from the file
lines = file.readlines()
# Find the start and end line numbers
start_line = None
end_line = None
for i, line in enumerate(lines):
if "CROSS SECTIONS FOR OUTGOING" in line:
start_line = i + 1 # Start reading after this line
elif "Finished all xsecs" in line:
end_line = i
break # Stop once the end line is found
# If start or end line not found, return empty lists
if start_line is None or end_line is None:
print("Start or end marker not found in the file.")
return angles, ratios
# Iterate over the identified range
for line in lines[start_line:end_line]:
line = line.strip()
# Look for the lines containing "deg."
if "deg.:" in line:
# Extract the angle
angle = float(line.split("deg.:")[0].strip())
angles.append(angle)
# Look for the lines containing "/R ="
elif "/R =" in line:
# Extract the /R value
ratio = float(line.split("/R =")[1].strip())
ratios.append(ratio)
return angles, ratios
# Example usage
angles, ratios = extract_angle_and_ratio(filename)
# Print or save the results
print("### Differential cross section :")
for angle, ratio in zip(angles, ratios):
if angle % 5 == 0 :
print(f"{angle:8.1f}, {ratio:8.4f}")
print(f"{angles[-1]:8.1f}, {ratios[-1]:8.4f}")
import matplotlib.pyplot as plt
def plot_SM(groups):
# Determine the number of groups
num_groups = len(groups)
# Create subplots (rows, columns) based on number of groups
fig, axes = plt.subplots(1, num_groups, figsize=(6 * num_groups,4))
# If there's only one group, axes will not be a list, so make it iterable
if num_groups == 1:
axes = [axes]
# Create a plot for each group
for i, (offset, entries) in enumerate(groups.items()):
# Extract real and imaginary parts, and L values
real_parts = [entry[0] for entry in entries]
imaginary_parts = [entry[1] for entry in entries]
L_values = [entry[2] for entry in entries]
# Plot real part vs L
axes[i].plot(L_values, real_parts, label=f'Re', marker='o')
# Plot imaginary part vs L
axes[i].plot(L_values, imaginary_parts, label=f'Im', marker='x')
# Adding labels and title
axes[i].set_xlabel('L')
axes[i].set_ylabel('Value')
axes[i].set_title(f'Real and Imaginary Parts vs L for Group {offset:+.1f}')
# Add grid lines
axes[i].set_xlim(-1, max(L_values)+1)
axes[i].set_ylim(-1.1, 1.1)
axes[i].set_xticks(np.arange(0, max(L_values)+3, 5)) # Set x-ticks from 0 to 20 with step 5
axes[i].grid(True)
# Show the legend
axes[i].legend()
# Adjust layout to prevent overlapping subplots
plt.tight_layout()
return fig
def plot_Ruth(angles, ratios):
# Plot the data
fig = plt.figure(figsize=(8, 6))
plt.plot(angles, ratios, linestyle='-', color='b', label='/R values')
plt.xscale('linear') # Linear scale for angles
plt.yscale('log') # Logarithmic scale for /R values
# Add labels, title, and legend
plt.xlabel('CM Angle (degrees)', fontsize=12)
plt.ylabel('d.c.s/Ruth', fontsize=12)
plt.legend(fontsize=10)
plt.grid(which='both', linestyle='--', linewidth=0.5)
plt.xlim(-5, 185)
plt.xticks(np.arange(0, 181, 20))
# Show the plot
plt.tight_layout()
return fig
fig1 = plot_SM(grouped_SMdata)
fig2 = plot_Ruth(angles, ratios)
plt.show(block=False)
input("Press Enter to exit.")