Observation of topological frequency combs
Data files
Jun 11, 2024 version files 52.76 MB
-
112323_A1_C3R3_Drop_Group_Delay_larger_range.txt
-
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_275__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
-
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_278__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
-
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_280__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
-
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_283__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
-
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_285__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
-
240311_A1_C3R3_Thru_ApexAttn0p005_Theta_24_1547p35_Spectrum.dat
-
240311_Run_3_A1_C3R3_Thru_Sample_Theta_24__FSV_BW_1kHz_AttnESA_0db_pts_31001_0_to_5p0GHz_wAPEX_bkTel_swl_1547p35_OSA_N_3_centerwav_1548p0_span_500p0.npz
-
CCW_Bulk_v1.png
-
CCW_v1.png
-
CW_v1.png
-
README.md
Abstract
On-chip generation of optical frequency combs using nonlinear ring resonators has enabled numerous applications of combs that were otherwise limited to mode-locked lasers. Nevertheless, on-chip frequency combs have relied predominantly on single-ring resonators. Here, we experimentally demonstrate the generation of a novel class of frequency combs, the topological frequency combs, in a two-dimensional lattice of hundreds of ring resonators that hosts fabrication-robust topological edge states with linear dispersion. By pumping these edge states, we demonstrate the generation of a nested frequency comb that shows oscillation of multiple edge state resonances across $\approx$40 longitudinal modes and is spatially confined at the lattice edge. Our results provide an opportunity to explore the interplay between topological physics and nonlinear frequency comb generation in a commercially available nanophotonic platform.
README: Observation of Topological Frequency Combs
[Access this dataset on Dryad] https://doi.org/10.5061/dryad.xwdbrv1mw
Description of the data and file structure
- 112323_A1_C3R3_Drop_Group_Delay_larger_range.txt
Contains linear transmission and group delay data from Fig. 2 of the manuscript. Format is simple .txt file. Variables, which are columns in the text file, are labeled. In order, they are: Wavelength (nm), Frequency (GHz), Insertion Loss (dB), Group Delay (ps), Chromatic Dispersion (ps/nm).
2. 231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_285__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_283__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_280__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_278__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
231122_Run_3_Chip_A1_Col_3_Row_3_HighResOSA_Drop_bkTel_Theta_275__bkTel_swl_1547p35_OSA_N_1_centerwav_1500p0_span_400p0.npz
Contain Optical Spectrum Analyzer (OSA) spectra for five different pump powers as shown in Fig. 3 of the manuscript. (275, 278, 280, 283, 285 correspond to {70, 78, 86, 92, 100} W of on-chip peak power.) These can be processed via simple python function shown below. Variables stored are "intensity", which is a numpy array of intensity values collected by the OSA, "times" which is a numpy array which stores timestamps for each datapoint in the "intensity" (dB) array, and "wl", a numpy array storing wavelength (nm) values that correspond to each value in "intensity".
3. 240311_Run_3_A1_C3R3_Thru_Sample_Theta_24__FSV_BW_1kHz_AttnESA_0db_pts_31001_0_to_5p0GHz_wAPEX_bkTel_swl_1547p35_OSA_N_3_centerwav_1548p0_span_500p0.npz
240311_A1_C3R3_Thru_ApexAttn0p005_Theta_24_1547p35_Spectrum.dat
These contain data shown in Fig. 4. The .npz file contains the low resolution OSA spectrum stored as described above in #2. High resolution nested data from the ultra-high resolution heterodyne-based optical spectrum analyzer is stored in the .dat file. The .dat processing script below returns two variables: freq_in_GHz gives the x-axis of the collected spectrum in GHz, signal_in_vol gives the y-axis of the collected spectrum in voltage.
4. CCW_v1.png
CCW_Bulk_v1.png
CW_v1.png
These are the raw images taken that were then processed for Fig. 5 in the manuscript. CCW_v1 corresponds to panel A, CW_v1 to panel B, and CCW_Bulk_v1 to panel C.
Python Code For Processing
- npz files can be processed with simple python function as follows.
import numpy as np
def load_sweep_file(filename):
npzfile = np.load(filename)
intensity = npzfile['intensity']
times = npzfile['times']
wl = npzfile['wl']
return intensity, times, wl
- .dat file requires a more complex script, but can be processed with the following:
# Created by Apex Technologies
import os
def read_spectrum_binary_file(path, name_file):
'''
This function is to read spectrum binary file saved from OSA.
The content of the spectrum binary stream is
b185000.000000 7876 kh\x02Fk...
b is a character of 'b' written into the binary file.
185000.000000 is defaul optical frequency base.
7876 is number of points.
kh\x02Fk... stream contains the encoded frequency and signal voltage.
Note: In this binary stream, the encoded optical frequency is in GHz,
signal is in Voltage.
'''
# Check if existing the path.
if os.path.exists(path) == False:
try:
os.mkdir(path)
except OSError:
print("Creation of the directory %s failed" % path + '\n')
else:
print("Successfully created the directory %s " % path + '\n')
else:
print("the directory exits %s " % path + '\n')
# Open and reading the file to get the data.
with open(path + '/' + name_file, 'rb') as binary_file:
# Read the first character 'b' in the binary sream.
ch = binary_file.read(1).decode('utf-8')
if ch != 'b':
path_file = path + '/' + name_file
print("The file %s" % path_file + "is not binary file.")
return
# Read the default optical frequency base.
optical_freq_base_GHz = binary_file.read(14).decode('utf-8')
# Read the number of points.
number_of_points = ''
while True:
ch = binary_file.read(1).decode('utf-8')
number_of_points = number_of_points + ch
if ch == str(' '):
break
number_of_points = int(number_of_points)
# Read and unpack the double-precision float frequency in GHz.
format_string = f'{number_of_points}f'
freq_in_GHz = struct.unpack(
format_string, binary_file.read(struct.calcsize(format_string)))
# Read and unpack the double-precision float signal in Voltage.
signal_in_vol = struct.unpack(
format_string, binary_file.read(struct.calcsize(format_string)))
# Convert tuple to list type.
freq_in_GHz = np.array(freq_in_GHz)
signal_in_vol = np.array(signal_in_vol)
# Decode frequency vector to real one.
freq_in_GHz += float(optical_freq_base_GHz)
return freq_in_GHz, signal_in_vol