import os, csv from pathlib import Path import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt sns.set_theme(style="ticks") def parse_NIST_data(path, min_J, max_J, max_wavenumber): data_list = [] with open(path) as f: reader = csv.reader(f, delimiter="\t") data_list = list(reader) #collect data Parity = np.zeros(len(data_list)) J = np.zeros(len(data_list)) Wavenumber = np.zeros(len(data_list)) for i in range(1, len(data_list)): try: tmp = data_list[:][i] if not tmp[0] == '' and tmp[0].find('*') != -1: Parity[i] = 1 elif not tmp[0] == '': Parity[i] = 0 J[i] = int(tmp[1]) Wavenumber[i] = float(tmp[3]) except ValueError: J[i] = np.nan Wavenumber[i] = np.nan remove_idxs = [] for i in range(1, len(data_list)): p = Parity[i] j = J[i] wn = Wavenumber[i] if np.isnan(p) or np.isnan(j) or np.isnan(wn): remove_idxs.append(i) Parity = np.delete(Parity, remove_idxs) J = np.delete(J, remove_idxs) Wavenumber = np.delete(Wavenumber, remove_idxs) #sort data sorting_indices = np.argsort(J) Parity = Parity[sorting_indices] J = J[sorting_indices] Wavenumber = Wavenumber[sorting_indices] # splice data to within user-defined range of Js splice_idx_start = np.where(J==min_J)[0][0] splice_idx_stop = len(J) - 1 - np.where(J[::-1]==max_J)[0][0] Parity = Parity[splice_idx_start:splice_idx_stop] J = J[splice_idx_start:splice_idx_stop] Wavenumber = Wavenumber[splice_idx_start:splice_idx_stop] # splice data to within user-defined range of Wavenumbers splice_idxs = [i for i in range(len(Wavenumber)) if Wavenumber[i] > max_wavenumber] Parity = [ele for idx, ele in enumerate(Parity) if idx not in splice_idxs] J = [ele for idx, ele in enumerate(J) if idx not in splice_idxs] Wavenumber = [ele for idx, ele in enumerate(Wavenumber) if idx not in splice_idxs] # Create a Pandas data frame with the data dataset = pd.DataFrame(np.array(list(zip(Parity, J, Wavenumber))), columns=['Parity', 'J', 'Wavenumber']) return dataset def plot_level_structure_with_red_and_blue_transitions(*args, **kwargs): #start plotting f, ax = plt.subplots(figsize=(4.5, 7)) #plt.subplots_adjust(top=0.973, bottom=0.121, left=0.244, right=0.959, hspace=0.2, wspace=0.2) named_colors = ['r', 'm'] Red_Blue_colors = ['#ab162a', '#cf5246', '#eb9172', '#fac8af', '#faeae1', '#e6eff4', '#bbdaea', '#7bb6d6', '#3c8abe', '#1e61a5'] #draw levels plot_handle = sns.scatterplot(x='J', y='Wavenumber', data = dataframe, s=2000, hue = 'Parity', palette = sns.color_palette(named_colors), marker = '_', linewidth=1.5, legend=False) #write electronic configuration for GS #ax.text(gs_J + 0.15, gs_wavenumber + 400, '$6s^2$') #draw guide line for GS #plt.axhline(y=gs_wavenumber, color='m', linestyle='--', linewidth=1, alpha=0.5) #write wavelength of red transition ax.text(red_J - 0.4, red_wavenumber * 0.5, '626.082 nm', color = '#db2929', fontsize = 16, fontweight = 'bold') #ax.text(red_J - 0.49, red_wavenumber * 0.42, '$(\\Gamma = 2\\pi\\times 136 ~ \mathrm{kHz})$', fontsize = 12, color = '#db2929') #draw red transition arrow ax.annotate('', xy=(red_J, red_wavenumber), xytext=(gs_J, gs_wavenumber), arrowprops=dict(color='#db2929', width=1.5), horizontalalignment='right', verticalalignment='top') #write electronic configuration for triplet excited state #ax.text(red_J + 0.35, red_wavenumber + 200, '$6s6p(^3P_1)$', fontsize = 10) #draw guide line for triplet excited state plt.axhline(y=red_wavenumber, color='m', linestyle='--', linewidth=1, alpha=0.5) #write wavelength of red transition ax.text(blue_J - 1.8, blue_wavenumber * 0.4, '421.291 nm', color = '#2630ea', fontsize = 16, fontweight = 'bold') #ax.text(blue_J - 1.85, blue_wavenumber * 0.4, '$(\\Gamma = 2\\pi\\times$', fontsize = 12, color = '#2630ea') #$(\\Gamma = 2\\pi\\times 32.2 ~ \mathrm{MHz})$ #ax.text(blue_J - 1.5, blue_wavenumber * 0.35, '$32.2 ~ \mathrm{MHz})$', fontsize = 12, color = '#2630ea') #draw blue transition arrow ax.annotate('', xy=(blue_J, blue_wavenumber), xytext=(gs_J, gs_wavenumber), arrowprops=dict(color='#2630ea', width=3.5), horizontalalignment='right', verticalalignment='top') #write electronic configuration for singlet excited state #ax.text(blue_J + 0.35, blue_wavenumber + 200, '$6s6p(^1P_1)$', fontsize = 10) #draw guide line for singlet excited state plt.axhline(y=blue_wavenumber, color='m', linestyle='--', linewidth=1, alpha=0.5) #figure options f.canvas.draw() plt.xlabel('J', fontsize=20, fontweight = 'bold') #plt.ylabel('$\\tilde{v}~(cm^{-1})$', fontsize=16) plt.ylabel('Wavelength (nm)', fontsize=20, fontweight = 'bold') plot_handle.set_xticks(range(min_J-1, max_J+2)) ax.get_xticklabels()[0].set_visible(False) ax.get_xticklabels()[-1].set_visible(False) ax.get_xticklines()[0].set_visible(False) ax.get_xticklines()[-2].set_visible(False) ax.set_xticklabels(ax.get_xticks(), weight='bold') yticklabels = [item.get_text() for item in ax.get_yticklabels()] yticklabels = ['' if item.startswith('−') or item.startswith('0') else item for item in yticklabels] yticks = [float(item) if item != '' else 0.0 for item in yticklabels] new_yticks = np.arange(min(yticks), max_wavenumber, 4000) plot_handle.set_yticks(new_yticks) new_yticklabels = [round(1e7/item) if item != 0 else item for item in new_yticks] ax.set_yticklabels(new_yticklabels, weight='bold') ax.get_yticklabels()[0].set_visible(False) #ax.get_yticklabels()[-1].set_visible(False) ax.get_yticklines()[0].set_visible(False) #ax.get_yticklines()[-2].set_visible(False) plt.tick_params(axis='both', which='major', labelsize=16) #f.tight_layout() #plt.show() f.savefig(Path(home_path + os.sep + 'result.pdf'), format='pdf', bbox_inches = "tight") if __name__ == '__main__': min_J = 8 max_J = 9 #max_wavenumber = 24500.0 max_wavenumber = 28500.0 #Ground State: [Xe]4f^{10} 6s^2(^5I_8) gs_J = 8 gs_wavenumber = 0.0 #626 nm transition GS ---> [Xe]4f^{10}(^5I_8) 6s6p(^3P_1)(8,1)_9 red_J = 9 red_wavenumber = 15972.35 #421 nm transition GS ---> [Xe]4f^{10}(^5I_8) 6s6p(^1P_1)(8,1)_9 blue_J = 9 blue_wavenumber = 23736.610 NIST_Dy_level_data_filename= 'Dylevels.txt' home_path = str(Path(__file__).parent.resolve()) dataframe = parse_NIST_data(home_path + os.sep + NIST_Dy_level_data_filename, min_J, max_J, max_wavenumber) plot_level_structure_with_red_and_blue_transitions(dataframe, gs_J, gs_wavenumber, red_J, red_wavenumber, blue_J, blue_wavenumber, max_wavenumber, home_path)