Repository navigation
Expand file tree
/
Copy pathBrukerWobble_Plot.py
More file actions
117 lines (107 loc) · 6.29 KB
/
Copy pathBrukerWobble_Plot.py
File metadata and controls
117 lines (107 loc) · 6.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import os
import matplotlib.pyplot as plt
# Define the file path to the JCAMP data file
jcamp_path = '/tmp/result.jcamp'
# Define the range of the wobble curves, likely related to the frequency span
wobble_range = 4
# Define the file path to the output PNG file
png_path = '/tmp/wobble_curves.png'
# Check if the specified file exists before attempting to open and read it
if not os.path.isfile(jcamp_path):
# If the file is not found, raise a FileNotFoundError with a descriptive message
raise FileNotFoundError(f"JCAMP file not found: {jcamp_path}")
# Initialize empty lists to store the two spectra that will be extracted from the file
spectrum1, spectrum2 = [], []
# Initialize a variable to store the number of data points (elements) expected in each spectrum
num_elements = 0
# Open the file specified by jcamp_path in read mode ('r' is the default)
with open(jcamp_path) as f:
# Avoid reading all lines into memory at once, which can be inefficient for large files.
# Iterate through the file object line by line.
for line in f:
# Remove any leading or trailing whitespace from the current line
line = line.strip()
# Check if the current line starts with the identifier for the wobble curve acquisition parameters
if line.startswith('##$ACQ_WobbleCurves='):
# Try to extract the number of elements from the line
try:
# The line format is expected to be something like '##$ACQ_WobbleCurves=(reps, elements)'
# Split the line at '(' to get the part after the identifier
part_after_equals = line.split('=')[1]
# Split the part after '(' at the comma to separate reps and elements
elements_part = part_after_equals.split(',')[1]
# Split the elements part at ')' to isolate the number of elements
num_elements_str = elements_part.split(')')[0]
# Remove any leading or trailing whitespace from the elements string and convert it to an integer
num_elements = int(num_elements_str.strip())
# Catch potential errors that might occur if the line format is unexpected
except (IndexError, ValueError):
# If there's an issue parsing the number of elements, raise a ValueError with an informative message
raise ValueError(f"Could not parse element count from line: {line}")
# Preallocate the lists for spectrum1 and spectrum2 with zeros. This can be more efficient than appending in a loop, especially for a known size.
spectrum1 = [0.0] * num_elements
spectrum2 = [0.0] * num_elements
# Initialize counters to keep track of how many elements have been read for each spectrum
count1, count2 = 0, 0
# Start another loop to read the lines containing the actual data for the spectra
for data_line in f:
# Remove any leading or trailing whitespace from the current data line
data_line = data_line.strip()
# Check if the current data line marks the end of the data section
if data_line.startswith('##END='):
# If the end marker is found, break out of the inner loop
break
# Attempt to parse numbers from the current data line.
# Split the line into individual strings (separated by whitespace).
# Filter these strings to keep only those that can be converted to float.
# The filter condition checks if the string, after removing a single potential decimal point and a single potential minus sign, consists only of digits.
numbers = [float(n) for n in data_line.split() if n.replace('.', '', 1).replace('-', '', 1).isdigit()]
# Iterate through the numbers extracted from the current line
for num in numbers:
# If spectrum1 is not yet full (less than num_elements)
if count1 < num_elements:
# Add the current number to spectrum1 at the current index
spectrum1[count1] = num
# Increment the counter for spectrum1
count1 += 1
# If spectrum1 is full but spectrum2 is not yet full
elif count2 < num_elements:
# Add the current number to spectrum2 at the current index
spectrum2[count2] = num
# Increment the counter for spectrum2
count2 += 1
# If both spectrum1 and spectrum2 are full
else:
# Set the reading_data flag to False (although not explicitly used in this version)
reading_data = False
# Break out of the inner loop as all expected data has been read
break
# After processing the data lines, break out of the outer loop (reading from the file)
break
# After reading the data, check if the expected number of elements was read for both spectra
if count1 != num_elements or count2 != num_elements:
# If the data is incomplete, raise a ValueError
raise ValueError(f"Data incomplete. Expected {num_elements} elements each; got {count1} and {count2}.")
# Generate a list of x-values representing the frequency range for plotting.
# It creates 'num_elements' evenly spaced points between -wobble_range/2 and +wobble_range/2.
x_values = [-wobble_range / 2 + wobble_range * i / (num_elements - 1) for i in range(num_elements)]
# Create a plot figure
plt.figure()
# Plot the data for spectrum1 against the x_values, with a label
plt.plot(x_values, spectrum1, label='1H:RES:1')
# Plot the data for spectrum2 against the x_values, with a label
plt.plot(x_values, spectrum2, label='1H:RES:2')
# Set the label for the x-axis
plt.xlabel('Frequency (MHz)')
# Set the label for the y-axis
plt.ylabel('Reflection Ratio')
# Set the title of the plot
plt.title('Wobble Curves')
# Display the legend to identify the different plots
plt.legend()
# Add a grid to the plot for better readability
plt.grid(True)
# Save the plot as a PNG image file at the specified path
plt.savefig(png_path)
# Close the plot figure to free up memory
plt.close()