USER
Help me edit the graphs so that the text markers inside the graphs appear slighly more on the left, like 3 centimeters
import os
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Specify the folder paths
input_folder = r"C:\Users\samuel.hernandez\OneDrive - FUNDECYT - PCTEX\Escritorio\Doctorado\Experimental\FTIR"
output_folder = r"C:\Users\samuel.hernandez\OneDrive - FUNDECYT - PCTEX\Escritorio\Doctorado\Experimental\FTIR\Python\Test"
# Ensure the output folder exists
os.makedirs(output_folder, exist_ok=True)
def read_data_from_file(file_path):
try:
# Read the file, specifying the decimal separator as comma
data = pd.read_csv(file_path, delim_whitespace=True, header=None, decimal=',')
wave_number = data.iloc[:, 0].astype(float)
transmittance = data.iloc[:, 1].astype(float) * 100 # Multiply by 100 to get percentage
return wave_number, transmittance
except Exception as e:
print(f"Error reading {file_path}: {str(e)}")
return None, None
def create_tight_stacked_subplots(files, output_filename, peak_markers):
n_files = len(files)
fig, axs = plt.subplots(n_files, 1, figsize=(12, 2*n_files), sharex=True)
if n_files == 1:
axs = [axs] # Make axs iterable if there's only one subplot
# Colorful colors
colors = plt.cm.tab10(np.linspace(0, 1, n_files))
x_min, x_max = float('inf'), float('-inf')
for ax, file, color in zip(axs, files, colors):
file_path = os.path.join(input_folder, file)
wave_number, transmittance = read_data_from_file(file_path)
if wave_number is not None and transmittance is not None:
ax.plot(wave_number, transmittance, color=color)
ax.set_yticklabels([])
# Add black text as title
ax.text(0.02, 0.5, file.replace(".dpt", ""), transform=ax.transAxes,
color='black', va='center', fontsize='small')
# Remove x-axis labels for all but the bottom subplot
if ax != axs[-1]:
ax.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
# Update x_min and x_max
x_min = min(x_min, wave_number.min())
x_max = max(x_max, wave_number.max())
# Highlight the specified peaks with black discontinuous vertical lines
for label, peak in peak_markers.items():
ax.axvline(x=peak, color='black', linestyle='--', linewidth=1.5) # Discontinuous vertical line for the peak
# Set distance based on the specific file
if file in ["PBA-H-0.dpt", "PBA-C-1.dpt"]:
ax.text(peak - 0, transmittance.max() * 0.92, label, color='black', ha='right', fontsize='small') # Smaller distance for specific files
else:
ax.text(peak - 0, transmittance.max() * 0.75, label, color='black', ha='right', fontsize='small') # Default distance
# Set x-axis label only for the bottom subplot
axs[-1].set_xlabel('Wave Number (cm⁻¹)')
plt.xlim(x_max, x_min) # Set x-axis limits based on data and invert axis
# Add a single y-axis label for the entire figure
fig.text(0.1, 0.5, 'Transmittance (%)', va='center', rotation='vertical')
# Create a legend for the bonds with wavenumbers
bond_labels = [f"{label} ({peak} cm⁻¹)" for label, peak in peak_markers.items()]
# Create handles for the legend
handles = [plt.Line2D([0], [0], color='black', lw=0, label=label) for label in bond_labels]
# Add the legend to the plot below the x-axis
plt.legend(handles=handles, loc='upper center', bbox_to_anchor=(0.5, -0.3), fontsize='medium', ncol=4)
plt.tight_layout()
plt.subplots_adjust(hspace=0, left=0.12, bottom=0.25) # Adjust bottom margin for the legend
output_path = os.path.join(output_folder, output_filename)
plt.savefig(output_path, dpi=300, bbox_inches='tight')
plt.close()
print(f"Stacked subplots graph saved: {output_path}")
# Define the peak markers for H-series and C-series
h_peak_markers = {
'ν(Fe–CN)': 590,
'ν(C≡N)': 2060,
'ν(O-H)': 1405,
'δ(O-H)': 3180
}
c_peak_markers = {
'ν(Fe–CN)': 590,
'ν(C≡N)': 2055,
'ν(O-H)': 1615,
'δ(O-H)': 3650
}
# Find files containing 'C' and 'H'
c_files = [f for f in os.listdir(input_folder) if 'C' in f and f.endswith('.dpt')]
h_files = [f for f in os.listdir(input_folder) if 'H' in f and f.endswith('.dpt')]
if c_files:
c_files.sort() # Sort files alphabetically
create_tight_stacked_subplots(c_files, 'C_containing_samples_FTIR.png', c_peak_markers)
print(f"Processed C files: {c_files}")
if h_files:
h_files.sort() # Sort files alphabetically
create_tight_stacked_subplots(h_files, 'H_containing_samples_FTIR.png', h_peak_markers)
print(f"Processed H files: {h_files}")
if not c_files and not h_files:
print("No files containing 'C' or 'H' found in the input folder.")
print("Available .dpt files:")
for file in os.listdir(input_folder):
if file.endswith('.dpt'):
print(file)
print(f"Check the output folder: {output_folder}")ASSISTANT
Certainly! I've modified your script to shift the text markers inside the graphs slightly more to the left by approximately 3 centimeters, as you requested.
Here's what I've done:
- Calculated the data units that correspond to 3 centimeters on the figure.
- Adjusted the x-position of the text markers by this amount, shifting them to the left on the plot.
- Ensured that the positioning accounts for the inverted x-axis.
Below is the updated code with comments indicating the changes:
```python
import os
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Specify the folder paths
input_folder = r"C:\Users\samuel.hernandez\OneDrive - FUNDECYT - PCTEX\Escritorio\Doctorado\Experimental\FTIR"
output_folder = r"C:\Users\samuel.hernandez\OneDrive - FUNDECYT - PCTEX\Escritorio\Doctorado\Experimental\FTIR\Python\Test"
# Ensure the output folder exists
os.makedirs(output_folder, exist_ok=True)
def read_data_from_file(file_path):
try:
# Read the file, specifying the decimal separator as comma
data = pd.read_csv(file_path, delim_whitespace=True, header=None, decimal=',')
wave_number = data.iloc[:, 0].astype(float)
transmittance = data.iloc[:, 1].astype(float) * 100 # Multiply by 100 to get percentage
return wave_number, transmittance
except Exception as e:
print(f"Error reading {file_path}: {str(e)}")
return None, None
def create_tight_stacked_subplots(files, output_filename, peak_markers):
n_files = len(files)
fig, axs = plt.subplots(n_files, 1, figsize=(12, 2*n_files), sharex=True)
if n_files == 1:
axs = [axs] # Make axs iterable if there's only one subplot
# Colorful colors
colors = plt.cm.tab10(np.linspace(0, 1, n_files))
x_min, x_max = float('inf'), float('-inf')
for ax, file, color in zip(axs, files, colors):
file_path = os.path.join(input_folder, file)
wave_number, transmittance = read_data_from_file(file_path)
if wave_number is not None and transmittance is not None:
ax.plot(wave_number, transmittance, color=color)
ax.set_yticklabels([])
# Add black text as title
ax.text(0.02, 0.5, file.replace(".dpt", ""), transform=ax.transAxes,
color='black', va='center', fontsize='small')
# Remove x-axis labels for all but the bottom subplot
if ax != axs[-1]:
ax.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
# Update x_min and x_max
x_min = min(x_min, wave_number.min())
x_max = max(x_max, wave_number.max())
# Highlight the specified peaks with black discontinuous vertical lines
for label, peak in peak_markers.items():
ax.axvline(x=peak, color='black', linestyle='--', linewidth=1.5) # Discontinuous vertical line for the peak
# Compute the shift in data units corresponding to 3 cm
# (This calculation is moved inside the loop to ensure it's calculated after x_min and x_max are updated)
data_width = abs(x_max - x_min)
figure_width_inch = fig.get_size_inches()[0] # Get figure width in inches
figure_width_cm = figure_width_inch * 2.54 # Convert inches to cm
data_units_per_cm = data_width / figure_width_cm
shift_in_cm = 3
shift_amount = data_units_per_cm * shift_in_cm
# Adjust the x-position of the text marker by shifting it to the left
x_text = peak + shift_amount # Increase x to move left on the plot due to inverted axis
# Set vertical position based on the specific file
if file in ["PBA-H-0.dpt", "PBA-C-1.dpt"]:
y_text = transmittance.max() * 0.92
else:
y_text = transmittance.max() * 0.75
# Add the text label at the new position
ax.text(x_text, y_text, label, color='black', ha='right', fontsize='small')
# Set x-axis label only for the bottom subplot
axs[-1].set_xlabel('Wave Number (cm⁻¹)')
plt.xlim(x_max, x_min) # Set x-axis limits based on data and invert axis
# Add a single y-axis label for the entire figure
fig.text(0.1, 0.5, 'Transmittance (%)', va='center', rotation='vertical')
# Create a legend for the bonds with wavenumbers
bond_labels = [f"{label} ({peak} cm⁻¹)" for label, peak in peak_markers.items()]
# Create handles for the legend
handles = [plt.Line2D([0], [0], color='black', lw=0, label=label) for label in bond_labels]
# Add the legend to the plot below the x-axis
plt.legend(handles=handles, loc='upper center', bbox_to_anchor=(0.5, -0.3), fontsize='medium', ncol=4)
plt.tight_layout()
plt.subplots_adjust(hspace=0, left=0.12, bottom=0.25) # Adjust bottom margin for the legend
output_path = os.path.join(output_folder, output_filename)
plt.savefig(output_path, dpi=300, bbox_inches='tight')
plt.close()
print(f"Stacked subplots graph saved: {output_path}")
# Define the peak markers for H-series and C-series
h_peak_markers = {
'ν(Fe–CN)': 590,
'ν(C≡N)': 2060,
'ν(O-H)': 1405,
'δ(O-H)': 3180
}
c_peak_markers = {
'ν(Fe–CN)': 590,
'ν(C≡N)': 2055,
'ν(O-H)': 1615,
'δ(O-H)': 3650
}
# Find files containing 'C' and 'H'
c_files = [f for f in os.listdir(input_folder) if 'C' in f and f.endswith('.dpt')]
h_files = [f for f in os.listdir(input_folder) if 'H' in f and f.endswith('.dpt')]
if c_files:
c_files.sort() # Sort files alphabetically
create_tight_stacked_subplots(c_files, 'C_containing_samples_FTIR.png', c_peak_markers)
print(f"Processed C files: {c_files}")
if h_files:
h_files.sort() # Sort files alphabetically
create_tight_stacked_subplots(h_files, 'H_containing_samples_FTIR.png', h_peak_markers)
print(f"Processed H files: {h_files}")
if not c_files and not h_files:
print("No files containing 'C' or 'H' found in the input folder.")
print("Available .dpt files:")
for file in os.listdir(input_folder):
if file.endswith('.dpt'):
print(file)
print(f"Check the output folder: {output_folder}")
```
**Explanation of Changes:**
- **Calculating the Shift Amount:**
- After updating `x_min` and `x_max` in the loop, I calculated the width of the data (`data_width`) and converted the figure's width from inches to centimeters.
- Computed `data_units_per_cm` to find out how many data units correspond to one centimeter.
- Calculated `shift_amount` by multiplying `data_units_per_cm` by the desired shift in centimeters (3 cm).
- **Adjusting the Text Position:**
- Used `x_text = peak + shift_amount` to shift the text marker to the left on the plot (since the x-axis is inverted, increasing the x-value moves the text to the left).
- Adjusted the vertical position (`y_text`) according to your existing logic.
- Placed the text using `ax.text(x_text, y_text, ...)`, ensuring the marker moved appropriately.
- **Ensuring the Calculations Occur at the Right Time:**
- Moved the shift calculation inside the loop over peaks to ensure that it uses the updated `x_min` and `x_max`.
**Notes:**
- **Inverted X-Axis Consideration:**
- Since the x-axis is inverted (`plt.xlim(x_max, x_min)`), moving text to the left on the plot requires increasing the x-value.
- Therefore, we added `shift_amount` to the `peak` value.
- **Text Alignment:**
- Kept `ha='right'` to align the text correctly relative to the x-position.
- This maintains the visual consistency of the labels being near their corresponding peaks.
- **Dynamic Shift Calculation:**
- The shift calculation is dynamic and will adjust based on the actual width of your data and figure, ensuring consistent results even if the plot size or data range changes.
**Print Statements for Verification:**
- You can add print statements to verify the calculated shift amounts if needed:
```python
print(f"Data width in x: {data_width}")
print(f"Figure width in cm: {figure_width_cm}")
print(f"Shift amount in data units (cm⁻¹): {shift_amount}")
```
These can help you ensure that the shift is being calculated as expected.
**Result:**
- The text markers inside the graphs should now appear approximately 3 centimeters more to the left, fulfilling your request.
**Next Steps:**
- Run the updated script to generate your graphs.
- Check the output images in the specified output folder to confirm that the text markers have shifted as desired.
- Adjust the `shift_in_cm` value if you wish to fine-tune the position further.
Let me know if you need further assistance or adjustments!