DOI: 10.5061/dryad.xwdbrv1mw
title: Observation of topological frequency combs

description: 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.
description: # Observation of Topological Frequency Combs \[Access this dataset on
 Dryad]
 [https://doi.org/10.5061/dryad.xwdbrv1mw](https://doi.org/10.5061/dryad.xwdbrv1mw) ## Description of the data and file structure 1. 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 1. 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 ``` 2. .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 ```