Repository: Wheeler1711/submm_python_routines (language: python)

Issue:
Keeping up to date with changes on the main branch. 



Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 2825371..afbddd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,3 +145,6 @@ dmypy.json
 
 # JetBrians (PyCharm)
 .idea
+
+# ouptput files
+output
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 056aa8d..a5fcc07 100644
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,7 @@ def get_file_paths(local_dir, desired_file_types):
 
 # Demo files
 desired_demo_file_types = {'ipynb'}
-local_demos_dir = os.path.join('submm', 'demos')
+local_demos_dir = os.path.join('submm', 'demo')
 demo_files = get_file_paths(local_dir=local_demos_dir, desired_file_types=desired_demo_file_types)
 
 
diff --git a/submm/KIDs/analyze_single_tone.py b/submm/KIDs/analyze_single_tone.py
index f5f937b..0a335fa 100644
--- a/submm/KIDs/analyze_single_tone.py
+++ b/submm/KIDs/analyze_single_tone.py
@@ -1,185 +1,171 @@
 import numpy as np
 import matplotlib.pyplot as plt
-from submm.KIDs import calibrate, resonance_fitting
+from submm.KIDs import calibrate
+from submm.KIDs.res.utils import amplitude_normalization_sep
 from scipy import interpolate
 import pickle
 from scipy.stats import binned_statistic
 
 
+def calibrate_single_tone(fine_f, fine_z, gain_f, gain_z, stream_f, stream_z, plot_period=1, interp="quadratic"):
+    fig = plt.figure(3, figsize=(16, 10))
 
-def calibrate_single_tone(fine_f,fine_z,gain_f,gain_z,stream_f,stream_z,plot_period = 1,interp = "quadratic"):
-
-    fig = plt.figure(3,figsize = (16,10))
-
-    plt.subplot(241,aspect = 'equal')
+    plt.subplot(241, aspect='equal')
     plt.title("Raw data")
-    plt.plot(np.real(stream_z[::plot_period]),np.real(stream_z[::plot_period]),'.')
-    plt.plot(np.real(fine_z),np.imag(fine_z),'o')
-    plt.plot(np.real(gain_z),np.imag(gain_z),'o')
+    plt.plot(np.real(stream_z[::plot_period]), np.real(stream_z[::plot_period]), '.')
+    plt.plot(np.real(fine_z), np.imag(fine_z), 'o')
+    plt.plot(np.real(gain_z), np.imag(gain_z), 'o')
 
     plt.subplot(242)
     plt.title("Raw data")
-    plt.plot(np.real(stream_z[::plot_period]),np.imag(stream_z[::plot_period]),'.')
-    plt.plot(np.real(fine_z),np.imag(fine_z),'o')
-    
-    # normalize amplistude variation in the gain scan                                        
-    amp_norm_dict = resonance_fitting.amplitude_normalization_sep(gain_f,
-                                                                  gain_z,
-                                                                  fine_f,
-                                                                  fine_z,
-                                                                  stream_f,
-                                                                  stream_z)
+    plt.plot(np.real(stream_z[::plot_period]), np.imag(stream_z[::plot_period]), '.')
+    plt.plot(np.real(fine_z), np.imag(fine_z), 'o')
+
+    # normalize amplitude variation in the gain scan
+    amp_norm_dict = amplitude_normalization_sep(gain_f, gain_z, fine_f, fine_z, stream_f, stream_z)
 
     plt.subplot(243)
     plt.title("Gain amplitude variation fit")
-    plt.plot(gain_f,10*np.log10(np.abs(gain_z)**2),'o')
-    plt.plot(gain_f,10*np.log10(np.abs(amp_norm_dict['normalized_gain'])**2),'o')
-    plt.plot(fine_f,10*np.log10(np.abs(amp_norm_dict['normalized_fine'])**2),'o')
-    plt.plot(gain_f,10*np.log10(np.abs(amp_norm_dict['poly_data'])**2))
-
+    plt.plot(gain_f, 10 * np.log10(np.abs(gain_z) ** 2), 'o')
+    plt.plot(gain_f, 10 * np.log10(np.abs(amp_norm_dict['normalized_gain']) ** 2), 'o')
+    plt.plot(fine_f, 10 * np.log10(np.abs(amp_norm_dict['normalized_fine']) ** 2), 'o')
+    plt.plot(gain_f, 10 * np.log10(np.abs(amp_norm_dict['poly_data']) ** 2))
 
     plt.subplot(244)
-    plt.title("Data nomalized for gain amplitude variation")
-    plt.plot(np.real(amp_norm_dict['normalized_fine']),np.imag(amp_norm_dict['normalized_fine']),'o')
-    #plt.plot(gain_dict['freqs'][:,k]*10**6,np.log10(np.abs(amp_norm_dict['poly_data'])**2))     
-    plt.plot(np.real(amp_norm_dict['normalized_stream'][::plot_period]),np.imag(amp_norm_dict['normalized_stream'][::plot_period]),'.')
-    #fit the gain   
-    gain_phase = np.arctan2(np.real(amp_norm_dict['normalized_gain']),np.imag(amp_norm_dict['normalized_gain']))
-    tau,fit_data_phase,gain_phase_rot = calibrate.fit_cable_delay(gain_f, gain_phase)
+    plt.title("Data normalized for gain amplitude variation")
+    plt.plot(np.real(amp_norm_dict['normalized_fine']), np.imag(amp_norm_dict['normalized_fine']), 'o')
+    # plt.plot(gain_dict['freqs'][:,k]*10**6,np.log10(np.abs(amp_norm_dict['poly_data'])**2))
+    plt.plot(np.real(amp_norm_dict['normalized_stream'][::plot_period]),
+             np.imag(amp_norm_dict['normalized_stream'][::plot_period]), '.')
+    # fit the gain
+    gain_phase = np.arctan2(np.real(amp_norm_dict['normalized_gain']), np.imag(amp_norm_dict['normalized_gain']))
+    tau, fit_data_phase, gain_phase_rot = calibrate.fit_cable_delay(gain_f, gain_phase)
 
     plt.subplot(245)
     plt.title("Gain phase fit")
-    plt.plot(gain_f,gain_phase_rot,'o')
-    plt.plot(gain_f,fit_data_phase)
+    plt.plot(gain_f, gain_phase_rot, 'o')
+    plt.plot(gain_f, fit_data_phase)
     plt.xlabel("Frequency (MHz)")
     plt.ylabel("Phase")
 
-
-    #remove cable delay
+    # remove cable delay
     gain_corr = calibrate.remove_cable_delay(gain_f, amp_norm_dict['normalized_gain'], tau)
     fine_corr = calibrate.remove_cable_delay(fine_f, amp_norm_dict['normalized_fine'], tau)
     stream_corr = calibrate.remove_cable_delay(stream_f, amp_norm_dict['normalized_stream'], tau)
 
-
     plt.subplot(246)
     plt.title("Cable delay removed")
-    plt.plot(np.real(gain_corr),np.imag(gain_corr),'o')
-    plt.plot(np.real(fine_corr),np.imag(fine_corr),'o')
-    plt.plot(np.real(stream_corr)[10:-10][::plot_period],np.imag(stream_corr)[10:-10][::plot_period],'.')
-
+    plt.plot(np.real(gain_corr), np.imag(gain_corr), 'o')
+    plt.plot(np.real(fine_corr), np.imag(fine_corr), 'o')
+    plt.plot(np.real(stream_corr)[10:-10][::plot_period], np.imag(stream_corr)[10:-10][::plot_period], '.')
 
     # fit a cicle to the data
-    xc, yc, R, residu  = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
+    xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
 
-    #move the data to the origin 
-    gain_corr = gain_corr - xc -1j*yc
-    fine_corr = fine_corr - xc -1j*yc
-    stream_corr = stream_corr  - xc -1j*yc
+    # move the data to the origin
+    gain_corr = gain_corr - xc - 1j * yc
+    fine_corr = fine_corr - xc - 1j * yc
+    stream_corr = stream_corr - xc - 1j * yc
 
     # rotate so streaming data is at 0 pi
-    phase_stream = np.arctan2(np.imag(stream_corr),np.real(stream_corr))
+    phase_stream = np.arctan2(np.imag(stream_corr), np.real(stream_corr))
     med_phase = np.median(phase_stream)
 
-    gain_corr = gain_corr*np.exp(-1j*med_phase)
-    fine_corr = fine_corr*np.exp(-1j*med_phase)
-    stream_corr = stream_corr*np.exp(-1j*med_phase)
-
+    gain_corr = gain_corr * np.exp(-1j * med_phase)
+    fine_corr = fine_corr * np.exp(-1j * med_phase)
+    stream_corr = stream_corr * np.exp(-1j * med_phase)
 
     plt.subplot(247)
     plt.title("Moved to 0,0 and rotated")
-    plt.plot(np.real(stream_corr)[2:-1][::plot_period],np.imag(stream_corr)[2:-1][::plot_period],'.')
-    plt.plot(np.real(gain_corr),np.imag(gain_corr),'o')
-    plt.plot(np.real(fine_corr),np.imag(fine_corr),'o')
+    plt.plot(np.real(stream_corr)[2:-1][::plot_period], np.imag(stream_corr)[2:-1][::plot_period], '.')
+    plt.plot(np.real(gain_corr), np.imag(gain_corr), 'o')
+    plt.plot(np.real(fine_corr), np.imag(fine_corr), 'o')
     calibrate.plot_data_circle(np.real(fine_corr) - xc, np.imag(fine_corr) - yc, 0, 0, R)
 
+    phase_fine = np.arctan2(np.imag(fine_corr), np.real(fine_corr))
+    use_index = np.where((-np.pi / 2. < phase_fine) & (phase_fine < np.pi / 2))
+    phase_stream = np.arctan2(np.imag(stream_corr), np.real(stream_corr))
 
-    phase_fine = np.arctan2(np.imag(fine_corr),np.real(fine_corr))
-    use_index = np.where((-np.pi/2.<phase_fine) & (phase_fine<np.pi/2))
-    phase_stream = np.arctan2(np.imag(stream_corr),np.real(stream_corr))
+    # interp phase to frequency
+    f_interp = interpolate.interp1d(phase_fine, fine_f, kind=interp, bounds_error=False, fill_value=0)
 
-    #interp phase to frequency
-    f_interp = interpolate.interp1d(phase_fine, fine_f,kind = interp,bounds_error = False,fill_value = 0)
-
-    phase_small = np.linspace(np.min(phase_fine),np.max(phase_fine),1000)
+    phase_small = np.linspace(np.min(phase_fine), np.max(phase_fine), 1000)
     freqs_stream = f_interp(phase_stream)
-    stream_df_over_f_all = stream_df_over_f = freqs_stream/np.mean(freqs_stream)-1.
+    stream_df_over_f_all = stream_df_over_f = freqs_stream / np.mean(freqs_stream) - 1.
 
     plt.subplot(248)
-    plt.plot(phase_fine,fine_f,'o')
-    plt.plot(phase_small,f_interp(phase_small),'--')
-    plt.plot(phase_stream[::plot_period],freqs_stream[::plot_period],'.')
-    plt.ylim(np.min(freqs_stream)-(np.max(freqs_stream)-np.min(freqs_stream))*3,np.max(freqs_stream)+(np.max(freqs_stream)-np.min(freqs_stream))*3)
-    plt.xlim(np.min(phase_stream)-np.pi/4,np.max(phase_stream)+np.pi/4)
+    plt.plot(phase_fine, fine_f, 'o')
+    plt.plot(phase_small, f_interp(phase_small), '--')
+    plt.plot(phase_stream[::plot_period], freqs_stream[::plot_period], '.')
+    plt.ylim(np.min(freqs_stream) - (np.max(freqs_stream) - np.min(freqs_stream)) * 3,
+             np.max(freqs_stream) + (np.max(freqs_stream) - np.min(freqs_stream)) * 3)
+    plt.xlim(np.min(phase_stream) - np.pi / 4, np.max(phase_stream) + np.pi / 4)
     plt.xlabel("phase")
     plt.ylabel("Frequency")
 
     plt.savefig("calibration.pdf")
 
-
     cal_dict = {'fine_z': fine_z,
-                        'gain_z': gain_z,
-                        'stream_z': stream_z,
-                        'fine_freqs':fine_f,
-                        'gain_freqs':gain_f,
-                        'stream_corr':stream_corr,
-                        'gain_corr':gain_corr,
-                        'fine_corr':fine_corr,
-                        'stream_df_over_f':stream_df_over_f_all}
-
-    pickle.dump( cal_dict, open( "cal.p", "wb" ),2 )  
+                'gain_z': gain_z,
+                'stream_z': stream_z,
+                'fine_freqs': fine_f,
+                'gain_freqs': gain_f,
+                'stream_corr': stream_corr,
+                'gain_corr': gain_corr,
+                'fine_corr': fine_corr,
+                'stream_df_over_f': stream_df_over_f_all}
+
+    pickle.dump(cal_dict, open("cal.p", "wb"), 2)
     return cal_dict
 
 
-
 def noise(cal_dict, sample_rate, title=None):
-
-    fft_freqs,Sxx,S_per,S_par = calibrate.fft_noise(cal_dict['stream_corr'], cal_dict['stream_df_over_f'], sample_rate)
-    plot_bins = np.logspace(-3,np.log10(250000),1000)
-    binnedfreq =  binned_statistic(fft_freqs, fft_freqs, bins=plot_bins)[0] #bin the frequecy against itself   
+    fft_freqs, Sxx, S_per, S_par = calibrate.fft_noise(cal_dict['stream_corr'], cal_dict['stream_df_over_f'],
+                                                       sample_rate)
+    plot_bins = np.logspace(-3, np.log10(250000), 1000)
+    binnedfreq = binned_statistic(fft_freqs, fft_freqs, bins=plot_bins)[0]  # bin the frequecy against itself
     binnedpsd = binned_statistic(fft_freqs, np.abs(Sxx), bins=plot_bins)[0]
 
     binnedper = binned_statistic(fft_freqs, np.abs(S_per), bins=plot_bins)[0]
     binnedpar = binned_statistic(fft_freqs, np.abs(S_par), bins=plot_bins)[0]
-    amp_subtracted = np.abs(binnedpsd)*(binnedpar-binnedper)/binnedpar
+    amp_subtracted = np.abs(binnedpsd) * (binnedpar - binnedper) / binnedpar
 
-
-    fig = plt.figure(4,figsize = (16,6))
+    fig = plt.figure(4, figsize=(16, 6))
     plt.subplot(122)
     if title is None:
         plt.title("Sxx")
     else:
         plt.title('Sxx ' + title)
-    #plt.loglog(fft_freqs,np.abs(Sxx))                                                                      
-    plt.loglog(binnedfreq,np.abs(binnedpsd),linewidth = 2,label = "Sxx raw")
-    plt.loglog(binnedfreq,amp_subtracted,linewidth = 2,label = "raw amp subtracted")
-    #plt.ylim(10**-18,10**-15) 
+    # plt.loglog(fft_freqs,np.abs(Sxx))
+    plt.loglog(binnedfreq, np.abs(binnedpsd), linewidth=2, label="Sxx raw")
+    plt.loglog(binnedfreq, amp_subtracted, linewidth=2, label="raw amp subtracted")
+    # plt.ylim(10**-18,10**-15)
     plt.ylabel("Sxx (1/Hz)")
     plt.xlabel("Frequency (Hz)")
     plt.legend()
 
     plt.subplot(121)
-    #plt.loglog(fft_freqs,S_per)
-    #plt.loglog(fft_freqs,S_par)
-    plt.loglog(binnedfreq,binnedper,label = "amp noise")
-    plt.loglog(binnedfreq,binnedpar,label = "detect noise")
+    # plt.loglog(fft_freqs,S_per)
+    # plt.loglog(fft_freqs,S_par)
+    plt.loglog(binnedfreq, binnedper, label="amp noise")
+    plt.loglog(binnedfreq, binnedpar, label="detect noise")
     plt.legend()
-    #plt.ylim(10**2,10**6)
+    # plt.ylim(10**2,10**6)
     plt.xlabel("Frequency (Hz)")
 
     plt.savefig("psd.pdf")
 
-
-    psd_dict = {'fft_freqs':fft_freqs,
-                    'Sxx':Sxx,
-                    'S_per':S_per,
-                    'S_par':S_par,
-                    'binned_freqs':binnedfreq,
-                    'Sxx_binned':binnedpsd,
-                    'S_per_binned':binnedper,
-                    'S_par_binned':binnedpar,
-                    'amp_subtracted':amp_subtracted}
-
-    #save the psd dictionary
-    pickle.dump( psd_dict, open("psd.p", "wb" ),2 )
+    psd_dict = {'fft_freqs': fft_freqs,
+                'Sxx': Sxx,
+                'S_per': S_per,
+                'S_par': S_par,
+                'binned_freqs': binnedfreq,
+                'Sxx_binned': binnedpsd,
+                'S_per_binned': binnedper,
+                'S_par_binned': binnedpar,
+                'amp_subtracted': amp_subtracted}
+
+    # save the psd dictionary
+    pickle.dump(psd_dict, open("psd.p", "wb"), 2)
 
     return psd_dict
diff --git a/submm/KIDs/find_resonances_interactive.py b/submm/KIDs/find_resonances_interactive.py
index 7f9d1b9..391486b 100644
--- a/submm/KIDs/find_resonances_interactive.py
+++ b/submm/KIDs/find_resonances_interactive.py
@@ -1,20 +1,13 @@
+import os
+import platform
+from typing import NamedTuple
+
 import numpy as np
 import matplotlib.pyplot as plt
-import os
 from scipy import signal, fftpack
-import platform
-try:
-    from submm_python_routines.KIDs import resonance_fitting as rf
-except ModuleNotFoundError:
-    from submm.KIDs import resonance_fitting as rf
 from matplotlib.backends.backend_pdf import PdfPages
-from typing import NamedTuple
-try:
-    from PyQt5.QtCore import pyqtRemoveInputHook
-    pyqtRemoveInputHook() #input() breaks during interactive plot on linux without this if using Qt backend
-except:
-    pass
 
+from submm.KIDs.res.fitting import fit_nonlinear_iq, fit_nonlinear_mag
 
 """
 Standalone version of kidPy's find_KIDs_interactive
@@ -33,7 +26,7 @@
 """
 
 
-def open_stored_sweep(savepath,load_std = False):
+def open_stored_sweep(savepath, load_std=False):
     """Opens sweep data
        inputs:
            char savepath: The absolute path where sweep data is saved
@@ -53,9 +46,9 @@ def open_stored_sweep(savepath,load_std = False):
             stdQ_list.append(os.path.join(savepath, filename))
     Is = np.array([np.load(filename) for filename in I_list])
     Qs = np.array([np.load(filename) for filename in Q_list])
-    if len(stdI_list) >0:
-            std_Is = np.array([np.load(filename) for filename in stdI_list])
-            std_Qs = np.array([np.load(filename) for filename in stdQ_list])
+    if len(stdI_list) > 0:
+        std_Is = np.array([np.load(filename) for filename in stdI_list])
+        std_Qs = np.array([np.load(filename) for filename in stdQ_list])
     if load_std:
         return Is, Qs, std_Is, std_Qs
     else:
@@ -80,12 +73,12 @@ class InteractivePlot(object):
     frequencies should be supplied in Hz
     """
 
-    def __init__(self, chan_freqs, data, kid_idx, flags = None, f_old=None, data_old=None, kid_idx_old=None):
+    def __init__(self, chan_freqs, data, kid_idx, flags=None, f_old=None, data_old=None, kid_idx_old=None):
         plt.rcParams['keymap.forward'] = ['v']
         plt.rcParams['keymap.back'] = ['c', 'backspace']  # remove arrows from back and forward on plot
-        plt.rcParams['keymap.quit'] = ['k'] #remove q for quit make it k for kill
-        plt.rcParams['keymap.home'] = ['h'] #remove r for home only make it h
-        plt.rcParams['keymap.fullscreen'] = ['shift+='] #remove ('f', 'ctrl+f'), make +
+        plt.rcParams['keymap.quit'] = ['k']  # remove q for quit make it k for kill
+        plt.rcParams['keymap.home'] = ['h']  # remove r for home only make it h
+        plt.rcParams['keymap.fullscreen'] = ['shift+=']  # remove ('f', 'ctrl+f'), make +
         self.chan_freqs = chan_freqs
         self.data = data
         self.f_old = f_old
@@ -104,21 +97,24 @@ def __init__(self, chan_freqs, data, kid_idx, flags = None, f_old=None, data_old
         self.fig.canvas.mpl_connect('key_press_event', self.on_key_press)
         self.fig.canvas.mpl_connect('key_release_event', self.on_key_release)
         self.fig.canvas.mpl_connect('button_press_event', self.onClick)
-        self.l1, = self.ax.plot(self.chan_freqs/10**9, self.data)
+        self.l1, = self.ax.plot(self.chan_freqs / 10 ** 9, self.data)
         self.flagged_indexes = self.get_flagged_indexes()
-        self.fp1, = self.ax.plot(self.chan_freqs[self.flagged_indexes]/10**9, self.data[self.flagged_indexes], "yo", markersize=9)
-        self.p1, = self.ax.plot(self.chan_freqs[self.kid_idx]/10**9, self.data[self.kid_idx], "r*", markersize=8)
+        self.fp1, = self.ax.plot(self.chan_freqs[self.flagged_indexes] / 10 ** 9, self.data[self.flagged_indexes], "yo",
+                                 markersize=9)
+        self.p1, = self.ax.plot(self.chan_freqs[self.kid_idx] / 10 ** 9, self.data[self.kid_idx], "r*", markersize=8)
         self.text_dict = {}
         for i in range(0, len(self.kid_idx)):
-            self.text_dict[i] = plt.text(self.chan_freqs[self.kid_idx][i]/10**9, self.data[self.kid_idx][i], str(i))
+            self.text_dict[i] = plt.text(self.chan_freqs[self.kid_idx][i] / 10 ** 9, self.data[self.kid_idx][i], str(i))
 
         if isinstance(self.f_old, np.ndarray):
-            self.l2, = self.ax.plot(self.f_old/10**9, self.data_old, color="C0", alpha=0.25)
-            self.p2, = self.ax.plot(self.f_old[self.kid_idx_old]/10**9, self.data_old[self.kid_idx_old], "r*", markersize=8,
+            self.l2, = self.ax.plot(self.f_old / 10 ** 9, self.data_old, color="C0", alpha=0.25)
+            self.p2, = self.ax.plot(self.f_old[self.kid_idx_old] / 10 ** 9, self.data_old[self.kid_idx_old], "r*",
+                                    markersize=8,
                                     alpha=0.1)
             self.text_dict_old = {}
             for i in range(0, len(self.kid_idx_old)):
-                self.text_dict_old[i] = plt.text(self.f_old[self.kid_idx_old][i]/10**9, self.data_old[self.kid_idx_old][i],
+                self.text_dict_old[i] = plt.text(self.f_old[self.kid_idx_old][i] / 10 ** 9,
+                                                 self.data_old[self.kid_idx_old][i],
                                                  str(i), color='Grey')
 
         self.shift_is_held = False
@@ -161,7 +157,7 @@ def on_key_press(self, event):
 
         if event.key == 'f':
             self.f_is_held = True
-                
+
         if event.key == 'right':  # pan right
             xlim_left, xlim_right = self.ax.get_xlim()
             xlim_size = xlim_right - xlim_left
@@ -252,24 +248,24 @@ def onClick(self, event):
         if event.button == 3:
             if self.shift_is_held:  # add point
                 print("adding point", event.xdata)
-                self.kid_idx.append(np.argmin(np.abs(self.chan_freqs - event.xdata*10**9)))
+                self.kid_idx.append(np.argmin(np.abs(self.chan_freqs - event.xdata * 10 ** 9)))
                 self.flags.append([])
-                zipped_lists = zip(self.kid_idx,self.flags)
+                zipped_lists = zip(self.kid_idx, self.flags)
                 sorted_pairs = sorted(zipped_lists)
                 tuples = zip(*sorted_pairs)
                 self.kid_idx, self.flags = [list(tuple) for tuple in tuples]
-                #self.kid_idx.sort()
+                # self.kid_idx.sort()
                 self.refresh_plot()
             elif self.control_is_held:  # delete point
                 print("removing point", event.xdata)
-                delete_index = np.argmin(np.abs(self.chan_freqs[self.kid_idx] - event.xdata*10**9))
+                delete_index = np.argmin(np.abs(self.chan_freqs[self.kid_idx] - event.xdata * 10 ** 9))
                 self.kid_idx.pop(delete_index)
                 self.flags.pop(delete_index)
                 self.refresh_plot()
-            elif self.f_is_held: #flag resonator
+            elif self.f_is_held:  # flag resonator
                 print("flagging point", event.xdata)
-                flag_index = np.argmin(np.abs(self.chan_freqs[self.kid_idx] - event.xdata*10**9))
-                print("current flags: ",self.flags[flag_index])
+                flag_index = np.argmin(np.abs(self.chan_freqs[self.kid_idx] - event.xdata * 10 ** 9))
+                print("current flags: ", self.flags[flag_index])
                 flag = input("Enter flag string: ").lower()
                 if flag == "c":
                     flag = "collision"
@@ -278,20 +274,20 @@ def onClick(self, event):
                 else:
                     pass
                 self.flags[flag_index].append(flag)
-                print("Flags are now: ",self.flags[flag_index])
+                print("Flags are now: ", self.flags[flag_index])
                 self.refresh_plot()
             else:
                 print("please hold either the shift or control key while right clicking to add or remove points")
 
     def refresh_plot(self):
         self.flagged_indexes = self.get_flagged_indexes()
-        self.fp1.set_data(self.chan_freqs[self.flagged_indexes]/10**9, self.data[self.flagged_indexes])
-        self.p1.set_data(self.chan_freqs[self.kid_idx]/10**9, self.data[self.kid_idx])
+        self.fp1.set_data(self.chan_freqs[self.flagged_indexes] / 10 ** 9, self.data[self.flagged_indexes])
+        self.p1.set_data(self.chan_freqs[self.kid_idx] / 10 ** 9, self.data[self.kid_idx])
         for i in range(0, self.kid_idx_len):
             self.text_dict[i].set_text("")  # clear all of the texts
         self.text_dict = {}
         for i in range(0, len(self.kid_idx)):
-            self.text_dict[i] = plt.text(self.chan_freqs[self.kid_idx][i]/10**9, self.data[self.kid_idx][i], str(i))
+            self.text_dict[i] = plt.text(self.chan_freqs[self.kid_idx][i] / 10 ** 9, self.data[self.kid_idx][i], str(i))
         self.kid_idx_len = len(self.kid_idx)
         plt.draw()
 
@@ -303,8 +299,8 @@ def get_flagged_indexes(self):
             else:
                 flags_empty = False
         if not flags_empty:
-            zipped = zip(self.kid_idx,self.flags)
-            pairs_with_flags = [pair for pair in zipped if len(pair[1])>0]
+            zipped = zip(self.kid_idx, self.flags)
+            pairs_with_flags = [pair for pair in zipped if len(pair[1]) > 0]
             tuples = zip(*pairs_with_flags)
             flagged_indexes, just_flags = [list(tuple) for tuple in tuples]
             return flagged_indexes
@@ -319,12 +315,11 @@ def __init__(self, f_Hz, s21_mag, peak_threshold_dB, spacing_threshold_Hz=1.0e5,
         plt.rcParams['keymap.back'] = ['c', 'backspace']  # remove arrows from back and forward on plot
         self.peak_threshold_dB = peak_threshold_dB
         self.spacing_threshold_Hz = spacing_threshold_Hz
-        
 
         self.window_pad_factor = window_pad_factor
         self.fitter_pad_factor = fitter_pad_factor
         self.f_Hz = f_Hz
-        self.spacing_threshold_Q = np.mean(self.f_Hz)/self.spacing_threshold_Hz
+        self.spacing_threshold_Q = np.mean(self.f_Hz) / self.spacing_threshold_Hz
         self.f_GHz = f_Hz * 1.0e-9
         self.s21_mag = s21_mag
 
@@ -345,14 +340,16 @@ def __init__(self, f_Hz, s21_mag, peak_threshold_dB, spacing_threshold_Hz=1.0e5,
             print("Press up or down to change the threshold by 0.1 dB or press t to enter a custom threshold value.")
             print("Press left or right to change the spacing threshold or y to enter a custom threshold value.")
             print("Close all plots when finished")
-            self.ax.set_xlabel(F"Frequency (GHz)\n Spacing threshold {'%.2E' % self.spacing_threshold_Hz} Hz or Q~{'%.2E' % self.spacing_threshold_Q}")
+            self.ax.set_xlabel(
+                F"Frequency (GHz)\n Spacing threshold {'%.2E' % self.spacing_threshold_Hz} Hz or Q~{'%.2E' % self.spacing_threshold_Q}")
             plt.ylabel('Power (dB)')
-            self.ax.set_title(F"Threshold: 3 adjacent points under {'%2.2f' % self.peak_threshold_dB} dB.\n Found {'%.0f' % len(self.local_minima)} minima")
+            self.ax.set_title(
+                F"Threshold: 3 adjacent points under {'%2.2f' % self.peak_threshold_dB} dB.\n Found {'%.0f' % len(self.local_minima)} minima")
             plt.show(block=True)
 
     def on_key_press(self, event):
         # print event.key
-        # has to be shift and ctrl because remote viewers only forward
+        # has to be shifted and ctrl because remote viewers only forward
         # certain key combinations
         # print event.key == 'd'
         if event.key == 'up':
@@ -362,12 +359,12 @@ def on_key_press(self, event):
             self.peak_threshold_dB = self.peak_threshold_dB - 0.1
             self.refresh_plot()
         if event.key == 'left':
-            self.spacing_threshold_Hz = self.spacing_threshold_Hz/1.4
-            self.spacing_threshold_Q = np.mean(self.f_Hz)/self.spacing_threshold_Hz
+            self.spacing_threshold_Hz = self.spacing_threshold_Hz / 1.4
+            self.spacing_threshold_Q = np.mean(self.f_Hz) / self.spacing_threshold_Hz
             self.refresh_plot()
         if event.key == 'right':
-            self.spacing_threshold_Hz = self.spacing_threshold_Hz*1.4
-            self.spacing_threshold_Q = np.mean(self.f_Hz)/self.spacing_threshold_Hz
+            self.spacing_threshold_Hz = self.spacing_threshold_Hz * 1.4
+            self.spacing_threshold_Q = np.mean(self.f_Hz) / self.spacing_threshold_Hz
             self.refresh_plot()
         if event.key == 't':
             self.peak_threshold_dB = np.float(input("What threshold would you like in dB? "))
@@ -380,8 +377,10 @@ def refresh_plot(self):
         self.calc_regions()
         self.p1.set_data(self.f_GHz[self.ilo], self.s21_mag[self.ilo])
         self.p2.set_data(self.f_GHz[self.local_minima], self.s21_mag[self.local_minima])
-        self.ax.set_title(F"Threshold: 3 adjacent points under {'%2.2f' % self.peak_threshold_dB} dB.\n Found {'%.0f' % len(self.local_minima)} minima")
-        self.ax.set_xlabel(F"Frequency (GHz)\n Spacing threshold {'%.2E' % self.spacing_threshold_Hz} Hz or Q~{'%.2E' % self.spacing_threshold_Q}")
+        self.ax.set_title(
+            F"Threshold: 3 adjacent points under {'%2.2f' % self.peak_threshold_dB} dB.\n Found {'%.0f' % len(self.local_minima)} minima")
+        self.ax.set_xlabel(
+            F"Frequency (GHz)\n Spacing threshold {'%.2E' % self.spacing_threshold_Hz} Hz or Q~{'%.2E' % self.spacing_threshold_Q}")
         plt.draw()
 
     def calc_regions(self):
@@ -607,9 +606,8 @@ def filtered_differential(data, df, filtertype=None, do_deriv=True):
     return out
 
 
-
 class InteractiveFilterPlot(object):
-    def __init__(self, f_Hz, s21_mag,smoothing_scale_Hz=5.0e6):
+    def __init__(self, f_Hz, s21_mag, smoothing_scale_Hz=5.0e6):
         self.smoothing_scale_Hz = smoothing_scale_Hz
         self.f_Hz = f_Hz
         self.f_GHz = f_Hz * 1.0e-9
@@ -621,24 +619,24 @@ def __init__(self, f_Hz, s21_mag,smoothing_scale_Hz=5.0e6):
 
         # first plot data and filter function before removing filter function
         self.filtermags = lowpass_cosine(y=self.s21_mag,
-                                    tau=self.f_Hz[1] - self.f_Hz[0],
-                                    f_3db=1. / self.smoothing_scale_Hz,
-                                    width=0.1 * (1.0 / self.smoothing_scale_Hz),
-                                    padd_data=True)
+                                         tau=self.f_Hz[1] - self.f_Hz[0],
+                                         f_3db=1. / self.smoothing_scale_Hz,
+                                         width=0.1 * (1.0 / self.smoothing_scale_Hz),
+                                         padd_data=True)
         # the cosine filter drops the last point is the array has an pdd number of points
         self.len_filtered = len(self.filtermags)
         self.s21_mag = self.s21_mag[:self.len_filtered]
         self.f_Hz = self.f_Hz[:self.len_filtered]
         self.f_GHz = self.f_Hz * 1.0e-9
         # calculations for peak spacing (rejection based on threshold)
-        self.highpass_mags = self.s21_mag - self.filtermags        
+        self.highpass_mags = self.s21_mag - self.filtermags
         self.l1, = self.ax.plot(self.f_GHz, self.s21_mag, label='#nofilter')
         self.l2, = self.ax.plot(self.f_GHz, self.filtermags, label='#filter')
         self.ax.set_title(F"Smoothing Scale: {'%.2E' % self.smoothing_scale_Hz} Hz.")
-        plt.legend(loc = 1)
-
+        plt.legend(loc=1)
 
-        print("Press left or right to change the smothing scale by 10% or press t to enter a custom smoothing scale value.")
+        print(
+            "Press left or right to change the smothing scale by 10% or press t to enter a custom smoothing scale value.")
         print("Close all plots when finished")
         plt.xlabel('Frequency (GHz)')
         plt.ylabel('Power (dB)')
@@ -650,10 +648,10 @@ def on_key_press(self, event):
         # certain key combinations
         # print event.key == 'd'
         if event.key == 'left':
-            self.smoothing_scale_Hz = self.smoothing_scale_Hz/1.4
+            self.smoothing_scale_Hz = self.smoothing_scale_Hz / 1.4
             self.refresh_plot()
         if event.key == 'right':
-            self.smoothing_scale_Hz = self.smoothing_scale_Hz*1.4
+            self.smoothing_scale_Hz = self.smoothing_scale_Hz * 1.4
             self.refresh_plot()
         if event.key == 't':
             self.smoothing_scale_Hz = np.float(input("What smoothing scale would you like in Hz? "))
@@ -662,10 +660,10 @@ def on_key_press(self, event):
     def refresh_plot(self):
         # first plot data and filter function before removing filter function
         self.filtermags = lowpass_cosine(y=self.s21_mag,
-                                    tau=self.f_Hz[1] - self.f_Hz[0],
-                                    f_3db=1. / self.smoothing_scale_Hz,
-                                    width=0.1 * (1.0 / self.smoothing_scale_Hz),
-                                    padd_data=True)
+                                         tau=self.f_Hz[1] - self.f_Hz[0],
+                                         f_3db=1. / self.smoothing_scale_Hz,
+                                         width=0.1 * (1.0 / self.smoothing_scale_Hz),
+                                         padd_data=True)
         # the cosine filter drops the last point is the array has an odd number of points
         self.len_filtered = len(self.filtermags)
         self.s21_mag = self.s21_mag[:self.len_filtered]
@@ -676,7 +674,7 @@ def refresh_plot(self):
         self.l1.set_data(self.f_GHz, self.s21_mag)
         self.l2.set_data(self.f_GHz, self.filtermags)
         self.ax.set_title(F"Smoothing Scale: {'%.2E' % self.smoothing_scale_Hz} Hz.")
-    
+
         plt.draw()
 
 
@@ -716,7 +714,7 @@ def lowpass_cosine(y, tau, f_3db, width, padd_data=True):
     nyquist = 1.0 / (2.0 * tau)
     freq = np.arange(-nyquist, nyquist, delta)
     # turn this into a positive frequency array
-    #print((len(ffty) // 2))
+    # print((len(ffty) // 2))
     pos_freq = freq[(len(ffty) // 2):]
     # make the transfer function for the first half of the data
     i_f_3db = min(np.where(pos_freq >= f_3db)[0])
@@ -747,9 +745,8 @@ def find_vna_sweep(f_Hz, z, smoothing_scale_Hz=5.0e6, spacing_threshold_Hz=1.0e5
     spacing threshold (Hz)
     """
     # first plot data and filter function before removing filter function
-    s21_mag = 20*np.log10(np.abs(z))
-    ipf = InteractiveFilterPlot(f_Hz,s21_mag,smoothing_scale_Hz = smoothing_scale_Hz)
-    
+    s21_mag = 20 * np.log10(np.abs(z))
+    ipf = InteractiveFilterPlot(f_Hz, s21_mag, smoothing_scale_Hz=smoothing_scale_Hz)
 
     # identify peaks using the interactive threshold plot
     ipt = InteractiveThresholdPlot(f_Hz=ipf.f_Hz,
@@ -758,7 +755,7 @@ def find_vna_sweep(f_Hz, z, smoothing_scale_Hz=5.0e6, spacing_threshold_Hz=1.0e5
                                    spacing_threshold_Hz=spacing_threshold_Hz)
 
     # Zero everything but the resonators
-    #highpass_mags[highpass_mags > -1.0 * ipt.peak_threshold_dB] = 0
+    # highpass_mags[highpass_mags > -1.0 * ipt.peak_threshold_dB] = 0
 
     # the spacing thresholding was move to be inside the interactive threshold class
     kid_idx = ipt.local_minima
@@ -766,14 +763,14 @@ def find_vna_sweep(f_Hz, z, smoothing_scale_Hz=5.0e6, spacing_threshold_Hz=1.0e5
     return ip
 
 
-def slice_vna(f, z, kid_index, q_slice=2000,flag_collided = True):
+def slice_vna(f, z, kid_index, q_slice=2000, flag_collided=True):
     # make f in Hz for fitting
     # Q = f/(delta f) for fitting is determined by the lowest frequencies assumed to be at index 0
     # delta f = f/Q
     df = f[1] - f[0]
     n_iq_points = int(f[0] / q_slice // df)
-    if np.mod(n_iq_points,2) == 0:
-        n_iq_points = n_iq_points+1
+    if np.mod(n_iq_points, 2) == 0:
+        n_iq_points = n_iq_points + 1
     print(n_iq_points)
     res_freq_array = np.zeros((len(kid_index), n_iq_points))
     res_array = np.zeros((len(kid_index), n_iq_points)).astype('complex')
@@ -812,8 +809,8 @@ def fit_slices(res_freq_array, res_array, do_plots=True, plot_filename='fits'):
         if do_plots:
             fig = plt.figure(i, figsize=(12, 6))
         try:
-            fit = rf.fit_nonlinear_iq(res_freq_array[i, :][~np.isnan(res_freq_array[i, :])],
-                                      res_array[i, :][~np.isnan(res_array[i, :])])
+            fit = fit_nonlinear_iq(res_freq_array[i, :][~np.isnan(res_freq_array[i, :])],
+                                   res_array[i, :][~np.isnan(res_array[i, :])])
             fits_dict_iq[i] = fit
             if do_plots:
                 plt.subplot(121)
@@ -823,12 +820,12 @@ def fit_slices(res_freq_array, res_array, do_plots=True, plot_filename='fits'):
                 plt.legend()
         except Exception as inst:
             print("could not fit")
-            print(type(inst))    # the exception instance
-            print(inst.args)     # arguments stored in .args
-            #print(inst)          # __str__ allows args to be printed directly,
+            print(type(inst))  # the exception instance
+            print(inst.args)  # arguments stored in .args
+            # print(inst)          # __str__ allows args to be printed directly,
             fits_dict_iq[i] = 'bad fit'
         try:
-            fit2 = rf.fit_nonlinear_mag(res_freq_array[i, :][~np.isnan(res_freq_array[i, :])],
+            fit2 = fit_nonlinear_mag(res_freq_array[i, :][~np.isnan(res_freq_array[i, :])],
                                         res_array[i, :][~np.isnan(res_array[i, :])])
             fits_dict_mag[i] = fit2
             if do_plots:
@@ -841,9 +838,9 @@ def fit_slices(res_freq_array, res_array, do_plots=True, plot_filename='fits'):
                 plt.legend()
         except Exception as inst:
             print("could not fit")
-            print(type(inst))    # the exception instance
-            print(inst.args)     # arguments stored in .args
-            #print(inst)          # __str__ allows args to be printed directly,
+            print(type(inst))  # the exception instance
+            print(inst.args)  # arguments stored in .args
+            # print(inst)          # __str__ allows args to be printed directly,
             fits_dict_mag[i] = 'bad fit'
         if do_plots:
             pdf_pages.savefig(fig)
@@ -872,6 +869,6 @@ def retune_vna(f, z, kid_index, n_points_look_around=0, look_low_high=[0, 0], f_
             kid_index[i] = new_index
 
     ip = InteractivePlot(f, 20 * np.log10(np.abs(z)), kid_index, f_old=f_old, data_old=20 * np.log10(np.abs(z_old)),
-                          kid_idx_old=kid_index_old)
+                         kid_idx_old=kid_index_old)
 
     return ip
diff --git a/submm/KIDs/res/__init__.py b/submm/KIDs/res/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/submm/KIDs/res/data_io.py b/submm/KIDs/res/data_io.py
new file mode 100644
index 0000000..2d11b33
--- /dev/null
+++ b/submm/KIDs/res/data_io.py
@@ -0,0 +1,418 @@
+"""
+Automated data storage and inspections tools for the various fitting functions
+"""
+
+import os
+from operator import attrgetter
+from typing import NamedTuple, Optional, Callable, Sequence
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+from submm.sample_data.abs_paths import abs_path_output_dir_default
+from submm.KIDs.res.utils import derived_text, filename_text, write_text, calc_qc_qi, line_format
+
+
+derived_params = {'qi', 'qc', 'red_chi_sqr'}
+field_to_first_format_int = {'fr': 5, 'qr': 7, 'amp': 1, 'phi': 2, 'a': 1, 'b0': 2, 'b1': 2, 'i0': 1, 'q0': 1, 'tau': 6,
+                             'f0': 5, 'qi': 7, 'qc': 7}
+field_to_decimal_format_int = {'fr': 4, 'qr': 0, 'amp': 2, 'phi': 2, 'a': 2, 'b0': 2, 'b1': 2, 'i0': 2, 'q0': 2,
+                               'tau': 2, 'f0': 4, 'qi': 0, 'qc': 0}
+field_to_format_letter = {'fr': 'f', 'qr': 'f', 'amp': 'f', 'phi': 'f', 'a': 'f', 'b0': 'E', 'b1': 'E', 'i0': 'E',
+                          'q0': 'E', 'tau': 'f', 'f0': 'f', 'qi': 'f', 'qc': 'f'}
+filed_to_field_label = {'fr': 'fr (MHz)', 'qr': 'Qr', 'amp': 'amp', 'phi': 'phi', 'a': 'a', 'b0': 'b0', 'b1': 'b1',
+                        'i0': 'i0', 'q0': 'q0', 'tau': 'tau (ns)', 'f0': 'f0 (MHz)', 'qi': 'Qi', 'qc': 'Qc'}
+field_to_multiplier = {'fr': 1.0e-6, 'tau': 1.0e9, 'f0': 1.0e-6}
+
+field_to_format_strs = {}
+field_to_text_len = {}
+for a_field in field_to_first_format_int.keys():
+    first_format_int = field_to_first_format_int[a_field]
+    decimal_format_int = field_to_decimal_format_int[a_field]
+    format_letter = field_to_format_letter[a_field]
+    field_to_format_strs[a_field] = f'{first_format_int}.{decimal_format_int}{format_letter}'
+    # the + 1 is to account for negative numbers with the extra '-'
+    text_len = first_format_int + decimal_format_int + 1
+    if decimal_format_int > 0:
+        # add a space for the decimal point
+        text_len += 1
+    if format_letter.lower() == 'e':
+        text_len += 4
+    field_to_text_len[a_field] = max(text_len, len(filed_to_field_label[a_field]))
+
+
+def format_field_value(field, value):
+    field = field.lower().strip()
+    if field in field_to_multiplier.keys():
+        value *= field_to_multiplier[field]
+    number_str = value.__format__(field_to_format_strs[field])
+    return number_str.center(field_to_text_len[field])
+
+
+def calc_left_right_spaces(text, total_space_available):
+    if len(text) > total_space_available:
+        return '', '', ' ' * (len(text) - total_space_available)
+    else:
+        right_space = (total_space_available - len(text)) // 2
+        left_space = total_space_available - right_space - len(text)
+        return ' ' * left_space, ' ' * right_space, ''
+
+
+class Res(NamedTuple):
+    """
+    base class for resonator parameters then a determined by a single fit
+    Needs to be mixed in with a typing.NamedTuple
+    """
+
+    def __getitem__(self, item):
+        if isinstance(item, str):
+            return getattr(self, item)
+        elif isinstance(item, int):
+            return self._asdict()[self._fields[item]]
+        elif isinstance(item, slice):
+            return tuple([self._asdict()[field] for field in self._fields[item]])
+        else:
+            raise TypeError(f"ResFit indices must be str, int, or slice, not {type(item)}")
+
+    def header_items(self):
+        for field in self._fields:
+            yield field
+
+    def header(self):
+        header_str = ''
+        for field in self.header_items():
+            header_str += f'{field},'
+        return header_str[:-1]
+
+    def input_items(self):
+        for field in self.header_items():
+            if field.lower() not in derived_params:
+                yield field
+
+    def __str__(self):
+        return_str = ''
+        for field in self.header_items():
+            return_str += f"{self.__getattribute__(field)},"
+        return return_str[:-1]
+
+    def console(self, label: str = None, print_header: bool = True, fields=None):
+        if label is None:
+            label = ''
+        if fields is None:
+            found_fields = {}
+            # non-derived parameters
+            for field in self.input_items():
+                value = self.__getattribute__(field)
+                if value is not None:
+                    found_fields[field.lower()] = value
+            # derived parameters
+            found_derived = {}
+            Qi = self.Qi
+            Qc = self.Qc
+            if (Qc is None or Qi is None) and 'qr' in found_fields.keys() and 'amp' in found_fields.keys():
+                Qc, Qi = calc_qc_qi(qr=self.Qr, amp=self.amp)
+            if Qi is not None:
+                found_derived['qi'] = Qi
+            if Qc is not None:
+                found_derived['qc'] = Qc
+
+        else:
+            found_fields = {}
+            found_derived = {}
+            for field in fields:
+                if field.lower() in derived_params:
+                    found_derived[field.lower()] = self.__getattribute__(field)
+                else:
+                    found_fields[field.lower()] = self.__getattribute__(field)
+        # determine console output
+        len_label = max(5, len(label))
+        label_spaces = ' ' * len_label
+        total_len_var_fit = sum([field_to_text_len[field] for field in found_fields.keys()])
+        total_len_var_fit += len(found_fields.keys()) - 1
+        var_fit_label = ' Variables fit '
+        var_fit_left_space, var_fit_right_space, var_fit_extra_header = \
+            calc_left_right_spaces(text=var_fit_label, total_space_available=total_len_var_fit)
+        derived_label = ' Derived variables '
+        total_len_derived = sum([field_to_text_len[field] for field in found_derived.keys()])
+        total_len_derived += len(found_derived.keys()) - 1
+        derived_fit_left_space, derived_fit_right_space, derived_fit_extra_header = \
+            calc_left_right_spaces(text=derived_label, total_space_available=total_len_derived)
+        # header only console output
+        if print_header:
+            if self.fr is None:
+                fr_mhz = '(Frequency not found)'
+            else:
+                fr_mhz = f'{self.fr / 1e6:.2f} MHz'
+            print(f'Resonator at {fr_mhz}')
+            super_header = f'{label_spaces}|{var_fit_left_space}{var_fit_label}{var_fit_right_space}'
+            sub_header = f'{label_spaces}|'
+            first_field = True
+            for field in found_fields.keys():
+                field_len = field_to_text_len[field]
+                formatted_field = filed_to_field_label[field].center(field_len)
+                if first_field:
+                    sub_header += f'{formatted_field}'
+                    first_field = False
+                else:
+                    sub_header += f'|{formatted_field}'
+            sub_header += var_fit_extra_header
+            if found_derived:
+                super_header += '|' + derived_text(f'{derived_fit_left_space}{derived_label}{derived_fit_right_space}')
+                sub_header += '|'
+                first_field = True
+                for field in found_derived.keys():
+                    field_len = field_to_text_len[field]
+                    formatted_field = filed_to_field_label[field].center(field_len)
+                    if first_field:
+                        sub_header += derived_text(f'{formatted_field}')
+                        first_field = False
+                    else:
+                        sub_header += derived_text(f'|{formatted_field}')
+
+                if derived_fit_extra_header != '':
+                    sub_header += derived_text(derived_fit_extra_header)
+            print(super_header)
+            print(sub_header)
+        # values output for console
+        values_str = label.__format__(f'<{len_label}')
+        for field in found_fields.keys():
+            values_str += '|' + format_field_value(field, found_fields[field])
+        values_str += var_fit_extra_header
+        if found_derived:
+            first_field = True
+            values_str += '|'
+            for field in found_derived.keys():
+                if first_field:
+                    values_str += derived_text(format_field_value(field, found_derived[field]))
+                    first_field = False
+                else:
+                    values_str += derived_text('|' + format_field_value(field, found_derived[field]))
+            if derived_fit_extra_header != '':
+                values_str += derived_text(derived_fit_extra_header)
+        print(values_str)
+
+
+class NonlinearIQResBase(NamedTuple):
+    """ Base resonator parameters for a NonLinear IQ fit, nonlinear_iq_for_fitter()"""
+    fr: Optional[float] = None
+    Qr: Optional[float] = None
+    amp: Optional[float] = None
+    phi: Optional[float] = None
+    a: Optional[float] = None
+    i0: Optional[float] = None
+    q0: Optional[float] = None
+    tau: Optional[float] = None
+    f0: Optional[float] = None
+    red_chi_sq: Optional[float] = None
+    Qi: Optional[float] = None
+    Qc: Optional[float] = None
+
+
+class NonlinearIQRes(NonlinearIQResBase, Res):
+    """ The resonator parameters for a NonLinear IQ fit, nonlinear_iq_for_fitter()"""
+
+
+class NonlinearMagResBase(NonlinearIQResBase):
+    """ Base resonator parameters for a NonLinear Mag fit, fit_nonlinear_mag()"""
+    fr: Optional[float] = None
+    Qr: Optional[float] = None
+    amp: Optional[float] = None
+    phi: Optional[float] = None
+    a: Optional[float] = None
+    b0: Optional[float] = None
+    b1: Optional[float] = None
+    flin: Optional[float] = None
+    red_chi_sq: Optional[float] = None
+    Qi: Optional[float] = None
+    Qc: Optional[float] = None
+
+
+class NonlinearMagRes(NonlinearMagResBase, Res):
+    """ The resonator parameters for a NonLinear Mag fit, fit_nonlinear_mag()"""
+
+
+class LinearMagResBase(NamedTuple):
+    """ Base resonator parameters for a Linear Mag fit, fit_linear_mag(), linear_mag()"""
+    fr: Optional[float] = None
+    Qr: Optional[float] = None
+    amp: Optional[float] = None
+    phi: Optional[float] = None
+    b0: Optional[float] = None
+    red_chi_sq: Optional[float] = None
+    Qi: Optional[float] = None
+    Qc: Optional[float] = None
+
+
+class LinearMagRes(LinearMagResBase, Res):
+    """ The resonator parameters for a Linear Mag fit, fit_linear_mag(), linear_mag()"""
+
+
+class Fit(NamedTuple):
+    origin: str
+    func: Callable
+    guess: Optional[Res] = None
+    result:  Optional[Res] = None
+    pcov: Optional[np.ndarray] = None
+    f_data: Optional[np.ndarray] = None
+    z_data: Optional[np.ndarray] = None
+    mask: Optional[np.ndarray] = None
+
+    def __getitem__(self, item):
+        if isinstance(item, str):
+            # this could be a field of the result
+            if item in self._fields:
+                return getattr(self, item)
+            elif item in self.result._fields:
+                return getattr(self.result, item)
+            elif item.lower() == 'fit':
+                return self.result, self.pcov
+            elif item.lower() == 'fit_result':
+                return self.z_fit()
+            elif item.lower() == 'x0_result':
+                return self.z_guess()
+            elif item.lower() == 'x0':
+                return self.guess
+            elif item.lower() == 'z':
+                return self.z_data
+            else:
+                raise KeyError(f'Unknown string key: {item}')
+        elif isinstance(item, int):
+            return self._asdict()[self._fields[item]]
+        elif isinstance(item, slice):
+            return tuple([self._asdict()[field] for field in self._fields[item]])
+        else:
+            raise TypeError(f"ResFit indices must be str, int, or slice, not {type(item)}")
+
+    """ Base class for a resonator fit results """
+    def z_fit(self) -> np.ndarray:
+        """Return the complex impedance of the fit."""
+        return self.func(self.f_data, *self.result[0:-len(derived_params)])
+
+    def z_guess(self) -> np.ndarray:
+        """Return the complex impedance of the guess."""
+        return self.func(self.f_data, *self.guess[0:-len(derived_params)])
+
+    def plot(self, show=True):
+        plt.figure()
+        plt.axes().set_aspect('equal')
+        plt.plot(np.real(self.z_data), np.imag(self.z_data), 'o', label="Input Data")
+        z_guess = self.z_guess()
+        plt.plot(np.real(z_guess), np.imag(z_guess), label="Initial Guess")
+        z_fit = self.z_fit()
+        plt.plot(np.real(z_fit), np.imag(z_fit), label="Fit Results")
+        plt.xlabel('Real')
+        plt.ylabel('Imaginary')
+        plt.legend()
+        if show:
+            plt.show()
+
+    def console(self, print_header=True, fields=None):
+        if self.guess is None:
+            if self.result is None:
+                print('No fit results')
+            else:
+                self.result.console(label='Fit', print_header=print_header, fields=fields)
+        else:
+            self.guess.console(label='Guess', print_header=print_header, fields=fields)
+            self.result.console(label='Fit', print_header=False, fields=fields)
+
+
+class ResSet:
+    def __init__(self, path: str = None, res_results: Sequence[Res] = None, res_fits: Sequence[Fit] = None,
+                 verbose: bool = True):
+        self.verbose = verbose
+        if path is None:
+            # use the default output directory, make it if it doesn't exist
+            if not os.path.exists(abs_path_output_dir_default):
+                os.mkdir(abs_path_output_dir_default)
+            res_set_dir = os.path.join(abs_path_output_dir_default, 'res_set')
+            if not os.path.exists(res_set_dir):
+                os.mkdir(res_set_dir)
+            # use a default file name buy do not overwrite an existing file
+            count = 0
+            path_test = os.path.join(res_set_dir, f'results{count:02}.csv')
+            # loop until we find a file name that doesn't exist
+            while os.path.exists(path_test):
+                count += 1
+                path_test = os.path.join(res_set_dir, f'results{count:02}.csv')
+            self.res_set_dir = res_set_dir
+            self.path = path_test
+        else:
+            # use the user specified path
+            self.path = path
+            self.res_set_dir = os.path.dirname(path)
+            # make a new directory if it doesn't exist
+            if not os.path.exists(self.res_set_dir):
+                os.mkdir(self.res_set_dir)
+
+        # set in self.read(), self.add_results(), self.add_res_fits methods
+        self.results = set()
+        # set only in the self.add_res_fits method
+        self.fit_results = {}
+
+        if res_results is None and res_fits is None:
+            if self.verbose:
+                print(f'No fits on initialization, triggering a read in of the the results.')
+            self.read()
+        else:
+            if res_results is not None:
+                self.add_results(res_results)
+            if res_fits is not None:
+                self.add_res_fits(res_fits)
+
+    def __iter__(self):
+        # iterate over the results in order of resonator frequency
+        for result in sorted(self.results, key=attrgetter('fr')):
+            yield result
+
+    def read(self, res_tuple=NonlinearIQRes):
+        if self.verbose:
+            print(f'Reading results from file at: {filename_text(self.path)}')
+        header_keys = []
+        with open(self.path, 'r') as f:
+            for line in f.readlines():
+                if not header_keys:
+                    # read the header, see what can be mapped into the NamedTuple specified with res_tuple
+                    header_keys_raw = line.strip().split(',')
+                    one_key_found = False
+                    for header_key in header_keys_raw:
+                        if header_key in res_tuple._fields:
+                            header_keys.append(header_key)
+                            one_key_found = True
+                        else:
+                            header_keys.append(None)
+                    if not one_key_found:
+                        raise ValueError(f'No valid header keys found in {self.path} ' +
+                                         f'for the header keys {header_keys_raw} and tuple fields: {res_tuple._fields}')
+                else:
+                    # read the data after a successful header read
+                    row_dict = {header_key: value_formatted for header_key, value_formatted
+                                in zip(header_keys, line_format(line)) if header_key is not None}
+                    self.results.add(res_tuple(**row_dict))
+
+    def write(self):
+        with open(self.path, 'w') as f:
+            first_row = True
+            for result in self:
+                # write the header
+                if first_row:
+                    f.write(result.header() + '\n')
+                    first_row = False
+                # write the results
+                f.write(str(result) + '\n')
+        if self.verbose:
+            print(f'{write_text("Results Written")} to file at: {filename_text(self.path)}')
+
+    def add_results(self, res_results: Sequence[Res]):
+        self.results.update(res_results)
+        if self.verbose:
+            print(f'Added {len(res_results)} results.')
+
+    def add_res_fits(self, res_fits: Sequence[Fit]):
+        for res_fit in res_fits:
+            result = res_fit.result
+            self.results.add(result)
+            self.fit_results[result] = res_fit
+        if self.verbose:
+            print(f'Added {len(res_fits)} results and fit_results.')
+
diff --git a/submm/KIDs/res/fit_funcs.py b/submm/KIDs/res/fit_funcs.py
new file mode 100644
index 0000000..ea49787
--- /dev/null
+++ b/submm/KIDs/res/fit_funcs.py
@@ -0,0 +1,279 @@
+import numpy as np
+from numba import jit
+
+from submm.KIDs.res.utils import cardan
+
+
+# at import time, create a dictionary of all the fitting functions in this module
+fitting_functions = {}
+
+
+def fit_func(func):
+    """Decorator to add a function to the fitting_functions dictionary"""
+    name_type = func.__name__
+    fitting_functions[name_type] = func
+    return func
+
+
+@fit_func
+@jit(nopython=True)
+def nonlinear_mag(f_hz, fr, Qr, amp, phi, a, b0, b1, flin):
+    """
+    function to describe the magnitude S21 of a non-linear resonator
+
+    This is based of fitting code from MUSIC
+    The idea is we are producing a model that is described by the equation below
+    the first two terms in the large parenthesis and all other terms are familiar to me,
+    but I am not sure where the last term comes from though it does seem to be important for fitting
+
+                              /        (j phi)            (j phi)    |  2
+    |S21|^2 = (b0+b1 x_lin)* |1 -amp*e^           +amp*(e^       -1) |^
+                             |   ------------      ----              |
+                             \     (1+ 2jy)         2               /
+
+        where the nonlinearity of y is described by the following equation taken from Response of superconducting
+        micro-resonators with nonlinear kinetic inductance:
+            yg = y+ a/(1+y^2)  where yg = Qr*xg and xg = (f-fr)/fr
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        The frequencies in your iq sweep covers in Hertz
+    fr : float
+        The center frequency of the resonator
+    Qr : float
+       The quality factor of the resonator
+    amp : float
+        Amplitude as Qr/Qc
+    phi : float
+        The rotation parameter for an impedance mismatch between the resonator and the readout system
+    a : float
+        The nonlinearity parameter, bifurcation occurs at a = 0.77
+    b0 : float
+        DC level of s21 away from resonator
+    b1 : float
+        Frequency dependant gain variation
+    flin : float
+        This is probably the frequency of the resonator when a = 0
+
+    Returns
+    -------
+    ResFit
+    """
+    xlin = (f_hz - flin) / flin
+    xg = (f_hz - fr) / fr
+    yg = Qr * xg
+    y = np.zeros(f_hz.shape[0])
+    # find the roots of the y equation above
+    for i in range(0, f_hz.shape[0]):
+        """
+        4y^3+ -4yg*y^2+ y -(yg+a)
+        roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
+        roots = cardan(4.0,-4.0*yg[i],1.0,-(yg[i]+a))
+        print(roots)
+        # more accurate version that doesn't seem to change the fit at all
+        # only cares about real roots
+        roots = np.roots((16.,-16.*yg[i],8.,-8.*yg[i]+4*a*yg[i]/Qr-4*a,1.,-yg[i]+a*yg[i]/Qr-a+a**2/Qr))       
+        where_real = np.where(np.imag(roots) == 0)
+        # analytic version has some floating point error accumulation
+        where_real = np.where(np.abs(np.imag(roots)) < 1e-10) 
+        """
+        # np.max(np.real(roots[where_real]))
+        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))
+    abs_val = np.abs(1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0))
+    z = (b0 + b1 * xlin) * abs_val ** 2
+    return z
+
+
+def nonlinear_mag_for_plot(f_hz, fr, Qr, amp, phi, a, b0, b1, flin):
+    """
+    The square root of the above function, nonlinear_mag(), needed for visualization and plotting
+    function to describe the magnitude S21 of a non-linear resonator
+
+    This is based of fitting code from MUSIC
+    The idea is we are producing a model that is described by the equation below
+    the first two terms in the large parenthesis and all other terms are familiar to me,
+    but I am not sure where the last term comes from though it does seem to be important for fitting
+
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        The frequencies in your iq sweep covers in Hertz
+    fr : float
+        The center frequency of the resonator
+    Qr : float
+       The quality factor of the resonator
+    amp : float
+        Amplitude as Qr/Qc
+    phi : float
+        The rotation parameter for an impedance mismatch between the resonator and the readout system
+    a : float
+        The nonlinearity parameter, bifurcation occurs at a = 0.77
+    b0 : float
+        DC level of s21 away from resonator
+    b1 : float
+        Frequency dependant gain variation
+    flin : float
+        This is probably the frequency of the resonator when a = 0
+
+    Returns
+    -------
+    ResFit
+    """
+    return np.sqrt(nonlinear_mag(f_hz=f_hz, fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, b0=b0, b1=b1, flin=flin))
+
+
+@fit_func
+@jit(nopython=True)
+def linear_mag(f_hz, fr, Qr, amp, phi, b0):
+    """
+    This is based of fitting code from MUSIC
+    The idea is we are producing a model that is described by the equation below
+    the first two terms in the large parenthesis and all other terms are familiar to me,
+    but I am not sure where the last term comes from though it does seem to be important for fitting
+
+                     /        (j phi)            (j phi)    |  2
+    |S21|^2 = (b0)* |1 -amp*e^           +amp*(e^       -1) |^
+                    |   ------------      ----              |
+                    \     (1+ 2jxg)         2              /
+
+        no y just xg, with no non-linear kinetic inductance
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        The frequencies in your iq sweep covers
+    fr : float
+        The center frequency of the resonator
+    Qr : float
+       The quality factor of the resonator
+    amp : float
+        Amplitude as Qr/Qc
+    phi : float
+        The rotation parameter for an impedance mismatch between the resonator and the readout system
+    b0 : float
+        DC level of s21 away from resonator
+
+    """
+    if not np.isscalar(fr):  # vectorize breaks numba though
+        f_hz = np.reshape(f_hz, (f_hz.shape[0], 1, 1, 1, 1, 1))
+    xg = (f_hz - fr) / fr
+    z = (b0) * np.abs(
+        1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * xg * Qr) + amp / 2. * (np.exp(1.0j * phi) - 1.0)) ** 2
+    return z
+
+
+def linear_mag_for_plot(f_hz, fr, Qr, amp, phi, b0):
+    """
+    The square root of the above function, linear_mag(), need for visualization and plotting
+    This is based of fitting code from MUSIC
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        The frequencies in your iq sweep covers
+    fr : float
+        The center frequency of the resonator
+    Qr : float
+       The quality factor of the resonator
+    amp : float
+        Amplitude as Qr/Qc
+    phi : float
+        The rotation parameter for an impedance mismatch between the resonator and the readout system
+    b0 : float
+        DC level of s21 away from resonator
+
+    """
+    return np.sqrt(linear_mag(f_hz=f_hz, fr=fr, Qr=Qr, amp=amp, phi=phi, b0=b0))
+
+
+@fit_func
+@jit(nopython=True)
+def nonlinear_iq(f_hz, fr, Qr, amp, phi, a, i0, q0, tau, f0):
+    """
+    To describe the I-Q loop of a nonlinear resonator
+
+    This is based of fitting code from MUSIC
+
+    The idea is we are producing a model that is described by the equation below
+    the first two terms in the big parenthesis and all other terms are familiar to me,
+    but I am not sure where the last term comes from though it does seem to be important for fitting
+
+                       (-j 2 pi deltaf tau)  /        (j phi)            (j phi)   |
+           (i0+j*q0)*e^                    *|1 -amp*e^           +amp*(e^       -1) |
+                                            |   ------------      ----              |
+                                             \     (1+ 2jy)         2              /
+
+        where the nonlinearity of y is described by the following equation taken from Response of superconducting
+        micro resonators with nonlinear kinetic inductance:
+            yg = y+ a/(1+y^2)  where yg = Qr*xg and xg = (f-fr)/fr
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        The frequencies in your iq sweep covers
+    fr : float
+        The center frequency of the resonator
+    Qr : float
+       The quality factor of the resonator
+    amp : float
+        Amplitude as Qr/Qc
+    phi : float
+        The rotation parameter for an impedance mismatch between the resonator and the readout system
+    a : float
+        The nonlinearity parameter, bifurcation occurs at a = 0.77
+    i0 : float
+    q0 : float
+        these are constants that describes an overall phase rotation of the iq loop + a DC gain offset
+    tau : float
+        The cable delay
+    f0 : float
+        The center frequency, not sure why we include this as a secondary parameter should be the same as fr
+    """
+    deltaf = (f_hz - f0)
+    xg = (f_hz - fr) / fr
+    yg = Qr * xg
+    y = np.zeros(f_hz.shape[0])
+    # find the roots of the y equation above
+    for i in range(0, f_hz.shape[0]):
+        """
+        4y^3+ -4yg*y^2+ y -(yg+a)
+        roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
+        # more accurate version that doesn't seem to change the fit at al     
+        roots = np.roots((16.,-16.*yg[i],8.,-8.*yg[i]+4*a*yg[i]/Qr-4*a,1.,-yg[i]+a*yg[i]/Qr-a+a**2/Qr))
+        only care about real roots
+        where_real = np.where(np.imag(roots) == 0)
+        y[i] = np.max(np.real(roots[where_real]))
+        """
+        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))
+    big_parenthesis = (1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0))
+    z = (i0 + 1.j * q0) * np.exp(-1.0j * 2 * np.pi * deltaf * tau) * big_parenthesis
+    return z
+
+
+@fit_func
+@jit(nopython=True)
+def nonlinear_iq_for_fitter(f_hz, fr, Qr, amp, phi, a, i0, q0, tau, f0):
+    """
+    when using a fitter that can't handel complex number
+    one needs to return both the real and imaginary components separately
+    """
+
+    deltaf = (f_hz - f0)
+    xg = (f_hz - fr) / fr
+    yg = Qr * xg
+    y = np.zeros(f_hz.shape[0])
+
+    for i in range(0, f_hz.shape[0]):
+        """
+        roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
+        where_real = np.where(np.imag(roots) == 0)
+        y[i] = np.max(np.real(roots[where_real]))
+        """
+        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))
+    z = (i0 + 1.j * q0) * np.exp(-1.0j * 2 * np.pi * deltaf * tau) * (
+            1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0))
+    real_z = np.real(z)
+    imag_z = np.imag(z)
+    return np.hstack((real_z, imag_z))
diff --git a/submm/KIDs/res/fitting.py b/submm/KIDs/res/fitting.py
new file mode 100644
index 0000000..1abb602
--- /dev/null
+++ b/submm/KIDs/res/fitting.py
@@ -0,0 +1,641 @@
+"""
+numba seems to make the fitting 10 times faster
+
+module for fitting resonances curves for kinetic inductance detectors.
+written by Jordan Wheeler 12/21/16
+
+for example see res_fit.ipynb in this demos directory
+
+To Do
+I think the error analysis on the fit_nonlinear_iq_with_err probably needs some work
+add in step by step fitting i.e. first amplitude normalization, then cable delay, then i0,q0 subtraction,
+     then phase rotation, then the rest of the fit.
+need to have fit option that just specifies tau because that never really changes for your cryostat
+
+Change log
+JDW 2017-08-17 added in a keyword/function to allow for gain variation "amp_var" to be taken out before fitting
+JDW 2017-08-30 added in fitting for magnitude fitting of resonators i.e. not in iq space
+JDW 2018-03-05 added more clever function for guessing x0 for fits
+JDW 2018-08-23 added more clever guessing for resonators with large phi into guess separate functions
+CHW 2022-09-02 PEP-8 formatting, spelling corrections, and minor code cleanup
+"""
+import inspect
+
+import numpy as np
+import scipy.optimize as optimization
+
+from submm.KIDs.res.fit_funcs import linear_mag, nonlinear_mag, nonlinear_iq, nonlinear_iq_for_fitter, \
+    nonlinear_mag_for_plot, linear_mag_for_plot
+from submm.KIDs.res.data_io import Fit, ResSet, NonlinearIQRes, NonlinearMagRes, LinearMagRes
+from submm.KIDs.res.utils import amplitude_normalization, calc_qc_qi, guess_x0_iq_nonlinear, guess_x0_mag_nonlinear, \
+    guess_x0_iq_nonlinear_sep, guess_x0_mag_nonlinear_sep
+
+
+def fit_nonlinear_iq(f_hz, z, bounds=None, x0: list = None, fr_guess: float = None, tau=None, tau_guess=None,
+                     amp_norm: bool = False, verbose: bool = True):
+    """Fit a nonlinear IQ with from an S21 sweep.
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        frequencies Hz
+    z : numpy.array
+        complex s21
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess  = x0[0]
+        Qr_guess  = x0[1]
+        amp_guess = x0[2]
+        phi_guess = x0[3]
+        a_guess   = x0[4]
+        i0_guess  = x0[5]
+        q0_guess  = x0[6]
+        tau_guess = x0[7]
+        f0_guess  = x0[8]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    fr_guess : float, optional (default None)
+        The center resonator frequency in Hz. If None, the center frequency is calculated from the data.
+        This overrides the value (x0[0]) specified in the x0 parameter list.
+    tau : float, optional (default None)
+        If not None, this the fitter to use a fixed value for tau (phase delay), speeding up the calculation.
+    tau_guess: float, optional (default None)
+        Set the initial guess for tau without. This overrides the value (xo[7]) specified in the x0 parameter list.
+    amp_norm: bool, optional (default False)
+        When True, a normalization is preformed for the amplitude variable. This parameter is useful when the transfer
+        function of the cryostat is not flat.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+
+    if bounds is None:
+        # define default bounds
+        if verbose:
+            print("default bounds used")
+        bounds = ([np.min(f_hz), 50, .01, -np.pi, 0, -np.inf, -np.inf, 0, np.min(f_hz)],
+                  [np.max(f_hz), 200000, 1, np.pi, 5, np.inf, np.inf, 1 * 10 ** -6, np.max(f_hz)])
+    if x0 is None:
+        # define default initial guess
+        if verbose:
+            print("default initial guess used")
+        # fr_guess = x[np.argmin(np.abs(z))]
+        # x0 = [fr_guess,10000.,0.5,0,0,np.mean(np.real(z)),np.mean(np.imag(z)),3*10**-7,fr_guess]
+        x0 = guess_x0_iq_nonlinear(f_hz, z)
+        # print(x0)
+    if fr_guess is not None:
+        x0[0] = fr_guess
+    if tau is None:
+        use_given_tau = False
+    else:
+        use_given_tau = True
+    if tau_guess is not None:
+        x0[7] = tau_guess
+    if amp_norm:
+        z = amplitude_normalization(f_hz, z)
+    z_stacked = np.hstack((np.real(z), np.imag(z)))
+    # map the initial guess to the standard data record
+    guess = NonlinearIQRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+    if use_given_tau:
+        del bounds[0][7]
+        del bounds[1][7]
+        del x0[7]
+        popt, pcov = optimization.curve_fit(
+            lambda x_lamb, a, b, c, d, e, f, g, h: nonlinear_iq_for_fitter(x_lamb, a, b, c, d, e, f, g, tau, h), f_hz,
+            z_stacked, x0, bounds=bounds)
+        popt = np.insert(popt, 7, tau)
+        # fill covariance matrix#
+        cov = np.ones((pcov.shape[0] + 1, pcov.shape[1] + 1)) * -1
+        cov[0:7, 0:7] = pcov[0:7, 0:7]
+        cov[8, 8] = pcov[7, 7]
+        cov[8, 0:7] = pcov[7, 0:7]
+        cov[0:7, 8] = pcov[0:7, 7]
+        pcov = cov
+    else:
+        popt, pcov = optimization.curve_fit(nonlinear_iq_for_fitter, f_hz, z_stacked, x0, bounds=bounds)
+    # human-readable results
+    fr, Qr, amp, phi, a, i0, q0, tau, f0 = popt
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = NonlinearIQRes(fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, i0=i0, q0=q0, tau=tau, f0=f0, Qc=Qc, Qi=Qi)
+    if verbose:
+        guess.console(label='Fit', print_header=False)
+    # make a packaged result (NamedTuple) to return
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=nonlinear_iq,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+def fit_nonlinear_iq_sep(fine_f_hz, fine_z, gain_f_hz, gain_z,
+                         fine_z_err=None, gain_z_err=None, bounds=None, x0=None, amp_norm: bool = False,
+                         verbose: bool = True):
+    """Same as fit_nonlinear_iq() but takes fine and gain scans separately
+
+    Parameters
+    ----------
+    fine_f_hz : numpy.array
+        frequencies Hz
+    fine_z : numpy.array
+        complex s21
+    gain_f_hz : numpy.array
+        frequencies Hz
+    gain_z : numpy.array
+        complex s21
+    fine_z_err : numpy.array, optional (default None)
+        The error in the fine scan, expected to bve the same size as fine_z. If either fine_z_err or gain_z_err is None,
+        the error is not used.
+    gain_z_err : numpy.array, optional (default None)
+        The error in the gain scan, expected to bve the same size as gain_z. If either fine_z_err or gain_z_err is None,
+        the error is not used.
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess  = x0[0]
+        Qr_guess  = x0[1]
+        amp_guess = x0[2]
+        phi_guess = x0[3]
+        a_guess   = x0[4]
+        i0_guess  = x0[5]
+        q0_guess  = x0[6]
+        tau_guess = x0[7]
+        f0_guess  = x0[8]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    amp_norm : bool, optional (default False)
+        When True, a normalization is preformed for the amplitude variable. This parameter is useful when the transfer
+        function of the cryostat is not flat.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+    if bounds is None:
+        # define default bounds
+        print("default bounds used")
+        bounds = ([np.min(fine_f_hz), 500., .01, -np.pi, 0, -np.inf, -np.inf, 1 * 10 ** -9, np.min(fine_f_hz)],
+                  [np.max(fine_f_hz), 1000000, 1, np.pi, 5, np.inf, np.inf, 1 * 10 ** -6, np.max(fine_f_hz)])
+    if x0 is None:
+        # define default initial guess
+        print("default initial guess used")
+        # fr_guess = x[np.argmin(np.abs(z))]
+        # x0 = [fr_guess,10000.,0.5,0,0,np.mean(np.real(z)),np.mean(np.imag(z)),3*10**-7,fr_guess]
+        x0 = guess_x0_iq_nonlinear_sep(fine_f_hz, fine_z, gain_f_hz, gain_z)
+    f_hz = np.hstack((fine_f_hz, gain_f_hz))
+    z = np.hstack((fine_z, gain_z))
+    if amp_norm:
+        z = amplitude_normalization(f_hz, z)
+    z_stacked = np.hstack((np.real(z), np.imag(z)))
+    # map the initial guess to the standard data record
+    guess = NonlinearIQRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+    if fine_z_err is not None and gain_z_err is not None:
+        z_err = np.hstack((fine_z_err, gain_z_err))
+        z_err_stacked = np.hstack((np.real(z_err), np.imag(z_err)))
+        popt, pcov = optimization.curve_fit(nonlinear_iq_for_fitter, f_hz, z_stacked, x0, sigma=z_err_stacked,
+                                            bounds=bounds)
+        fr, Qr, amp, phi, a, i0, q0, tau, f0 = popt
+        fit_result = nonlinear_iq(f_hz=f_hz, fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, i0=i0, q0=q0, tau=tau, f0=f0)
+        # only do it for fine data
+        red_chi_sqr = np.sum((np.hstack((np.real(fine_z), np.imag(fine_z))) - np.hstack(
+            (np.real(fit_result[0:len(fine_z)]), np.imag(fit_result[0:len(fine_z)])))) ** 2 / np.hstack(
+            (np.real(fine_z_err), np.imag(fine_z_err))) ** 2) / (len(fine_z) * 2. - 8.)
+
+    else:
+        popt, pcov = optimization.curve_fit(nonlinear_iq_for_fitter, f_hz, z_stacked, x0, bounds=bounds)
+        fr, Qr, amp, phi, a, i0, q0, tau, f0 = popt
+        red_chi_sqr = None
+
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = NonlinearIQRes(fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, i0=i0, q0=q0, tau=tau, f0=f0,
+                            red_chi_sqr=red_chi_sqr, Qc=Qc, Qi=Qi)
+    if verbose:
+        result.console(label='Fit', print_header=False)
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=nonlinear_iq,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+def fit_nonlinear_iq_with_err(f_hz, z, bounds=None, x0=None, amp_norm: bool = False, verbose: bool = True):
+    """Same as fit_nonlinear_iq(), but double fits so that it can get error and a proper covariance matrix out.
+
+    Parameters
+    ----------
+    f_hz : numpy.array
+        frequencies Hz
+    z : numpy.array
+        complex s21
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess  = x0[0]
+        Qr_guess  = x0[1]
+        amp_guess = x0[2]
+        phi_guess = x0[3]
+        a_guess   = x0[4]
+        i0_guess  = x0[5]
+        q0_guess  = x0[6]
+        tau_guess = x0[7]
+        f0_guess  = x0[8]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    amp_norm : bool, optional (default False)
+        When True, a normalization is preformed for the amplitude variable. This parameter is useful when the transfer
+        function of the cryostat is not flat.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+    if bounds is None:
+        # define default bounds
+        print("default bounds used")
+        bounds = ([np.min(f_hz), 2000, .01, -np.pi, 0, -5, -5, 1 * 10 ** -9, np.min(f_hz)],
+                  [np.max(f_hz), 200000, 1, np.pi, 5, 5, 5, 1 * 10 ** -6, np.max(f_hz)])
+    if x0 is None:
+        # define default initial guess
+        print("default initial guess used")
+        x0 = guess_x0_iq_nonlinear(f_hz, z)
+    if amp_norm:
+        z = amplitude_normalization(f_hz, z)
+    guess = NonlinearIQRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+    z_stacked = np.hstack((np.real(z), np.imag(z)))
+    popt_first, pcov_first = optimization.curve_fit(nonlinear_iq_for_fitter, f_hz, z_stacked, x0, bounds=bounds)
+    fr_first, Qr_first, amp_first, phi_first, a_first, i0_first, q0_first, tau_first, f0_first = popt_first
+    
+    fit_result_stacked = nonlinear_iq_for_fitter(f_hz=f_hz, fr=fr_first, Qr=Qr_first, amp=amp_first, phi=phi_first, 
+                                                 a=a_first, i0=i0_first, q0=q0_first, tau=tau_first, f0=f0_first)
+    # get error
+    var = np.sum((z_stacked - fit_result_stacked) ** 2) / (z_stacked.shape[0] - 1)
+    err = np.ones(z_stacked.shape[0]) * np.sqrt(var)
+    # refit
+    popt, pcov = optimization.curve_fit(nonlinear_iq_for_fitter, f_hz, z_stacked, x0, err, bounds=bounds)
+    fr, Qr, amp, phi, a, i0, q0, tau, f0 = popt
+    # make a dictionary to return
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = NonlinearIQRes(fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, i0=i0, q0=q0, tau=tau, f0=f0, Qc=Qc, Qi=Qi)
+    if verbose:
+        result.console(label='Fit', print_header=False)
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=nonlinear_iq,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+# function for fitting an iq sweep with the above equation
+def fit_nonlinear_mag(f_hz, z, bounds=None, x0=None, verbose=True):
+    """
+    Parameters
+    ----------
+    f_hz : numpy.array
+        frequencies Hz
+    z : numpy.array
+        complex s21
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess  = x0[0]
+        Qr_guess  = x0[1]
+        amp_guess = x0[2]
+        phi_guess = x0[3]
+        a_guess   = x0[4]
+        b0_guess  = x0[5]
+        b1_guess  = x0[6]
+        flin_guess= x0[7]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+    if bounds is None:
+        print("default bounds used")
+        bounds = ([np.min(f_hz), 100, .01, -np.pi, 0, -np.inf, -np.inf, np.min(f_hz)],
+                  [np.max(f_hz), 200000, 1, np.pi, 5, np.inf, np.inf, np.max(f_hz)])
+    if x0 is None:
+        # define default initial guess
+        print("default initial guess used")
+        # x0 = [fr_guess,10000.,0.5,0,0,np.abs(z[0])**2,np.abs(z[0])**2,fr_guess]
+        x0 = guess_x0_mag_nonlinear(f_hz, z, verbose=verbose)
+
+    guess = NonlinearMagRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+
+    popt, pcov = optimization.curve_fit(nonlinear_mag, f_hz, np.abs(z) ** 2, x0, bounds=bounds)
+    fr, Qr, amp, phi, a, b0, b1, flin = popt
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = NonlinearMagRes(fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, b0=b0, b1=b1, flin=flin, Qc=Qc, Qi=Qi)
+    if verbose:
+        result.console(label='Fit', print_header=False)
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=nonlinear_mag_for_plot,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+def fit_linear_mag(f_hz, z, bounds=None, x0=None, verbose=True):
+    """
+    Parameters
+    ----------
+    f_hz : numpy.array
+        frequencies Hz
+    z : numpy.array
+        complex s21
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess  = x0[0]
+        Qr_guess  = x0[1]
+        amp_guess = x0[2]
+        phi_guess = x0[3]
+        b0_guess  = x0[4]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+    if bounds is None:
+        # define default bounds
+        print("default bounds used")
+        bounds = ([np.min(f_hz), 100, .01, -np.pi, -np.inf], [np.max(f_hz), 200000, 1, np.pi, np.inf])
+    if x0 is None:
+        # define default initial guess
+        if verbose:
+            print("default initial guess used")
+        # x0 = [fr_guess,10000.,0.5,0,0,np.abs(z[0])**2,np.abs(z[0])**2,fr_guess]
+        x0 = guess_x0_mag_nonlinear(f_hz, z, verbose=verbose)
+        x0 = np.delete(x0, [4, 6, 7])
+    guess = LinearMagRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+    popt, pcov = optimization.curve_fit(linear_mag, f_hz, np.abs(z) ** 2, x0, bounds=bounds)
+    # human-readable results
+    fr, Qr, amp, phi, b0 = popt
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = LinearMagRes(fr=fr, Qr=Qr, amp=amp, phi=phi, b0=b0, Qc=Qc, Qi=Qi)
+    if verbose:
+        result.console(label='Fit', print_header=False)
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=linear_mag_for_plot,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+def fit_nonlinear_mag_sep(fine_f_hz, fine_z, gain_f_hz, gain_z, 
+                          fine_z_err=None, gain_z_err=None, bounds=None, x0=None, verbose=True):
+    """Same as, fit_nonlinear_mag(), above but fine and gain scans are provided separately.
+    
+    Parameters
+    ----------
+    fine_f_hz : numpy.array
+        frequencies Hz
+    fine_z : numpy.array
+        complex s21
+    gain_f_hz : numpy.array
+        frequencies Hz
+    gain_z : numpy.array
+        complex s21
+    fine_z_err : numpy.array, optional (default None)
+        The error in the fine scan, expected to bve the same size as fine_z. If either fine_z_err or gain_z_err is None,
+        the error is not used.
+    gain_z_err : numpy.array, optional (default None)
+        The error in the gain scan, expected to bve the same size as gain_z. If either fine_z_err or gain_z_err is None,
+        the error is not used.
+    bounds : tuple, option (default None)
+        A 2d tuple of low values bounds[0] the high values bounds[1] to bound the fitting problem.
+    x0 : list, optional (default None)
+        The initial guesses for all parameters:
+        fr_guess   = x0[0]
+        Qr_guess   = x0[1]
+        amp_guess  = x0[2]
+        phi_guess  = x0[3]
+        a_guess    = x0[4]
+        b0_guess   = x0[5]
+        b1_guess   = x0[6]
+        flin_guess = x0[7]
+        The fit's initial guess can be very important because least squares fitting does not completely search the
+        parameter space.
+    verbose : bool, optional (default True)
+        Uses the print function to display fit results when true, no prints to the console when false.
+
+    Returns
+    -------
+    fit : Fit
+        A Fit NamedTuple containing the fit results.
+    """
+    if bounds is None:
+        # define default bounds
+        print("default bounds used")
+        bounds = ([np.min(fine_f_hz), 100, .01, -np.pi, 0, -np.inf, -np.inf, np.min(fine_f_hz)],
+                  [np.max(fine_f_hz), 1000000, 100, np.pi, 5, np.inf, np.inf, np.max(fine_f_hz)])
+    if x0 is None:
+        # define default initial guess
+        print("default initial guess used")
+        x0 = guess_x0_mag_nonlinear_sep(fine_f_hz, fine_z, gain_f_hz, gain_z)
+        
+    guess = NonlinearMagRes(*x0)
+    if verbose:
+        guess.console(label='Guess', print_header=True)
+    # stack the scans for curve_fit
+    f_hz = np.hstack((fine_f_hz, gain_f_hz))
+    z = np.hstack((fine_z, gain_z))
+    if fine_z_err is not None and gain_z_err is not None:
+        z_err = np.hstack((fine_z_err, gain_z_err))
+        # propagation of errors left out cross term
+        z_err = np.sqrt(4 * np.real(z_err) ** 2 * np.real(z) ** 2 + 4 * np.imag(z_err) ** 2 * np.imag(z) ** 2)
+        popt, pcov = optimization.curve_fit(nonlinear_mag, f_hz, np.abs(z) ** 2, x0, sigma=z_err, bounds=bounds)
+        fr, Qr, amp, phi, a, b0, b1, flin = popt
+        fit_result = nonlinear_mag(f_hz=f_hz, fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, b0=b0, b1=b1, flin=flin)
+        red_chi_sqr = np.sum((np.abs(fine_z) ** 2 - fit_result[0:len(fine_z)]) ** 2 / z_err[0:len(fine_z)] ** 2) / (
+                len(fine_z) - 7.)
+    else:
+        popt, pcov = optimization.curve_fit(nonlinear_mag, f_hz, np.abs(z) ** 2, x0, bounds=bounds)
+        fr, Qr, amp, phi, a, b0, b1, flin = popt
+        red_chi_sqr = None
+    # human-readable results
+    Qc, Qi = calc_qc_qi(qr=Qr, amp=amp)
+    result = NonlinearMagRes(fr=fr, Qr=Qr, amp=amp, phi=phi, a=a, b0=b0, b1=b1, flin=flin, 
+                             red_chi_sqr=red_chi_sqr, Qc=Qc, Qi=Qi)
+    if verbose:
+        result.console(label='Fit', print_header=False)
+    fit = Fit(origin=inspect.currentframe().f_code.co_name, func=nonlinear_mag_for_plot,
+              guess=guess, result=result, pcov=pcov, f_data=f_hz, z_data=z)
+    return fit
+
+
+def fit_nonlinear_iq_multi(f_hz, z, tau: float = None, verbose: bool = True):
+    """
+    wrapper for handling n resonator fits at once
+    f_hz and z should have shape n_iq_points x n_res points
+    return same thing as fitter but in arrays for all resonators
+    """
+
+    center_freqs = f_hz[f_hz.shape[0] // 2, :]
+    res_fits = []
+    for i in range(0, f_hz.shape[1]):
+        f_single = f_hz[:, i]
+        z_single = z[:, i]
+        # flag data that is too close to other resonators              
+        distance = center_freqs - center_freqs[i]
+        if center_freqs[i] != np.min(center_freqs):  # don't do if lowest frequency resonator
+            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
+            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
+            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index]) / 2.
+        else:
+            halfway_low = 0
+
+        if center_freqs[i] != np.max(center_freqs):  # don't do if highest frequenct
+            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
+            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
+            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index]) / 2.
+        else:
+            halfway_high = np.inf
+
+        use_index = np.where(((f_single > halfway_low) & (f_single < halfway_high)))
+        mask = np.zeros(len(f_single))
+        mask[use_index] = 1
+        f_single_res = f_single[use_index]
+        z_single_res = z_single[use_index]
+
+        try:
+            fit_single_res = fit_nonlinear_iq(f_single_res, z_single_res, tau=tau, verbose=verbose)
+        except Exception as e:
+            if verbose:
+                print(e)
+                print("failed to fit")
+        else:
+            # overwrite fit data with full data set
+            fit_dict = fit_single_res._asdict()
+            fit_dict['f_data'] = f_single
+            fit_dict['z_data'] = z_single
+            fit_dict['mask'] = mask
+            fit = Fit(**fit_dict)
+            res_fits.append(fit)
+    res_set = ResSet(res_fits=res_fits, verbose=verbose)
+    return res_set
+
+
+def fit_linear_mag_multi(f_hz, z, verbose: bool = True):
+    """
+    wrapper for handling n resonator fits at once
+    f_hz and z should have shape n_iq_points x n_res points
+    return same thing as fitter but in arrays for all resonators
+    """
+    center_freqs = f_hz[f_hz.shape[0] // 2, :]
+    res_fits = []
+    for i in range(0, f_hz.shape[1]):
+        f_single = f_hz[:, i]
+        z_single = z[:, i]
+        # flag data that is too close to other resonators              
+        distance = center_freqs - center_freqs[i]
+        if center_freqs[i] != np.min(center_freqs):  # don't do if lowest frequency resonator
+            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
+            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
+            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index]) / 2.
+        else:
+            halfway_low = 0
+
+        if center_freqs[i] != np.max(center_freqs):  # don't do if highest frequency
+            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
+            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
+            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index]) / 2.
+        else:
+            halfway_high = np.inf
+        use_index = np.where(((f_single > halfway_low) & (f_single < halfway_high)))
+        mask = np.zeros(len(f_single))
+        mask[use_index] = 1
+        f_single_res = f_single[use_index]
+        z_single_res = z_single[use_index]
+        try:
+            fit_single_res = fit_linear_mag(f_single_res, z_single_res, verbose=verbose)
+        except Exception as e:
+            if verbose:
+                print("problem")
+                print(e)
+                print("failed to fit")
+        else:
+            # overwrite fit data with full data set
+            fit_dict = fit_single_res._asdict()
+            fit_dict['f_data'] = f_single
+            fit_dict['z_data'] = z_single
+            fit_dict['mask'] = mask
+            fit = Fit(**fit_dict)
+            res_fits.append(fit)
+    res_set = ResSet(res_fits=res_fits, verbose=verbose)
+    return res_set
+
+
+if __name__ == '__main__':
+    # get demo data
+    import os
+    from scipy.io import loadmat
+    from submm.sample_data.abs_paths import abs_path_sample_data
+    data_path = os.path.join(abs_path_sample_data,
+                             "Survey_Tbb20.000K_Tbath170mK_Pow-60dBm_array_temp_sweep_long.mat")
+    sample_data = loadmat(data_path)
+
+    freq_ghz = sample_data['f'][:, 0]
+    freq_mhz = freq_ghz * 1.0e3
+    freq_hz = freq_ghz * 1.0e9
+    s21_complex = sample_data['z'][:, 0]
+    s21_mag = 20 * np.log10(np.abs(s21_complex))
+
+    freq_hz_res1 = freq_hz[21050: 21250]
+    freq_mhz_res1 = freq_hz[21050: 21250]
+    s21_complex_res1 = s21_complex[21050: 21250]
+    s21_mag_res1 = s21_mag[21050: 21250]
+
+    # # Caleb's testing area
+    # Test the Res() instance for the fit result directly
+    res_fit = fit_nonlinear_iq(f_hz=freq_hz_res1, z=s21_complex_res1)
+    print(f'Res fit res_fit.result["fr"] from key = {res_fit.result["fr"]}')
+    print(f'res_fit.result[0], from index = {res_fit.result[0]}')
+    print(f'res_fit.result[0:2], from slice = {res_fit.result[0:2]}')
+    print(f'res_fit.result.fr, from attribute = {res_fit.result.fr}\n')
+
+    # test the Fit() instance for to get Res parameters
+    print(f'Res fit fr (res_fit["fr"]) from key = {res_fit.result["fr"]}')
+    print(f'Res fit Qc (res_fit["Qc"]) from key = {res_fit.result["Qc"]}\n')
+
+    # test the console (print data to screen) output
+    res_fit.console()
+
+    # test hash ability of the result
+    test_set = {res_fit.result}
+
+    # test the plot
+    # res_fit.plot()
+
+    # test write, read, and iteration class
+    res_set_test = ResSet(res_fits=[res_fit])
+    res_set_test.write()
+    res_set_read = ResSet(path=res_set_test.path)
+    for read_result in res_set_read:
+        read_result.console(label='Read', fields=['fr', 'tau', 'Qc'])
diff --git a/submm/KIDs/res/fitting_legacy.py b/submm/KIDs/res/fitting_legacy.py
new file mode 100644
index 0000000..6a0493b
--- /dev/null
+++ b/submm/KIDs/res/fitting_legacy.py
@@ -0,0 +1,131 @@
+import numpy as np
+import matplotlib.pyplot as plt
+
+from submm.KIDs.res.fit_funcs import linear_mag
+
+
+def brute_force_linear_mag_fit(f_hz, z, ranges, n_grid_points, error=None, plot=False):
+    """
+    Parameters
+    ----------
+    f_hz : numpy.array
+        frequencies Hz
+    z : numpy.array
+        complex or abs of s21
+    ranges : numpy.array
+        The ranges for each parameter as in:
+        np.asarray(([f_low,Qr_low,amp_low,phi_low,b0_low],[f_high,Qr_high,amp_high,phi_high,b0_high]))
+    n_grid_points: int
+        How finely to sample each parameter space. This can be very slow for n>10, an increase by a factor of 2 will
+        take 2**5 times longer to marginalize over you must minimize over the unwanted axes of sum_dev
+        i.e. for fr np.min(np.min(np.min(np.min(fit['sum_dev'],axis = 4),axis = 3),axis = 2),axis = 1)
+    error : numpy.array, optional (default = None)
+        The error on the complex or abs of s21, used for weighting squares
+    plot : bool, optional (default = False)
+        If true, will plot the fit and the data
+    """
+    if error is None:
+        error = np.ones(len(f_hz))
+
+    fs = np.linspace(ranges[0][0], ranges[1][0], n_grid_points)
+    Qrs = np.linspace(ranges[0][1], ranges[1][1], n_grid_points)
+    amps = np.linspace(ranges[0][2], ranges[1][2], n_grid_points)
+    phis = np.linspace(ranges[0][3], ranges[1][3], n_grid_points)
+    b0s = np.linspace(ranges[0][4], ranges[1][4], n_grid_points)
+    evaluated_ranges = np.vstack((fs, Qrs, amps, phis, b0s))
+
+    a, b, c, d, e = np.meshgrid(fs, Qrs, amps, phis, b0s, indexing="ij")  # always index ij
+
+    evaluated = linear_mag(f_hz, a, b, c, d, e)
+    data_values = np.reshape(np.abs(z) ** 2, (abs(z).shape[0], 1, 1, 1, 1, 1))
+    error = np.reshape(error, (abs(z).shape[0], 1, 1, 1, 1, 1))
+    sum_dev = np.sum(((np.sqrt(evaluated) - np.sqrt(data_values)) ** 2 / error ** 2),
+                     axis=0)  # comparing in magnitude space rather than magnitude squared
+
+    min_index = np.where(sum_dev == np.min(sum_dev))
+    index1 = min_index[0][0]
+    index2 = min_index[1][0]
+    index3 = min_index[2][0]
+    index4 = min_index[3][0]
+    index5 = min_index[4][0]
+    fit_values = np.asarray((fs[index1], Qrs[index2], amps[index3], phis[index4], b0s[index5]))
+    fit_values_names = ('f0', 'Qr', 'amp', 'phi', 'b0')
+    fit_result = linear_mag(f_hz, fs[index1], Qrs[index2], amps[index3], phis[index4], b0s[index5])
+
+    marginalized_1d = np.zeros((5, n_grid_points))
+    marginalized_1d[0, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2), axis=1)
+    marginalized_1d[1, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2), axis=0)
+    marginalized_1d[2, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=1), axis=0)
+    marginalized_1d[3, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=1), axis=0)
+    marginalized_1d[4, :] = np.min(np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=1), axis=0)
+
+    marginalized_2d = np.zeros((5, 5, n_grid_points, n_grid_points))
+    # 0 _
+    # 1 x _
+    # 2 x x _
+    # 3 x x x _
+    # 4 x x x x _
+    #  0 1 2 3 4
+    marginalized_2d[0, 1, :] = marginalized_2d[1, 0, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2)
+    marginalized_2d[2, 0, :] = marginalized_2d[0, 2, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=1)
+    marginalized_2d[2, 1, :] = marginalized_2d[1, 2, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=0)
+    marginalized_2d[3, 0, :] = marginalized_2d[0, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=1)
+    marginalized_2d[3, 1, :] = marginalized_2d[1, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=0)
+    marginalized_2d[3, 2, :] = marginalized_2d[2, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=1), axis=0)
+    marginalized_2d[4, 0, :] = marginalized_2d[0, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=1)
+    marginalized_2d[4, 1, :] = marginalized_2d[1, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=0)
+    marginalized_2d[4, 2, :] = marginalized_2d[2, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=1), axis=0)
+    marginalized_2d[4, 3, :] = marginalized_2d[3, 4, :] = np.min(np.min(np.min(sum_dev, axis=2), axis=1), axis=0)
+
+    if plot:
+        levels = [2.3, 4.61]  # delta chi squared two parameters 68 90 % confidence
+        fig_fit = plt.figure(-1)
+        axs = fig_fit.subplots(5, 5)
+        for i in range(0, 5):  # y starting from top
+            for j in range(0, 5):  # x starting from left
+                if i > j:
+                    # plt.subplot(5,5,i+1+5*j)
+                    # axs[i, j].set_aspect('equal', 'box')
+                    extent = [evaluated_ranges[j, 0], evaluated_ranges[j, n_grid_points - 1], evaluated_ranges[i, 0],
+                              evaluated_ranges[i, n_grid_points - 1]]
+                    axs[i, j].imshow(marginalized_2d[i, j, :] - np.min(sum_dev), extent=extent, origin='lower',
+                                     cmap='jet')
+                    axs[i, j].contour(evaluated_ranges[j], evaluated_ranges[i],
+                                      marginalized_2d[i, j, :] - np.min(sum_dev), levels=levels, colors='white')
+                    axs[i, j].set_ylim(evaluated_ranges[i, 0], evaluated_ranges[i, n_grid_points - 1])
+                    axs[i, j].set_xlim(evaluated_ranges[j, 0], evaluated_ranges[j, n_grid_points - 1])
+                    axs[i, j].set_aspect((evaluated_ranges[j, 0] - evaluated_ranges[j, n_grid_points - 1]) / (
+                            evaluated_ranges[i, 0] - evaluated_ranges[i, n_grid_points - 1]))
+                    if j == 0:
+                        axs[i, j].set_ylabel(fit_values_names[i])
+                    if i == 4:
+                        axs[i, j].set_xlabel("\n" + fit_values_names[j])
+                    if i < 4:
+                        axs[i, j].get_xaxis().set_ticks([])
+                    if j > 0:
+                        axs[i, j].get_yaxis().set_ticks([])
+
+                elif i < j:
+                    fig_fit.delaxes(axs[i, j])
+
+        for i in range(0, 5):
+            # axes.subplot(5,5,i+1+5*i)
+            axs[i, i].plot(evaluated_ranges[i, :], marginalized_1d[i, :] - np.min(sum_dev))
+            axs[i, i].plot(evaluated_ranges[i, :], np.ones(len(evaluated_ranges[i, :])) * 1., color='k')
+            axs[i, i].plot(evaluated_ranges[i, :], np.ones(len(evaluated_ranges[i, :])) * 2.7, color='k')
+            axs[i, i].yaxis.set_label_position("right")
+            axs[i, i].yaxis.tick_right()
+            axs[i, i].xaxis.set_label_position("top")
+            axs[i, i].xaxis.tick_top()
+            axs[i, i].set_xlabel(fit_values_names[i])
+
+        # axs[0,0].set_ylabel(fit_values_names[0])
+        # axs[4,4].set_xlabel(fit_values_names[4])
+        axs[4, 4].xaxis.set_label_position("bottom")
+        axs[4, 4].xaxis.tick_bottom()
+
+    # make a dictionary to return
+    fit_dict = {'fit_values': fit_values, 'fit_values_names': fit_values_names, 'sum_dev': sum_dev,
+                'fit_result': fit_result, 'marginalized_2d': marginalized_2d, 'marginalized_1d': marginalized_1d,
+                'evaluated_ranges': evaluated_ranges}  # , 'x0':x0, 'z':z}
+    return fit_dict
diff --git a/submm/KIDs/res_sweep_tools.py b/submm/KIDs/res/sweep_tools.py
similarity index 55%
rename from submm/KIDs/res_sweep_tools.py
rename to submm/KIDs/res/sweep_tools.py
index 5f9958b..23ed7e7 100644
--- a/submm/KIDs/res_sweep_tools.py
+++ b/submm/KIDs/res/sweep_tools.py
@@ -22,39 +22,40 @@ def find_max_didq(z, look_around):
     neg_offset_I = np.roll(Is, -1, axis=0)
     pos_offset_Q = np.roll(Qs, 1, axis=0)
     neg_offset_Q = np.roll(Qs, -1, axis=0)
-    pos_dist = np.sqrt((Is-pos_offset_I)**2+(Qs-pos_offset_Q)**2)
-    neg_dist = np.sqrt((Is-neg_offset_I)**2+(Qs-neg_offset_Q)**2)
-    ave_dist = (pos_dist + neg_dist)/2.
+    pos_dist = np.sqrt((Is - pos_offset_I) ** 2 + (Qs - pos_offset_Q) ** 2)
+    neg_dist = np.sqrt((Is - neg_offset_I) ** 2 + (Qs - neg_offset_Q) ** 2)
+    ave_dist = (pos_dist + neg_dist) / 2.
     # zero out the last and first values
     ave_dist[0, :] = 0
-    ave_dist[ave_dist.shape[0]-1, :] = 0
-    min_index = np.argmax(ave_dist[Is.shape[0]//2-look_around:Is.shape[0]//2+look_around],
-                          axis=0)+(Is.shape[0]//2-look_around)
+    ave_dist[ave_dist.shape[0] - 1, :] = 0
+    min_index = np.argmax(ave_dist[Is.shape[0] // 2 - look_around:Is.shape[0] // 2 + look_around],
+                          axis=0) + (Is.shape[0] // 2 - look_around)
     return min_index
 
 
-class interactive_plot(object):
-    '''
+class InteractivePlot(object):
+    """
     interactive plot for plot many resonators iq data
     chan freqs and z should have dimension n_iq points by n_res
     also can provide multiple sweeps for plotting by adding extra dimension
     i.e. chan freqs and z could have dimension n_iq points by n_res by n_sweeps
     combined data should have dimension n_res by n_different_types of data
-    '''
-    def __init__(self, chan_freqs, z, look_around=2,stream_data = None, retune=True, find_min=True,
-                 combined_data = None,combined_data_names = None,sweep_labels = None,sweep_line_styles = None,
-                     combined_data_format = None):
-        if len(z.shape)<3: # only one sweep
-            self.z = z.reshape((z.shape[0],z.shape[1],1))
-            self.chan_freqs = chan_freqs.reshape((chan_freqs.shape[0],chan_freqs.shape[1],1))
+    """
+
+    def __init__(self, chan_freqs, z, look_around=2, stream_data=None, retune=True, find_min=True,
+                 combined_data=None, combined_data_names=None, sweep_labels=None, sweep_line_styles=None,
+                 combined_data_format=None):
+        if len(z.shape) < 3:  # only one sweep
+            self.z = z.reshape((z.shape[0], z.shape[1], 1))
+            self.chan_freqs = chan_freqs.reshape((chan_freqs.shape[0], chan_freqs.shape[1], 1))
         else:
             self.z = z
             self.chan_freqs = chan_freqs
-            
+
         self.Is = np.real(self.z)
         self.Qs = np.imag(self.z)
         self.find_min = find_min
-        self.retune = retune 
+        self.retune = retune
         self.combined_data = combined_data
         self.combined_data_names = combined_data_names
         self.stream_data = stream_data
@@ -68,7 +69,7 @@ def __init__(self, chan_freqs, z, look_around=2,stream_data = None, retune=True,
         self.update_min_index()
         if retune:
             self.combined_data_names = ['min index']
-        
+
         if self.combined_data is not None:
             self.fig = plt.figure(1, figsize=(13, 10))
             self.ax = self.fig.add_subplot(221)
@@ -81,7 +82,7 @@ def __init__(self, chan_freqs, z, look_around=2,stream_data = None, retune=True,
             self.ax3.set_ylabel("")
             self.ax3.set_xlabel("Resonator index")
         else:
-            self.fig = plt.figure(1,figsize = (13,6))
+            self.fig = plt.figure(1, figsize=(13, 6))
             self.ax = self.fig.add_subplot(121)
             self.ax.set_ylabel("Power (dB)")
             self.ax.set_xlabel("Frequecy (MHz)")
@@ -94,36 +95,38 @@ def __init__(self, chan_freqs, z, look_around=2,stream_data = None, retune=True,
         if self.stream_data is not None:
             self.s2, = self.ax2.plot(np.real(self.stream_data[:, self.plot_index]),
                                      np.imag(self.stream_data[:, self.plot_index]), '.')
-        
+
         if not sweep_line_styles:
             sweep_line_styles = ["-o"]
-            for i in range(1,self.z.shape[2]):
+            for i in range(1, self.z.shape[2]):
                 sweep_line_styles.append("-")
         if not sweep_labels:
             sweep_labels = ["Data 1"]
-            for i in range(1,self.z.shape[2]):
-                sweep_labels.append("Data "+str(i+1))
-        self._mag_lines = [self.ax.plot(self.chan_freqs[:, self.plot_index,i]/10**6, 10*np.log10(
-            self.Is[:, self.plot_index,i]**2+self.Qs[:, self.plot_index,i]**2), sweep_line_styles[i],mec = "k",label = sweep_labels[i])
-            for i in range(0,self.z.shape[2])]
+            for i in range(1, self.z.shape[2]):
+                sweep_labels.append("Data " + str(i + 1))
+        self._mag_lines = [self.ax.plot(self.chan_freqs[:, self.plot_index, i] / 10 ** 6, 10 * np.log10(
+            self.Is[:, self.plot_index, i] ** 2 + self.Qs[:, self.plot_index, i] ** 2), sweep_line_styles[i], mec="k",
+                                        label=sweep_labels[i])
+                           for i in range(0, self.z.shape[2])]
 
         self.ax_leg = self.ax.legend()
-            
+
         self._iq_lines = [self.ax2.plot(
-            self.Is[:, self.plot_index,i], self.Qs[:, self.plot_index,i], sweep_line_styles[i],mec = "k",label = sweep_labels[i])
-            for i in range(0,self.z.shape[2])]
-        
+            self.Is[:, self.plot_index, i], self.Qs[:, self.plot_index, i], sweep_line_styles[i], mec="k",
+            label=sweep_labels[i])
+            for i in range(0, self.z.shape[2])]
+
         if self.retune:
-            self.p1, = self.ax.plot(self.chan_freqs[self.min_index[self.plot_index], self.plot_index,0]/10**6,
-                                    10*np.log10(self.Is[self.min_index[self.plot_index],self.plot_index,0]**2+\
-                                                self.Qs[self.min_index[self.plot_index], self.plot_index,0]**2),
+            self.p1, = self.ax.plot(self.chan_freqs[self.min_index[self.plot_index], self.plot_index, 0] / 10 ** 6,
+                                    10 * np.log10(self.Is[self.min_index[self.plot_index], self.plot_index, 0] ** 2 + \
+                                                  self.Qs[self.min_index[self.plot_index], self.plot_index, 0] ** 2),
                                     '*', markersize=15)
-            self.p2, = self.ax2.plot(self.Is[self.min_index[self.plot_index], self.plot_index,0],
-                                     self.Qs[self.min_index[self.plot_index], self.plot_index,0], '*', markersize=15)
-            
-        self.ax.set_title("Resonator Index "+str(self.plot_index))
+            self.p2, = self.ax2.plot(self.Is[self.min_index[self.plot_index], self.plot_index, 0],
+                                     self.Qs[self.min_index[self.plot_index], self.plot_index, 0], '*', markersize=15)
+
+        self.ax.set_title("Resonator Index " + str(self.plot_index))
         if self.retune:
-            self.ax2.set_title("Look Around Points "+str(self.look_around))
+            self.ax2.set_title("Look Around Points " + str(self.look_around))
         print("")
         print("Interactive Resonance Plotting Activated")
         print("Use left and right arrows to switch between resonators")
@@ -139,78 +142,81 @@ def __init__(self, chan_freqs, z, look_around=2,stream_data = None, retune=True,
             print("Use the up and down arrows to change data in bottom plot")
             print("double click on point in bottom plot to jump to that resonator index")
             if retune:
-                print("Warning both look around points and combined data are mapped to "+\
-                      "up and down arrows, consider not returning and ploting combined "+\
+                print("Warning both look around points and combined data are mapped to " + \
+                      "up and down arrows, consider not returning and ploting combined " + \
                       "data at the same time")
             self.combined_data = np.asarray(self.combined_data)
             if len(self.combined_data.shape) == 1:
-                self.combined_data = np.expand_dims(self.combined_data,1)
-                
+                self.combined_data = np.expand_dims(self.combined_data, 1)
+
             if not combined_data_format:
                 self.combined_data_format = []
-                for i in range(0,self.combined_data.shape[1]):
-                    self.combined_data_format.append(self.combined_data_names[i]+': {:g}')
+                for i in range(0, self.combined_data.shape[1]):
+                    self.combined_data_format.append(self.combined_data_names[i] + ': {:g}')
             else:
                 self.combined_data_format = combined_data_format
             self.ax3.set_title(self.combined_data_names[self.combined_data_index])
             self.ax3.set_ylabel(self.combined_data_names[self.combined_data_index])
-            self.combined_data_points, = self.ax3.plot(np.arange(0,self.combined_data.shape[0]),
-                                                       self.combined_data[:,self.combined_data_index],'o',mec = "k")
+            self.combined_data_points, = self.ax3.plot(np.arange(0, self.combined_data.shape[0]),
+                                                       self.combined_data[:, self.combined_data_index], 'o', mec="k")
             self.combined_data_highlight, = self.ax3.plot(self.plot_index,
-                                                          self.combined_data[self.plot_index,self.combined_data_index],
-                                                          'o',mec = "k",label = self.combined_data_format[self.combined_data_index].format(
-                                                              self.combined_data[self.plot_index,self.combined_data_index]))
+                                                          self.combined_data[self.plot_index, self.combined_data_index],
+                                                          'o', mec="k", label=self.combined_data_format[
+                    self.combined_data_index].format(
+                    self.combined_data[self.plot_index, self.combined_data_index]))
             self.ax3_legend = self.ax3.legend()
         plt.show(block=True)
 
     def update_min_index(self):
         if self.find_min:
-            self.min_index = np.argmin(self.Is[self.targ_size//2-self.look_around:self.targ_size//2+self.look_around,:,0]**2 +
-                                               self.Qs[self.targ_size//2-self.look_around:self.targ_size//2+self.look_around,:,0]**2,
-                                               axis=0)+(self.targ_size//2-self.look_around)
+            self.min_index = np.argmin(
+                self.Is[self.targ_size // 2 - self.look_around:self.targ_size // 2 + self.look_around, :, 0] ** 2 +
+                self.Qs[self.targ_size // 2 - self.look_around:self.targ_size // 2 + self.look_around, :, 0] ** 2,
+                axis=0) + (self.targ_size // 2 - self.look_around)
         else:
-            self.min_index = find_max_didq(self.z[:,:,0], self.look_around)
-        #handel overidden points
-        for i,overide_index in enumerate(self.res_index_overide):
+            self.min_index = find_max_didq(self.z[:, :, 0], self.look_around)
+        # handel overidden points
+        for i, overide_index in enumerate(self.res_index_overide):
             self.min_index[overide_index] = self.overide_freq_index[i]
-            
+
         if self.retune:
-            self.combined_data = np.expand_dims(self.min_index,1)
+            self.combined_data = np.expand_dims(self.min_index, 1)
 
     def refresh_plot(self):
         for i, mag_line in enumerate(self._mag_lines):
-            mag_line[0].set_data(self.chan_freqs[:, self.plot_index,i]/10**6, 10*np.log10(
-                self.Is[:, self.plot_index,i]**2+self.Qs[:, self.plot_index,i]**2))
+            mag_line[0].set_data(self.chan_freqs[:, self.plot_index, i] / 10 ** 6, 10 * np.log10(
+                self.Is[:, self.plot_index, i] ** 2 + self.Qs[:, self.plot_index, i] ** 2))
         if self.retune:
-            self.p1.set_data(self.chan_freqs[self.min_index[self.plot_index], self.plot_index,0]/10**6,
-                                 10*np.log10(self.Is[self.min_index[self.plot_index], self.plot_index,0]**2 +
-                                             self.Qs[self.min_index[self.plot_index], self.plot_index,0]**2))
-                    
+            self.p1.set_data(self.chan_freqs[self.min_index[self.plot_index], self.plot_index, 0] / 10 ** 6,
+                             10 * np.log10(self.Is[self.min_index[self.plot_index], self.plot_index, 0] ** 2 +
+                                           self.Qs[self.min_index[self.plot_index], self.plot_index, 0] ** 2))
+
         self.ax.relim()
         self.ax.autoscale()
-        self.ax.set_title("Resonator Index "+str(self.plot_index))
+        self.ax.set_title("Resonator Index " + str(self.plot_index))
         if self.retune:
-            self.ax2.set_title("Look Around Points "+str(self.look_around))
+            self.ax2.set_title("Look Around Points " + str(self.look_around))
         for i, iq_line in enumerate(self._iq_lines):
-            iq_line[0].set_data((self.Is[:, self.plot_index,i],
-                          self.Qs[:, self.plot_index,i]))
+            iq_line[0].set_data((self.Is[:, self.plot_index, i],
+                                 self.Qs[:, self.plot_index, i]))
         if self.retune:
-            self.p2.set_data(self.Is[self.min_index[self.plot_index], self.plot_index,0],
-                                 self.Qs[self.min_index[self.plot_index], self.plot_index,0])
+            self.p2.set_data(self.Is[self.min_index[self.plot_index], self.plot_index, 0],
+                             self.Qs[self.min_index[self.plot_index], self.plot_index, 0])
 
         if self.stream_data is not None:
             self.s2.set_data(np.real(self.stream_data[:, self.plot_index]),
-                                 np.imag(self.stream_data[:, self.plot_index]))
+                             np.imag(self.stream_data[:, self.plot_index]))
         self.ax2.relim()
         self.ax2.autoscale()
         if self.combined_data is not None:
             self.ax3.set_title(self.combined_data_names[self.combined_data_index])
             self.ax3.set_ylabel(self.combined_data_names[self.combined_data_index])
-            self.combined_data_points.set_data(np.arange(0,self.combined_data.shape[0]),
-                                               self.combined_data[:,self.combined_data_index])
-            self.combined_data_highlight.set_data(self.plot_index,self.combined_data[self.plot_index,self.combined_data_index])
+            self.combined_data_points.set_data(np.arange(0, self.combined_data.shape[0]),
+                                               self.combined_data[:, self.combined_data_index])
+            self.combined_data_highlight.set_data(self.plot_index,
+                                                  self.combined_data[self.plot_index, self.combined_data_index])
             self.ax3_legend.texts[0].set_text(self.combined_data_format[self.combined_data_index].format(
-                self.combined_data[self.plot_index,self.combined_data_index]))
+                self.combined_data[self.plot_index, self.combined_data_index]))
             self.ax3.relim()
             self.ax3.autoscale()
         plt.draw()
@@ -218,7 +224,7 @@ def refresh_plot(self):
     def on_key_press(self, event):
         # print event.key
         if event.key == 'right':
-            if self.plot_index != self.chan_freqs.shape[1]-1:
+            if self.plot_index != self.chan_freqs.shape[1] - 1:
                 self.plot_index = self.plot_index + 1
                 self.refresh_plot()
 
@@ -228,13 +234,13 @@ def on_key_press(self, event):
                 self.refresh_plot()
 
         if event.key == 'up':
-            if self.look_around != self.chan_freqs.shape[0]//2:
+            if self.look_around != self.chan_freqs.shape[0] // 2:
                 self.look_around = self.look_around + 1
                 self.update_min_index()
                 if self.retune:
-                    self.combined_data = np.expand_dims(self.min_index,1)
+                    self.combined_data = np.expand_dims(self.min_index, 1)
             if self.combined_data is not None:
-                if self.combined_data_index != self.combined_data.shape[1]-1:
+                if self.combined_data_index != self.combined_data.shape[1] - 1:
                     self.combined_data_index = self.combined_data_index + 1
             self.refresh_plot()
 
@@ -243,7 +249,7 @@ def on_key_press(self, event):
                 self.look_around = self.look_around - 1
                 self.update_min_index()
                 if self.retune:
-                    self.combined_data = np.expand_dims(self.min_index,1)
+                    self.combined_data = np.expand_dims(self.min_index, 1)
             if self.combined_data is not None:
                 if self.combined_data_index != 0:
                     self.combined_data_index = self.combined_data_index + -1
@@ -256,7 +262,6 @@ def on_key_press(self, event):
             if event.key == 'shift':
                 self.shift_is_held = True
 
-
     def on_key_release(self, event):
         # windows or mac
         if platform.system() == 'Darwin':
@@ -266,23 +271,22 @@ def on_key_release(self, event):
             if event.key == 'shift':
                 self.shift_is_held = False
 
-
     def onClick(self, event):
         if self.combined_data is not None:
             if event.dblclick:
-                self.plot_index = np.argmin(np.abs(np.arange(0,self.combined_data.shape[0]) - event.xdata))
+                self.plot_index = np.argmin(np.abs(np.arange(0, self.combined_data.shape[0]) - event.xdata))
                 self.refresh_plot()
                 return
         if event.button == 3:
             if self.shift_is_held:
                 print("overiding point selection", event.xdata)
                 # print(self.chan_freqs[:,self.plot_index][50])
-                #print((self.res_index_overide == self.plot_index).any())
+                # print((self.res_index_overide == self.plot_index).any())
                 if (self.res_index_overide == self.plot_index).any():
                     replace_index = np.argwhere(
                         self.res_index_overide == self.plot_index)[0][0]
                     new_freq = np.argmin(
-                        np.abs(event.xdata-self.chan_freqs[:, self.plot_index]/10**6))
+                        np.abs(event.xdata - self.chan_freqs[:, self.plot_index] / 10 ** 6))
                     self.overide_freq_index[replace_index] = np.int(new_freq)
 
                 else:
@@ -290,8 +294,8 @@ def onClick(self, event):
                         self.res_index_overide, np.int(np.asarray(self.plot_index)))
                     # print(self.res_index_overide)
                     new_freq = np.argmin(
-                        np.abs(event.xdata-self.chan_freqs[:, self.plot_index]/10**6))
-                    #print("new index is ",new_freq)
+                        np.abs(event.xdata - self.chan_freqs[:, self.plot_index] / 10 ** 6))
+                    # print("new index is ",new_freq)
                     self.overide_freq_index = np.append(
                         self.overide_freq_index, np.int(np.asarray(new_freq)))
                     # print(self.overide_freq_index)
@@ -301,34 +305,34 @@ def onClick(self, event):
 
 def tune_kids(f, z, find_min=True, interactive=True, **kwargs):
     # f and z should have shape (npts_sweep,n_res)
-    #iq_dict = read_iq_sweep(filename)
+    # iq_dict = read_iq_sweep(filename)
     if "look_around" in kwargs:
         print("you are using " +
-              str(kwargs['look_around'])+" look around points")
+              str(kwargs['look_around']) + " look around points")
         look_around = kwargs['look_around']
     else:
-        look_around = f.shape[0]//2
+        look_around = f.shape[0] // 2
     if find_min:  # fine the minimum
         print("centering on minimum")
         print(f.shape)
         if interactive:
-            ip = interactive_plot(f, z, look_around)
+            ip = InteractivePlot(f, z, look_around)
             print(ip.min_index.shape)
             print(ip.res_index_overide.shape)
             for i in range(0, len(ip.res_index_overide)):
                 ip.min_index[ip.res_index_overide[i]
-                             ] = ip.overide_freq_index[i]
+                ] = ip.overide_freq_index[i]
             new_freqs = f[(ip.min_index, np.arange(0, f.shape[1]))]
         else:
-            min_index = np.argmin(np.abs(z)**2, axis=0)
+            min_index = np.argmin(np.abs(z) ** 2, axis=0)
             new_freqs = f[(min_index, np.arange(0, f.shape[1]))]
     else:  # find the max of dIdQ
         print("centering on max dIdQ")
         if interactive:
-            ip = interactive_plot(f, z, look_around, find_min=False)
+            ip = InteractivePlot(f, z, look_around, find_min=False)
             for i in range(0, len(ip.res_index_overide)):
                 ip.min_index[ip.res_index_overide[i]
-                             ] = ip.overide_freq_index[i]
+                ] = ip.overide_freq_index[i]
             new_freqs = f[(ip.min_index, np.arange(0, f.shape[1]))]
         else:
             min_index = find_max_didq(z, look_around)
@@ -336,9 +340,8 @@ def tune_kids(f, z, find_min=True, interactive=True, **kwargs):
     return new_freqs
 
 
-
-class interactive_power_tuning_plot(object):
-    '''
+class InteractivePowerTuningPlot(object):
+    """
     special interactive plot for tune the readout power of resonators based on fist to thier non-linearity parameter
     f (frequencies of iq_sweep shape n_pts_iq_sweep x n_res x (optionally n_powers)
     z complex number where i is real and q is imaginary part shape n_pts_iq_sweep x n_res,  n_powers
@@ -347,11 +350,12 @@ class interactive_power_tuning_plot(object):
     attn_levels list or array of power levels
     desired_a the desired non-linearity paramter to have powers set to
     Optional
-    z_fit_mag data to display as the fit 
+    z_fit_mag data to display as the fit
     z_fit_iq data to display as the fit
-    '''
+    """
 
-    def __init__(self,f,z,attn_levels,fitted_a_mag = None,fitted_a_iq = None,desired_a = 0.5,z_fit_mag = None,z_fit_iq = None):
+    def __init__(self, f, z, attn_levels, fitted_a_mag=None, fitted_a_iq=None, desired_a=0.5, z_fit_mag=None,
+                 z_fit_iq=None):
         self.attn_levels = np.asarray(attn_levels)
         self.bif_level = desired_a
         self.z = z
@@ -364,46 +368,50 @@ def __init__(self,f,z,attn_levels,fitted_a_mag = None,fitted_a_iq = None,desired
             self.Qs_fit_iq = np.imag(z_fit_iq)
         self.fitted_a_mag = fitted_a_mag
         self.fitted_a_iq = fitted_a_iq
-        if len(f.shape)>2:
+        if len(f.shape) > 2:
             self.f = f
         else:
             self.f = np.zeros(self.z.shape)
-            for k in range(0,self.z.shape[1]):
-                self.f[:,k,:] = self.f
+            for k in range(0, self.z.shape[1]):
+                self.f[:, k, :] = self.f
         self.chan_freqs = f
-        #self.targ_size = self.chan_freqs.shape[0]
+        # self.targ_size = self.chan_freqs.shape[0]
         self.plot_index = 0
         self.power_index = 0
-        self.res_index_overide = np.asarray((),dtype = np.int16)
-        self.overide_freq_index = np.asarray((),dtype = np.int16)
+        self.res_index_overide = np.asarray((), dtype=np.int16)
+        self.overide_freq_index = np.asarray((), dtype=np.int16)
         self.shift_is_held = False
         if fitted_a_mag is not None:
             self.bif_levels_mag = np.zeros(fitted_a_mag.shape[0])
         if fitted_a_iq is not None:
             self.bif_levels_iq = np.zeros(fitted_a_iq.shape[0])
         # here we compute our best guess for the proper power level from the fit data
-        for i in range(0,self.f.shape[1]):
+        for i in range(0, self.f.shape[1]):
             if fitted_a_mag is not None:
                 try:
-                    first_bif_mag = np.where(fitted_a_mag[i,:]>bif_level)[0][0]
+                    first_bif_mag = np.where(fitted_a_mag[i, :] > bif_level)[0][0]
                 except:
-                    first_bif_mag = fitted_a_mag.shape[1]-1
+                    first_bif_mag = fitted_a_mag.shape[1] - 1
                 if first_bif_mag == 0:
-                    first_bif_mag =1
-                interp_mag  = interpolate.interp1d(-self.attn_levels[0:first_bif_mag+1],fitted_a_mag[i,:][0:first_bif_mag+1])
-                powers_mag = np.linspace(-self.attn_levels[0]+.01,-self.attn_levels[first_bif_mag]-0.01,1000)
-                bifurcation_mag = powers_mag[np.argmin(np.abs(interp_mag(powers_mag)-np.ones(len(powers_mag))*self.bif_level))]
+                    first_bif_mag = 1
+                interp_mag = interpolate.interp1d(-self.attn_levels[0:first_bif_mag + 1],
+                                                  fitted_a_mag[i, :][0:first_bif_mag + 1])
+                powers_mag = np.linspace(-self.attn_levels[0] + .01, -self.attn_levels[first_bif_mag] - 0.01, 1000)
+                bifurcation_mag = powers_mag[
+                    np.argmin(np.abs(interp_mag(powers_mag) - np.ones(len(powers_mag)) * self.bif_level))]
                 self.bif_levels_mag[i] = bifurcation_mag
             if fitted_a_iq is not None:
                 try:
-                    first_bif_iq = np.where(fitted_a_iq[i,:]>bif_level)[0][0]
+                    first_bif_iq = np.where(fitted_a_iq[i, :] > bif_level)[0][0]
                 except:
-                    first_bif_iq = self.fitted_a_iq.shape[1]-1
+                    first_bif_iq = self.fitted_a_iq.shape[1] - 1
                 if first_bif_iq == 0:
                     first_bif_iq = 1
-                interp_iq  = interpolate.interp1d(-self.attn_levels[0:first_bif_iq+1],fitted_a_iq[i,:][0:first_bif_iq+1] )
-                powers_iq = np.linspace(-self.attn_levels[0]+.01,-self.attn_levels[first_bif_iq]-0.01,1000)
-                bifurcation_iq = powers_iq[np.argmin(np.abs(interp_iq(powers_iq)-np.ones(len(powers_iq))*self.bif_level))]
+                interp_iq = interpolate.interp1d(-self.attn_levels[0:first_bif_iq + 1],
+                                                 fitted_a_iq[i, :][0:first_bif_iq + 1])
+                powers_iq = np.linspace(-self.attn_levels[0] + .01, -self.attn_levels[first_bif_iq] - 0.01, 1000)
+                bifurcation_iq = powers_iq[
+                    np.argmin(np.abs(interp_iq(powers_iq) - np.ones(len(powers_iq)) * self.bif_level))]
                 self.bif_levels_iq[i] = bifurcation_iq
 
         if self.fitted_a_mag is not None:
@@ -414,8 +422,8 @@ def __init__(self,f,z,attn_levels,fitted_a_mag = None,fitted_a_iq = None,desired
             except:
                 print("you must supply fits to the non-linearity paramter one of two fit variables")
                 return
-        self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index]+self.attn_levels))
-        self.fig = plt.figure(1,figsize = (13,10))
+        self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index] + self.attn_levels))
+        self.fig = plt.figure(1, figsize=(13, 10))
         self.ax = self.fig.add_subplot(221)
         self.ax.set_ylabel("Power (dB)")
         self.ax.set_xlabel("Frequecy (MHz)")
@@ -429,102 +437,110 @@ def __init__(self,f,z,attn_levels,fitted_a_mag = None,fitted_a_iq = None,desired
         self.fig.canvas.mpl_connect('key_release_event', self.on_key_release)
         self.fig.canvas.mpl_connect('button_press_event', self.onClick)
         if z_fit_mag is not None:
-            self.l1_fit, = self.ax.plot(self.chan_freqs[:,self.plot_index,self.power_index],
-                                        10*np.log10(self.z_fit_mag[:,self.plot_index,self.power_index]),label = "Fit")
-        self.l1, = self.ax.plot(self.chan_freqs[:,self.plot_index,self.power_index],
-                                20*np.log10(np.abs(self.z[:,self.plot_index,self.power_index])),'o',mec = "k",label = "Data")
+            self.l1_fit, = self.ax.plot(self.chan_freqs[:, self.plot_index, self.power_index],
+                                        10 * np.log10(self.z_fit_mag[:, self.plot_index, self.power_index]),
+                                        label="Fit")
+        self.l1, = self.ax.plot(self.chan_freqs[:, self.plot_index, self.power_index],
+                                20 * np.log10(np.abs(self.z[:, self.plot_index, self.power_index])), 'o', mec="k",
+                                label="Data")
         self.ax.legend()
         if self.z_fit_iq is not None:
-            self.l2_fit, = self.ax2.plot(self.Is_fit_iq[:,self.plot_index,self.power_index],
-                                     self.Qs_fit_iq[:,self.plot_index,self.power_index],label = "Fit")
-        self.l2, = self.ax2.plot(self.Is[:,self.plot_index,self.power_index],self.Qs[:,self.plot_index,self.power_index],
-                                 'o',mec = "k",label = "Data")
+            self.l2_fit, = self.ax2.plot(self.Is_fit_iq[:, self.plot_index, self.power_index],
+                                         self.Qs_fit_iq[:, self.plot_index, self.power_index], label="Fit")
+        self.l2, = self.ax2.plot(self.Is[:, self.plot_index, self.power_index],
+                                 self.Qs[:, self.plot_index, self.power_index],
+                                 'o', mec="k", label="Data")
         self.ax2.legend()
         if self.fitted_a_mag is not None:
-            self.l3, = self.ax3.plot(-self.attn_levels,self.fitted_a_mag[self.plot_index,:],color = 'r',label = "Mag fit")
+            self.l3, = self.ax3.plot(-self.attn_levels, self.fitted_a_mag[self.plot_index, :], color='r',
+                                     label="Mag fit")
         if self.fitted_a_iq is not None:
-            self.l4, = self.ax3.plot(-self.attn_levels,self.fitted_a_iq[self.plot_index,:],color = 'g',label = "IQ fit")
-        self.l8, = self.ax3.plot((self.bif_levels[self.plot_index],self.bif_levels[self.plot_index]),(0,1),
-                                 "--",color = 'm',linewidth = 3,label = "Power pick")
-        self.l5, = self.ax3.plot((-self.attn_levels[self.power_index],-self.attn_levels[self.power_index]),
-                                 (0,1),"--",color = 'k',label = "Current power")
+            self.l4, = self.ax3.plot(-self.attn_levels, self.fitted_a_iq[self.plot_index, :], color='g', label="IQ fit")
+        self.l8, = self.ax3.plot((self.bif_levels[self.plot_index], self.bif_levels[self.plot_index]), (0, 1),
+                                 "--", color='m', linewidth=3, label="Power pick")
+        self.l5, = self.ax3.plot((-self.attn_levels[self.power_index], -self.attn_levels[self.power_index]),
+                                 (0, 1), "--", color='k', label="Current power")
         if self.fitted_a_mag is not None:
-            self.l6, = self.ax3.plot((self.bif_levels_mag[self.plot_index],self.bif_levels_mag[self.plot_index]),
-                                 (0,self.bif_level),"--",color = 'r')
+            self.l6, = self.ax3.plot((self.bif_levels_mag[self.plot_index], self.bif_levels_mag[self.plot_index]),
+                                     (0, self.bif_level), "--", color='r')
         if self.fitted_a_iq is not None:
-            self.l7, = self.ax3.plot((self.bif_levels_iq[self.plot_index],self.bif_levels_iq[self.plot_index]),
-                                 (0,self.bif_level),"--",color = 'g')
+            self.l7, = self.ax3.plot((self.bif_levels_iq[self.plot_index], self.bif_levels_iq[self.plot_index]),
+                                     (0, self.bif_level), "--", color='g')
         self.ax3.legend()
-        self.ax3.set_ylim(0,1)
-        self.ax.set_title("Resonator index "+str(self.plot_index))
-        self.ax2.set_title("Power level "+str(-self.attn_levels[self.power_index]))
+        self.ax3.set_ylim(0, 1)
+        self.ax.set_title("Resonator index " + str(self.plot_index))
+        self.ax2.set_title("Power level " + str(-self.attn_levels[self.power_index]))
         print("")
         print("Interactive Power Tuning Activated")
         print("Use left and right arrows to switch between resonators")
         print("Use the up and down arrows to change between power levels")
         print("Hold shift and right click on the bottom plot to overide picked power level")
         print("or hold shift and press enter to overide picked power level to the current plotted power level")
-        plt.show(block = True)
+        plt.show(block=True)
 
     def refresh_plot(self):
-        self.l1.set_data(self.chan_freqs[:,self.plot_index,self.power_index],
-                         10*np.log10(self.Is[:,self.plot_index,self.power_index]**2+self.Qs[:,self.plot_index,self.power_index]**2))
+        self.l1.set_data(self.chan_freqs[:, self.plot_index, self.power_index],
+                         10 * np.log10(self.Is[:, self.plot_index, self.power_index] ** 2 + self.Qs[:, self.plot_index,
+                                                                                            self.power_index] ** 2))
         if self.z_fit_mag is not None:
-            self.l1_fit.set_data(self.chan_freqs[:,self.plot_index,self.power_index],
-                                 10*np.log10(self.z_fit_mag[:,self.plot_index,self.power_index]))
+            self.l1_fit.set_data(self.chan_freqs[:, self.plot_index, self.power_index],
+                                 10 * np.log10(self.z_fit_mag[:, self.plot_index, self.power_index]))
         self.ax.relim()
         self.ax.autoscale()
-        self.ax.set_title("Resonator index "+str(self.plot_index))
-        self.ax2.set_title("Power level "+str(-self.attn_levels[self.power_index]))
-        self.l2.set_data((self.Is[:,self.plot_index,self.power_index],self.Qs[:,self.plot_index,self.power_index]))
+        self.ax.set_title("Resonator index " + str(self.plot_index))
+        self.ax2.set_title("Power level " + str(-self.attn_levels[self.power_index]))
+        self.l2.set_data((self.Is[:, self.plot_index, self.power_index], self.Qs[:, self.plot_index, self.power_index]))
         if self.z_fit_iq is not None:
-            self.l2_fit.set_data((self.Is_fit_iq[:,self.plot_index,self.power_index],self.Qs_fit_iq[:,self.plot_index,self.power_index]))
+            self.l2_fit.set_data((self.Is_fit_iq[:, self.plot_index, self.power_index],
+                                  self.Qs_fit_iq[:, self.plot_index, self.power_index]))
         if self.fitted_a_mag is not None:
-            self.l3.set_data(-self.attn_levels,self.fitted_a_mag[self.plot_index,:])
-        self.l4.set_data(-self.attn_levels,self.fitted_a_iq[self.plot_index,:])        
-        self.l5.set_data((-self.attn_levels[self.power_index],-self.attn_levels[self.power_index]),(0,1))
+            self.l3.set_data(-self.attn_levels, self.fitted_a_mag[self.plot_index, :])
+        self.l4.set_data(-self.attn_levels, self.fitted_a_iq[self.plot_index, :])
+        self.l5.set_data((-self.attn_levels[self.power_index], -self.attn_levels[self.power_index]), (0, 1))
         if self.fitted_a_mag is not None:
-            self.l6.set_data((self.bif_levels_mag[self.plot_index],self.bif_levels_mag[self.plot_index]),(0,self.bif_level))
+            self.l6.set_data((self.bif_levels_mag[self.plot_index], self.bif_levels_mag[self.plot_index]),
+                             (0, self.bif_level))
         if self.fitted_a_iq is not None:
-            self.l7.set_data((self.bif_levels_iq[self.plot_index],self.bif_levels_iq[self.plot_index]),(0,self.bif_level))
-        
-        self.l8.set_data((self.bif_levels[self.plot_index],self.bif_levels[self.plot_index]),(0,1))
+            self.l7.set_data((self.bif_levels_iq[self.plot_index], self.bif_levels_iq[self.plot_index]),
+                             (0, self.bif_level))
+
+        self.l8.set_data((self.bif_levels[self.plot_index], self.bif_levels[self.plot_index]), (0, 1))
         self.ax2.relim()
         self.ax2.autoscale()
         plt.draw()
-        
+
     def on_key_press(self, event):
-        #print(event.key) #for debugging
+        # print(event.key) #for debugging
         if event.key == 'right':
-           if self.plot_index != self.chan_freqs.shape[1]-1:
-               self.plot_index = self.plot_index +1
-               #snap to the automated choice in power level
-               self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index]+self.attn_levels))
-               self.refresh_plot()
+            if self.plot_index != self.chan_freqs.shape[1] - 1:
+                self.plot_index = self.plot_index + 1
+                # snap to the automated choice in power level
+                self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index] + self.attn_levels))
+                self.refresh_plot()
 
         if event.key == 'left':
-           if self.plot_index != 0:
-               self.plot_index = self.plot_index -1
-               #snap to the automated choice in power level
-               self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index]+self.attn_levels))
-               self.refresh_plot()
+            if self.plot_index != 0:
+                self.plot_index = self.plot_index - 1
+                # snap to the automated choice in power level
+                self.power_index = np.argmin(np.abs(self.bif_levels[self.plot_index] + self.attn_levels))
+                self.refresh_plot()
 
         if event.key == 'up':
-            if self.power_index != self.Is.shape[2]-1:
-                self.power_index = self.power_index +1
+            if self.power_index != self.Is.shape[2] - 1:
+                self.power_index = self.power_index + 1
             self.refresh_plot()
 
         if event.key == 'down':
             if self.power_index != 0:
-               self.power_index = self.power_index -1
+                self.power_index = self.power_index - 1
             self.refresh_plot()
 
         if event.key == 'shift':
-                self.shift_is_held = True
-                #print("shift pressed") #for debugging
+            self.shift_is_held = True
+            # print("shift pressed") #for debugging
 
-        if event.key == 'enter': # is this still needed on any os?
-            #print("enter pressed")
+        if event.key == 'enter':  # is this still needed on any os?
+            # print("enter pressed")
             if self.shift_is_held:
                 self.bif_levels[self.plot_index] = -self.attn_levels[self.power_index]
                 self.refresh_plot()
@@ -533,52 +549,50 @@ def on_key_press(self, event):
             self.bif_levels[self.plot_index] = -self.attn_levels[self.power_index]
             self.refresh_plot()
 
-    def on_key_release(self,event):
+    def on_key_release(self, event):
         if event.key == "shift":
             self.shift_is_held = False
-            #print("shift released") #for debugging
+            # print("shift released") #for debugging
 
-    def onClick(self,event):
+    def onClick(self, event):
         if event.button == 3:
             if self.shift_is_held:
-                print("overiding point selection",event.xdata)
+                print("overiding point selection", event.xdata)
                 self.bif_levels[self.plot_index] = event.xdata
                 self.refresh_plot()
 
 
-
-
-def tune_resonance_power(f,z,attn_levels,fitted_a_mag = None,fitted_a_iq = None,desired_a = 0.5,z_fit_mag = None,z_fit_iq = None):
+def tune_resonance_power(f, z, attn_levels, fitted_a_mag=None, fitted_a_iq=None, desired_a=0.5, z_fit_mag=None,
+                         z_fit_iq=None):
     # Call the interactive plot
-    ip = interactive_power_tuning_plot(f,z,attn_levels,fitted_a_mag = fitted_a_mag,
-                                       fitted_a_iq = fitted_a_iq,desired_a = desired_a,
-                                       z_fit_mag = z_fit_mag,z_fit_iq = z_fit_iq)
-            
-    picked_power_levels = ip.bif_levels+attn_levels[-1]
-    #plot the resultant picked power levels and the corresponding transfer function
-    plt.figure(1,figsize = (12,10))
+    ip = InteractivePowerTuningPlot(f, z, attn_levels, fitted_a_mag=fitted_a_mag,
+                                    fitted_a_iq=fitted_a_iq, desired_a=desired_a,
+                                    z_fit_mag=z_fit_mag, z_fit_iq=z_fit_iq)
+
+    picked_power_levels = ip.bif_levels + attn_levels[-1]
+    # plot the resultant picked power levels and the corresponding transfer function
+    plt.figure(1, figsize=(12, 10))
     plt.subplot(211)
     plt.title("Bifurcation power")
-    plt.plot(picked_power_levels,'o',color = 'g',label = "Picked Valuse")
+    plt.plot(picked_power_levels, 'o', color='g', label="Picked Valuse")
     plt.xlabel("Resonator index")
-    plt.ylabel("Power at a = "+ str(desired_a))
-    plt.legend(loc = 4)
-    
-    normalizing_amplitudes = np.sqrt(10**((ip.bif_levels+attn_levels[-1])/10)/np.min(10**((ip.bif_levels+attn_levels[-1])/10)))
+    plt.ylabel("Power at a = " + str(desired_a))
+    plt.legend(loc=4)
+
+    normalizing_amplitudes = np.sqrt(
+        10 ** ((ip.bif_levels + attn_levels[-1]) / 10) / np.min(10 ** ((ip.bif_levels + attn_levels[-1]) / 10)))
     plt.subplot(212)
     plt.title("Transfer function")
-    plt.plot(normalizing_amplitudes,'o')
+    plt.plot(normalizing_amplitudes, 'o')
     plt.xlabel("Resonator index")
     plt.ylabel("Voltage factor")
 
-    #plt.savefig("power_sweep_results_"+fine_names[0].split('/')[-1]+".pdf")
+    # plt.savefig("power_sweep_results_"+fine_names[0].split('/')[-1]+".pdf")
 
     # save the output
-    #np.savetxt("bif_levels_mag_"+fine_names[0].split('/')[-1]+".csv",ip.bif_levels_mag+attn_levels[-1])
-    #np.savetxt("bif_levels_iq_"+fine_names[0].split('/')[-1]+".csv",ip.bif_levels_iq+attn_levels[-1])
-    #np.save("trans_func_"+fine_names[0].split('/')[-1],np.sqrt(10**((ip.bif_levels+attn_levels[-1])/10)/np.min(10**((ip.bif_levels+attn_levels[-1])/10))))
+    # np.savetxt("bif_levels_mag_"+fine_names[0].split('/')[-1]+".csv",ip.bif_levels_mag+attn_levels[-1])
+    # np.savetxt("bif_levels_iq_"+fine_names[0].split('/')[-1]+".csv",ip.bif_levels_iq+attn_levels[-1])
+    # np.save("trans_func_"+fine_names[0].split('/')[-1],np.sqrt(10**((ip.bif_levels+attn_levels[-1])/10)/np.min(10**((ip.bif_levels+attn_levels[-1])/10))))
 
     plt.show()
-    return picked_power_levels,normalizing_amplitudes
-
-
+    return picked_power_levels, normalizing_amplitudes
diff --git a/submm/KIDs/res/utils.py b/submm/KIDs/res/utils.py
new file mode 100644
index 0000000..f6cbe14
--- /dev/null
+++ b/submm/KIDs/res/utils.py
@@ -0,0 +1,566 @@
+import numpy as np
+from numba import jit
+
+from submm.KIDs import calibrate
+
+J = np.exp(2j * np.pi / 3)
+Jc = 1 / J
+
+
+@jit(nopython=True)
+def cardan(a, b, c, d):
+    """
+    analytical root finding fast: using numba looks like x10 speed up
+    returns only the largest real root
+    """
+    u = np.empty(2, np.complex128)
+    z0 = b / 3 / a
+    a2, b2 = a * a, b * b
+    p = -b2 / 3 / a2 + c / a
+    q = (b / 27 * (2 * b2 / a2 - 9 * c / a) + d) / a
+    D = -4 * p * p * p - 27 * q * q
+    r = np.sqrt(-D / 27 + 0j)
+    one_third = 1 / 3.0
+    u = ((-q - r) / 2) ** one_third  # 0.33333333333333333333333
+    v = ((-q + r) / 2) ** one_third  # 0.33333333333333333333333
+    w = u * v
+    w0 = np.abs(w + p / 3)
+    w1 = np.abs(w * J + p / 3)
+    w2 = np.abs(w * Jc + p / 3)
+    if w0 < w1:
+        if w2 < w0:
+            v *= Jc
+    elif w2 < w1:
+        v *= Jc
+    else:
+        v *= J
+    roots = np.asarray((u + v - z0, u * J + v * Jc - z0, u * Jc + v * J - z0))
+    # print(roots)
+    where_real = np.where(np.abs(np.imag(roots)) < 1e-15)
+    # if len(where_real)>1: print(len(where_real))
+    # print(D)
+    if D > 0:
+        return np.max(np.real(roots))  # three real roots
+    else:
+        # one real root get the value that has the smallest imaginary component
+        return np.real(roots[np.argsort(np.abs(np.imag(roots)))][0])
+    # return np.max(np.real(roots[where_real]))
+    # return np.asarray((u+v-z0, u*J+v*Jc-z0,u*Jc+v*J-z0))
+
+
+def amplitude_normalization(x, z):
+    """
+    # normalize the amplitude varation requires a gain scan
+    #flag frequencies to use in amplitude normaliztion
+    """
+    index_use = np.where(np.abs(x - np.median(x)) > 100000)  # 100kHz away from resonator
+    poly = np.polyfit(x[index_use], np.abs(z[index_use]), 2)
+    poly_func = np.poly1d(poly)
+    normalized_data = z / poly_func(x) * np.median(np.abs(z[index_use]))
+    return normalized_data
+
+
+def amplitude_normalization_sep(gain_x, gain_z, fine_x, fine_z, stream_x, stream_z):
+    """
+    # normalize the amplitude varation requires a gain scan
+    # uses gain scan to normalize does not use fine scan
+    #flag frequencies to use in amplitude normaliztion
+    """
+    index_use = np.where(np.abs(gain_x - np.median(gain_x)) > 100000)  # 100kHz away from resonator
+    poly = np.polyfit(gain_x[index_use], np.abs(gain_z[index_use]), 2)
+    poly_func = np.poly1d(poly)
+    poly_data = poly_func(gain_x)
+    normalized_gain = gain_z / poly_data * np.median(np.abs(gain_z[index_use]))
+    normalized_fine = fine_z / poly_func(fine_x) * np.median(np.abs(gain_z[index_use]))
+    normalized_stream = stream_z / poly_func(stream_x) * np.median(np.abs(gain_z[index_use]))
+    amp_norm_dict = {'normalized_gain': normalized_gain,
+                     'normalized_fine': normalized_fine,
+                     'normalized_stream': normalized_stream,
+                     'poly_data': poly_data}
+    return amp_norm_dict
+
+
+def guess_x0_iq_nonlinear(x, z, verbose=False):
+    """
+    # this is less robust than guess_x0_iq_nonlinear_sep
+    # below. it is recommended to use that instead
+    #make sure data is sorted from low to high frequency
+    """
+    sort_index = np.argsort(x)
+    x = x[sort_index]
+    z = z[sort_index]
+    # extract just fine data
+    df = np.abs(x - np.roll(x, 1))
+    fine_df = np.min(df[np.where(df != 0)])
+    fine_z_index = np.where(df < fine_df * 1.1)
+    fine_z = z[fine_z_index]
+    fine_x = x[fine_z_index]
+    # extract the gain scan
+    gain_z_index = np.where(df > fine_df * 1.1)
+    gain_z = z[gain_z_index]
+    gain_x = x[gain_z_index]
+    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
+
+    # guess f0
+    fr_guess_index = np.argmin(np.abs(z))
+    # fr_guess = x[fr_guess_index]
+    fr_guess_index_fine = np.argmin(np.abs(fine_z))
+    # below breaks if there is not a right and left side in the fine scan
+    if fr_guess_index_fine == 0:
+        fr_guess_index_fine = len(fine_x) // 2
+    elif fr_guess_index_fine == (len(fine_x) - 1):
+        fr_guess_index_fine = len(fine_x) // 2
+    fr_guess = fine_x[fr_guess_index_fine]
+
+    # guess Q
+    mag_max = np.max(np.abs(fine_z) ** 2)
+    mag_min = np.min(np.abs(fine_z) ** 2)
+    mag_3dB = (mag_max + mag_min) / 2.
+    half_distance = np.abs(fine_z) ** 2 - mag_3dB
+    right = half_distance[fr_guess_index_fine:-1]
+    left = half_distance[0:fr_guess_index_fine]
+    right_index = np.argmin(np.abs(right)) + fr_guess_index_fine
+    left_index = np.argmin(np.abs(left))
+    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+    Q_guess = fr_guess / Q_guess_Hz
+
+    # guess amp
+    d = np.max(20 * np.log10(np.abs(z))) - np.min(20 * np.log10(np.abs(z)))
+    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
+
+    # guess impedance rotation phi
+    phi_guess = 0
+
+    # guess non-linearity parameter
+    # might be able to guess this by taking the ratio of the distance between min and max distance between iq points in fine sweep
+    a_guess = 0
+
+    # i0 and iq guess
+    if np.max(np.abs(fine_z)) == np.max(np.abs(z)):
+        # if the resonator has an impedance mismatch rotation that makes the fine greater that the cable delay
+        i0_guess = np.real(fine_z[np.argmax(np.abs(fine_z))])
+        q0_guess = np.imag(fine_z[np.argmax(np.abs(fine_z))])
+    else:
+        i0_guess = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2.
+        q0_guess = (np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
+
+    # cable delay guess tau
+    # y = mx +b
+    # m = (y2 - y1)/(x2-x1)
+    # b = y-mx
+    if len(gain_z) > 1:  # is there a gain scan?
+        m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
+        b = gain_phase - m * gain_x
+        m_best = np.median(m[~np.isnan(m)])
+        tau_guess = m_best / (2 * np.pi)
+    else:
+        tau_guess = 3 * 10 ** -9
+
+    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, i0_guess, q0_guess, tau_guess, fr_guess]
+
+    if verbose:
+        print_fit_string_nonlinear_iq(x0)
+    return x0
+
+
+def guess_x0_mag_nonlinear(x, z, verbose=False):
+    """
+    # this is less robust than guess_x0_mag_nonlinear_sep
+    #below it is recommended to use that instead
+    #make sure data is sorted from low to high frequency
+    """
+    sort_index = np.argsort(x)
+    x = x[sort_index]
+    z = z[sort_index]
+    # extract just fine data
+    # this will probably break if there is no fine scan
+    df = np.abs(x - np.roll(x, 1))
+    fine_df = np.min(df[np.where(df != 0)])
+    fine_z_index = np.where(df < fine_df * 1.1)
+    fine_z = z[fine_z_index]
+    fine_x = x[fine_z_index]
+    # extract the gain scan
+    gain_z_index = np.where(df > fine_df * 1.1)
+    gain_z = z[gain_z_index]
+    gain_x = x[gain_z_index]
+    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
+
+    # guess f0
+    fr_guess_index = np.argmin(np.abs(z))
+    # fr_guess = x[fr_guess_index]
+    fr_guess_index_fine = np.argmin(np.abs(fine_z))
+    if fr_guess_index_fine == 0:
+        fr_guess_index_fine = len(fine_x) // 2
+    elif fr_guess_index_fine == (len(fine_x) - 1):
+        fr_guess_index_fine = len(fine_x) // 2
+    fr_guess = fine_x[fr_guess_index_fine]
+
+    # guess Q
+    mag_max = np.max(np.abs(fine_z) ** 2)
+    mag_min = np.min(np.abs(fine_z) ** 2)
+    mag_3dB = (mag_max + mag_min) / 2.
+    half_distance = np.abs(fine_z) ** 2 - mag_3dB
+    right = half_distance[fr_guess_index_fine:-1]
+    left = half_distance[0:fr_guess_index_fine]
+    right_index = np.argmin(np.abs(right)) + fr_guess_index_fine
+    left_index = np.argmin(np.abs(left))
+    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+    Q_guess = fr_guess / Q_guess_Hz
+
+    # guess amp
+    d = np.max(20 * np.log10(np.abs(z))) - np.min(20 * np.log10(np.abs(z)))
+    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
+
+    # guess impedance rotation phi
+    phi_guess = 0
+
+    # guess non-linearity parameter
+    # might be able to guess this by using the ratio of the distance between min and max distance between iq points
+    #   in fine sweep
+    a_guess = 0
+
+    # b0 and b1 guess
+
+    if len(gain_z) > 1:
+        xlin = (gain_x - fr_guess) / fr_guess
+        b1_guess = (np.abs(gain_z)[-1] ** 2 - np.abs(gain_z)[0] ** 2) / (xlin[-1] - xlin[0])
+    else:
+        xlin = (fine_x - fr_guess) / fr_guess
+        b1_guess = (np.abs(fine_z)[-1] ** 2 - np.abs(fine_z)[0] ** 2) / (xlin[-1] - xlin[0])
+    b0_guess = np.median(np.abs(gain_z) ** 2)
+
+    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, b0_guess, b1_guess, fr_guess]
+
+    if verbose:
+        print_fit_string_nonlinear_mag(x0)
+
+    return x0
+
+
+def guess_x0_iq_nonlinear_sep(fine_x, fine_z, gain_x, gain_z, verbose=False):
+    """
+    # this is the same as guess_x0_iq_nonlinear except that it takes
+    # takes the fine scan and the gain scan as seperate variables
+    # this runs into less issues when trying to sort out what part of
+    # data is fine and what part is gain for the guessing
+    #make sure data is sorted from low to high frequency
+    """
+
+    # gain phase
+    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
+
+    # guess f0
+    fr_guess_index = np.argmin(np.abs(fine_z))
+    # below breaks if there is not a right and left side in the fine scan
+    if fr_guess_index == 0:
+        fr_guess_index = len(fine_x) // 2
+    elif fr_guess_index == (len(fine_x) - 1):
+        fr_guess_index = len(fine_x) // 2
+    fr_guess = fine_x[fr_guess_index]
+
+    # guess Q
+    mag_max = np.max(np.abs(fine_z) ** 2)
+    mag_min = np.min(np.abs(fine_z) ** 2)
+    mag_3dB = (mag_max + mag_min) / 2.
+    half_distance = np.abs(fine_z) ** 2 - mag_3dB
+    right = half_distance[fr_guess_index:-1]
+    left = half_distance[0:fr_guess_index]
+    right_index = np.argmin(np.abs(right)) + fr_guess_index
+    left_index = np.argmin(np.abs(left))
+    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+    Q_guess = fr_guess / Q_guess_Hz
+
+    # guess amp
+    d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z)))
+    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
+
+    # guess impedance rotation phi
+    # phi_guess = 0
+    # guess impedance rotation phi
+    # fit a circle to the iq loop
+    xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_z), np.imag(fine_z))
+    # compute angle between (off_res,off_res),(0,0) and (off_ress,off_res),(xc,yc) of the the fitted circle
+    off_res_i, off_res_q = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2., (
+            np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
+    x1, y1, = -off_res_i, -off_res_q
+    x2, y2 = xc - off_res_i, yc - off_res_q
+    dot = x1 * x2 + y1 * y2  # dot product
+    det = x1 * y2 - y1 * x2  # determinant
+    angle = np.arctan2(det, dot)
+    phi_guess = angle
+
+    # if phi is large better re guess f0
+    # f0 should be the farthers from the off res point
+    if (np.abs(phi_guess) > 0.3):
+        dist1 = np.sqrt((np.real(fine_z[0]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[0]) - np.imag(fine_z)) ** 2)
+        dist2 = np.sqrt((np.real(fine_z[-1]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[-1]) - np.imag(fine_z)) ** 2)
+        fr_guess_index = np.argmax((dist1 + dist2))
+        fr_guess = fine_x[fr_guess_index]
+        # also fix the Q gues
+        fine_z_derot = (fine_z - (off_res_i + 1.j * off_res_q)) * np.exp(1j * (-phi_guess)) + (
+                off_res_i + 1.j * off_res_q)
+        # fr_guess_index = np.argmin(np.abs(fine_z_derot))
+        # fr_guess = fine_x[fr_guess_index]
+        mag_max = np.max(np.abs(fine_z_derot) ** 2)
+        mag_min = np.min(np.abs(fine_z_derot) ** 2)
+        mag_3dB = (mag_max + mag_min) / 2.
+        half_distance = np.abs(fine_z_derot) ** 2 - mag_3dB
+        right = half_distance[np.argmin(np.abs(fine_z_derot)):-1]
+        left = half_distance[0:np.argmin(np.abs(fine_z_derot))]
+        right_index = np.argmin(np.abs(right)) + np.argmin(np.abs(fine_z_derot))
+        left_index = np.argmin(np.abs(left))
+        Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+        Q_guess = fr_guess / Q_guess_Hz
+        # also fix amp guess
+        d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z_derot)))
+        amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
+
+    # guess non-linearity parameter
+    # might be able to guess this by taking the ratio of the distance between min and max distance between iq points
+    # in fine sweep
+    a_guess = 0
+
+    # i0 and iq guess
+    if np.max(np.abs(fine_z)) > np.max(np.abs(gain_z)):
+        # if the resonator has an impedance mismatch rotation that makes the fine greater that the cable delay
+        i0_guess = np.real(fine_z[np.argmax(np.abs(fine_z))])
+        q0_guess = np.imag(fine_z[np.argmax(np.abs(fine_z))])
+    else:
+        i0_guess = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2.
+        q0_guess = (np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
+
+    # cable delay guess tau
+    # y = mx +b
+    # m = (y2 - y1)/(x2-x1)
+    # b = y-mx
+    m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
+    b = gain_phase - m * gain_x
+    m_best = np.median(m[~np.isnan(m)])
+    tau_guess = m_best / (2 * np.pi)
+
+    if verbose == True:
+        print("fr guess  = %.3f MHz" % (fr_guess / 10 ** 6))
+        print("Q guess   = %.2f kHz, %.1f" % ((Q_guess_Hz / 10 ** 3), Q_guess))
+        print("amp guess = %.2f" % amp_guess)
+        print("phi guess = %.2f" % phi_guess)
+        print("i0 guess  = %.2f" % i0_guess)
+        print("q0 guess  = %.2f" % q0_guess)
+        print("tau guess = %.2f x 10^-7" % (tau_guess / 10 ** -7))
+
+    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, i0_guess, q0_guess, tau_guess, fr_guess]
+    return x0
+
+
+def guess_x0_mag_nonlinear_sep(fine_x, fine_z, gain_x, gain_z, verbose=False):
+    """
+    # this is the same as guess_x0_mag_nonlinear except that it takes
+    # takes the fine scan and the gain scan as seperate variables
+    # this runs into less issues when trying to sort out what part of
+    # data is fine and what part is gain for the guessing
+    #make sure data is sorted from low to high frequency
+    """
+
+    # phase of gain
+    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
+
+    # guess f0
+    fr_guess_index = np.argmin(np.abs(fine_z))
+    # protect against guessing the first or last data points
+    if fr_guess_index == 0:
+        fr_guess_index = len(fine_x) // 2
+    elif fr_guess_index == (len(fine_x) - 1):
+        fr_guess_index = len(fine_x) // 2
+    fr_guess = fine_x[fr_guess_index]
+
+    # guess Q
+    mag_max = np.max(np.abs(fine_z) ** 2)
+    mag_min = np.min(np.abs(fine_z) ** 2)
+    mag_3dB = (mag_max + mag_min) / 2.
+    half_distance = np.abs(fine_z) ** 2 - mag_3dB
+    right = half_distance[fr_guess_index:-1]
+    left = half_distance[0:fr_guess_index]
+    right_index = np.argmin(np.abs(right)) + fr_guess_index
+    left_index = np.argmin(np.abs(left))
+    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+    Q_guess = fr_guess / Q_guess_Hz
+
+    # guess amp
+    d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z)))
+    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + \
+                0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
+    # polynomial fit to amp versus depth calculated empirically
+
+    # guess impedance rotation phi
+    # fit a circle to the iq loop
+    xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_z), np.imag(fine_z))
+    # compute angle between (off_res,off_res),(0,0) and (off_ress,off_res),(xc,yc) of the the fitted circle
+    off_res_i, off_res_q = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2., (
+            np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
+    x1, y1, = -off_res_i, -off_res_q
+    x2, y2 = xc - off_res_i, yc - off_res_q
+    dot = x1 * x2 + y1 * y2  # dot product
+    det = x1 * y2 - y1 * x2  # determinant
+    angle = np.arctan2(det, dot)
+    phi_guess = angle
+
+    # if phi is large better re guess f0
+    # f0 should be the farthers from the off res point
+    if (np.abs(phi_guess) > 0.3):
+        dist1 = np.sqrt((np.real(fine_z[0]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[0]) - np.imag(fine_z)) ** 2)
+        dist2 = np.sqrt((np.real(fine_z[-1]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[-1]) - np.imag(fine_z)) ** 2)
+        fr_guess_index = np.argmax((dist1 + dist2))
+        fr_guess = fine_x[fr_guess_index]
+        fine_z_derot = (fine_z - (off_res_i + 1.j * off_res_q)) * np.exp(1j * (-phi_guess)) + (
+                off_res_i + 1.j * off_res_q)
+        # fr_guess_index = np.argmin(np.abs(fine_z_derot))
+        # fr_guess = fine_x[fr_guess_index]
+        mag_max = np.max(np.abs(fine_z_derot) ** 2)
+        mag_min = np.min(np.abs(fine_z_derot) ** 2)
+        mag_3dB = (mag_max + mag_min) / 2.
+        half_distance = np.abs(fine_z_derot) ** 2 - mag_3dB
+        right = half_distance[np.argmin(np.abs(fine_z_derot)):-1]
+        left = half_distance[0:np.argmin(np.abs(fine_z_derot))]
+        right_index = np.argmin(np.abs(right)) + np.argmin(np.abs(fine_z_derot))
+        left_index = np.argmin(np.abs(left))
+        Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
+        Q_guess = fr_guess / Q_guess_Hz
+        # also fix amp guess
+        d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z_derot)))
+        amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
+
+    # guess non-linearity parameter
+    # might be able to guess this by taking the ratio of the distance between min and max distance between
+    # iq points in fine sweep
+    a_guess = 0
+
+    # b0 and b1 guess
+    xlin = (gain_x - fr_guess) / fr_guess
+    b1_guess = (np.abs(gain_z)[-1] ** 2 - np.abs(gain_z)[0] ** 2) / (xlin[-1] - xlin[0])
+    b0_guess = np.max((np.max(np.abs(fine_z) ** 2), np.max(np.abs(gain_z) ** 2)))
+
+    # cable delay guess tau
+    # y = mx +b
+    # m = (y2 - y1)/(x2-x1)
+    # b = y-mx
+    m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
+    b = gain_phase - m * gain_x
+    m_best = np.median(m[~np.isnan(m)])
+    tau_guess = m_best / (2 * np.pi)
+
+    if verbose:
+        print("fr guess  = %.3f MHz" % (fr_guess / 10 ** 6))
+        print("Q guess   = %.2f kHz, %.1f" % ((Q_guess_Hz / 10 ** 3), Q_guess))
+        print("amp guess = %.2f" % amp_guess)
+        print("phi guess = %.2f" % phi_guess)
+        print("b0 guess  = %.2f" % b0_guess)
+        print("b1 guess  = %.2f" % b1_guess)
+        print("tau guess = %.2f x 10^-7" % (tau_guess / 10 ** -7))
+
+    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, b0_guess, b1_guess, fr_guess]
+    return x0
+
+
+def calc_qc_qi(qr: float, amp: float):
+    qc = qr / amp
+    qi = 1.0 / ((1.0 / qr) - (1.0 / qc))
+    return qc, qi
+
+
+default_null_strings = {'', 'None', 'none', 'null', 'NaN', 'nan'}
+default_true_strings = {'Y', 'y', 'True', 'true'}
+default_false_strings = {'N', 'n', 'False', 'false'}
+
+
+def make_int(test_num_str):
+    """
+    Parameters
+    ----------
+    test_num_str:
+        str, required. A string to test to see it can be cast into and integer.
+    Returns int, if the string can be cast into and integer, otherwise it returns the original string.
+    -------
+    """
+    try:
+        return int(test_num_str)
+    except ValueError:
+        return test_num_str
+
+
+def make_num(test_datum):
+
+    # tests to se if this string is an int
+    test_datum_maybe_int = make_int(test_num_str=test_datum)
+    if isinstance(test_datum_maybe_int, int):
+        return test_datum_maybe_int
+    else:
+        # either a float or a sting.
+        try:
+            return float(test_datum_maybe_int)
+        except ValueError:
+            return test_datum_maybe_int
+
+
+def format_datum(test_datum, null_strs=None, true_strs=None, false_strs=None):
+    # strip off spaces and newline charters
+    test_datum_stripped = test_datum.strip()
+    # Null handling
+    if null_strs is None:
+        null_strs = default_null_strings
+    if not isinstance(null_strs, set):
+        null_strs = set(null_strs)
+    # True handling
+    if true_strs is None:
+        true_strs = default_true_strings
+    if not isinstance(true_strs, set):
+        true_strs = set(true_strs)
+    # False handling
+    if false_strs is None:
+        false_strs = default_false_strings
+    if not isinstance(false_strs, set):
+        false_strs = set(false_strs)
+    # see if this an expected null, true, or false value, else move on to number testing
+    if test_datum_stripped in null_strs:
+        return None
+    elif test_datum_stripped in true_strs:
+        return True
+    elif test_datum_stripped in false_strs:
+        return False
+    else:
+        return make_num(test_datum=test_datum_stripped)
+
+
+def line_format(raw_line, delimiter=','):
+    return [format_datum(datum_raw) for datum_raw in raw_line.split(delimiter)]
+
+
+# https://stackabuse.com/how-to-print-colored-text-in-python/
+style_to_number = {'normal': 0, 'bold': 1, 'dark': 2, 'light': 3, 'underline': 4, 'blink': 5}
+text_color_to_number = {'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34, 'purple': 35,
+                        'cyan': 36, 'white': 37}
+background_color_to_number = {'black': 40, 'red': 41, 'green': 42, 'yellow': 43, 'blue': 44, 'purple': 45,
+                              'cyan': 46, 'white': 47}
+
+
+def colorize_text(text: str, style_text: str = 'normal', color_text: str = 'white', color_background: str = 'black'):
+    if style_text not in style_to_number.keys():
+        raise ValueError(f"Style '{style_text}' not found, options are {style_to_number.keys()}")
+    if color_text not in text_color_to_number.keys():
+        raise ValueError(f"Color '{color_text}' not found, options are {text_color_to_number.keys()}")
+    if color_background not in background_color_to_number.keys():
+        raise ValueError(f"Color '{color_background}' not found, options are {background_color_to_number.keys()}")
+    style_number = style_to_number[style_text]
+    text_color_number = text_color_to_number[color_text]
+    background_color_number = background_color_to_number[color_background]
+    return f"\033[{style_number};{text_color_number};{background_color_number}m{text}\033[0;0m"
+
+
+def derived_text(text):
+    return colorize_text(text, style_text='bold', color_text='black', color_background='green')
+
+
+def filename_text(text):
+    return colorize_text(text, style_text='bold', color_text='white', color_background='black')
+
+
+def write_text(text):
+    return colorize_text(text, style_text='bold', color_text='black', color_background='purple')
diff --git a/submm/KIDs/resonance_fitting.py b/submm/KIDs/resonance_fitting.py
deleted file mode 100644
index 2769524..0000000
--- a/submm/KIDs/resonance_fitting.py
+++ /dev/null
@@ -1,1437 +0,0 @@
-"""
-numba seems to make the fitting 10 times faster
-
-module for fitting resonances curves for kinetic inductance detectors.
-written by Jordan Wheeler 12/21/16
-
-for example see res_fit.ipynb in this demos directory
-
-To Do
-I think the error analysis on the fit_nonlinear_iq_with_err probably needs some work
-add in step by step fitting i.e. first amplitude normalization, then cable delay, then i0,q0 subtraction,
-     then phase rotation, then the rest of the fit.
-need to have fit option that just specifies tau because that never really changes for your cryostat
-
-Change log
-JDW 2017-08-17 added in a keyword/function to allow for gain variation "amp_var" to be taken out before fitting
-JDW 2017-08-30 added in fitting for magnitude fitting of resonators i.e. not in iq space
-JDW 2018-03-05 added more clever function for guessing x0 for fits
-JDW 2018-08-23 added more clever guessing for resonators with large phi into guess separate functions
-CHW 2022-09-02 PEP-8 formatting, spelling corrections, and minor code cleanup
-"""
-
-import numpy as np
-from numba import jit
-import scipy.optimize as optimization
-import matplotlib.pyplot as plt
-
-from submm.KIDs import calibrate
-
-J = np.exp(2j * np.pi / 3)
-Jc = 1 / J
-
-
-@jit(nopython=True)
-def cardan(a, b, c, d):
-    """
-    analytical root finding fast: using numba looks like x10 speed up
-    returns only the largest real root
-    """
-    u = np.empty(2, np.complex128)
-    z0 = b / 3 / a
-    a2, b2 = a * a, b * b
-    p = -b2 / 3 / a2 + c / a
-    q = (b / 27 * (2 * b2 / a2 - 9 * c / a) + d) / a
-    D = -4 * p * p * p - 27 * q * q
-    r = np.sqrt(-D / 27 + 0j)
-    u = ((-q - r) / 2) ** (1 / 3.)  # 0.33333333333333333333333
-    v = ((-q + r) / 2) ** (1 / 3.)  # 0.33333333333333333333333
-    w = u * v
-    w0 = np.abs(w + p / 3)
-    w1 = np.abs(w * J + p / 3)
-    w2 = np.abs(w * Jc + p / 3)
-    if w0 < w1:
-        if w2 < w0:
-            v *= Jc
-    elif w2 < w1:
-        v *= Jc
-    else:
-        v *= J
-    roots = np.asarray((u + v - z0, u * J + v * Jc - z0, u * Jc + v * J - z0))
-    # print(roots)
-    where_real = np.where(np.abs(np.imag(roots)) < 1e-15)
-    # if len(where_real)>1: print(len(where_real))
-    # print(D)
-    if D > 0:
-        return np.max(np.real(roots))  # three real roots
-    else:
-        return np.real(roots[np.argsort(np.abs(np.imag(roots)))][
-                           0])  # one real root get the value that has smallest imaginary component
-    # return np.max(np.real(roots[where_real]))
-
-
-# return np.asarray((u+v-z0, u*J+v*Jc-z0,u*Jc+v*J-z0))
-
-
-# function to descript the magnitude S21 of a non linear resonator
-@jit(nopython=True)
-def nonlinear_mag(x, fr, Qr, amp, phi, a, b0, b1, flin):
-    """
-    x is the frequencies in your iq sweep covers
-    fr is the center frequency of the resonator
-    Qr is the quality factor of the resonator
-    amp is Qr/Qc
-    phi is a rotation parameter for an impedance mismatch between the resonator and the readout system
-    a is the non-linearity parameter bifurcation occurs at a = 0.77
-    b0 DC level of s21 away from resonator
-    b1 Frequency dependant gain varation
-    flin is probably the frequency of the resonator when a = 0
-
-    This is based of fitting code from MUSIC
-    The idea is we are producing a model that is described by the equation below
-    the frist two terms in the large parentasis and all other terms are farmilar to me
-    but I am not sure where the last term comes from though it does seem to be important for fitting
-
-                             /        (j phi)            (j phi)   |  2
-    |S21|^2 = (b0+b1 x_lin)* |1 -amp*e^           +amp*(e^       -1) |^
-                            |   ------------      ----              |
-                             \     (1+ 2jy)         2              /
-
-    where the nonlineaity of y is described by the following eqution taken from Response of superconducting microresonators
-    with nonlinear kinetic inductance
-                                        yg = y+ a/(1+y^2)  where yg = Qr*xg and xg = (f-fr)/fr
-
-    """
-    xlin = (x - flin) / flin
-    xg = (x - fr) / fr
-    yg = Qr * xg
-    y = np.zeros(x.shape[0])
-    # find the roots of the y equation above
-    for i in range(0, x.shape[0]):
-        # 4y^3+ -4yg*y^2+ y -(yg+a)
-        # roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
-        # roots = cardan(4.0,-4.0*yg[i],1.0,-(yg[i]+a))
-        # print(roots)
-        # roots = np.roots((16.,-16.*yg[i],8.,-8.*yg[i]+4*a*yg[i]/Qr-4*a,1.,-yg[i]+a*yg[i]/Qr-a+a**2/Qr))   #more accurate version that doesn't seem to change the fit at al     
-        # only care about real roots
-        # where_real = np.where(np.imag(roots) == 0)
-        # where_real = np.where(np.abs(np.imag(roots)) < 1e-10) #analytic version has some floating point error accumulation
-        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))  # np.max(np.real(roots[where_real]))
-    z = (b0 + b1 * xlin) * np.abs(
-        1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0)) ** 2
-    return z
-
-
-jit(nopython=True)
-
-
-def linear_mag(x, fr, Qr, amp, phi, b0):
-    """
-    simplier version for quicker fitting when applicable
-    x is the frequeciesn your iq sweep covers
-    fr is the center frequency of the resonator
-    Qr is the quality factor of the resonator
-    amp is Qr/Qc
-    phi is a rotation paramter for an impedance mismatch between the resonaotor and the readout system
-    b0 DC level of s21 away from resonator
-
-    This is based of fitting code from MUSIC
-    The idea is we are producing a model that is described by the equation below
-    the frist two terms in the large parentasis and all other terms are farmilar to me
-    but I am not sure where the last term comes from though it does seem to be important for fitting
-
-                    /        (j phi)            (j phi)   |  2
-    |S21|^2 = (b0)* |1 -amp*e^           +amp*(e^       -1) |^
-                   |   ------------      ----              |
-                    \     (1+ 2jxg)         2              /
-
-    no y just xg
-    with no nonlinear kinetic inductance
-    """
-    if not np.isscalar(fr):  # vectorize breaks numba though
-        x = np.reshape(x, (x.shape[0], 1, 1, 1, 1, 1))
-    xg = (x - fr) / fr
-    z = (b0) * np.abs(
-        1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * xg * Qr) + amp / 2. * (np.exp(1.0j * phi) - 1.0)) ** 2
-    return z
-
-
-# function to describe the i q loop of a nonlinear resonator
-@jit(nopython=True)
-def nonlinear_iq(x, fr, Qr, amp, phi, a, i0, q0, tau, f0):
-    """
-    x is the frequeciesn your iq sweep covers
-    fr is the center frequency of the resonator
-    Qr is the quality factor of the resonator
-    amp is Qr/Qc
-    phi is a rotation paramter for an impedance mismatch between the resonaotor and the readou system
-    a is the non-linearity paramter bifurcation occurs at a = 0.77
-    i0
-    q0 these are constants that describes an overall phase rotation of the iq loop + a DC gain offset
-    tau cabel delay
-    f0 is all the center frequency, not sure why we include this as a secondary paramter should be the same as fr
-
-    This is based of fitting code from MUSIC
-
-    The idea is we are producing a model that is described by the equation below
-    the frist two terms in the large parentasis and all other terms are farmilar to me
-    but I am not sure where the last term comes from though it does seem to be important for fitting
-
-                       (-j 2 pi deltaf tau)  /        (j phi)            (j phi)   |
-           (i0+j*q0)*e^                    *|1 -amp*e^           +amp*(e^       -1) |
-                                            |   ------------      ----              |
-                                             \     (1+ 2jy)         2              /
-
-    where the nonlineaity of y is described by the following eqution taken from Response of superconducting microresonators
-    with nonlinear kinetic inductance
-                                        yg = y+ a/(1+y^2)  where yg = Qr*xg and xg = (f-fr)/fr
-
-    """
-    deltaf = (x - f0)
-    xg = (x - fr) / fr
-    yg = Qr * xg
-    y = np.zeros(x.shape[0])
-    # find the roots of the y equation above
-    for i in range(0, x.shape[0]):
-        # 4y^3+ -4yg*y^2+ y -(yg+a)
-        # roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
-        # roots = np.roots((16.,-16.*yg[i],8.,-8.*yg[i]+4*a*yg[i]/Qr-4*a,1.,-yg[i]+a*yg[i]/Qr-a+a**2/Qr))   #more accurate version that doesn't seem to change the fit at al     
-        # only care about real roots
-        # where_real = np.where(np.imag(roots) == 0)
-        # y[i] = np.max(np.real(roots[where_real]))
-        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))
-    z = (i0 + 1.j * q0) * np.exp(-1.0j * 2 * np.pi * deltaf * tau) * (
-            1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0))
-    return z
-
-
-@jit(nopython=True)
-def nonlinear_iq_for_fitter(x, fr, Qr, amp, phi, a, i0, q0, tau, f0):
-    """
-    when using a fitter that can't handel complex number 
-    one needs to return both the real and imaginary components seperatly
-    """
-
-    deltaf = (x - f0)
-    xg = (x - fr) / fr
-    yg = Qr * xg
-    y = np.zeros(x.shape[0])
-
-    for i in range(0, x.shape[0]):
-        # roots = np.roots((4.0,-4.0*yg[i],1.0,-(yg[i]+a)))
-        # where_real = np.where(np.imag(roots) == 0)
-        # y[i] = np.max(np.real(roots[where_real]))
-        y[i] = cardan(4.0, -4.0 * yg[i], 1.0, -(yg[i] + a))
-    z = (i0 + 1.j * q0) * np.exp(-1.0j * 2 * np.pi * deltaf * tau) * (
-            1.0 - amp * np.exp(1.0j * phi) / (1.0 + 2.0 * 1.0j * y) + amp / 2. * (np.exp(1.0j * phi) - 1.0))
-    real_z = np.real(z)
-    imag_z = np.imag(z)
-    return np.hstack((real_z, imag_z))
-
-
-def brute_force_linear_mag_fit(x, z, ranges, n_grid_points, error=None, plot=False, **keywords):
-    """
-    x frequencies Hz
-    z complex or abs of s21
-    ranges is the ranges for each parameter i.e. np.asarray(([f_low,Qr_low,amp_low,phi_low,b0_low],[f_high,Qr_high,amp_high,phi_high,b0_high]))
-    n_grid_points how finely to sample each parameter space.
-    this can be very slow for n>10
-    an increase by a factor of 2 will take 2**5 times longer
-    to marginalize over you must minimize over the unwanted axies of sum_dev
-    i.e for fr np.min(np.min(np.min(np.min(fit['sum_dev'],axis = 4),axis = 3),axis = 2),axis = 1)
-    """
-    if error is None:
-        error = np.ones(len(x))
-
-    fs = np.linspace(ranges[0][0], ranges[1][0], n_grid_points)
-    Qrs = np.linspace(ranges[0][1], ranges[1][1], n_grid_points)
-    amps = np.linspace(ranges[0][2], ranges[1][2], n_grid_points)
-    phis = np.linspace(ranges[0][3], ranges[1][3], n_grid_points)
-    b0s = np.linspace(ranges[0][4], ranges[1][4], n_grid_points)
-    evaluated_ranges = np.vstack((fs, Qrs, amps, phis, b0s))
-
-    a, b, c, d, e = np.meshgrid(fs, Qrs, amps, phis, b0s, indexing="ij")  # always index ij
-
-    evaluated = linear_mag(x, a, b, c, d, e)
-    data_values = np.reshape(np.abs(z) ** 2, (abs(z).shape[0], 1, 1, 1, 1, 1))
-    error = np.reshape(error, (abs(z).shape[0], 1, 1, 1, 1, 1))
-    sum_dev = np.sum(((np.sqrt(evaluated) - np.sqrt(data_values)) ** 2 / error ** 2),
-                     axis=0)  # comparing in magnitude space rather than magnitude squared
-
-    min_index = np.where(sum_dev == np.min(sum_dev))
-    index1 = min_index[0][0]
-    index2 = min_index[1][0]
-    index3 = min_index[2][0]
-    index4 = min_index[3][0]
-    index5 = min_index[4][0]
-    fit_values = np.asarray((fs[index1], Qrs[index2], amps[index3], phis[index4], b0s[index5]))
-    fit_values_names = ('f0', 'Qr', 'amp', 'phi', 'b0')
-    fit_result = linear_mag(x, fs[index1], Qrs[index2], amps[index3], phis[index4], b0s[index5])
-
-    marginalized_1d = np.zeros((5, n_grid_points))
-    marginalized_1d[0, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2), axis=1)
-    marginalized_1d[1, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2), axis=0)
-    marginalized_1d[2, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=1), axis=0)
-    marginalized_1d[3, :] = np.min(np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=1), axis=0)
-    marginalized_1d[4, :] = np.min(np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=1), axis=0)
-
-    marginalized_2d = np.zeros((5, 5, n_grid_points, n_grid_points))
-    # 0 _
-    # 1 x _
-    # 2 x x _
-    # 3 x x x _ 
-    # 4 x x x x _
-    #  0 1 2 3 4
-    marginalized_2d[0, 1, :] = marginalized_2d[1, 0, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=2)
-    marginalized_2d[2, 0, :] = marginalized_2d[0, 2, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=1)
-    marginalized_2d[2, 1, :] = marginalized_2d[1, 2, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=3), axis=0)
-    marginalized_2d[3, 0, :] = marginalized_2d[0, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=1)
-    marginalized_2d[3, 1, :] = marginalized_2d[1, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=2), axis=0)
-    marginalized_2d[3, 2, :] = marginalized_2d[2, 3, :] = np.min(np.min(np.min(sum_dev, axis=4), axis=1), axis=0)
-    marginalized_2d[4, 0, :] = marginalized_2d[0, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=1)
-    marginalized_2d[4, 1, :] = marginalized_2d[1, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=2), axis=0)
-    marginalized_2d[4, 2, :] = marginalized_2d[2, 4, :] = np.min(np.min(np.min(sum_dev, axis=3), axis=1), axis=0)
-    marginalized_2d[4, 3, :] = marginalized_2d[3, 4, :] = np.min(np.min(np.min(sum_dev, axis=2), axis=1), axis=0)
-
-    if plot:
-        levels = [2.3, 4.61]  # delta chi squared two parameters 68 90 % confidence
-        fig_fit = plt.figure(-1)
-        axs = fig_fit.subplots(5, 5)
-        for i in range(0, 5):  # y starting from top
-            for j in range(0, 5):  # x starting from left
-                if i > j:
-                    # plt.subplot(5,5,i+1+5*j)
-                    # axs[i, j].set_aspect('equal', 'box')
-                    extent = [evaluated_ranges[j, 0], evaluated_ranges[j, n_grid_points - 1], evaluated_ranges[i, 0],
-                              evaluated_ranges[i, n_grid_points - 1]]
-                    axs[i, j].imshow(marginalized_2d[i, j, :] - np.min(sum_dev), extent=extent, origin='lower',
-                                     cmap='jet')
-                    axs[i, j].contour(evaluated_ranges[j], evaluated_ranges[i],
-                                      marginalized_2d[i, j, :] - np.min(sum_dev), levels=levels, colors='white')
-                    axs[i, j].set_ylim(evaluated_ranges[i, 0], evaluated_ranges[i, n_grid_points - 1])
-                    axs[i, j].set_xlim(evaluated_ranges[j, 0], evaluated_ranges[j, n_grid_points - 1])
-                    axs[i, j].set_aspect((evaluated_ranges[j, 0] - evaluated_ranges[j, n_grid_points - 1]) / (
-                            evaluated_ranges[i, 0] - evaluated_ranges[i, n_grid_points - 1]))
-                    if j == 0:
-                        axs[i, j].set_ylabel(fit_values_names[i])
-                    if i == 4:
-                        axs[i, j].set_xlabel("\n" + fit_values_names[j])
-                    if i < 4:
-                        axs[i, j].get_xaxis().set_ticks([])
-                    if j > 0:
-                        axs[i, j].get_yaxis().set_ticks([])
-
-                elif i < j:
-                    fig_fit.delaxes(axs[i, j])
-
-        for i in range(0, 5):
-            # axes.subplot(5,5,i+1+5*i)
-            axs[i, i].plot(evaluated_ranges[i, :], marginalized_1d[i, :] - np.min(sum_dev))
-            axs[i, i].plot(evaluated_ranges[i, :], np.ones(len(evaluated_ranges[i, :])) * 1., color='k')
-            axs[i, i].plot(evaluated_ranges[i, :], np.ones(len(evaluated_ranges[i, :])) * 2.7, color='k')
-            axs[i, i].yaxis.set_label_position("right")
-            axs[i, i].yaxis.tick_right()
-            axs[i, i].xaxis.set_label_position("top")
-            axs[i, i].xaxis.tick_top()
-            axs[i, i].set_xlabel(fit_values_names[i])
-
-        # axs[0,0].set_ylabel(fit_values_names[0])
-        # axs[4,4].set_xlabel(fit_values_names[4])
-        axs[4, 4].xaxis.set_label_position("bottom")
-        axs[4, 4].xaxis.tick_bottom()
-
-    # make a dictionary to return
-    fit_dict = {'fit_values': fit_values, 'fit_values_names': fit_values_names, 'sum_dev': sum_dev,
-                'fit_result': fit_result, 'marginalized_2d': marginalized_2d, 'marginalized_1d': marginalized_1d,
-                'evaluated_ranges': evaluated_ranges}  # , 'x0':x0, 'z':z}
-    return fit_dict
-
-
-# function for fitting an iq sweep with the above equation
-def fit_nonlinear_iq(x, z, verbose=True, **keywords):
-    """
-    keywords are
-    bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    x0    --- initial guess for the fit this can be very important because least square space over all
-              parameters is not completely searched.
-    amp_norm --- do a normalization for variable amplitude. This parameter is useful when the
-                 transfer function of the cryostat is not flat
-    tau forces tau to specific value
-    tau_guess fixes the guess for tau without have to specify all of x0
-    """
-    if 'tau' in keywords:
-        use_given_tau = True
-        tau = keywords['tau']
-    else:
-        use_given_tau = False
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        if verbose:
-            print("default bounds used")
-        bounds = ([np.min(x), 50, .01, -np.pi, 0, -np.inf, -np.inf, 0, np.min(x)],
-                  [np.max(x), 200000, 1, np.pi, 5, np.inf, np.inf, 1 * 10 ** -6, np.max(x)])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        if verbose:
-            print("default initial guess used")
-        # fr_guess = x[np.argmin(np.abs(z))]
-        # x0 = [fr_guess,10000.,0.5,0,0,np.mean(np.real(z)),np.mean(np.imag(z)),3*10**-7,fr_guess]
-        x0 = guess_x0_iq_nonlinear(x, z, verbose=verbose)
-        # print(x0)
-    if 'fr_guess' in keywords:
-        x0[0] = keywords['fr_guess']
-    if 'tau_guess' in keywords:
-        x0[7] = keywords['tau_guess']
-    # Amplitude normalization?
-    do_amp_norm = 0
-    if 'amp_norm' in keywords:
-        amp_norm = keywords['amp_norm']
-        if amp_norm == True:
-            do_amp_norm = 1
-        elif amp_norm == False:
-            do_amp_norm = 0
-        else:
-            print("please specify amp_norm as True or False")
-    if do_amp_norm == 1:
-        z = amplitude_normalization(x, z)
-    z_stacked = np.hstack((np.real(z), np.imag(z)))
-
-    if use_given_tau:
-        del bounds[0][7]
-        del bounds[1][7]
-        del x0[7]
-        fit = optimization.curve_fit(
-            lambda x_lamb, a, b, c, d, e, f, g, h: nonlinear_iq_for_fitter(x_lamb, a, b, c, d, e, f, g, tau, h), x,
-            z_stacked, x0, bounds=bounds)
-
-        fit = list(fit)
-        fit[0] = np.insert(fit[0], 7, tau)
-        # fill covariance matrix#
-        cov = np.ones((fit[1].shape[0] + 1, fit[1].shape[1] + 1)) * -1
-        cov[0:7, 0:7] = fit[1][0:7, 0:7]
-        cov[8, 8] = fit[1][7, 7]
-        cov[8, 0:7] = fit[1][7, 0:7]
-        cov[0:7, 8] = fit[1][0:7, 7]
-        fit[1] = cov
-        fit = tuple(fit)
-
-        # print(fit[1])
-
-        x0 = np.insert(x0, 7, tau)
-
-    else:
-        fit = optimization.curve_fit(nonlinear_iq_for_fitter, x, z_stacked, x0, bounds=bounds)
-
-    # human-readable results
-    fr = fit[0][0]
-    Qr = fit[0][1]
-    amp = fit[0][2]
-    phi = fit[0][3]
-    a = fit[0][4]
-    i0 = fit[0][5]
-    q0 = fit[0][6]
-    tau = fit[0][7]
-    Qc = Qr / amp
-    Qi = 1.0 / ((1.0 / Qr) - (1.0 / Qc))
-
-    fit_result = nonlinear_iq(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6], fit[0][7],
-                              fit[0][8])
-    x0_result = nonlinear_iq(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7], x0[8])
-
-    if verbose:
-        print_fit_string_nonlinear_iq(fit[0], print_header=False, label="Fit  ")
-
-    # make a dictionary to return
-    fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z,
-                'fr': fr, 'Qr': Qr, 'amp': amp, 'phi': phi, 'a': a, 'i0': i0, 'q0': q0, 'tau': tau, 'Qi': Qi, 'Qc': Qc}
-    return fit_dict
-
-
-def fit_nonlinear_iq_sep(fine_x, fine_z, gain_x, gain_z, **keywords):
-    """
-    # same as above funciton but takes fine and gain scans seperatly
-    # keywards are
-    # bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    # x0    --- intial guess for the fit this can be very important becuase because least square space over all the parameter is comple
-    # amp_norm --- do a normalization for variable amplitude. usefull when tranfer function of the cryostat is not flat  
-    """
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        print("default bounds used")
-        bounds = ([np.min(fine_x), 500., .01, -np.pi, 0, -np.inf, -np.inf, 1 * 10 ** -9, np.min(fine_x)],
-                  [np.max(fine_x), 1000000, 1, np.pi, 5, np.inf, np.inf, 1 * 10 ** -6, np.max(fine_x)])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        print("default initial guess used")
-        # fr_guess = x[np.argmin(np.abs(z))]
-        # x0 = [fr_guess,10000.,0.5,0,0,np.mean(np.real(z)),np.mean(np.imag(z)),3*10**-7,fr_guess]
-        x0 = guess_x0_iq_nonlinear_sep(fine_x, fine_z, gain_x, gain_z)
-        # print(x0)
-    # Amplitude normalization?
-    do_amp_norm = 0
-    if 'amp_norm' in keywords:
-        amp_norm = keywords['amp_norm']
-        if amp_norm:
-            do_amp_norm = 1
-        elif not amp_norm:
-            do_amp_norm = 0
-        else:
-            print("please specify amp_norm as True or False")
-
-    if 'fine_z_err' in keywords and 'gain_z_err' in keywords:
-        use_err = True
-        fine_z_err = keywords['fine_z_err']
-        gain_z_err = keywords['gain_z_err']
-    else:
-        use_err = False
-
-    x = np.hstack((fine_x, gain_x))
-    z = np.hstack((fine_z, gain_z))
-    if use_err:
-        z_err = np.hstack((fine_z_err, gain_z_err))
-
-    if do_amp_norm == 1:
-        z = amplitude_normalization(x, z)
-
-    z_stacked = np.hstack((np.real(z), np.imag(z)))
-    if use_err:
-        z_err_stacked = np.hstack((np.real(z_err), np.imag(z_err)))
-        fit = optimization.curve_fit(nonlinear_iq_for_fitter, x, z_stacked, x0, sigma=z_err_stacked, bounds=bounds)
-    else:
-        fit = optimization.curve_fit(nonlinear_iq_for_fitter, x, z_stacked, x0, bounds=bounds)
-
-    fit_result = nonlinear_iq(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6], fit[0][7],
-                              fit[0][8])
-    x0_result = nonlinear_iq(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7], x0[8])
-
-    if use_err:
-        # only do it for fine data
-        # red_chi_sqr = np.sum(z_stacked-np.hstack((np.real(fit_result),np.imag(fit_result))))**2/z_err_stacked**2)/(len(z_stacked)-8.)
-        # only do it for fine data
-        red_chi_sqr = np.sum((np.hstack((np.real(fine_z), np.imag(fine_z))) - np.hstack(
-            (np.real(fit_result[0:len(fine_z)]), np.imag(fit_result[0:len(fine_z)])))) ** 2 / np.hstack(
-            (np.real(fine_z_err), np.imag(fine_z_err))) ** 2) / (len(fine_z) * 2. - 8.)
-
-    # make a dictionary to return
-    if use_err:
-        fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z, 'fit_freqs': x,
-                    'red_chi_sqr': red_chi_sqr}
-    else:
-        fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z, 'fit_freqs': x}
-    return fit_dict
-
-
-# same function but double fits so that it can get error and a proper covariance matrix out
-def fit_nonlinear_iq_with_err(x, z, **keywords):
-    """
-    # keywards are
-    # bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    # x0    --- intial guess for the fit this can be very important becuase because least square space over all the parameter is comple
-    # amp_norm --- do a normalization for variable amplitude. usefull when tranfer function of the cryostat is not flat 
-    """
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        print("default bounds used")
-        bounds = ([np.min(x), 2000, .01, -np.pi, 0, -5, -5, 1 * 10 ** -9, np.min(x)],
-                  [np.max(x), 200000, 1, np.pi, 5, 5, 5, 1 * 10 ** -6, np.max(x)])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        print("default initial guess used")
-        fr_guess = x[np.argmin(np.abs(z))]
-        x0 = guess_x0_iq_nonlinear(x, z)
-    # Amplitude normalization?
-    do_amp_norm = 0
-    if 'amp_norm' in keywords:
-        amp_norm = keywords['amp_norm']
-        if amp_norm:
-            do_amp_norm = 1
-        elif not amp_norm:
-            do_amp_norm = 0
-        else:
-            print("please specify amp_norm as True or False")
-    if do_amp_norm == 1:
-        z = amplitude_normalization(x, z)
-    z_stacked = np.hstack((np.real(z), np.imag(z)))
-    fit = optimization.curve_fit(nonlinear_iq_for_fitter, x, z_stacked, x0, bounds=bounds)
-    fit_result = nonlinear_iq(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6], fit[0][7],
-                              fit[0][8])
-    fit_result_stacked = nonlinear_iq_for_fitter(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5],
-                                                 fit[0][6], fit[0][7], fit[0][8])
-    x0_result = nonlinear_iq(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7], x0[8])
-    # get error
-    var = np.sum((z_stacked - fit_result_stacked) ** 2) / (z_stacked.shape[0] - 1)
-    err = np.ones(z_stacked.shape[0]) * np.sqrt(var)
-    # refit
-    fit = optimization.curve_fit(nonlinear_iq_for_fitter, x, z_stacked, x0, err, bounds=bounds)
-    fit_result = nonlinear_iq(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6], fit[0][7],
-                              fit[0][8])
-    x0_result = nonlinear_iq(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7], x0[8])
-
-    # make a dictionary to return
-    fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z}
-    return fit_dict
-
-
-# function for fitting an iq sweep with the above equation
-def fit_nonlinear_mag(x, z, verbose=True, **keywords):
-    """
-    # keywards are
-    # bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    # x0    --- intial guess for the fit this can be very important becuase because least square space over all the parameter is comple
-    # amp_norm --- do a normalization for variable amplitude. usefull when tranfer function of the cryostat is not flat  
-    """
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        print("default bounds used")
-        bounds = ([np.min(x), 100, .01, -np.pi, 0, -np.inf, -np.inf, np.min(x)],
-                  [np.max(x), 200000, 1, np.pi, 5, np.inf, np.inf, np.max(x)])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        print("default initial guess used")
-        fr_guess = x[np.argmin(np.abs(z))]
-        # x0 = [fr_guess,10000.,0.5,0,0,np.abs(z[0])**2,np.abs(z[0])**2,fr_guess]
-        x0 = guess_x0_mag_nonlinear(x, z, verbose=verbose)
-
-    fit = optimization.curve_fit(nonlinear_mag, x, np.abs(z) ** 2, x0, bounds=bounds)
-    fit_result = np.sqrt(
-        nonlinear_mag(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6], fit[0][7]))
-    x0_result = np.sqrt(nonlinear_mag(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7]))
-
-    if verbose:
-        print_fit_string_nonlinear_mag(fit[0], print_header=False, label="Fit  ")
-
-    # human-readable results
-    fr = fit[0][0]
-    Qr = fit[0][1]
-    amp = fit[0][2]
-    phi = fit[0][3]
-    a = fit[0][4]
-    b0 = fit[0][5]
-    b1 = fit[0][6]
-    Qc = Qr / amp
-    Qi = 1.0 / ((1.0 / Qr) - (1.0 / Qc))
-
-    # make a dictionary to return
-    fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z,
-                'fr': fr, 'Qr': Qr, 'amp': amp, 'phi': phi, 'a': a, 'b0': b0, 'b1': b1, 'Qi': Qi, 'Qc': Qc}
-    return fit_dict
-
-
-def fit_linear_mag(x, z, verbose=True, **keywords):
-    """
-    # keywards are
-    # bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    # x0    --- intial guess for the fit this can be very important becuase because least square space over all the parameter is comple
-    # amp_norm --- do a normalization for variable amplitude. usefull when tranfer function of the cryostat is not flat  
-    """
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        print("default bounds used")
-        bounds = ([np.min(x), 100, .01, -np.pi, -np.inf], [np.max(x), 200000, 1, np.pi, np.inf])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        print("default initial guess used")
-        fr_guess = x[np.argmin(np.abs(z))]
-        # x0 = [fr_guess,10000.,0.5,0,0,np.abs(z[0])**2,np.abs(z[0])**2,fr_guess]
-        x0 = guess_x0_mag_nonlinear(x, z, verbose=verbose)
-        x0 = np.delete(x0, [4, 6, 7])
-
-    fit = optimization.curve_fit(linear_mag, x, np.abs(z) ** 2, x0, bounds=bounds)
-    fit_result = np.sqrt(linear_mag(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4]))
-    x0_result = np.sqrt(linear_mag(x, x0[0], x0[1], x0[2], x0[3], x0[4]))
-
-    if verbose:
-        print_fit_string_linear_mag(fit[0], print_header=False, label="Fit  ")
-
-    # human-readable results
-    fr = fit[0][0]
-    Qr = fit[0][1]
-    amp = fit[0][2]
-    phi = fit[0][3]
-    b0 = fit[0][4]
-    Qc = Qr / amp
-    Qi = 1.0 / ((1.0 / Qr) - (1.0 / Qc))
-
-    # make a dictionary to return
-    fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z,
-                'fr': fr, 'Qr': Qr, 'amp': amp, 'phi': phi, 'b0': b0, 'Qi': Qi, 'Qc': Qc}
-    return fit_dict
-
-
-def fit_nonlinear_mag_sep(fine_x, fine_z, gain_x, gain_z, **keywords):
-    """
-    # same as above but fine and gain scans are provided seperatly
-    # keywards are
-    # bounds ---- which is a 2d tuple of low the high values to bound the problem by
-    # x0    --- intial guess for the fit this can be very important becuase because least square space over all the parameter is comple
-    # amp_norm --- do a normalization for variable amplitude. usefull when tranfer function of the cryostat is not flat 
-    """
-    if 'bounds' in keywords:
-        bounds = keywords['bounds']
-    else:
-        # define default bounds
-        print("default bounds used")
-        bounds = ([np.min(fine_x), 100, .01, -np.pi, 0, -np.inf, -np.inf, np.min(fine_x)],
-                  [np.max(fine_x), 1000000, 100, np.pi, 5, np.inf, np.inf, np.max(fine_x)])
-    if 'x0' in keywords:
-        x0 = keywords['x0']
-    else:
-        # define default intial guess
-        print("default initial guess used")
-        x0 = guess_x0_mag_nonlinear_sep(fine_x, fine_z, gain_x, gain_z)
-    if 'fine_z_err' in keywords and 'gain_z_err' in keywords:
-        use_err = True
-        fine_z_err = keywords['fine_z_err']
-        gain_z_err = keywords['gain_z_err']
-    else:
-        use_err = False
-
-    # stack the scans for curvefit
-    x = np.hstack((fine_x, gain_x))
-    z = np.hstack((fine_z, gain_z))
-    if use_err:
-        z_err = np.hstack((fine_z_err, gain_z_err))
-        z_err = np.sqrt(4 * np.real(z_err) ** 2 * np.real(z) ** 2 + 4 * np.imag(z_err) ** 2 * np.imag(
-            z) ** 2)  # propogation of errors left out cross term  
-        fit = optimization.curve_fit(nonlinear_mag, x, np.abs(z) ** 2, x0, sigma=z_err, bounds=bounds)
-    else:
-        fit = optimization.curve_fit(nonlinear_mag, x, np.abs(z) ** 2, x0, bounds=bounds)
-    fit_result = nonlinear_mag(x, fit[0][0], fit[0][1], fit[0][2], fit[0][3], fit[0][4], fit[0][5], fit[0][6],
-                               fit[0][7])
-    x0_result = nonlinear_mag(x, x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7])
-
-    # compute reduced chi squared
-    print(len(z))
-    if use_err:
-        # red_chi_sqr = np.sum((np.abs(z)**2-fit_result)**2/z_err**2)/(len(z)-7.)
-        # only use fine scan for reduced chi squared.
-        red_chi_sqr = np.sum((np.abs(fine_z) ** 2 - fit_result[0:len(fine_z)]) ** 2 / z_err[0:len(fine_z)] ** 2) / (
-                len(fine_z) - 7.)
-
-    # make a dictionary to return
-    if use_err:
-        fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z, 'fit_freqs': x,
-                    'red_chi_sqr': red_chi_sqr}
-    else:
-        fit_dict = {'fit': fit, 'fit_result': fit_result, 'x0_result': x0_result, 'x0': x0, 'z': z, 'fit_freqs': x}
-    return fit_dict
-
-
-def amplitude_normalization(x, z):
-    """
-    # normalize the amplitude varation requires a gain scan
-    #flag frequencies to use in amplitude normaliztion
-    """
-    index_use = np.where(np.abs(x - np.median(x)) > 100000)  # 100kHz away from resonator
-    poly = np.polyfit(x[index_use], np.abs(z[index_use]), 2)
-    poly_func = np.poly1d(poly)
-    normalized_data = z / poly_func(x) * np.median(np.abs(z[index_use]))
-    return normalized_data
-
-
-def amplitude_normalization_sep(gain_x, gain_z, fine_x, fine_z, stream_x, stream_z):
-    """
-    # normalize the amplitude varation requires a gain scan
-    # uses gain scan to normalize does not use fine scan
-    #flag frequencies to use in amplitude normaliztion
-    """
-    index_use = np.where(np.abs(gain_x - np.median(gain_x)) > 100000)  # 100kHz away from resonator
-    poly = np.polyfit(gain_x[index_use], np.abs(gain_z[index_use]), 2)
-    poly_func = np.poly1d(poly)
-    poly_data = poly_func(gain_x)
-    normalized_gain = gain_z / poly_data * np.median(np.abs(gain_z[index_use]))
-    normalized_fine = fine_z / poly_func(fine_x) * np.median(np.abs(gain_z[index_use]))
-    normalized_stream = stream_z / poly_func(stream_x) * np.median(np.abs(gain_z[index_use]))
-    amp_norm_dict = {'normalized_gain': normalized_gain,
-                     'normalized_fine': normalized_fine,
-                     'normalized_stream': normalized_stream,
-                     'poly_data': poly_data}
-    return amp_norm_dict
-
-
-def guess_x0_iq_nonlinear(x, z, verbose=False):
-    """
-    # this is less robust than guess_x0_iq_nonlinear_sep
-    # below. it is recommended to use that instead   
-    #make sure data is sorted from low to high frequency
-    """
-    sort_index = np.argsort(x)
-    x = x[sort_index]
-    z = z[sort_index]
-    # extract just fine data
-    df = np.abs(x - np.roll(x, 1))
-    fine_df = np.min(df[np.where(df != 0)])
-    fine_z_index = np.where(df < fine_df * 1.1)
-    fine_z = z[fine_z_index]
-    fine_x = x[fine_z_index]
-    # extract the gain scan
-    gain_z_index = np.where(df > fine_df * 1.1)
-    gain_z = z[gain_z_index]
-    gain_x = x[gain_z_index]
-    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
-
-    # guess f0
-    fr_guess_index = np.argmin(np.abs(z))
-    # fr_guess = x[fr_guess_index]
-    fr_guess_index_fine = np.argmin(np.abs(fine_z))
-    # below breaks if there is not a right and left side in the fine scan
-    if fr_guess_index_fine == 0:
-        fr_guess_index_fine = len(fine_x) // 2
-    elif fr_guess_index_fine == (len(fine_x) - 1):
-        fr_guess_index_fine = len(fine_x) // 2
-    fr_guess = fine_x[fr_guess_index_fine]
-
-    # guess Q
-    mag_max = np.max(np.abs(fine_z) ** 2)
-    mag_min = np.min(np.abs(fine_z) ** 2)
-    mag_3dB = (mag_max + mag_min) / 2.
-    half_distance = np.abs(fine_z) ** 2 - mag_3dB
-    right = half_distance[fr_guess_index_fine:-1]
-    left = half_distance[0:fr_guess_index_fine]
-    right_index = np.argmin(np.abs(right)) + fr_guess_index_fine
-    left_index = np.argmin(np.abs(left))
-    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-    Q_guess = fr_guess / Q_guess_Hz
-
-    # guess amp
-    d = np.max(20 * np.log10(np.abs(z))) - np.min(20 * np.log10(np.abs(z)))
-    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
-
-    # guess impedance rotation phi
-    phi_guess = 0
-
-    # guess non-linearity parameter
-    # might be able to guess this by ratioing the distance between min and max distance between iq points in fine sweep
-    a_guess = 0
-
-    # i0 and iq guess
-    if np.max(np.abs(fine_z)) == np.max(np.abs(z)):
-        # if the resonator has an impedance mismatch rotation that makes the fine greater that the cabel delay
-        i0_guess = np.real(fine_z[np.argmax(np.abs(fine_z))])
-        q0_guess = np.imag(fine_z[np.argmax(np.abs(fine_z))])
-    else:
-        i0_guess = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2.
-        q0_guess = (np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
-
-    # cabel delay guess tau
-    # y = mx +b
-    # m = (y2 - y1)/(x2-x1)
-    # b = y-mx
-    if len(gain_z) > 1:  # is there a gain scan?
-        m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
-        b = gain_phase - m * gain_x
-        m_best = np.median(m[~np.isnan(m)])
-        tau_guess = m_best / (2 * np.pi)
-    else:
-        tau_guess = 3 * 10 ** -9
-
-    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, i0_guess, q0_guess, tau_guess, fr_guess]
-
-    if verbose:
-        print_fit_string_nonlinear_iq(x0)
-    return x0
-
-
-def guess_x0_mag_nonlinear(x, z, verbose=False):
-    """
-    # this is less robust than guess_x0_mag_nonlinear_sep
-    #below it is recommended to use that instead   
-    #make sure data is sorted from low to high frequency
-    """
-    sort_index = np.argsort(x)
-    x = x[sort_index]
-    z = z[sort_index]
-    # extract just fine data
-    # this will probably break if there is no fine scan
-    df = np.abs(x - np.roll(x, 1))
-    fine_df = np.min(df[np.where(df != 0)])
-    fine_z_index = np.where(df < fine_df * 1.1)
-    fine_z = z[fine_z_index]
-    fine_x = x[fine_z_index]
-    # extract the gain scan
-    gain_z_index = np.where(df > fine_df * 1.1)
-    gain_z = z[gain_z_index]
-    gain_x = x[gain_z_index]
-    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
-
-    # guess f0
-    fr_guess_index = np.argmin(np.abs(z))
-    # fr_guess = x[fr_guess_index]
-    fr_guess_index_fine = np.argmin(np.abs(fine_z))
-    if fr_guess_index_fine == 0:
-        fr_guess_index_fine = len(fine_x) // 2
-    elif fr_guess_index_fine == (len(fine_x) - 1):
-        fr_guess_index_fine = len(fine_x) // 2
-    fr_guess = fine_x[fr_guess_index_fine]
-
-    # guess Q
-    mag_max = np.max(np.abs(fine_z) ** 2)
-    mag_min = np.min(np.abs(fine_z) ** 2)
-    mag_3dB = (mag_max + mag_min) / 2.
-    half_distance = np.abs(fine_z) ** 2 - mag_3dB
-    right = half_distance[fr_guess_index_fine:-1]
-    left = half_distance[0:fr_guess_index_fine]
-    right_index = np.argmin(np.abs(right)) + fr_guess_index_fine
-    left_index = np.argmin(np.abs(left))
-    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-    Q_guess = fr_guess / Q_guess_Hz
-
-    # guess amp
-    d = np.max(20 * np.log10(np.abs(z))) - np.min(20 * np.log10(np.abs(z)))
-    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
-
-    # guess impedance rotation phi
-    phi_guess = 0
-
-    # guess non-linearity parameter
-    # might be able to guess this by using the ratio of the distance between min and max distance between iq points
-    #   in fine sweep
-    a_guess = 0
-
-    # b0 and b1 guess
-
-    if len(gain_z) > 1:
-        xlin = (gain_x - fr_guess) / fr_guess
-        b1_guess = (np.abs(gain_z)[-1] ** 2 - np.abs(gain_z)[0] ** 2) / (xlin[-1] - xlin[0])
-    else:
-        xlin = (fine_x - fr_guess) / fr_guess
-        b1_guess = (np.abs(fine_z)[-1] ** 2 - np.abs(fine_z)[0] ** 2) / (xlin[-1] - xlin[0])
-    b0_guess = np.median(np.abs(gain_z) ** 2)
-
-    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, b0_guess, b1_guess, fr_guess]
-
-    if verbose:
-        print_fit_string_nonlinear_mag(x0)
-
-    return x0
-
-
-def guess_x0_iq_nonlinear_sep(fine_x, fine_z, gain_x, gain_z, verbose=False):
-    """
-    # this is the same as guess_x0_iq_nonlinear except that it takes
-    # takes the fine scan and the gain scan as seperate variables
-    # this runs into less issues when trying to sort out what part of 
-    # data is fine and what part is gain for the guessing 
-    #make sure data is sorted from low to high frequency
-    """
-
-    # gain phase
-    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
-
-    # guess f0
-    fr_guess_index = np.argmin(np.abs(fine_z))
-    # below breaks if there is not a right and left side in the fine scan
-    if fr_guess_index == 0:
-        fr_guess_index = len(fine_x) // 2
-    elif fr_guess_index == (len(fine_x) - 1):
-        fr_guess_index = len(fine_x) // 2
-    fr_guess = fine_x[fr_guess_index]
-
-    # guess Q
-    mag_max = np.max(np.abs(fine_z) ** 2)
-    mag_min = np.min(np.abs(fine_z) ** 2)
-    mag_3dB = (mag_max + mag_min) / 2.
-    half_distance = np.abs(fine_z) ** 2 - mag_3dB
-    right = half_distance[fr_guess_index:-1]
-    left = half_distance[0:fr_guess_index]
-    right_index = np.argmin(np.abs(right)) + fr_guess_index
-    left_index = np.argmin(np.abs(left))
-    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-    Q_guess = fr_guess / Q_guess_Hz
-
-    # guess amp
-    d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z)))
-    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4  # polynomial fit to amp verus depth
-
-    # guess impedance rotation phi
-    # phi_guess = 0
-    # guess impedance rotation phi
-    # fit a circle to the iq loop
-    xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_z), np.imag(fine_z))
-    # compute angle between (off_res,off_res),(0,0) and (off_ress,off_res),(xc,yc) of the the fitted circle
-    off_res_i, off_res_q = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2., (
-            np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
-    x1, y1, = -off_res_i, -off_res_q
-    x2, y2 = xc - off_res_i, yc - off_res_q
-    dot = x1 * x2 + y1 * y2  # dot product
-    det = x1 * y2 - y1 * x2  # determinant
-    angle = np.arctan2(det, dot)
-    phi_guess = angle
-
-    # if phi is large better re guess f0
-    # f0 should be the farthers from the off res point
-    if (np.abs(phi_guess) > 0.3):
-        dist1 = np.sqrt((np.real(fine_z[0]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[0]) - np.imag(fine_z)) ** 2)
-        dist2 = np.sqrt((np.real(fine_z[-1]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[-1]) - np.imag(fine_z)) ** 2)
-        fr_guess_index = np.argmax((dist1 + dist2))
-        fr_guess = fine_x[fr_guess_index]
-        # also fix the Q gues
-        fine_z_derot = (fine_z - (off_res_i + 1.j * off_res_q)) * np.exp(1j * (-phi_guess)) + (
-                off_res_i + 1.j * off_res_q)
-        # fr_guess_index = np.argmin(np.abs(fine_z_derot))
-        # fr_guess = fine_x[fr_guess_index]
-        mag_max = np.max(np.abs(fine_z_derot) ** 2)
-        mag_min = np.min(np.abs(fine_z_derot) ** 2)
-        mag_3dB = (mag_max + mag_min) / 2.
-        half_distance = np.abs(fine_z_derot) ** 2 - mag_3dB
-        right = half_distance[np.argmin(np.abs(fine_z_derot)):-1]
-        left = half_distance[0:np.argmin(np.abs(fine_z_derot))]
-        right_index = np.argmin(np.abs(right)) + np.argmin(np.abs(fine_z_derot))
-        left_index = np.argmin(np.abs(left))
-        Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-        Q_guess = fr_guess / Q_guess_Hz
-        # also fix amp guess
-        d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z_derot)))
-        amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
-
-    # guess non-linearity parameter
-    # might be able to guess this by ratioing the distance between min and max distance between iq points in fine sweep
-    a_guess = 0
-
-    # i0 and iq guess
-    if np.max(np.abs(fine_z)) > np.max(
-            np.abs(
-                gain_z)):  # if the resonator has an impedance mismatch rotation that makes the fine greater that the cabel delay
-        i0_guess = np.real(fine_z[np.argmax(np.abs(fine_z))])
-        q0_guess = np.imag(fine_z[np.argmax(np.abs(fine_z))])
-    else:
-        i0_guess = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2.
-        q0_guess = (np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
-
-    # cabel delay guess tau
-    # y = mx +b
-    # m = (y2 - y1)/(x2-x1)
-    # b = y-mx
-    m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
-    b = gain_phase - m * gain_x
-    m_best = np.median(m[~np.isnan(m)])
-    tau_guess = m_best / (2 * np.pi)
-
-    if verbose == True:
-        print("fr guess  = %.3f MHz" % (fr_guess / 10 ** 6))
-        print("Q guess   = %.2f kHz, %.1f" % ((Q_guess_Hz / 10 ** 3), Q_guess))
-        print("amp guess = %.2f" % amp_guess)
-        print("phi guess = %.2f" % phi_guess)
-        print("i0 guess  = %.2f" % i0_guess)
-        print("q0 guess  = %.2f" % q0_guess)
-        print("tau guess = %.2f x 10^-7" % (tau_guess / 10 ** -7))
-
-    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, i0_guess, q0_guess, tau_guess, fr_guess]
-    return x0
-
-
-def guess_x0_mag_nonlinear_sep(fine_x, fine_z, gain_x, gain_z, verbose=False):
-    """
-    # this is the same as guess_x0_mag_nonlinear except that it takes
-    # takes the fine scan and the gain scan as seperate variables
-    # this runs into less issues when trying to sort out what part of 
-    # data is fine and what part is gain for the guessing 
-    #make sure data is sorted from low to high frequency 
-    """
-
-    # phase of gain
-    gain_phase = np.arctan2(np.real(gain_z), np.imag(gain_z))
-
-    # guess f0
-    fr_guess_index = np.argmin(np.abs(fine_z))
-    # protect against guessing the first or last data points
-    if fr_guess_index == 0:
-        fr_guess_index = len(fine_x) // 2
-    elif fr_guess_index == (len(fine_x) - 1):
-        fr_guess_index = len(fine_x) // 2
-    fr_guess = fine_x[fr_guess_index]
-
-    # guess Q
-    mag_max = np.max(np.abs(fine_z) ** 2)
-    mag_min = np.min(np.abs(fine_z) ** 2)
-    mag_3dB = (mag_max + mag_min) / 2.
-    half_distance = np.abs(fine_z) ** 2 - mag_3dB
-    right = half_distance[fr_guess_index:-1]
-    left = half_distance[0:fr_guess_index]
-    right_index = np.argmin(np.abs(right)) + fr_guess_index
-    left_index = np.argmin(np.abs(left))
-    Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-    Q_guess = fr_guess / Q_guess_Hz
-
-    # guess amp
-    d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z)))
-    amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
-    # polynomial fit to amp verus depth calculated emperically
-
-    # guess impedance rotation phi
-    # fit a circle to the iq loop
-    xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_z), np.imag(fine_z))
-    # compute angle between (off_res,off_res),(0,0) and (off_ress,off_res),(xc,yc) of the the fitted circle
-    off_res_i, off_res_q = (np.real(fine_z[0]) + np.real(fine_z[-1])) / 2., (
-            np.imag(fine_z[0]) + np.imag(fine_z[-1])) / 2.
-    x1, y1, = -off_res_i, -off_res_q
-    x2, y2 = xc - off_res_i, yc - off_res_q
-    dot = x1 * x2 + y1 * y2  # dot product
-    det = x1 * y2 - y1 * x2  # determinant
-    angle = np.arctan2(det, dot)
-    phi_guess = angle
-
-    # if phi is large better re guess f0
-    # f0 should be the farthers from the off res point
-    if (np.abs(phi_guess) > 0.3):
-        dist1 = np.sqrt((np.real(fine_z[0]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[0]) - np.imag(fine_z)) ** 2)
-        dist2 = np.sqrt((np.real(fine_z[-1]) - np.real(fine_z)) ** 2 + (np.imag(fine_z[-1]) - np.imag(fine_z)) ** 2)
-        fr_guess_index = np.argmax((dist1 + dist2))
-        fr_guess = fine_x[fr_guess_index]
-        fine_z_derot = (fine_z - (off_res_i + 1.j * off_res_q)) * np.exp(1j * (-phi_guess)) + (
-                off_res_i + 1.j * off_res_q)
-        # fr_guess_index = np.argmin(np.abs(fine_z_derot))
-        # fr_guess = fine_x[fr_guess_index]
-        mag_max = np.max(np.abs(fine_z_derot) ** 2)
-        mag_min = np.min(np.abs(fine_z_derot) ** 2)
-        mag_3dB = (mag_max + mag_min) / 2.
-        half_distance = np.abs(fine_z_derot) ** 2 - mag_3dB
-        right = half_distance[np.argmin(np.abs(fine_z_derot)):-1]
-        left = half_distance[0:np.argmin(np.abs(fine_z_derot))]
-        right_index = np.argmin(np.abs(right)) + np.argmin(np.abs(fine_z_derot))
-        left_index = np.argmin(np.abs(left))
-        Q_guess_Hz = fine_x[right_index] - fine_x[left_index]
-        Q_guess = fr_guess / Q_guess_Hz
-        # also fix amp guess
-        d = np.max(20 * np.log10(np.abs(gain_z))) - np.min(20 * np.log10(np.abs(fine_z_derot)))
-        amp_guess = 0.0037848547850284574 + 0.11096782437821565 * d - 0.0055208783469291173 * d ** 2 + 0.00013900471000261687 * d ** 3 + -1.3994861426891861e-06 * d ** 4
-
-    # guess non-linearity parameter
-    # might be able to guess this by ratioing the distance between min and max distance between iq points in fine sweep
-    a_guess = 0
-
-    # b0 and b1 guess
-    xlin = (gain_x - fr_guess) / fr_guess
-    b1_guess = (np.abs(gain_z)[-1] ** 2 - np.abs(gain_z)[0] ** 2) / (xlin[-1] - xlin[0])
-    b0_guess = np.max((np.max(np.abs(fine_z) ** 2), np.max(np.abs(gain_z) ** 2)))
-
-    # cabel delay guess tau
-    # y = mx +b
-    # m = (y2 - y1)/(x2-x1)
-    # b = y-mx
-    m = (gain_phase - np.roll(gain_phase, 1)) / (gain_x - np.roll(gain_x, 1))
-    b = gain_phase - m * gain_x
-    m_best = np.median(m[~np.isnan(m)])
-    tau_guess = m_best / (2 * np.pi)
-
-    if verbose:
-        print("fr guess  = %.3f MHz" % (fr_guess / 10 ** 6))
-        print("Q guess   = %.2f kHz, %.1f" % ((Q_guess_Hz / 10 ** 3), Q_guess))
-        print("amp guess = %.2f" % amp_guess)
-        print("phi guess = %.2f" % phi_guess)
-        print("b0 guess  = %.2f" % b0_guess)
-        print("b1 guess  = %.2f" % b1_guess)
-        print("tau guess = %.2f x 10^-7" % (tau_guess / 10 ** -7))
-
-    x0 = [fr_guess, Q_guess, amp_guess, phi_guess, a_guess, b0_guess, b1_guess, fr_guess]
-    return x0
-
-
-def fit_nonlinear_iq_multi(f, z, center_freqs = None, tau=None,fit_overlap = 0.5,verbose = True):
-    """
-    wrapper for handling n resonator fits at once
-    mostly just a for loop for fitting but also trys to fit in a way that
-    better handles collisions by not fitting to close to other resonators
-    f and z should have shape n_iq_points x n_res points 
-    center_freqs can be specified if you are fitting n resonators but you
-    know there are actually more the n resonators at the frequency locations
-    in center_freqs. This is useful if you didn't collect data for all of the 
-    resonators but don't want collisions to screw up your fitting.
-    fit_overlap: default 0.5 will only use data to halfway between the resonator
-    you are trying to fit and the nearest neighbor resonators if it is close by.
-    return same thing as fitter but in arrays for all resonators
-    """
-
-    if center_freqs is None:
-        center_freqs = f[f.shape[0] // 2, :]
-
-    all_fits = np.zeros((f.shape[1], 9))
-    all_fit_results = np.zeros((f.shape[0], f.shape[1]), dtype=np.complex_)
-    all_x0_results = np.zeros((f.shape[0], f.shape[1]), dtype=np.complex_)
-    all_masks = np.zeros((f.shape[0], f.shape[1]))
-    all_x0 = np.zeros((f.shape[1], 9))
-    all_fr = np.zeros(f.shape[1])
-    all_Qr = np.zeros(f.shape[1])
-    all_amp = np.zeros(f.shape[1])
-    all_phi = np.zeros(f.shape[1])
-    all_a = np.zeros(f.shape[1])
-    all_i0 = np.zeros(f.shape[1])
-    all_q0 = np.zeros(f.shape[1])
-    all_tau = np.zeros(f.shape[1])
-    all_Qi = np.zeros(f.shape[1])
-    all_Qc = np.zeros(f.shape[1])
-
-    for i in range(0, f.shape[1]):
-        f_single = f[:, i]
-        z_single = z[:, i]
-        # flag data that is too close to other resonators
-        if center_freqs is not None:
-            center_index = np.argmin(np.abs(center_freqs-f_single[len(f_single)//2]))
-        else:
-            center_index = i
-        distance = center_freqs - center_freqs[center_index]
-        if center_freqs[center_index] != np.min(center_freqs):  # don't do if lowest frequency resonator
-            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
-            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
-            halfway_low = center_freqs[center_index] - \
-                (center_freqs[center_index] - center_freqs[closest_lower_index])*fit_overlap
-        else:
-            halfway_low = 0
-
-        if center_freqs[center_index] != np.max(center_freqs):  # don't do if highest frequenct
-            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
-            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
-            halfway_high = center_freqs[center_index] + \
-                (center_freqs[closest_higher_index]-center_freqs[center_index]) * fit_overlap
-        else:
-            halfway_high = np.inf
-
-        use_index = np.where(((f_single > halfway_low) & (f_single < halfway_high)))
-        mask = np.zeros(len(f_single))
-        mask[use_index] = 1
-        f_single = f_single[use_index]
-        z_single = z_single[use_index]
-
-        try:
-            if tau is not None:
-                fit_dict_iq = fit_nonlinear_iq(f_single, z_single, tau = tau, verbose = verbose)
-            else:
-                fit_dict_iq = fit_nonlinear_iq(f_single, z_single, verbose = verbose)
-
-            all_fits[i, :] = fit_dict_iq['fit'][0]
-            # all_fit_results[i,:] = fit_dict_iq['fit_result']
-            # all_x0_results[i,:] = fit_dict_iq['x0_result']
-            all_fit_results[:, i] = nonlinear_iq(f[:, i], all_fits[i, 0], all_fits[i, 1], all_fits[i, 2],
-                                                 all_fits[i, 3], all_fits[i, 4],
-                                                 all_fits[i, 5], all_fits[i, 6], all_fits[i, 7], all_fits[i, 8])
-            all_x0_results[:, i] = nonlinear_iq(f[:, i], fit_dict_iq['x0'][0], fit_dict_iq['x0'][1],
-                                                fit_dict_iq['x0'][2],
-                                                fit_dict_iq['x0'][3], fit_dict_iq['x0'][4], fit_dict_iq['x0'][5],
-                                                fit_dict_iq['x0'][6], fit_dict_iq['x0'][7], fit_dict_iq['x0'][8])
-            all_masks[:, i] = mask
-            all_x0[i, :] = fit_dict_iq['x0']
-            all_fr[i] = fit_dict_iq['fr']
-            all_Qr[i] = fit_dict_iq['Qr']
-            all_amp[i] = fit_dict_iq['amp']
-            all_phi[i] = fit_dict_iq['phi']
-            all_a[i] = fit_dict_iq['a']
-            all_i0[i] = fit_dict_iq['i0']
-            all_q0[i] = fit_dict_iq['q0']
-            all_tau[i] = fit_dict_iq['tau']
-            all_Qc[i] = all_Qr[i] / all_amp[i]
-            all_Qi[i] = 1.0 / ((1.0 / all_Qr[i]) - (1.0 / all_Qc[i]))
-
-        except Exception as e:
-            print(e)
-            print("failed to fit")
-
-    all_fits_dict = {'fits': all_fits, 'fit_results': all_fit_results, 'x0_results': all_x0_results, 'masks': all_masks,
-                     'x0': all_x0,
-                     'fr': all_fr, 'Qr': all_Qr, 'amp': all_amp, 'phi': all_phi, 'a': all_a, 'i0': all_i0, 'q0': all_q0,
-                     'tau': all_tau, 'Qi': all_Qi, 'Qc': all_Qc}
-
-    return all_fits_dict
-
-
-def fit_linear_mag_multi(f, z):
-    """
-    wrapper for handling n resonator fits at once
-    f and z should have shape n_iq_points x n_res points 
-    return same thing as fitter but in arrays for all resonators
-    """
-
-    center_freqs = f[f.shape[0] // 2, :]
-
-    all_fits = np.zeros((f.shape[1], 5))
-    all_fit_results = np.zeros((f.shape[0], f.shape[1]))
-    all_x0_results = np.zeros((f.shape[0], f.shape[1]))
-    all_masks = np.zeros((f.shape[0], f.shape[1]))
-    all_x0 = np.zeros((f.shape[1], 5))
-    all_fr = np.zeros(f.shape[1])
-    all_Qr = np.zeros(f.shape[1])
-    all_amp = np.zeros(f.shape[1])
-    all_phi = np.zeros(f.shape[1])
-    all_b0 = np.zeros(f.shape[1])
-    all_Qi = np.zeros(f.shape[1])
-    all_Qc = np.zeros(f.shape[1])
-
-    for i in range(0, f.shape[1]):
-        f_single = f[:, i]
-        z_single = z[:, i]
-        # flag data that is too close to other resonators              
-        distance = center_freqs - center_freqs[i]
-        if center_freqs[i] != np.min(center_freqs):  # don't do if lowest frequency resonator
-            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
-            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
-            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index]) / 2.
-        else:
-            halfway_low = 0
-
-        if center_freqs[i] != np.max(center_freqs):  # don't do if highest frequenct
-            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
-            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
-            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index]) / 2.
-        else:
-            halfway_high = np.inf
-
-        use_index = np.where(((f_single > halfway_low) & (f_single < halfway_high)))
-        mask = np.zeros(len(f_single))
-        mask[use_index] = 1
-        f_single = f_single[use_index]
-        z_single = z_single[use_index]
-
-        try:
-            fit_dict_iq = fit_linear_mag(f_single, z_single)
-            # ranges = np.asarray(([300*10**6,10,0,-3.14,8000],[500*10**6,20,1,3.14,10000]))
-            # fit_dict_iq = brute_force_linear_mag_fit(f_single,z_single,ranges = ranges,n_grid_points = 10)
-
-            all_fits[i, :] = fit_dict_iq['fit'][0]
-            all_fit_results[:, i] = np.sqrt(linear_mag(f[:, i], all_fits[i, 0], all_fits[i, 1], all_fits[i, 2],
-                                                       all_fits[i, 3], all_fits[i, 4]))
-            all_x0_results[:, i] = np.sqrt(linear_mag(f[:, i], fit_dict_iq['x0'][0], fit_dict_iq['x0'][1],
-                                                      fit_dict_iq['x0'][2], fit_dict_iq['x0'][3], fit_dict_iq['x0'][4]))
-            all_masks[:, i] = mask
-            all_x0[i, :] = fit_dict_iq['x0']
-            all_fr[i] = fit_dict_iq['fr']
-            all_Qr[i] = fit_dict_iq['Qr']
-            all_amp[i] = fit_dict_iq['amp']
-            all_phi[i] = fit_dict_iq['phi']
-            all_b0[i] = fit_dict_iq['b0']
-            all_Qc[i] = all_Qr[i] / all_amp[i]
-            all_Qi[i] = 1.0 / ((1.0 / all_Qr[i]) - (1.0 / all_Qc[i]))
-
-        except Exception as e:
-            print("problem")
-            print(e)
-            print("failed to fit")
-
-    all_fits_dict = {'fits': all_fits, 'fit_results': all_fit_results, 'x0_results': all_x0_results, 'masks': all_masks,
-                     'x0': all_x0,
-                     'fr': all_fr, 'Qr': all_Qr, 'amp': all_amp, 'phi': all_phi, 'b0': all_b0, 'Qi': all_Qi,
-                     'Qc': all_Qc}
-
-    return all_fits_dict
-
-
-def print_fit_string_nonlinear_iq(vals, print_header=True, label="Guess"):
-    Qc_guess = vals[1] / vals[2]
-    Qi_guess = 1.0 / ((1.0 / vals[1]) - (1.0 / Qc_guess))
-    if print_header:
-        print("Resonator at %.2f MHz" % (vals[0] / 10 ** 6))
-        print(f'     |                             Variables fit                           ' +
-              '\033[1;30;42m|Derived variables|\033[0;0m')
-    guess_header_str = '     |'
-    guess_header_str += ' fr (MHz)|'
-    guess_header_str += '   Qr   |'
-    guess_header_str += ' amp |'
-    guess_header_str += ' phi  |'
-    guess_header_str += ' a   |'
-    guess_header_str += '   i0     |'
-    guess_header_str += '   q0     |'
-    guess_header_str += ' tau (ns)\033[1;30;42m|'
-    guess_header_str += '   Qi   |'
-    guess_header_str += '   Qc   |\033[0;0m'
-
-    guess_str = label
-    guess_str += f'| {"%3.4f" % (vals[0] / 10 ** 6)}'
-    guess_str += f'| {"%7.0f" % (vals[1])}'
-    guess_str += f'| {"%0.2f" % (vals[2])}'
-    guess_str += f'| {"% 1.2f" % (vals[3])}'
-    guess_str += f'| {"%0.2f" % (vals[4])}'
-    guess_str += f'| {"% .2E" % (vals[5])}'
-    guess_str += f'| {"% .2E" % (vals[6])}'
-    guess_str += f'| {"%6.2f" % (vals[7] * 10 ** 9)}  '
-    guess_str += f'\033[1;30;42m| {"%7.0f" % (Qi_guess)}'
-    guess_str += f'| {"%7.0f" % (Qc_guess)}|\033[0;0m'
-
-    if print_header:
-        print(guess_header_str)
-    print(guess_str)
-
-
-def print_fit_string_nonlinear_mag(vals, print_header=True, label="Guess"):
-    Qc_guess = vals[1] / vals[2]
-    Qi_guess = 1.0 / ((1.0 / vals[1]) - (1.0 / Qc_guess))
-    if print_header:
-        print("Resonator at %.2f MHz" % (vals[0] / 10 ** 6))
-        print(f'     |                       Variables fit                       ' +
-              '\033[1;30;42m|Derived variables|\033[0;0m')
-    guess_header_str = '     |'
-    guess_header_str += ' fr (MHz)|'
-    guess_header_str += '   Qr   |'
-    guess_header_str += ' amp |'
-    guess_header_str += ' phi  |'
-    guess_header_str += ' a   |'
-    guess_header_str += '   b0     |'
-    guess_header_str += '   b1     \033[1;30;42m|'
-    guess_header_str += '   Qi   |'
-    guess_header_str += '   Qc   |\033[0;0m'
-
-    guess_str = label
-    guess_str += f'| {"%3.4f" % (vals[0] / 10 ** 6)}'
-    guess_str += f'| {"%7.0f" % (vals[1])}'
-    guess_str += f'| {"%0.2f" % (vals[2])}'
-    guess_str += f'| {"% 1.2f" % (vals[3])}'
-    guess_str += f'| {"%0.2f" % (vals[4])}'
-    guess_str += f'| {"% .2E" % (vals[5])}'
-    guess_str += f'| {"% .2E" % (vals[6])}'
-    guess_str += f'\033[1;30;42m| {"%7.0f" % (Qi_guess)}'
-    guess_str += f'| {"%7.0f" % (Qc_guess)}|\033[0;0m'
-
-    if print_header:
-        print(guess_header_str)
-    print(guess_str)
-
-
-def print_fit_string_linear_mag(vals, print_header=True, label="Guess"):
-    Qc_guess = vals[1] / vals[2]
-    Qi_guess = 1.0 / ((1.0 / vals[1]) - (1.0 / Qc_guess))
-    if print_header:
-        print("Resonator at %.2f MHz" % (vals[0] / 10 ** 6))
-        print(f'     |                       Variables fit                       ' +
-              '\033[1;30;42m|Derived variables|\033[0;0m')
-    guess_header_str = '     |'
-    guess_header_str += ' fr (MHz)|'
-    guess_header_str += '   Qr   |'
-    guess_header_str += ' amp |'
-    guess_header_str += ' phi  |'
-    guess_header_str += ' a   |'
-    guess_header_str += '   b0     |'
-    guess_header_str += '   b1     \033[1;30;42m|'
-    guess_header_str += '   Qi   |'
-    guess_header_str += '   Qc   |\033[0;0m'
-
-    guess_str = label
-    guess_str += f'| {"%3.4f" % (vals[0] / 10 ** 6)}'
-    guess_str += f'| {"%7.0f" % (vals[1])}'
-    guess_str += f'| {"%0.2f" % (vals[2])}'
-    guess_str += f'| {"% 1.2f" % (vals[3])}'
-    guess_str += f'| --- '
-    guess_str += f'| {"% .2E" % (vals[4])}'
-    guess_str += f'| -------- '
-    guess_str += f'\033[1;30;42m| {"%7.0f" % (Qi_guess)}'
-    guess_str += f'| {"%7.0f" % (Qc_guess)}|\033[0;0m'
-
-    if print_header:
-        print(guess_header_str)
-    print(guess_str)
diff --git a/submm/KIDs/single_tone.py b/submm/KIDs/single_tone.py
index 368e7b5..215b973 100644
--- a/submm/KIDs/single_tone.py
+++ b/submm/KIDs/single_tone.py
@@ -1,510 +1,524 @@
-from submm.instruments import NIDAQ as n
-from submm.instruments import anritsu as an
-import resonance_fitting
 import time
-import numpy as np
-import matplotlib.pyplot as plt
 import pickle
-from submm.lab_brick import core
 import os.path
 
+import numpy as np
+import matplotlib.pyplot as plt
 
-class single_tone(object):
-
-	def __init__(self):
-
-		# Declare two internal objects: Anritsu/NIDAQ
-		self.anritsu = an.Anritsu()
-		self.daq = n.NIDAQ()
-		self.daq.sample_rate = 60000
-
-
-		# Initializing Standard Configurations
-		self.switch_time = 0.1
-		self.iq_integration_time = 1.
-		self.integration_time = 45
-		self.anritsu.set_power(8)
-		self.anritsu.turn_outputOn()
-		self.iq_dictionary = {}
-		self.power_dictionary = {}
+from submm.lab_brick import core
+from submm.instruments import NIDAQ as n
+from submm.instruments import anritsu as an
+from submm.KIDs.res.fitting import fit_nonlinear_mag_sep, fit_nonlinear_iq_sep
+from submm.KIDs.res.utils import guess_x0_mag_nonlinear_sep, guess_x0_iq_nonlinear_sep
 
 
-		# Preset Span variables
-		self.gain_span = 2*10**6
-		self.rough_span = 500*10**3
-		self.med_span = 100*10**3
-		self.fine_span = 20*10**3
+class single_tone(object):
 
-		# Preset number of points to be taken
-		self.gain_numpoints = 100
-		self.rough_numpoints = 100
-		self.med_numpoints = 100
-		self.fine_numpoints = 100
+    def __init__(self):
+
+        # Declare two internal objects: Anritsu/NIDAQ
+        self.anritsu = an.Anritsu()
+        self.daq = n.NIDAQ()
+        self.daq.sample_rate = 60000
+
+        # Initializing Standard Configurations
+        self.switch_time = 0.1
+        self.iq_integration_time = 1.
+        self.integration_time = 45
+        self.anritsu.set_power(8)
+        self.anritsu.turn_outputOn()
+        self.iq_dictionary = {}
+        self.power_dictionary = {}
 
-		# Center freq to be saved
-		self.center_frequency = 0
+        # Preset Span variables
+        self.gain_span = 2 * 10 ** 6
+        self.rough_span = 500 * 10 ** 3
+        self.med_span = 100 * 10 ** 3
+        self.fine_span = 20 * 10 ** 3
 
-		# Directory for Dictionary data
-		self.output_dir = "c:/users/Tycho/Data/"
+        # Preset number of points to be taken
+        self.gain_numpoints = 100
+        self.rough_numpoints = 100
+        self.med_numpoints = 100
+        self.fine_numpoints = 100
 
-		# Initialize the lab brick
-		# If lab brick isn't connected, output to screen
-		try:
-			self.input_attn = core.Attenuator(0x041f, 0x1208, "15915")
-			self.input_attn.set_attenuation(30)
-			time.sleep(0.5)
-			self.input_attn_value = self.input_attn.get_attenuation()
-		except:
-			print("Unable to connect to input attenuator")
-			self.input_attn = None
-		try:
-			self.output_attn = core.Attenuator(0x041f, 0x1208, "16776")
-			self.output_attn.set_attenuation(30)
-			time.sleep(0.5)
-			self.output_attn_value = self.output_attn.get_attenuation()
-		except:
-			print("Unable to connect to output attenuator")
-			self.output_attn = None
+        # Center freq to be saved
+        self.center_frequency = 0
 
-	# This method passes a frequency, span(+-), and number
-	# of total points to be evaluated. The function measures
-	# the profile of the resonator and returns 3 arrays:
-	# 1 frequency array and 2 voltages array
-	def iq_sweep(self,center_freq, span, numpoints):
-		i = np.zeros(numpoints)
-		q = np.zeros(numpoints)
+        # Directory for Dictionary data
+        self.output_dir = "c:/users/Tycho/Data/"
 
-		freqs = np.linspace(center_freq - span/2, center_freq + span/2, numpoints)
+        # Initialize the lab brick
+        # If lab brick isn't connected, output to screen
+        try:
+            self.input_attn = core.Attenuator(0x041f, 0x1208, "15915")
+            self.input_attn.set_attenuation(30)
+            time.sleep(0.5)
+            self.input_attn_value = self.input_attn.get_attenuation()
+        except:
+            print("Unable to connect to input attenuator")
+            self.input_attn = None
+        try:
+            self.output_attn = core.Attenuator(0x041f, 0x1208, "16776")
+            self.output_attn.set_attenuation(30)
+            time.sleep(0.5)
+            self.output_attn_value = self.output_attn.get_attenuation()
+        except:
+            print("Unable to connect to output attenuator")
+            self.output_attn = None
 
-		for k in range(0, numpoints):
-			print(k)
-			self.anritsu.set_frequency(freqs[k])
-			time.sleep(self.switch_time)
+    # This method passes a frequency, span(+-), and number
+    # of total points to be evaluated. The function measures
+    # the profile of the resonator and returns 3 arrays:
+    # 1 frequency array and 2 voltages array
+    def iq_sweep(self, center_freq, span, numpoints):
+        i = np.zeros(numpoints)
+        q = np.zeros(numpoints)
 
-			i[k], q[k] = self.daq.average_2ch(self.iq_integration_time)
+        freqs = np.linspace(center_freq - span / 2, center_freq + span / 2, numpoints)
 
-		return freqs, i, q
+        for k in range(0, numpoints):
+            print(k)
+            self.anritsu.set_frequency(freqs[k])
+            time.sleep(self.switch_time)
 
-	# This method passes a frequency to be streamed
-	# and returns two arrays that stores frequency
-	def stream(self, center_freq):
+            i[k], q[k] = self.daq.average_2ch(self.iq_integration_time)
 
-		self.anritsu.set_frequency(center_freq)
-		time.sleep(self.switch_time)
+        return freqs, i, q
 
-		i, q = self.daq.stream_2ch(self.integration_time)
+    # This method passes a frequency to be streamed
+    # and returns two arrays that stores frequency
+    def stream(self, center_freq):
 
-		return i, q
+        self.anritsu.set_frequency(center_freq)
+        time.sleep(self.switch_time)
 
-	def stream3(self, center_freq):
+        i, q = self.daq.stream_2ch(self.integration_time)
 
-		self.anritsu.set_frequency(center_freq)
-		time.sleep(self.switch_time)
+        return i, q
 
-		i, q, ref = self.daq.stream_3ch(self.integration_time)
+    def stream3(self, center_freq):
 
-		return i, q, ref
+        self.anritsu.set_frequency(center_freq)
+        time.sleep(self.switch_time)
 
-	# This method finds the minimum frequency and
-	# the index position of that frequency
-	def find_min(self, freqs, i, q):
-		index = np.argmin(i**2 + q**2)
+        i, q, ref = self.daq.stream_3ch(self.integration_time)
 
-		return freqs[index], index
-
-	# This methods finds the largest i and q separation,
-	# and returns the value and it's index position
-	def find_max_iq_sep(self, freqs, i, q):
-		i2 = np.roll(i,1)
-		q2 = np.roll(q,1)
-
-		dist = np.sqrt((i-i2)**2 + (q-q2)**2)
-
-		dist[0] = 0
-		dist[-1] = 0
-
-		index = np.argmax(dist)
-
-		return freqs[index], index
+        return i, q, ref
 
-	def rough(self, center_freq):
-		freqs, i, q = self.iq_sweep(center_freq, self.rough_span, self.rough_numpoints)
-
-		return freqs, i, q
+    # This method finds the minimum frequency and
+    # the index position of that frequency
+    def find_min(self, freqs, i, q):
+        index = np.argmin(i ** 2 + q ** 2)
+
+        return freqs[index], index
+
+    # This methods finds the largest i and q separation,
+    # and returns the value and it's index position
+    def find_max_iq_sep(self, freqs, i, q):
+        i2 = np.roll(i, 1)
+        q2 = np.roll(q, 1)
+
+        dist = np.sqrt((i - i2) ** 2 + (q - q2) ** 2)
+
+        dist[0] = 0
+        dist[-1] = 0
+
+        index = np.argmax(dist)
+
+        return freqs[index], index
+
+    def rough(self, center_freq):
+        freqs, i, q = self.iq_sweep(center_freq, self.rough_span, self.rough_numpoints)
+
+        return freqs, i, q
+
+    def med(self, center_freq):
+        freqs, i, q = self.iq_sweep(center_freq, self.med_span, self.med_numpoints)
 
-	def med(self, center_freq):
-		freqs, i, q = self.iq_sweep(center_freq, self.med_span, self.med_numpoints)
+        return freqs, i, q
 
-		return freqs, i, q
+    def fine(self, center_freq):
+        freqs, i, q = self.iq_sweep(center_freq, self.fine_span, self.fine_numpoints)
 
-	def fine(self, center_freq):
-		freqs, i , q = self.iq_sweep(center_freq, self.fine_span, self.fine_numpoints)
+        return freqs, i, q
 
-		return freqs, i, q
+    def gain(self, center_freq):
+        freqs, i, q = self.iq_sweep(center_freq, self.gain_span, self.gain_numpoints)
 
-	def gain(self, center_freq):
-		freqs, i, q = self.iq_sweep(center_freq, self.gain_span, self.gain_numpoints)
+        return freqs, i, q
 
-		return freqs, i, q
+    # This method passes a frequency to be evaluated and
+    # returns a dictionary with all the values being
+    # tested. It finds the best place to take data
+
+    def take_noise_set(self, center_freq, chan3=False, take_noise=True, filename="",
+                       pause_before_noise=False):
+
+        if (len(filename) < 2):
+
+            timestr = time.strftime("%Y%m%d-%H%M%S")
+            file_name = os.path.join(self.output_dir + timestr + "_noiseData.txt")
+            file_name2 = os.path.join(self.output_dir + timestr)
+        else:
+            file_name = str(filename + ".txt")
+            file_name2 = str(filename)
 
-	# This method passes a frequency to be evaluated and
-	# returns a dictionary with all of the values being
-	# tested. It finds the best place to take data
-
-	def take_noise_set(self, center_freq, chan3 = False, take_noise = True, filename = ""):
-
-		if(len(filename) < 2):
-
-			timestr = time.strftime("%Y%m%d-%H%M%S")
-			file_name = os.path.join(self.output_dir + timestr + "_noiseData.txt")
-			file_name2 = os.path.join(self.output_dir + timestr)
-		else:
-			file_name = str(filename + ".txt")
-			file_name2 = str(filename)
+        self.center_frequency = center_freq
 
-		self.center_frequency = center_freq
+        print("taking rough scan")
+        freqs_rough, I_rough, Q_rough = self.rough(center_freq)
+        rough_center_freq, min_pos_rough = self.find_min(freqs_rough, I_rough, Q_rough)
 
-		print("taking rough scan")
-		freqs_rough, I_rough, Q_rough = self.rough(center_freq)
-		rough_center_freq, min_pos_rough = self.find_min(freqs_rough, I_rough, Q_rough)
+        print("taking med scan")
+        freqs_med, I_med, Q_med = self.med(rough_center_freq)
+        med_center_freq, min_pos_med = self.find_min(freqs_med, I_med, Q_med)
 
-		print("taking med scan")
-		freqs_med, I_med, Q_med = self.med(rough_center_freq)
-		med_center_freq, min_pos_med = self.find_min(freqs_med, I_med, Q_med)
+        print("taking fine scan")
+        freqs_fine, I_fine, Q_fine = self.fine(med_center_freq)
+        fine_center_freq, max_iq_pos = self.find_max_iq_sep(freqs_fine, I_fine, Q_fine)
 
-		print("taking fine scan")
-		freqs_fine, I_fine, Q_fine = self.fine(med_center_freq)
-		fine_center_freq, max_iq_pos = self.find_max_iq_sep(freqs_fine, I_fine, Q_fine)
+        print("taking gain scan")
+        freqs_gain, I_gain, Q_gain = self.gain(fine_center_freq)
 
-		print("taking gain scan")
-		freqs_gain, I_gain, Q_gain = self.gain(fine_center_freq)
+        if (take_noise == True):
 
-		if (take_noise == True):
+            print('\n')
+            if pause_before_noise == True:
+                input("Program paused before streaming. Press enter to continue....")
+            if (chan3 == True):
+                print("taking noise data")
+                I_noise, Q_noise, ref_noise = self.stream3(fine_center_freq)
+                self.iq_dictionary['ref_noise'] = ref_noise
+                self.iq_dictionary['I_noise'] = I_noise
+                self.iq_dictionary['Q_noise'] = Q_noise
+            else:
+                I_noise, Q_noise = self.stream(fine_center_freq)
+                self.iq_dictionary['I_noise'] = I_noise
+                self.iq_dictionary['Q_noise'] = Q_noise
+
+        self.iq_dictionary['freqs_rough'] = freqs_rough
+        self.iq_dictionary['I_rough'] = I_rough
+        self.iq_dictionary['Q_rough'] = Q_rough
+        self.iq_dictionary['freqs_med'] = freqs_med
+        self.iq_dictionary['I_med'] = I_med
+        self.iq_dictionary['Q_med'] = Q_med
+        self.iq_dictionary['freqs_fine'] = freqs_fine
+        self.iq_dictionary['I_fine'] = I_fine
+        self.iq_dictionary['Q_fine'] = Q_fine
+        self.iq_dictionary['freqs_gain'] = freqs_gain
+        self.iq_dictionary['I_gain'] = I_gain
+        self.iq_dictionary['Q_gain'] = Q_gain
+        self.iq_dictionary['rough_center_freq'] = rough_center_freq
+        self.iq_dictionary['med_center_freq'] = med_center_freq
+        self.iq_dictionary['fine_center_freq'] = fine_center_freq
+        self.iq_dictionary['min_pos_rough'] = min_pos_rough
+        self.iq_dictionary['min_pos_med'] = min_pos_med
+        self.iq_dictionary['max_iq_pos'] = max_iq_pos
+
+        try:
+            self.iq_dictionary['input_attn'] = self.input_attn_value
+            self.iq_dictionary['output_attn'] = self.output_attn_value
+        except:
+            pass
+
+        self.export_file(file_name, self.iq_dictionary)
+        self.save_log_iq(file_name2)
+
+        print('\n')
+        print("Best Frequency: " + str(fine_center_freq / 10 ** 6) + " Mhz")
+
+        return self.iq_dictionary
+
+    # This method exports the object's dictionary
+    # to a file to be saved
+    def export_file(self, file_name, dictionary):
+
+        file_object = open(str(file_name), "w")
+        pickle.dump(dictionary, file_object)
+        file_object.close()
+
+    # This method returns a saved file of all the variables
+    # and their values
+    def save_log_iq(self, file_name):
+
+        file_object = open(file_name + "_logIQ.txt", "w")
+
+        file_object.write("switch_time: " + str(self.switch_time) + "\n")
+        file_object.write("iq_integration_time: " + str(self.iq_integration_time) + "\n")
+        file_object.write("integration_time: " + str(self.integration_time) + "\n")
+        file_object.write("anritsu_power: " + str(self.anritsu.get_power()) + "\n")
+        file_object.write("gain_span: " + str(self.gain_span) + "\n")
+        file_object.write("rough_span: " + str(self.rough_span) + "\n")
+        file_object.write("med_span: " + str(self.med_span) + "\n")
+        file_object.write("fine_span: " + str(self.fine_span) + "\n")
+        file_object.write("gain_numpoints: " + str(self.gain_numpoints) + "\n")
+        file_object.write("rough_numpoints: " + str(self.rough_numpoints) + "\n")
+        file_object.write("med_numpoints: " + str(self.med_numpoints) + "\n")
+        file_object.write("fine_numpoints: " + str(self.fine_numpoints) + "\n")
+        file_object.write("input_attn_value: " + str(self.input_attn_value) + "\n")
+        try:
+            file_object.write("output_attn_value: " + str(self.output_attn_value) + "\n")
+        except:
+            pass
+        file_object.write("sample_rate: " + str(self.daq.sample_rate) + "\n")
+        file_object.write("center_freq: " + str(self.center_frequency) + "\n")
+
+        file_object.close()
+
+    # If the input changes, then output needs to be
+    # reciprocated to that input value
+    def change_attn_balanced(self, input):
+
+        if (self.output_attn != None):
+
+            delta_attn = input - self.input_attn_value
+
+            self.input_attn.set_attenuation(input)
+            time.sleep(0.5)
+            self.input_attn_value = self.input_attn.get_attenuation()
+
+            self.output_attn.set_attenuation(self.output_attn_value - delta_attn)
+            time.sleep(0.5)
+            self.output_attn_value = self.output_attn.get_attenuation()
+        else:
+            self.input_attn.set_attenuation(input)
+            time.sleep(0.5)
+            self.input_attn_value = self.input_attn.get_attenuation()
+
+    def set_input_attn(self, input):
+        self.input_attn.set_attenuation(input)
+        time.sleep(0.5)
+        self.input_attn_value = self.input_attn.get_attenuation()
+
+    def set_output_attn(self, output):
+
+        if (self.output_attn != None):
+            self.output_attn.set_attenuation(output)
+            time.sleep(0.5)
+            self.output_attn_value = self.output_attn.get_attenuation()
+        else:
+            print("Output not connected!")
+
+    def power_sweep(self, low_power, high_power, step, center_freq, filename=""):
+
+        if (filename == ""):
+
+            timestr = time.strftime("%Y%m%d-%H%M%S")
+            file_name = os.path.join(self.output_dir + timestr + "_powerData.txt")
+        else:
+            file_name = os.path.join(self.output_dir + filename + ".txt")
+            file_name2 = os.path.join(self.output_dir + filename)
+
+        powers = np.arange(low_power, high_power - step, -step)
+
+        i_gain = np.zeros(shape=(len(powers), self.gain_numpoints))
+        q_gain = np.zeros(shape=(len(powers), self.gain_numpoints))
+        i_fine = np.zeros(shape=(len(powers), self.fine_numpoints))
+        q_fine = np.zeros(shape=(len(powers), self.fine_numpoints))
+        freqs_gain = np.linspace(center_freq - (self.gain_span / 2), center_freq + (self.gain_span / 2),
+                                 self.gain_numpoints)
+        freqs_fine = np.linspace(center_freq - (self.fine_span / 2), center_freq + (self.fine_span / 2),
+                                 self.fine_numpoints)
+        position = 0
+
+        for k in range(0, len(powers)):
+            freqs_gain, i_gain[k][:], q_gain[k][:] = self.gain(center_freq)
+            freqs_fine, i_fine[k][:], q_fine[k][:] = self.fine(center_freq)
+
+            center_freq, position = self.find_min(freqs_fine, i_fine[k][:], q_fine[k][:])
+
+        self.power_dictionary['powers'] = powers
+        self.power_dictionary['i_gain'] = i_gain
+        self.power_dictionary['q_gain'] = q_gain
+        self.power_dictionary['i_fine'] = i_fine
+        self.power_dictionary['q_fine'] = q_fine
+        self.power_dictionary['freqs_gain'] = freqs_gain
+        self.power_dictionary['freqs_fine'] = freqs_fine
+        self.power_dictionary['center_freq'] = center_freq
+        self.power_dictionary['position'] = position
+
+        self.export_file(file_name, self.power_dictionary)
+        self.save_log_power(file_name2)
+        return self.power_dictionary
+
+    def save_log_power(self, file_name):
+
+        file_object = open(file_name + "_logPower.txt", "w")
+
+        file_object.write("Powers: " + str(self.power_dictionary['powers']) + "\n")
+        file_object.write("i_gain: " + str(self.power_dictionary['i_gain']) + "\n")
+        file_object.write("q_gain: " + str(self.power_dictionary['q_gain']) + "\n")
+        file_object.write("i_fine: " + str(self.power_dictionary['i_fine']) + "\n")
+        file_object.write("q_fine: " + str(self.power_dictionary['q_fine']) + "\n")
+        file_object.write("freqs_gain: " + str(self.power_dictionary['freqs_gain']) + "\n")
+        file_object.write("freqs_fine: " + str(self.power_dictionary['freqs_fine']) + "\n")
+        file_object.write("center_freq: " + str(self.power_dictionary['center_freq']) + "\n")
+        file_object.write("position: " + str(self.power_dictionary['position']) + "\n")
+
+        file_object.close()
 
-			print('\n')
-			if pause_before_noise == True:
-				raw_input("Program paused before streaming. Press enter to continue....")
-			if (chan3 == True):
-				print("taking noise data")
-				I_noise, Q_noise, ref_noise = self.stream3(fine_center_freq)
-				self.iq_dictionary['ref_noise'] = ref_noise
-				self.iq_dictionary['I_noise'] = I_noise
-				self.iq_dictionary['Q_noise'] = Q_noise
-			else:
-				I_noise, Q_noise = self.stream(fine_center_freq)
-				self.iq_dictionary['I_noise'] = I_noise
-				self.iq_dictionary['Q_noise'] = Q_noise
-
-		self.iq_dictionary['freqs_rough'] =  freqs_rough
-		self.iq_dictionary['I_rough'] = I_rough
-		self.iq_dictionary['Q_rough'] = Q_rough
-		self.iq_dictionary['freqs_med'] = freqs_med
-		self.iq_dictionary['I_med'] = I_med
-		self.iq_dictionary['Q_med'] = Q_med
-		self.iq_dictionary['freqs_fine'] = freqs_fine
-		self.iq_dictionary['I_fine'] = I_fine
-		self.iq_dictionary['Q_fine'] = Q_fine
-		self.iq_dictionary['freqs_gain'] = freqs_gain
-		self.iq_dictionary['I_gain'] = I_gain
-		self.iq_dictionary['Q_gain'] = Q_gain
-		self.iq_dictionary['rough_center_freq'] = rough_center_freq
-		self.iq_dictionary['med_center_freq'] = med_center_freq
-		self.iq_dictionary['fine_center_freq'] = fine_center_freq
-		self.iq_dictionary['min_pos_rough'] = min_pos_rough
-		self.iq_dictionary['min_pos_med'] = min_pos_med
-		self.iq_dictionary['max_iq_pos'] = max_iq_pos
-
-		try:
-			self.iq_dictionary['input_attn'] = self.input_attn_value
-			self.iq_dictionary['output_attn'] = self.output_attn_value
-		except:
-			pass
-
-		self.export_file(file_name, self.iq_dictionary)
-		self.save_log_iq(file_name2)
-
-		print('\n')
-		print("Best Frequency: " + str(fine_center_freq / 10**6) + " Mhz")
-
-		return self.iq_dictionary
-
-	# This method exports the object's dictionary
-	# to a file to be saved
-	def export_file(self, file_name, dictionary):
-
-		file_object = open(str(file_name), "w")
-		pickle.dump(dictionary, file_object)
-		file_object.close()
-
-	# This method returns a saved file of all the variables
-	# and their values
-	def save_log_iq(self, file_name):
-
-		file_object = open(file_name + "_logIQ.txt", "w")
-
-		file_object.write("switch_time: " + str(self.switch_time) + "\n")
-		file_object.write("iq_integration_time: " + str(self.iq_integration_time) + "\n")
-		file_object.write("integration_time: " + str(self.integration_time) + "\n")
-		file_object.write("anritsu_power: " + str(self.anritsu.get_power()) + "\n")
-		file_object.write("gain_span: " + str(self.gain_span) + "\n")
-		file_object.write("rough_span: " + str(self.rough_span) + "\n")
-		file_object.write("med_span: " + str(self.med_span) + "\n")
-		file_object.write("fine_span: " + str(self.fine_span) + "\n")
-		file_object.write("gain_numpoints: " + str(self.gain_numpoints) + "\n")
-		file_object.write("rough_numpoints: " + str(self.rough_numpoints) + "\n")
-		file_object.write("med_numpoints: " + str(self.med_numpoints) + "\n")
-		file_object.write("fine_numpoints: " + str(self.fine_numpoints) + "\n")
-		file_object.write("input_attn_value: " + str(self.input_attn_value) + "\n")
-		try:
-			file_object.write("output_attn_value: " + str(self.output_attn_value) + "\n")
-		except:
-			pass
-		file_object.write("sample_rate: " + str(self.daq.sample_rate) + "\n" )
-		file_object.write("center_freq: " + str(self.center_frequency) + "\n")
-
-		file_object.close()
-
-	# If the input changes, then output needs to be
-	# reciprocated to that input value
-	def change_attn_balanced(self, input):
-
-		if (self.output_attn != None):
-
-			delta_attn = input - self.input_attn_value
-
-			self.input_attn.set_attenuation(input)
-			time.sleep(0.5)
-			self.input_attn_value = self.input_attn.get_attenuation()
-
-			self.output_attn.set_attenuation(self.output_attn_value - delta_attn)
-			time.sleep(0.5)
-			self.output_attn_value = self.output_attn.get_attenuation()
-		else:
-			self.input_attn.set_attenuation(input)
-			time.sleep(0.5)
-			self.input_attn_value = self.input_attn.get_attenuation()
-
-	def set_input_attn(self, input):
-		self.input_attn.set_attenuation(input)
-		time.sleep(0.5)
-		self.input_attn_value = self.input_attn.get_attenuation()
-
-	def set_output_attn(self, output):
-
-		if (self.output_attn != None):
-			self.output_attn.set_attenuation(output)
-			time.sleep(0.5)
-			self.output_attn_value = self.output_attn.get_attenuation()
-		else:
-			print("Output not connected!")
-
-	def power_sweep(self, low_power, high_power, step, center_freq, filename = ""):
-
-		if (filename == ""):
-
-			timestr = time.strftime("%Y%m%d-%H%M%S")
-			file_name = os.path.join(self.output_dir + timestr + "_powerData.txt")
-		else:
-			file_name = os.path.join(self.output_dir + filename +".txt")
-			file_name2 = os.path.join(self.output_dir + filename)
-
-		powers = np.arange(low_power, high_power-step, -step)
-
-		i_gain = np.zeros(shape = (len(powers), self.gain_numpoints))
-		q_gain = np.zeros(shape = (len(powers), self.gain_numpoints))
-		i_fine = np.zeros(shape = (len(powers), self.fine_numpoints))
-		q_fine = np.zeros(shape = (len(powers), self.fine_numpoints))
-		freqs_gain = np.linspace(center_freq - (self.gain_span/2), center_freq + (self.gain_span/2), self.gain_numpoints)
-		freqs_fine = np.linspace(center_freq - (self.fine_span/2), center_freq + (self.fine_span/2), self.fine_numpoints)
-		position = 0
-
-		for k in range(0, len(powers)):
-			freqs_gain, i_gain[k][:], q_gain[k][:] = self.gain(center_freq)
-			freqs_fine, i_fine[k][:], q_fine[k][:] = self.fine(center_freq)
-
-			center_freq, position = self.find_min(freqs_fine, i_fine[k][:], q_fine[k][:])
-
-		self.power_dictionary['powers'] = powers
-		self.power_dictionary['i_gain'] = i_gain
-		self.power_dictionary['q_gain'] = q_gain
-		self.power_dictionary['i_fine'] = i_fine
-		self.power_dictionary['q_fine'] = q_fine
-		self.power_dictionary['freqs_gain'] = freqs_gain
-		self.power_dictionary['freqs_fine'] = freqs_fine
-		self.power_dictionary['center_freq'] = center_freq
-		self.power_dictionary['position'] = position
-
-		self.export_file(file_name, self.power_dictionary)
-		self.save_log_power(file_name2)
-		return self.power_dictionary
-
-	def save_log_power(self, file_name):
-
-		file_object = open(file_name + "_logPower.txt", "w")
-
-		file_object.write("Powers: " + str(self.power_dictionary['powers']) + "\n")
-		file_object.write("i_gain: " + str(self.power_dictionary['i_gain']) + "\n")
-		file_object.write("q_gain: " + str(self.power_dictionary['q_gain']) + "\n")
-		file_object.write("i_fine: " + str(self.power_dictionary['i_fine']) + "\n")
-		file_object.write("q_fine: " + str(self.power_dictionary['q_fine']) + "\n")
-		file_object.write("freqs_gain: " + str(self.power_dictionary['freqs_gain']) + "\n")
-		file_object.write("freqs_fine: " + str(self.power_dictionary['freqs_fine']) + "\n")
-		file_object.write("center_freq: " + str(self.power_dictionary['center_freq']) + "\n")
-		file_object.write("position: " + str(self.power_dictionary['position']) + "\n")
-
-		file_object.close()
 
 # This method opens up a file that contains the object's
 # dictionary and stores it back into another dictionary
 def import_file(file_name):
-	file_object = open(file_name, "rU")
-	dictionary = pickle.load(file_object)
-	file_object.close()
-	return dictionary
+    file_object = open(file_name, "rU")
+    dictionary = pickle.load(file_object)
+    file_object.close()
+    return dictionary
+
 
 # Fitting noise and guessing
 def fit_noise_set(dictionary):
-	#figure out where to save
-	fine_f = dict['freqs_fine']
-	gain_f = dict['freqs_gain']
-	fine_z = dict['I_fine']+1.j*dict['Q_fine']
-	gain_z = dict['I_gain']+1.j*dict['Q_gain']
-
-	fig = plt.figure(figsize = (8,8))
-
-	# Subplot 221/223 refers to noise and power
-	plt.subplot(221)
-	plt.plot(dict['freqs_fine']/10**6,10*np.log10(dict['I_fine']**2+dict['Q_fine']**2),'o',label = "fine")
-	plt.plot(dict['freqs_gain']/10**6,10*np.log10(dict['I_gain']**2+dict['Q_gain']**2),'o',label = "gain")
-	plt.xlabel("Frequency (MHz)")
-	plt.ylabel("Power (dB)")
-
-	plt.subplot(223)
-	plt.plot(dict['freqs_fine']/10**6,10*np.log10(dict['I_fine']**2+dict['Q_fine']**2),'o')
-	plt.plot(dict['freqs_gain']/10**6,10*np.log10(dict['I_gain']**2+dict['Q_gain']**2),'o')
-	plt.xlabel("Frequency (MHz)")
-	plt.ylabel("Power (dB)")
-	plt.xlim(np.min(dict['freqs_fine']/10**6),np.max(dict['freqs_fine']/10**6))
-
-	# fit nonlinear magnitude
-	try:
-		x0 = resonance_fitting.guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-		fit_dict_mag = resonance_fitting.fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_z, x0=x0)#,bounds =bounds)
-
-		plt.subplot(221)
-		plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+",label = "fit")
-		plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x",label = "x0 guess")
-		plt.title(str("Non-linearity param a = %.2f")  % fit_dict_mag['fit'][0][4])
-
-		plt.legend()
-		plt.subplot(223)
-		plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+")
-		plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x")
-	except Exception as e:
-		print(e)
-		print("could not fit the resonator")
-
-	# Subplot 222/224 refers to just noise
-	plt.subplot(222,aspect ='equal')
-	plt.plot(dict['I_fine'],dict['Q_fine'],'o')
-	plt.plot(dict['I_gain'],dict['Q_gain'],'o')
-	plt.xlabel("I")
-	plt.ylabel("Q")
-
-	plt.subplot(224,aspect ='equal')
-	plt.plot(dict['I_fine'],dict['Q_fine'],'o')
-	plt.plot(dict['I_gain'],dict['Q_gain'],'o')
-
-	plt.xlabel("I")
-	plt.ylabel("Q")
-	plt.xlim(np.min(dict['I_fine']),np.max(dict['I_fine']))
-	plt.ylim(np.min(dict['Q_fine']),np.max(dict['Q_fine']))
-
-	# fit nonlinear iq
-	try:
-		x0 = resonance_fitting.guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-		fit_dict_iq = resonance_fitting.fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, x0=x0)
-
-		plt.subplot(222,aspect ='equal')
-		plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-		plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-
-		plt.title(str("Non-linearity param a = %0.2f") % fit_dict_iq['fit'][0][4])
-
-		plt.subplot(224,aspect ='equal')
-		plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-		plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-		plt.plot(dict['I_fine'],dict['Q_fine'])
-	except Exception as e:
-		print(e)
-		print("could not fit the resonator")
-
-
-	plt.show()
+    # figure out where to save
+    fine_f = dict['freqs_fine']
+    gain_f = dict['freqs_gain']
+    fine_z = dict['I_fine'] + 1.j * dict['Q_fine']
+    gain_z = dict['I_gain'] + 1.j * dict['Q_gain']
+
+    fig = plt.figure(figsize=(8, 8))
+
+    # Subplot 221/223 refers to noise and power
+    plt.subplot(221)
+    plt.plot(dict['freqs_fine'] / 10 ** 6, 10 * np.log10(dict['I_fine'] ** 2 + dict['Q_fine'] ** 2), 'o', label="fine")
+    plt.plot(dict['freqs_gain'] / 10 ** 6, 10 * np.log10(dict['I_gain'] ** 2 + dict['Q_gain'] ** 2), 'o', label="gain")
+    plt.xlabel("Frequency (MHz)")
+    plt.ylabel("Power (dB)")
+
+    plt.subplot(223)
+    plt.plot(dict['freqs_fine'] / 10 ** 6, 10 * np.log10(dict['I_fine'] ** 2 + dict['Q_fine'] ** 2), 'o')
+    plt.plot(dict['freqs_gain'] / 10 ** 6, 10 * np.log10(dict['I_gain'] ** 2 + dict['Q_gain'] ** 2), 'o')
+    plt.xlabel("Frequency (MHz)")
+    plt.ylabel("Power (dB)")
+    plt.xlim(np.min(dict['freqs_fine'] / 10 ** 6), np.max(dict['freqs_fine'] / 10 ** 6))
+
+    # fit nonlinear magnitude
+    try:
+        x0 = guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+        fit_dict_mag = fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_z, x0=x0)  # ,bounds =bounds)
+
+        plt.subplot(221)
+        plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+", label="fit")
+        plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x", label="x0 guess")
+        plt.title(str("Non-linearity param a = %.2f") % fit_dict_mag['fit'][0][4])
+
+        plt.legend()
+        plt.subplot(223)
+        plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+")
+        plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x")
+    except Exception as e:
+        print(e)
+        print("could not fit the resonator")
+
+    # Subplot 222/224 refers to just noise
+    plt.subplot(222, aspect='equal')
+    plt.plot(dict['I_fine'], dict['Q_fine'], 'o')
+    plt.plot(dict['I_gain'], dict['Q_gain'], 'o')
+    plt.xlabel("I")
+    plt.ylabel("Q")
+
+    plt.subplot(224, aspect='equal')
+    plt.plot(dict['I_fine'], dict['Q_fine'], 'o')
+    plt.plot(dict['I_gain'], dict['Q_gain'], 'o')
+
+    plt.xlabel("I")
+    plt.ylabel("Q")
+    plt.xlim(np.min(dict['I_fine']), np.max(dict['I_fine']))
+    plt.ylim(np.min(dict['Q_fine']), np.max(dict['Q_fine']))
+
+    # fit nonlinear iq
+    try:
+        x0 = guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+        fit_dict_iq = fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, x0=x0)
+
+        plt.subplot(222, aspect='equal')
+        plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+        plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+
+        plt.title(str("Non-linearity param a = %0.2f") % fit_dict_iq['fit'][0][4])
+
+        plt.subplot(224, aspect='equal')
+        plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+        plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+        plt.plot(dict['I_fine'], dict['Q_fine'])
+    except Exception as e:
+        print(e)
+        print("could not fit the resonator")
+
+    plt.show()
+
 
 # This method passes a dictionary parameter and plots
 # the dictionary values and returns 2 figures to be
 # evaluated
 def plot_iq_dict(dictionary):
-	plt.figure(1)
-	plt.title("IQ")
-	plt.xlabel("I")
-	plt.ylabel("Q")
-
-	try:
-		plt.plot(dictionary['I_noise'][::100],dictionary['Q_noise'][::100], 'm-', label = "IQ noise")
-
-	except:
-		pass
-
-	plt.plot(dictionary['I_rough'], dictionary['Q_rough'], 'r-',label = "rough")
-	plt.plot(dictionary['I_med'], dictionary['Q_med'], 'b-',label = "med")
-	plt.plot(dictionary['I_fine'], dictionary['Q_fine'], 'g-', label = "fine")
-	plt.plot(dictionary['I_gain'], dictionary['Q_gain'], 'y-', label = "gain")
-	plt.plot(dictionary['I_fine'][dictionary['max_iq_pos']] , dictionary['Q_fine'][dictionary['max_iq_pos']], '*', label = "max sep")
-	plt.legend()
-
-
-
-
-	plt.figure(2)
-	plt.title("Magnitude")
-	plt.xlabel("Frequency (Mhz)")
-	plt.ylabel("Magnitude")
-
-	plt.plot(dictionary['freqs_rough'] / 10**6, dictionary['I_rough']**2 + dictionary['Q_rough']**2, 'r-', label = "rough")
-	plt.plot(dictionary['freqs_rough'][dictionary['min_pos_rough']]/ 10**6,dictionary['I_rough'][dictionary['min_pos_rough']]**2+ dictionary['Q_rough'][dictionary['min_pos_rough']]**2, '*')
-	plt.plot(dictionary['freqs_med']/ 10**6, dictionary['I_med']**2 + dictionary['Q_med']**2, 'b-', label = "med")
-	plt.plot(dictionary['freqs_med'][dictionary['min_pos_med']]/ 10**6,dictionary['I_med'][dictionary['min_pos_med']]**2+ dictionary['Q_med'][dictionary['min_pos_med']]**2, '*', label = "med min")
-
-	plt.plot(dictionary['freqs_fine']/ 10**6, dictionary['I_fine']**2 + dictionary['Q_fine']**2, 'g-', label = "fine")
-	plt.plot(dictionary['freqs_fine'][dictionary['max_iq_pos']]/ 10**6, dictionary['I_fine'][dictionary['max_iq_pos']]**2 + dictionary['Q_fine'][dictionary['max_iq_pos']]**2, '*', label = "iq pos")
-
-	plt.plot(dictionary['freqs_gain']/ 10**6, dictionary['I_gain']**2 + dictionary['Q_gain']**2, 'y-', label = "gain")
-
-	plt.legend()
+    plt.figure(1)
+    plt.title("IQ")
+    plt.xlabel("I")
+    plt.ylabel("Q")
+
+    try:
+        plt.plot(dictionary['I_noise'][::100], dictionary['Q_noise'][::100], 'm-', label="IQ noise")
+
+    except:
+        pass
+
+    plt.plot(dictionary['I_rough'], dictionary['Q_rough'], 'r-', label="rough")
+    plt.plot(dictionary['I_med'], dictionary['Q_med'], 'b-', label="med")
+    plt.plot(dictionary['I_fine'], dictionary['Q_fine'], 'g-', label="fine")
+    plt.plot(dictionary['I_gain'], dictionary['Q_gain'], 'y-', label="gain")
+    plt.plot(dictionary['I_fine'][dictionary['max_iq_pos']], dictionary['Q_fine'][dictionary['max_iq_pos']], '*',
+             label="max sep")
+    plt.legend()
+
+    plt.figure(2)
+    plt.title("Magnitude")
+    plt.xlabel("Frequency (Mhz)")
+    plt.ylabel("Magnitude")
+
+    plt.plot(dictionary['freqs_rough'] / 10 ** 6, dictionary['I_rough'] ** 2 + dictionary['Q_rough'] ** 2, 'r-',
+             label="rough")
+    plt.plot(dictionary['freqs_rough'][dictionary['min_pos_rough']] / 10 ** 6,
+             dictionary['I_rough'][dictionary['min_pos_rough']] ** 2 + dictionary['Q_rough'][
+                 dictionary['min_pos_rough']] ** 2, '*')
+    plt.plot(dictionary['freqs_med'] / 10 ** 6, dictionary['I_med'] ** 2 + dictionary['Q_med'] ** 2, 'b-', label="med")
+    plt.plot(dictionary['freqs_med'][dictionary['min_pos_med']] / 10 ** 6,
+             dictionary['I_med'][dictionary['min_pos_med']] ** 2 + dictionary['Q_med'][dictionary['min_pos_med']] ** 2,
+             '*', label="med min")
+
+    plt.plot(dictionary['freqs_fine'] / 10 ** 6, dictionary['I_fine'] ** 2 + dictionary['Q_fine'] ** 2, 'g-',
+             label="fine")
+    plt.plot(dictionary['freqs_fine'][dictionary['max_iq_pos']] / 10 ** 6,
+             dictionary['I_fine'][dictionary['max_iq_pos']] ** 2 + dictionary['Q_fine'][dictionary['max_iq_pos']] ** 2,
+             '*', label="iq pos")
+
+    plt.plot(dictionary['freqs_gain'] / 10 ** 6, dictionary['I_gain'] ** 2 + dictionary['Q_gain'] ** 2, 'y-',
+             label="gain")
+
+    plt.legend()
+
+    plt.show()
 
-	plt.show()
 
 def plot_power_dict(dictionary):
+    plt.figure(1)
+    plt.title("I&Q w/ Powers")
+    plt.xlabel("I_fine")
+    plt.ylabel("Q_fine")
 
-	plt.figure(1)
-	plt.title("I&Q w/ Powers")
-	plt.xlabel("I_fine")
-	plt.ylabel("Q_fine")
+    for k in range(0, len(dictionary['powers'])):
+        plt.plot(dictionary['i_fine'][k, :], dictionary['q_fine'][k, :], label=str(dictionary['powers'][k]) + " db")
 
-	for k in range(0, len(dictionary['powers'])):
-		plt.plot(dictionary['i_fine'][k,:], dictionary['q_fine'][k,:], label = str(dictionary['powers'][k]) + " db")
+    plt.legend()
+    plt.show()
 
-	plt.legend()
-	plt.show()
 
 def plot_iq_single(freq, i, q):
-	plt.figure(1)
-	plt.title("Magnitude")
-	plt.xlabel("Frequency (Mhz)")
-	plt.ylabel("Power (dB)")
+    plt.figure(1)
+    plt.title("Magnitude")
+    plt.xlabel("Frequency (Mhz)")
+    plt.ylabel("Power (dB)")
 
-	plt.plot((freq / 10**6), (10*np.log10(i**2 + q**2)))
+    plt.plot((freq / 10 ** 6), (10 * np.log10(i ** 2 + q ** 2)))
 
-	plt.show()
+    plt.show()
diff --git a/submm/demo/find_res_and_fit.py b/submm/demo/find_res_and_fit.py
index 2cc30a1..3572a58 100644
--- a/submm/demo/find_res_and_fit.py
+++ b/submm/demo/find_res_and_fit.py
@@ -1,22 +1,22 @@
 import os
 import time
+
 import numpy as np
-import matplotlib.pyplot as plt
 from scipy.io import loadmat
-from submm.KIDs import resonance_fitting as res_fit
+
 from submm.KIDs import find_resonances_interactive as find_kids
 from submm.sample_data.abs_paths import abs_path_sample_data
-from submm.KIDs import res_sweep_tools as res_sweep_tools
+from submm.KIDs.res.sweep_tools import InteractivePlot
+from submm.KIDs.res.fitting import fit_nonlinear_iq_multi, fit_linear_mag_multi
 
-linear = False # if resonators are well below bifurcation fitting can be much faster
+linear = False  # if resonators are well below bifurcation fitting can be much faster
 
-
-#load the sample data
+# load the sample data
 data_path = os.path.join(abs_path_sample_data,
                          "Survey_Tbb20.000K_Tbath170mK_Pow-60dBm_array_temp_sweep_long.mat")
 sample_data = loadmat(data_path)
 
-#recast the data
+# recast the data
 freq_ghz = sample_data['f'][:, 0]
 freq_mhz = freq_ghz * 1.0e3
 freq_hz = freq_ghz * 1.0e9
@@ -27,40 +27,39 @@
 # 1st filter
 # 2nd find peaks
 # 3rd manual correction
-ip = find_kids.find_vna_sweep(freq_hz,s21_complex)
+ip = find_kids.find_vna_sweep(freq_hz, s21_complex)
 
-#slice up the vna with a span equal to to q_slice where q = f/delta_f
-res_freq_array,res_array = find_kids.slice_vna(freq_hz,s21_complex,ip.kid_idx,q_slice = 2000,flag_collided = False)
+# slice up the vna with a span equal to to q_slice where q = f/delta_f
+res_freq_array, res_array = find_kids.slice_vna(freq_hz, s21_complex, ip.kid_idx, q_slice=2000, flag_collided=False)
 
 # fit the resonators
 t1 = time.time()
 if not linear:
-    fits = res_fit.fit_nonlinear_iq_multi(res_freq_array.T,res_array.T,tau = 97*10**-9)
+    res_set = fit_nonlinear_iq_multi(res_freq_array.T, res_array.T, tau=97 * 10 ** -9)
 else:
-    fits = res_fit.fit_linear_mag_multi(res_freq_array.T,res_array.T)
+    res_set = fit_linear_mag_multi(res_freq_array.T, res_array.T)
 t2 = time.time()
-print("time to fit {:.2f} s".format(t2-t1))
+print("time to fit {:.2f} s".format(t2 - t1))
 
 # stack fit data with Qi and Qc skip second f0
 if not linear:
-    fit_data = np.vstack((fits['fits'][:,:-1].T,fits['Qi'],fits['Qc'])).T
-    fit_data[:,0] = fit_data[:,0]/10**6
-    fit_data[:,7] = fit_data[:,7]*10**9
-    data_names = ["Resonator Frequencies (MHz)","Qr","amp","phi","a","i0","q0","tau (ns)","Qi","Qc"]
+    fit_data = np.vstack((fits['fits'][:, :-1].T, fits['Qi'], fits['Qc'])).T
+    fit_data[:, 0] = fit_data[:, 0] / 10 ** 6
+    fit_data[:, 7] = fit_data[:, 7] * 10 ** 9
+    data_names = ["Resonator Frequencies (MHz)", "Qr", "amp", "phi", "a", "i0", "q0", "tau (ns)", "Qi", "Qc"]
 else:
-    fit_data = np.vstack((fits['fits'][:,:].T,fits['Qi'],fits['Qc'])).T
-    fit_data[:,0] = fit_data[:,0]/10**6
-    data_names = ["Resonator Frequencies (MHz)","Qr","amp","phi","b0","Qi","Qc"]
+    fit_data = np.vstack((fits['fits'][:, :].T, fits['Qi'], fits['Qc'])).T
+    fit_data[:, 0] = fit_data[:, 0] / 10 ** 6
+    data_names = ["Resonator Frequencies (MHz)", "Qr", "amp", "phi", "b0", "Qi", "Qc"]
 
 # stack the data with fit data
-multi_sweep_freqs = np.dstack((np.expand_dims(res_freq_array.T,axis = 2),np.expand_dims(res_freq_array.T,axis = 2)))
-multi_sweep_z = np.dstack((np.expand_dims(res_array.T,axis = 2),np.expand_dims(fits['fit_results'],axis = 2)))
-
-ip2 = res_sweep_tools.interactive_plot(multi_sweep_freqs,multi_sweep_z,retune = False,combined_data = fit_data,
-                                           combined_data_names = data_names,
-                                           sweep_labels = ['Data','Fit'])
+multi_sweep_freqs = np.dstack((np.expand_dims(res_freq_array.T, axis=2), np.expand_dims(res_freq_array.T, axis=2)))
+multi_sweep_z = np.dstack((np.expand_dims(res_array.T, axis=2), np.expand_dims(fits['fit_results'], axis=2)))
 
-#below is example of retuning resontors
+ip2 = InteractivePlot(multi_sweep_freqs, multi_sweep_z, retune=False, combined_data=fit_data,
+                      combined_data_names=data_names,
+                      sweep_labels=['Data', 'Fit'])
 
-#ip2 = res_sweep_tools.interactive_plot(res_freq_array.T,res_array.T,retune = True,find_min = False)
+# below is example of retuning resonators
 
+# ip2 = res_sweep_tools.InteractivePlot(res_freq_array.T,res_array.T,retune = True,find_min = False)
diff --git a/submm/demo/res_fit.ipynb b/submm/demo/res_fit.ipynb
index 55d1622..c2b893d 100644
--- a/submm/demo/res_fit.ipynb
+++ b/submm/demo/res_fit.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 200,
+   "execution_count": 1,
    "metadata": {
     "pycharm": {
      "name": "#%%\n"
@@ -36,7 +36,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 201,
+   "execution_count": 2,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -67,7 +67,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 202,
+   "execution_count": 3,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -99,7 +99,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 203,
+   "execution_count": 4,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -112,24 +112,18 @@
    "outputs": [
     {
      "data": {
-      "text/plain": [
-       "Text(0, 0.5, 'Magnitude (dB)')"
-      ]
+      "text/plain": "Text(0, 0.5, 'Magnitude (dB)')"
      },
-     "execution_count": 203,
+     "execution_count": 4,
      "metadata": {},
      "output_type": "execute_result"
     },
     {
      "data": {
-      "image/png": "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czX9wvJyHLZ8OXJK+I00EVFjYiZoPgnA7wCcp/1+G8BFCAXMY1zJFRmyUspf3KULBt9zD8pGjHAxR5QU38pklCA170dERN4w0+TcLgC3av/ibXc8R+SK8gkT/M4CERERUdoy0+RcVwA3AOgFoCA8XCnVxcV8EREREREFhpn2rR4GcA+AWoSqY8wG8JibmSLKOOxghoiIKK2ZCZoLlVKvABCl1Hql1J8ATHE3W0REREREwWHmQ8A9IpIFYK2InA1gI4Bid7NFRERERBQcZkqazwXQBMDvAQwC8H8ATnQzU0REREREQWKm9Yyl2p/bAZzsbnbIEOvGpic2OUdERJTWdINmEXk+2YxKqcOdzw6Z5kMQ1v2CC9Bq2DDPl0tERETkt2QlzcMBfAXgXwDeA8CisiDxocS521lneb5MIiIioiBIFjS3BXAogBkAfgVgPoB/KaU+8SJjpIOv+YmIiIg8p/shoFKqTin1glLqRADDAKwD8JrWggYRERERUaOR9ENAEclHqE3mGQAqAdwB4Bn3s0VEREREFBzJPgScDaAPgAUAZimlPvYsV0QZIq+0FOWTJ6PLSSf5nRUiIiJKQbKS5hMA7EConebfy/66tAJAKaWaupw3orQnWVkYfOedfmeDiIiIUqQbNCulzHR8Ql5jO81EREREnmNgnK7YigYRERGRZxg0ExEREREZYNBMRERERGSAQTMRERERkQEGzUREREREBhg0ExEREREZYNBMRERERGSAQXO6YTvNRERERJ5j0ExEREREZIBBc7phpyZEREREnmPQTERERERkgEEzEREREZGBHL8zQETWjFm0CLu++cbvbBARETUqDJqJ0kxx584o7tzZ72wQERE1KgyaiYgyXNuJE/3OAhFR2mPQnG7YTjMRWTTk7rv9zgIRUdrjh4BERERERAYYNBMRERERGWDQTERERERkwLWgWUQ6ishiEflURD4RkXO14X8SkY0iskL7N9mtPBAREREROcHNDwFrAVyolFomIiUAPhCRl7VxtymlbnFx2UREREREjnEtaFZKfQvgW+3vbSKyCkB7t5ZHREREROQWT+o0i0glgAEA3tMGnS0iH4nI30WkhRd5ICIiIiKyy/WgWUSKAfwHwHlKqa0A7gFQBaA/QiXRt+rMd7qIvC8i7//4449uZzNtNO/XDwCQU1Tkc06IiIiIGg9Xg2YRyUUoYH5cKfU0ACilvldK1Sml6gE8AGBoonmVUvcrpQYrpQaXlZW5mc200u+GG3DwM8+goHVrv7NCRERE1Gi42XqGAHgIwCql1F+ihpdHTXYkgI/dykMmyi4oQPMDDvA7G0RERESNiputZ4wE8H8AVorICm3Y5QBmiEh/AArAlwDOcDEPREREREQpc7P1jLcASIJRC9xaJhERERGRG9gjIBERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAQbNREREREQGGDQTERERERlg0ExEREREZIBBMxERERGRAdeCZhHpKCKLReRTEflERM7VhpeKyMsislb7v4VbeSAiIiIicoKbJc21AC5USvUCMAzAWSLSC8ClAF5RSnUF8Ir2m4iIiIgosFwLmpVS3yqllml/bwOwCkB7AEcAeFSb7FEA093KAxERERGREzyp0ywilQAGAHgPQBul1LfaqO8AtPEiD0REREREdrkeNItIMYD/ADhPKbU1epxSSgFQOvOdLiLvi8j7P/74o9vZJCIiIiLS5WrQLCK5CAXMjyulntYGfy8i5dr4cgA/JJpXKXW/UmqwUmpwWVmZm9kkIiIiIkrKzdYzBMBDAFYppf4SNep5ACdqf58I4Dm38kBERERE5IQcF9MeCeD/AKwUkRXasMsB/BnAkyJyKoD1AI5xMQ9ERERERClzLWhWSr0FQHRGj3NruURERERETmOPgEREREREBhg0p5E248f7nQUiIiKiRsnNOs3koMNWrEB2QYHf2SAiIiJqlBg0p4nckhK/s0BE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\n",
-      "text/plain": [
-       "<Figure size 864x360 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
+      "text/plain": "<Figure size 1200x500 with 1 Axes>",
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+QAAAHACAYAAAAr/6IYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAACSsUlEQVR4nO3dd3gU1foH8O9uek9IIAWSEJIQSgiEHqT3KggqAgoIiiiC7VrwZ7lWsKJeAfWKoPeiXEFRKYIUKSJIEQRFWgBB6b0nIZnfH5B1N9tmdmfmzG6+n+fxkczOnnl3dnbmvHPOnGOSJEkCEREREREREenKLDoAIiIiIiIiosqICTkRERERERGRAEzIiYiIiIiIiARgQk5EREREREQkABNyIiIiIiIiIgGYkBMREREREREJwISciIiIiIiISAAm5EREREREREQCBIoOQGtlZWU4dOgQoqKiYDKZRIdDREREREREfk6SJJw/fx4pKSkwm523g/t9Qn7o0CGkpqaKDoOIiIiIiIgqmYMHD6JGjRpOX/f7hDwqKgrAtR0RHR0tOBoiIiIiIiLyd+fOnUNqaqolH3XG7xPy8m7q0dHRTMiJiIiIiIhIN+4em+agbkREREREREQCMCEnIiIiIiIiEoAJOREREREREZEATMiJiIiIiIiIBGBCTkRERERERCQAE3IiIiIiIiIiAZiQExEREREREQnAhJyIiIiIiIhIACbkRERERERERAIwISciIiIiIiISgAk5ERERERERkQBMyImIiIiIiIgEYEJOREREREREJECg6ACIiIiIiIiIJEnCpT/+wPJOnVyu127BAkTXqaNTVNpiQk5ERERERES6k8rK8MMtt+DMli2K3reyVy/0KSzUJiidMSEnIiIiIiIiXZQWFWFhvXqiwzAMJuRERERERESkmSvHj2NJy5Yevz+6bl3U6N8fJpMJ4WlpSHLTpd2XMCEnIiIiIiIi1R1asACbxo2Tta45OBjdNm1CYHi4xlEZCxNyIiIiIiLye5IkwWQyiQ7D70mShPlZWbLWbfP114jNzdU4ImNjQk5ERERERH5jXmam09e6b94Mc0gISs6eRWi1apAkCQCYqKvg4h9/YHnHjm7X671rF0wBATpE5BuYkBMRERERkV8oOnHC5euL8vMdLg9LSUHmqFFIu+UWBISG4tiqVYisVQvhNWpoEaZf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gVdffRXBwcH44IMPUKtWLS1iJCIiIiIiIvI7ihPyp556ChcvXgQAPP/88+jduzfatGmD+Ph4/O9//1M9QCK9SGwJJSIiIiIiHSlOyLt162b5d1ZWFnbs2IFTp04hLi6OI2GTBZNb0hyPMSIiIiLycR7PQ26tSpUqahRDREREREREVGnITshHjBgha72PPvrI42CIiGRjjxwicdhDhYiISBWyE/IZM2YgPT0d+fn57I5Mbvni4wtBkZGiQyAiIiIiokpEdkJ+77334rPPPsO+fftw55134vbbb2dXdfILeS++iCvHjyOqdm3RoRARERERUSUiex7yyZMn4/Dhw3jssccwb948pKam4tZbb8XixYvZYk4+LX3QIOSMGyc6DCIiIiIiqmRkJ+QAEBISgkGDBmHJkiXYvn076tevj/vuuw81a9bEhQsXtIqRiIiIjMQHH0siIiIyIkUJuc0bzWaYTCZIkoTS0lI1YyIiMg4mHkRERESkEUUJeVFRET777DN06dIFtWvXxrZt2/Duu+/iwIEDiOSAWERERERERESyyR7U7b777sOsWbOQmpqKESNG4LPPPkNCQoKWsRERiccxMoiIiIhII7IT8vfeew9paWmoVasWVq5ciZUrVzpc78svv1QtOPJR7OJLOgiMiBAdAhERERGRV2Qn5EOHDvXJuaWJyL80nDABB+bMQe0HHhAdChERERGRV2Qn5DNmzNAwDPI3nAqPtJJ2661Iu/VW0WEQEREREXnN41HWiYiIqJLiTVciIiJVMCEnIiIiIiIiEoAJOREREREREZEATMiJiIhIGQ7ySkREpAom5EREREREREQCMCEnTXCKPCIiIiIiIteYkBMREREREREJwISciIiIiIiISAAm5KQ+zk9LRERERETkFhNyIiIiIiIiIgGYkBMREREREREJwIScNCGx2zoRkf/iOZ6IiEgVTMhJfZzyjIiIiIiIyC0m5ERERKQMb7wSERGpggk5ERERERERkQBMyImIiIiIiIgEYEJOREREREREJAATciIiIiIiIiIBmJATEbkQmZEhOgQiIiIi8lOBogMgIjKyek8+CVNgIGr07y86FCIiIiLyM0zIiYhcCI6NRcOXXxYdBhERERH5IXZZJ02YOEctERERERGRS0zIiYiISJbETp0AABnDh4sNhIiIyE+wyzppQpIk0SEQEZHKmr33HopPn0ZIfLzoUIiIiPwCW8iJiIhIFpPZzGSciIhIRUzIiYiIiIiIiARgQk5EREREREQkABNyIiIiIiIiIgGYkJP6OOUZERERERGRW0zIiYiIiIiIiAQQmpBPmDABzZo1Q1RUFKpVq4Z+/fph586dNuu0b98eJpPJ5r/Ro0cLipiIiIiIiIhIHUIT8pUrV2LMmDFYt24dlixZgpKSEnTt2hUXL160We/uu+/G4cOHLf+9+uqrgiImIiIiIiIiUkegyI0vWrTI5u8ZM2agWrVq2LRpE9q2bWtZHh4ejqSkJL3DIyIiIiIiItKMoZ4hP3v2LACgSpUqNstnzpyJhIQE5ObmYvz48bh06ZLTMoqKinDu3Dmb/4iIiIiIiIiMRmgLubWysjI8+OCDuOGGG5Cbm2tZPnjwYKSnpyMlJQVbt27F448/jp07d+LLL790WM6ECRPw3HPP6RU2ERERERERkUcMk5CPGTMGv/76K3744Qeb5aNGjbL8u0GDBkhOTkanTp1QWFiIzMxMu3LGjx+Phx9+2PL3uXPnkJqaql3g5FBcfj4OzJolOgwiIiIiIiLDMkRCfv/992P+/PlYtWoVatSo4XLdFi1aAAD27NnjMCEPCQlBSEiIJnGSTJKE1P79AUlCXOPGoqMhIiIiIiIyJKEJuSRJGDt2LObOnYsVK1YgIyPD7Xu2bNkCAEhOTtY4OvKGyWxG2i23iA6DiIiIiIjIsIQm5GPGjMGnn36Kr7/+GlFRUThy5AgAICYmBmFhYSgsLMSnn36Knj17Ij4+Hlu3bsVDDz2Etm3bIi8vT2ToRERERERERF4RmpBPnToVANC+fXub5dOnT8fw4cMRHByMpUuX4q233sLFixeRmpqKAQMG4KmnnhIQLREREREREZF6hHdZdyU1NRUrV67UKRoiIiIiIiIi/RhqHnIiIiIiIiKiyoIJOREREREREZEATMhJfSaT6AiIiIiIiIgMjwk5ERERERERkQBMyImIiIiIiIgEYEJOREREREREJAATciIiIiIiIiIBmJATERERERERCcCEnIiIiIiIiEgAJuREREREREREAjAhJyIiIiIiIhKACTkRERERERGRAEzIiYiIiIiIiARgQk5EREREREQkABNyIiIiIiIiIgGYkBMREREREREJwISciIiIiIiISAAm5EREREREREQCMCEn1ZlMJtEhEBERERERGR4TciIiIiIiIiIBmJATERERERERCcCEnIiIiIiIiEgAJuREREREREREAjAhJ9VJkiQ6BCIiIiIiIsNjQk5EREREREQkABNyIiIiIiIiIgGYkBMREREREREJwISciIiIiIiISAAm5EREREREREQCMCEnIiIiIiIiEoAJOREREREREZEATMiJiIiIiIiIBGBCTkRERERERCQAE3JSnclkEh0CERERERGR4TEhJyIiIiIiIhKACTkRERERERGRAEzIiYiIiIiIiARgQk5EREREREQkABNyIiIiIiIiIgGYkBMREREREREJwISciIiIiIiISAAm5EREREREREQCMCEnIiIiIiIiEoAJOREREREREZEATMiJiIiIiIiIBGBCTkRERERERCQAE3IiIiIiIiIiAZiQExEREREREQnAhJyIiIiIiIhIACbkpD6TSXQEREREREREhseEnIiIiIiIiEgAJuSkPkkSHQEREREREZHhMSEnIiIiIiIiEoAJOREREREREZEATMiJiIiIiIiIBGBCTkRERERERCQAE3IiIiIiIiIiAZiQExEREREREQnAhJyIiIiIiIhIACbkRERERERERAIwISciIiIiIiISgAk5ERERERERkQBMyImIiIiIiIgEYEJOREREREREJAATclKfySQ6AiIiIiIiIsNjQk5EREREREQkgNCEfMKECWjWrBmioqJQrVo19OvXDzt37rRZ58qVKxgzZgzi4+MRGRmJAQMG4OjRo4IiJiIiIiIiIlKH0IR85cqVGDNmDNatW4clS5agpKQEXbt2xcWLFy3rPPTQQ5g3bx5mz56NlStX4tChQ+jfv7/AqImIiIiIiIi8Fyhy44sWLbL5e8aMGahWrRo2bdqEtm3b4uzZs5g2bRo+/fRTdOzYEQAwffp01K1bF+vWrUPLli1FhE1ERERERETkNUM9Q3727FkAQJUqVQAAmzZtQklJCTp37mxZp06dOkhLS8PatWsdllFUVIRz587Z/EdERERERERkNIZJyMvKyvDggw/ihhtuQG5uLgDgyJEjCA4ORmxsrM26iYmJOHLkiMNyJkyYgJiYGMt/qampWodOREREREREpJhhEvIxY8bg119/xaxZs7wqZ/z48Th79qzlv4MHD6oUIREREREREZF6hD5DXu7+++/H/PnzsWrVKtSoUcOyPCkpCcXFxThz5oxNK/nRo0eRlJTksKyQkBCEhIRoHTIRERERERGRV4S2kEuShPvvvx9z587F8uXLkZGRYfN6kyZNEBQUhGXLllmW7dy5EwcOHEBBQYHe4RIRERERERGpRmgL+ZgxY/Dpp5/i66+/RlRUlOW58JiYGISFhSEmJgYjR47Eww8/jCpVqiA6Ohpjx45FQUEBR1gnIiIiIiIinyY0IZ86dSoAoH379jbLp0+fjuHDhwMAJk2aBLPZjAEDBqCoqAjdunXDlClTdI6UiIiIiIiISF1CE3JJktyuExoaismTJ2Py5Mk6RERERERERESkD8OMsk5ERERERERUmTAhJyIiIiIiIhKACTmpJiwlBQCQ3K2b4EiIiIiIiIiMzxDzkJN/aP/ddyg6fhwRaWmiQyEiIiIiIjI8JuSkmsCwMAQyGSciIiIiIpKFXdaJiIiIiIiIBGBCTkRERERERCQAE3IiIiIiIiIiAZiQExEREREREQnAhJyIiIiIiIhIACbkRERERERERAIwISciIiIiIiISgAk5ERERERERkQBMyImIiIiIiIgEYEJOREREREREJAATciIiIiIiIiIBmJATERERERERCcCEnIiIiIiIiEgAJuREREREREREAgSKDkBrkiQBAM6dOyc4EiIiIiIiIqoMyvPP8nzUGb9PyM+fPw8ASE1NFRwJERERERERVSbnz59HTEyM09dNkruU3ceVlZXh0KFDiIqKgslkEh2OS+fOnUNqaioOHjyI6Oho0eGQD+AxQ0rweCGleMyQEjxeSCkeM6SErx0vkiTh/PnzSElJgdns/Elxv28hN5vNqFGjhugwFImOjvaJg4yMg8cMKcHjhZTiMUNK8HghpXjMkBK+dLy4ahkvx0HdiIiIiIiIiARgQk5EREREREQkABNyAwkJCcGzzz6LkJAQ0aGQj+AxQ0rweCGleMyQEjxeSCkeM6SEvx4vfj+oGxEREREREZERsYWciIiIiIiISAAm5EREREREREQCMCEnIiIiIiIiEoAJOREREREREZEATMg1NnXqVOTl5VkmsC8oKMC3335ref3KlSsYM2YM4uPjERkZiQEDBuDo0aM2ZRw4cAC9evVCeHg4qlWrhkcffRRXr17V+6OQTtwdM+3bt4fJZLL5b/To0TZl8JipvCZOnAiTyYQHH3zQsoznGXLG0fHCcwxZ++c//2l3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I6T09HQpODhYqlq1qtSpUydLMi5JknT58mXpvvvuk+Li4qTw8HDppptukg4fPmxTxv79+6UePXpIYWFhUkJCgvTII49IJSUlen8U0omrY+bAgQNS27ZtpSpVqkghISFSVlaW9Oijj0pnz561KYPHTOVWMSHneYZcsT5eeI6higYOHCglJydLwcHBUvXq1aWBAwdKe/bssbzO8wtV5OqY4TmGHJk3b56Um5srhYSESHXq1JE++OADm9fLysqkp59+WkpMTJRCQkKkTp06STt37rRZ5+TJk9KgQYOkyMhIKTo6Wrrzzjul8+fP6/kxPGaSJEkS3UpPREREREREVNnwGXIiIiIiIiIiAZiQExEREREREQnAhJyIiIiIiIhIACbkRERERERERAIwISciIiIiIiISgAk5ERERERERkQBMyImIiIiIiIgEYEJOREREuiguLkZWVhZ+/PFHoXEsWrQIjRo1QllZmdA4iIiImJATERF5YPjw4TCZTHb/7dmzR3RohvXee+8hIyMDrVq1siwr32/r1q2zWbeoqAjx8fEwmUxYsWKFzfpfffWVXdnDhw9Hv379ZMXRvXt3BAUFYebMmZ58DCIiItUwISciIvJQ9+7dcfjwYZv/MjIy7NYrLi4WEJ2xSJKEd999FyNHjrR7LTU1FdOnT7dZNnfuXERGRmoWz/Dhw/HOO+9oVj4REZEcTMiJiIg8FBISgqSkJJv/AgIC0L59e9x///148MEHkZCQgG7dugEAfv31V/To0QORkZFITEzEHXfcgRMnTljKu3jxIoYOHYrIyEgkJyfjjTfeQPv27fHggw9a1nHUQhwbG4sZM2ZY/j548CBuvfVWxMbGokqVKujbty/2799veb28Nfn1119HcnIy4uPjMWbMGJSUlFjWKSoqwuOPP47U1FSEhIQgKysL06ZNgyRJyMrKwuuvv24Tw5YtW1z2ENi0aRMKCwvRq1cvu9eGDRuGWbNm4fLly5ZlH330EYYNG+Z037uyf/9+h70X2rdvb1mnT58+2LhxIwoLCz3aBhERkRqYkBMREWng448/RnBwMNasWYP33nsPZ86cQceOHZGfn4+NGzdi0aJFOHr0KG699VbLex599FGsXLkSX3/9Nb777jusWLECP//8s6LtlpSUoFu3boiKisLq1auxZs0aREZGonv37jYt9d9//z0KCwvx/fff4+OPP8aMGTNskvqhQ4fis88+wzvvvIPff/8d77//PiIjI2EymTBixAi7Fu3p06ejbdu2yMrKchjX6tWrUbt2bURFRdm91qRJE9SsWRNffPEFAODAgQNYtWoV7rjjDkWfvVxqaqpNr4XNmzcjPj4ebdu2tayTlpaGxMRErF692qNtEBERqSFQdABERES+av78+Tbdqnv06IHZs2cDALKzs/Hqq69aXnvxxReRn5+Pl19+2bLso48+QmpqKnbt2oWUlBRMmzYN//3vf9GpUycA15L6GjVqKIrpf//7H8rKyvDhhx/CZDIBuJYsx8bGYsWKFejatSsAIC4uDu+++y4CAgJQp04d9OrVC8uWLcPdd9+NXbt24fPPP8eSJUvQuXNnAECtWrUs2xg+fDieeeYZrF+/Hs2bN0dJSQk+/fRTu1Zza3/88QdSUlKcvj5ixAh89NFHuP322zFjxgz07NkTVatWdbjuoEGDEBAQYLOsqKjI0voeEBCApKQkAMCVK1fQr18/FBQU4J///KfNe1JSUvDHH384jYmIiEhrTMiJiIg81KFDB0ydOtXyd0REhOXfTZo0sVn3l19+wffff+/wuejCwkJcvnwZxcXFaNGihWV5lSpVkJOToyimX375BXv27LFrib5y5YpN9+z69evbJLXJycnYtm0bgGvdzwMCAtCuXTuH20hJSUGvXr3w0UcfoXnz5pg3bx6Kiopwyy23OI3r8uXLCA0Ndfr67bffjieeeAJ79+7FjBkzXD7fPWnSJMuNgnKPP/44SktL7dYdMWIEzp8/jyVLlsBstu0YGBYWhkuXLjndDhERkdaYkBMREXkoIiLCaRdt6+QcAC5cuIA+ffrglVdesVs3OTlZ9ujsJpMJkiTZLLN+9vvChQto0qSJwxHErVucg4KC7MotnwYsLCzMbRx33XUX7rjjDkyaNAnTp0/HwIEDER4e7nT9hIQES8LvSHx8PHr37o2RI0fiypUr6NGjB86fP+9w3aSkJLv9HhUVhTNnztgse/HFF7F48WKsX7/eYVf5U6dOOW2FJyIi0gOfISciItJB48aN8dtvv6FmzZrIysqy+S8iIgKZmZkICgrCTz/9ZHnP6dOnsWvXLptyqlatisOHD1v+3r17t00rb+PGjbF7925Uq1bNbjsxMTGyYm3QoAHKysqwcuVKp+v07NkTERERmDp1KhYtWoQRI0a4LDM/Px87duywu5lgbcSIEVixYgWGDh1q1yVdqS+++ALPP/88Pv/8c2RmZtq9Xt5jID8/36vtEBEReYMJORERkQ7GjBmDU6dOYdCgQdiwYQMKCwuxePFi3HnnnSgtLUVkZCRGjhyJRx99FMuXL8evv/6K4cOH23Wz7tixI959911s3rwZGzduxOjRo21au4cMGYKEhAT07dsXq1evxr59+7BixQqMGzcOf/75p6xYa9asiWHDhmHEiBH46quvLGV8/vnnlnUCAgIwfPhwjB8/HtnZ2SgoKHBZZocOHXDhwgX89ttvTtfp3r07jh8/jueff15WnM78+uuvGDp0KB5//HHUr18fR44cwZEjR3Dq1CnLOuvWrUNISIjbuImIiLTEhJyIiEgHKSkpWLNmDUpLS9G1a1c0aNAADz74IGJjYy1J92uvvYY2bdqgT58+6Ny5M1q3bm33LPobb7yB1NRUtGnTBoMHD8Y//vEPm67i4eHhWLVqFdLS0tC/f3/UrVvX0g08OjpadrxTp07FzTffjPvuuw916tTB3XffjYsXL9qsM3LkSBQXF+POO+90W158fDxuuukmh13py5lMJiQkJCA4OFh2nI5s3LgRly5dwosvvojk5GTLf/3797es89lnn2HIkCEuu9kTERFpzSS56jtGREREQrVv3x6NGjXCW2+9JToUO6tXr0anTp1w8OBBJCYmul1/69at6NKlCwoLCx0ObqeXEydOICcnBxs3bkRGRoawOIiIiNhCTkRERIoUFRXhzz//xD//+U/ccsstspJxAMjLy8Mrr7yCffv2aRyha/v378eUKVOYjBMRkXAcZZ2IiIgU+eyzzzBy5Eg0atQIn3zyiaL3Dh8+XJugFGjatCmaNm0qOgwiIiJ2WSciIiIiIiISgV3WiYiIiIiIiARgQk5EREREREQkABNyIiIiIiIiIgGYkBMREREREREJwISciIiIiIiISAAm5EREREREREQCMCEnIiIiIiIiEoAJOREREREREZEATMiJiIiIiIiIBPh/hE3GX1mK9eEAAAAASUVORK5CYII=\n"
      },
+     "metadata": {},
      "output_type": "display_data"
     }
    ],
@@ -153,7 +147,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 204,
+   "execution_count": 5,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -166,24 +160,18 @@
    "outputs": [
     {
      "data": {
-      "text/plain": [
-       "[<matplotlib.lines.Line2D at 0x147e3bc40>]"
-      ]
+      "text/plain": "[<matplotlib.lines.Line2D at 0x177a6b8d9f0>]"
      },
-     "execution_count": 204,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     },
     {
      "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 432x288 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
+      "text/plain": "<Figure size 640x480 with 1 Axes>",
+      "image/png": "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UVhYiI0bN+LYsWO46667cNttt+HEiRMAmu/UrlQq8eabb0KSJFRVVeE///kPJk2a1O7AA+DIBxERkVsyH/koKyvDkCFDUFZWhgEDBhjWmzRpEn7zm9/gxRdfBADs27cPM2fOxE8//QRJkhAXF4edO3eiV69e7f7eHPkgIiIiFBcXQ5IkDB8+HP7+/obHvn378N133wEAzp8/jz/84Q+YN28eDh48iH379sHLywtpaWmwZSzDo7veBBEREbmOK1euQKVS4fDhw1CpVCbP+fv7AwBeffVVBAYG4u9//7vhuXfffRfh4eH4/PPPERsb267vxeCDiIiIcNNNN0GSJFRWViIhIcHiOrW1tYZEU5kcqOj1+nZ/L067EBERuYkrV66gqKgIRUVFAJpLZ4uKilBWVobhw4fjnnvuwdy5c6HVanHq1Cl88cUXyMrKwo4dOwAA06ZNw8GDB/HCCy/gxIkTOHLkCB544AEMGjQIN910U7v3gwmnREREbiI/Px9JSUktls+bNw9vvfUWGhsb8be//Q3vvPMOzp49i759+yI2NhZLly5FdHQ0AGDjxo34+9//jtLSUvj5+SEuLg4vvfQSbrzxxnbvB4MPIiIisitOuxAREZFdMfggIiIiu2LwQURERHbF4IOIiIjsisEHERER2RWDDyIiIrIrBh9ERERkVww+iIiIyK4YfBAREZFdMfggIiIiu2LwQURERHbF4IOIiIjs6v8D6D4aAtTOOGMAAAAASUVORK5CYII=\n"
      },
+     "metadata": {},
      "output_type": "display_data"
     }
    ],
@@ -211,7 +199,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 205,
+   "execution_count": 6,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -230,7 +218,7 @@
       "default initial guess used\n",
       "Resonator at 312.72 MHz\n",
       "     |                             Variables fit                           \u001B[1;30;42m|Derived variables|\u001B[0;0m\n",
-      "     | fr (MHz)|   Q    | amp | phi  | a   |   i0     |   q0     | tau (ns)\u001B[1;30;42m|   Qi   |   Qc   |\u001B[0;0m\n",
+      "     | fr (MHz)|   Qr   | amp | phi  | a   |   i0     |   q0     | tau (ns)\u001B[1;30;42m|   Qi   |   Qc   |\u001B[0;0m\n",
       "Guess| 312.7237|   21755| 0.61|  0.00| 0.00|  6.44E+01| -3.83E+01|   3.00  \u001B[1;30;42m|   55254|   35882|\u001B[0;0m\n",
       "Fit  | 312.7256|   21268| 0.60| -0.14| 0.10|  6.38E+01| -3.90E+01|  73.75  \u001B[1;30;42m|   53681|   35224|\u001B[0;0m\n"
      ]
@@ -254,7 +242,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 206,
+   "execution_count": 7,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -267,24 +255,18 @@
    "outputs": [
     {
      "data": {
-      "text/plain": [
-       "<matplotlib.legend.Legend at 0x148268dc0>"
-      ]
+      "text/plain": "<matplotlib.legend.Legend at 0x177a99f8dc0>"
      },
-     "execution_count": 206,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     },
     {
      "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 432x288 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
+      "text/plain": "<Figure size 640x480 with 1 Axes>",
+      "image/png": "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aMGll17qeey7776jV69eBAYGEhUVxahRo7yuFf7h1QjQTRU/KxW9AxX1sn2TAOs0Ceb9998nJCSEP//8kz///NPrMUVRuPvuu+sluMagpg1Tdd0o6lqsqgRTzJPndZMJMA2Jswj+46elKY8ehPKZbnXw6aefcu+997Jy5UpWrFjB5MmTGTJkCKNHj6527qpVqzjttNP4448/6NGjh2fT2aoKCwu599576d27NwUFBUydOpWLLrqIpKQkzw7yR5OUlMSWLVuYMWPGEc+vPFHuWHbt2sXYsWN59tln+eijjzh06BB33nknd955Jx9//DGrV6/m7rvv5vPPP2fw4MFkZWWxZMkSwOgCnjhxIi+88AIXXXQR+fn5LFmyRErENQCnJUYSHmQhp8gJqOi6gqLoKIrbk/jMpvLE2IATYHJycn3H0ahV3TBV1ywAFCkKJkVnbBe7nyMUTUXv3r09G1J36tSJt956i/nz59eYAMt3f4+KiiIu7sh1FS+55BKv+x999BExMTFs3ryZnj17HjOm7du3A9ClSxfPsYyMDNq3b++5/8ILL3D77bcf87kAnnvuOa688kr+9a9/Acb7fOONNzjzzDOZPn06KSkpBAcHc9555xEaGkrbtm09O96npqbicrm4+OKLadu2LYCnbrFoSBSjFai4au4CbcgtQFHd2J7xjO4ex6rkLBbsy2fmXqMFCEBp/gl96xf1zBJktMT89donoLwrsVx8fDwZGRkn9Jw7duxg6tSprFy5ksOHD3vW9aakpNQqAdYkKirKM/lm+PDh1fYMPZr169ezYcMGvvzyS88xXdfRNI3k5GRGjx5N27Ztad++PWPHjmXs2LFcdNFFBAUF0adPH8466yx69erF2WefzZgxY7j00kuJiIio0/sQ9WdVclZZ66+MbgK8E2CpWwdT9WtPllonwHvvvZdnnnmG4OBg7r333qOe+8orr5xwYI2RSVUY1CEKl62VkQBNZX+9pfk+qWwuaklRGu0XEovF4nVfUZRqhSiO1/jx42nbti0ffPABLVu2RNM0evbsWeuk1alTJwC2bdvmaYmZTCY6duwIGLu9lyvvIq3cJel0VvpQBAoKCrjllltqHEpp06YNVquVtWvXsmjRIubOncvUqVN56qmn+PvvvwkPD2fevHksX76cuXPn8uabb/LYY4+xcuVKz5io8I+0XO9F77pu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ueQS1q5dy5gxY7jwwgs98w5E4zOgbQQKeD4jKxKg8eWuvZoKQIoeS3qh22dx1XkdYElJCRs2bCAjI8PTGix3/vnnn3BgR5OVlcWXX37J4MGDPV0vK1asYNiwYV5dOWeffTbPP/882dnZRETU3P1YWlpKaWlF87y8ss3xWJWc5dnksZyuGd+eD5UlwHYlW1mVnMWgDlHVrhe+pShKvXdDnizBwcGe5FRfoqOj6dixIx07duTbb7+lV69enHLKKXTv3p2CggLi4+NZtGhRtevCw8MBY5xv0qRJ/Prrr/z22288+eSTzJw5k4suughVVauNczqdzuOOcdy4cezdu5fZs2czb948zjrrLO644w5eeumlurxl4Wdr9mZXNBAUB2rZJBjNaXwuJyrGIvk9ely11uLJVKcEOGfOHK655hoOHz5c7TFFUTw7QtS3hx56iLfeeouioiIGDhzIL7/84nksLS2NxMREr/NbtGjheexICfC5555j2rRpJxRX1Sm+UPHNJtNs/LP3UXexu4bzhKgPVqu1Tv/vEhISuPzyy3nkkUf46aef6N+/P2lpaZjN5qN2O3bu3JnOnTszZcoUJk6cyMcff8xFF11ETEwMaWlp6LrumYyTlJRUp9hjYmK49tprufbaaznjjDN44IEHJAE2UpU/I1WLsdxBdweAZnwRbVeWAA+aWjExMdJncdVpFuhdd93FhAkTSE1NRdM0r9vx/Cd8+OGHa1znVPlWedulBx54gHXr1jF37lxMJhPXXHPNCc86feSRR8jNzfXc9u3bd9zPUdM3FndJKwBKrIVkqypdlX3E+WaLK9EMtWvXjsWLF3PgwIEav5gezT333MOsWbNYvXo1o0aNYtCgQVx44YXMnTuXPXv2sHz5ch577DFWr15NcXExd955J4sWLWLv3r0sW7aMv//+m27dugHGjNRDhw7xwgsvsGvXLt5+++1jLrFo164dK1euZM+ePRw+fBhN05g6dSo//fQTO3fuZNOmTfzyyy+e1xCNz57DRZ6fFWsmAJqjojcsUTG6QFt26OnTYaI6JcD09HTuvfdeTwurru677z62bNly1Fv79u0950dHR9O5c2dGjx7NzJkzmT17tmcJRlxcnGdnispxlj92JDabjbCwMK/b8TotMZJ4e4D3TF8tEHdpDADLrBFYFDenBOw/7ucWojaefvpp9uzZQ4cOHYiJiTmua7t3786YMWOYOnUqiqIwe/Zshg0bxnXXXUfnzp254oor2Lt3Ly1atMBkMpGZmck111xD586dueyyyxg3bpynF6Vbt2688847vP322/Tp04dVq1Zx//33H/X177//fkwmE927dycmJoaUlBSsViuPPPIIvXv3ZtiwYZhMJmbOnFnnvx/hP25N5+NlyZ77qsWY7ak5K1p67csS4JmDBvk0NkWvQxPq+uuvZ8iQIdxwww0nI6ZaSUlJoW3btixcuJDhw4czffp0HnvsMdLT0z3jgo8++ig//PBDjZv3HkleXh52u53c3NzjSobls0ChYqA3oOXXWOzrODsziJfytsLZz8Gg22v9nKJ+lJSUkJycTGJiIgEBvhtfEA2f/G6cfK//sYNX/9juuW9r8TPWyOWUHj4Tx6Fx2HCwyXY9ZkWDKZvB3uqEXu94PsPrNAb41ltvMWHCBJYsWUKvXr2qrQG6++676/K0R7Ry5Ur+/vtvhg4dSkREBLt27eKJJ56gQ4cODCr7xjBp0iSmTZvGDTfcwEMPPcTGjRt5/fXXefXVV+s1liMZ2zOe6Vf196wDBHAXt8ZiX8fhmDDIAw6s8UksQgjREFRt/UFFC1AvawF2UvZjVjRKrRHYfLgIHuqYAGfMmMHcuXMJCAhg0aJFXpUnFEWp9wQYFBTEDz/8wJNPPklhYSHx8fGMHTuWxx9/3LNWyW63M3fuXO644w4GDBhAdHQ0U6dO9ckawHJje8Yzunscq5KzyMgvoYAw/m/9LJJNBeiAIglQCNGMrErOIqfYexawYvXuAu2u7gWgOLI7tmNUMapvdUqAjz32GNOmTePhhx/2Wg94svTq1YsFCxYc87zevXuzZMmSkx7P0ZhUxbPUodQdzUv/mMlyFnDQbKJVdjIUZUGQ72Y5CSGEv1SfIe9GrTIJprtiJMCwxP6+DA2o4yQYh8PB5Zdf7pPk15jZTDa6RHQB4J+oNsZBaQUKIZqJqjPkVethFMWN7rahl60BLG8BEtfL1+HVLQFee+21fP311/UdS5PUM7onABvtZTNmJQH6TdWCDULI78TJdVpiJJHBFXNE1ABjvZ9W2gJQUNDopqQAsMHVxufx1akL1O1288ILL/D777/Tu3fvapNgXnnllXoJrinoGd2Tr7d9zcbyv2lJgD5ntVpRVZWDBw8SExOD1Wo95o4JomnTdR2Hw8GhQ4dQVdWrgpSoPyZV4YI+Lfl4udHKU21GAnSXGkvTEpU0QpViSnQLP+8PpO8A38ZXpwT4zz//0K9fPwA2btxYrwE1Nb2ijWb95tLDuADzgTWg6yAfwD6jqiqJiYmkpqZy8OBBf4cjGpCgoCDatGkjwzknUeuIirKDJlt5C9BIgANUY3nEer0D361L57Hxuk8XwtcpAS5cuLC+42iy2oW1I9gSTKGzkN0BQXQuyoScvRDRzt+hNStWq5U2bdrgcrlOWqk+0biYTCbMZrP0Bpxk+3MqtrFSqyTA/soOANZqnchzuHxeL/m4EmBt9vpTFIXvv/++zgE1NSbVRI+oHqxKW8XGmHZ03rcZ9q+WBOgHiqJgsVjqvHedEOL4uDWdH9cdMO6oJahWow6ou9SYE1HeAlytdQZqrqt8Mh1XArTb7ScrjiatZ3RPVqWt4p+QcC4GOLAWel3q77CEEOKkemvBTrKLjHWAprJSkJojEtzB2Cmgs2okx7WasaekL3eCgONMgB9//PHJiqNJ88wEVcoWhMpEGCFEEzdnY6pXCTRToLHRgLu4NQD9VKP7c5cWTzZhxNsDOM2HO0FAHZdBiONTPhFmR8khihUFUteD+/j3SBNCiMbArek89fMmr2NqeQIsSQDgVHUbAOt0o/X35PjuPt8wXBKgD7QIakF0YDRuXWNbcAS4iiFji7/DEkKIk2JVchZpeaWVjuieFqBWbCTAIaqxgmCFuzvvTOrH2J7xvg5TEqAvKIri6Qb9J6atcfDAaj9GJIQQJ0/VySyKORfVnI+uq7hLWhFGAb0Vo0h2q/7jOKe3b4tgl5ME6CPl3aD/BAYbB2QcUAjRRFWdzGIKMhbCayXxoFsYrG5GVXR2aK04vU9Pf4QISAL0Gc9EGK3QOHBgrR+jEUKIk+e0xEjCAyvmWJqCdgPgLkoEYKj6DwBLtZ5ox78lbb2RBOgjPaJ6ALCvNJMcVTXGAEvz/RyVEELUP5OqMLjSgnZz0C4AXEXtARhaNv63VOvJyuRM3wdYRhKgj9htdtqEGuN/a0LjAB33gXX+DUoIIU4SHWNGp2LOQ7UdRtcV3EWJJCjptFPTcekqK7VugP8q8UgC9JE5G1M5mB4NwC+6sQ3IzC8/ZM7GVH+GJYQQ9c6t6axMNja+Le/+1EpaghbICDUJgDV6ZwoI8mnps6okAfrAnI2p3PbFWgryjJlOa2zGRJjRrj+584u/JQkKIZqUVclZZBU6ADCVdX+6izoAkKAcQtMVFrj7EWIzMbC9/xJgnYphi9pzazrTZm1GB9xl61+yAvLJ1EOIVXIYqv7DtFnBjO4e5/NFoEIIcTL8vqniS7052GgBugqN8b9/u67iHdf5aKhcPjDBr5970gI8yVYlZ5Gaa6yJ0Urj0XUTirmQj02nAHCJaTGpuSWsKusuEEKIxmz2hlQ+XWEse1AsmajWTGP9X3E7zznZhJFLCCO7tvBTlAZJgCeZ14JQ3YK7wCj787+QUADGqGsIo9DnVdCFEKK+zdmYyu1fraV8ZYM5ZCsA7qJ2oNVQ6NrPnV6SAE+yqgtCnblGyy8nLJktWitsipNzTCt9XgVdCCHqU/lwT2XlCdBV0LXGaw4XlNZ43FckAZ5kpyVGEm8P8HzRceV3RXMFoVryeMdmVIeZaF3q8yroQghRnyoP9wCglFYsgD9CAvT3F39JgCeZSVV4cnx3oLy1b8aV1xeAJWEabl2hj74VU/Zuf4UohBAnLC232Ou+OXgniupGc0SiOWKqnR8RZPH7F39JgD4wtmc806/qT5zd+LbjzB0AgDt0B3vjBhknrZ/pr/CEEOKELdt52Ou+KcTY7sjo/qw+2Hdxv1Z+n/kuCdBHxvaMZ+lDI5lx00BeueAcWgd1AMXN3116Gyesnwma5t8ghRCiDtyazuyNaZWPYA419gN0FXSr8ZpR3eN8ENnRSQL0IZOqMKhDFBf2a83E7hcD8FPRXrCFQW4K7F3m5wiFEOL4/bUrkyKH23PfFJSMai5EcwXhLlv/V5k/dn+viSRAPzm3/bmYFTP/ZG5iV9fRxsH1M/wblBBC1MGK3d7dn+YwY7cHV34PwFTtfH/s/l4TSYB+EhUYxdDWQwH4yW7UBmXzT+Ao9GNUQghx/Nxa5S2N3JhDjd0eXPm9vM6zqPDuVf39svt7TSQB+tGFHS4EYNbhtbgi2oKjALb84t+ghBDiOOUWOz0/l3d/6q4g3IUdvM67dEBCg0l+IAnQr4a1HkaELYLDxYdZ3vlM4+D6r/wblBBCHKeNB3I9P5d3fzoLulO1+9PfC9+rkgToRxaThXPbnwvAT+ayb1C7/4Tc/X6MSgghas+t6WxOzTPuKC4soWXjf3m9q50bbGtY+y9IAvSzCzpeAMDCtFXkth0I6LDha/8GJYQQtbR852FcZSu4zCFbUcxFaM4w3IUdq517Sf/WPo7u6CQB+lnXyK50ieiCU3Myu7VRMYakGXiqyQohRAP21KyNnp8t9jUAOHP7UTW9qMDgjtE+jOzYJAE2ABd2vBCAn4r3gzkQMnfAgTX+DUoIIY5h9oZUdh0qAkAx5VdUfymrdlVZYnRQg1j6UJkkwAbgnPbnYFbMbMreyrbOZwGQPP8DVuzKrDK9WAghGga3pvPg9xs89832JBRFw12cgOaIrXZ+r9bhPoyudiQBNgCRAZEMaz0MgCkZRjWFiN2zuPaDJQx9fgFzNqYe7XIhhPC5v3ZlUlDq8tz3dH/mVG/9QcMb/wNJgA1GgtVIgHsD97JPjyRcKWSkuo603BJu+2KtJEEhRIPy+V/Jnp/VgP2YAtLQNRPOGmZ/BljUBjf+B5IAGwS3pvPdklA0VzCquYA3A4zqCbeYf0HH6AKdNmuzdIcKIRqE2RtSmbMpw3PfGrECKKv8ogVVO/+VCX0a3PgfSAJsEFYlZ5GW68SV2w+A30OsFOk2+qk7OVtdjQ6k5pawKjnLv4EKIZq9ORtTuf2rtRUHTIWYw9YD4MgeVO38c3rGck7vlr4K77hIAmwAMvKNXZQr9gncydu6USD7AfPXmHB7nSeEEP7g1nQe/uEfr2MW+xoU1YW7JB6tuE21a64cmOir8I6bJMAGIDbU2ChXK43HXdISRXHzWXA8WXoIHdWDXGJa7HWeEEL4w1sLdpJT5Kx0RMMasRIAZ/Ygatr4tqGVP6tMEmADcFpiJPH2ABTAmXMqAFrUCl53jwdgivl72oUpDWL/LCFE8+TWdD5elux1zBS8A9Waie4OwJnbt8brGvIXd0mADYBJVXhyvFEFxpVzKpojAtWSxzf2AA7o0cQrWbzbZW2DHEQWQjQPq5KzyCl2eh0rn/zizB0AurXaNSE2U4P+4i4JsIEY2zOe6Vf1Jy4shNJDZwNgilrKOzZj5/iuOz6A4hw/RiiEaM7Scou97qvWdMyhW9F1BUdW9ckvABMGtG7QX9wlATYgY3vGs/ShkXx62c20DOyEYioleGQ4xHaHkhxY9pqfIxRCNEdzNqbyzK9bvI5Zo4y5Ca787ujOmtf4jenRcPb+q4kkwAbGpCoM6RjD02c8BMC3278jZcjtxoN/vQt5siBeCOE7czamctsXa8kqdHiOKeY8zPYkAByZZ9Z4Xbw9oEF3f4IkwAbr9PjTGdpqKC7dxevZSZAwEFzF8Of/+Ts0IUQz4dZ0ps3aTNUSHJaI5SiKG1dRO7SS6ksfAJ4c371Bd3+CJMAGbcqAKSgozN07lw2nXWscXPs5HN7h38CEEM3CquQsUnOrrD9WS7FG/AWAI3NYjded1i6CsT0bdvcnSAJs0DpHdPZsmPvKgbnoncaC7oYFz/g5MiFEc1BT8Q1L+EoUUwnu0hjcBV1rvO6ukZ1Odmj1QhJgA3dH3zuwmWysSV/Dn73PAxTY/JPsFyiEOOmig23eBxSHZ/KL0fqrnkIaauHrmkgCbODiguO4qttVALy66ztcva8wHvjjKdk1XghxUv29x7v+sCV8Faq5AM0RiSu3f43XNNTC1zWRBNgI3NDrBsJt4ezO3c2P7fuDyQrJi2HXAn+HJoRootyazifL91QcUJxYo/8EwJE5HDBVu2Z877gGW/i6JpIAG4FQayi39L4FgLe3z6DolOuMB/54CjTNf4EJIZqsqpVfjNZfPpojHGdO9dafCrx2Rc2twoZKEmAjcVmXy2gV0orDxYf5PCYebGGQtgE2/eDv0IQQTZDXBBjFiTWqvPU3AjBXO79nq7BG0/VZThJgI2E1Wbmn/z0AfLRtJpmn32Q8sOBZcDmOcqUQQhy/ykWsFbUUd1F7NEeEZ9u2qq4Z1M5HkdUfSYCNyNntzqZHVA+KXEVMt2k4AqIhO5ndc9+R3eKFEPWqfJcaAN0dQsnBKyjcPQX06q0/gFYR1XeCb+gkATYiqqJy74B7Afh6x/94sOQsAMJWvsz4//uBORulTJoQon5U3qXGo4YdH6BxlD2riSTARiYrMwFXQRdQNOZG5bFFSyBayeP+4je47Ys1kgSFEPVmbM943r2qP+FBlhofV8pujaHsWU0kATYi5XX5SjPGoesKprBN3Ga6lFLdwkhTEleb5jFt1mbpDhVC1JuxPeNZ8/hopozqTHigdyKMswcw/ar+jaLsWU1q7swVDVJFXb44nLkDsIavJj12Nf/eP5GnLZ/xqPlLVuR1Z1VyXwZ1iPJ3uEKIJsKkKtwzqhN3juzIquQsMvJLiA01uj0bY8uvnLQAG5HK05Idh0ajaxbMQXuZERrOIncfAhQnb1je4nBOnh+jFEI0VSZVYVCHKC7o24pBHaIadfIDSYCNSuVpybrLTumhMQDYWvzCveolHNbD6KamMGDnG/4KUQghGg1JgI1I+bTk8u9czqwhuAo6o6guSlrO4n7XDQC03PIR7Jzvv0CFEKIRaHQJsLS0lL59+6IoCklJSV6PbdiwgTPOOIOAgAASEhJ44YUX/BPkSVJ5WrKRBFVKDk5Ac4VgCkhnRfQB9naYZJz8421QmOmvUIUQosFrdAnwwQcfpGXL6sVW8/LyGDNmDG3btmXNmjW8+OKLPPXUU7z//vt+iPLkGdsznulX9SfOs0A1lJKDlwFgjfyLnUPOh+guUJAOP98lO0YIIcQRNKpZoL/99htz587l+++/57fffvN67Msvv8ThcPDRRx9htVrp0aMHSUlJvPLKK9x8881HfM7S0lJKS0s99/PyGv4EkrE94xndPa7SbKyBLM1y89nmT3ly1b/pce7zxH1xGWz7FdZ8DKdc7++QhRCiwWk0LcD09HRuuukmPv/8c4KCqpfcWbFiBcOGDcNqrahUcPbZZ7Nt2zays7OP+LzPPfccdrvdc0tISDgp8de3qrOx/tX/HrpHdSe3NJdHtn2Ge+QTxolzHoVD2/0brBBCNECNIgHqus7kyZO59dZbOeWUU2o8Jy0tjRYtWngdK7+flpZ2xOd+5JFHyM3N9dz27dtXf4H7kMVk4YVhLxBoDmR1+mo+DLZC+xHgKobvb5CC2UIIUYVfE+DDDz+MoihHvW3dupU333yT/Px8HnnkkXqPwWazERYW5nVrrNqGteXxgY8DMH3Du6w7404IjDS2TVr4rJ+jE0KIhsWvY4D33XcfkydPPuo57du3Z8GCBaxYsQKbzeb12CmnnMKVV17Jp59+SlxcHOnp6V6Pl9+Pi4ur17gbsvHtx7P84HJ+3f0rD615ge/OeYGw72+EZW9Ah7Og/Zn+DlEIIRoERdcb/jTBlJQUr8kpBw8e5Oyzz+a7777j9NNPp3Xr1kyfPp3HHnuM9PR0LBajXt2jjz7KDz/8wNatW2v9Wnl5edjtdnJzcxtta7DAUcCEWRPYX7CfMW3H8FKeE2XtpxDaEm5bBkGNr2q7EELUxvF8hjeKMcA2bdrQs2dPz61z584AdOjQgdatWwMwadIkrFYrN9xwA5s2beLrr7/m9ddf59577/Vn6H4RYg3h+WHPY1bMzN07l/91GgRRnSD/IMy6R5ZGCCEEjSQB1obdbmfu3LkkJyczYMAA7rvvPqZOnXrUJRBNWe+Y3tzZ704A/m/tq+w4+yk01QJbfmbX77KBrhBCNIouUF9qCl2g5TRd45Z5t/BX6l+ozpZM2NOWx81f49BNPGB9jHEXTGq025gIIURNmlwXqKgbVVEZHXMPuisYzXKQz6MUfnYPwqq4+Y/jed758jvZQFcI0WxJAmzC3JrOq3PSKU6dAIA1cjkP2kawxN2TYKWUj6wv8N+f/pDuUCFEsyQJsAkr30DXXdAVR9YQAMwtv+NW9Uo2aIlEK3m8XDqNdZtqP0tWCCGaCkmATVjlDXRLM8bhLmqDYiqBhC+YrN/MHq0FbdRDdJp3LZTk+jFSIYTwPUmATVjlDXTRzRTtm4y7pAWqJZ/SNt9wlXYXh3Q79rxtMPNKcJYc+cmEEKKJkQTYhFXdQBctiOJ916M5IlCtmWQl/MIU24Po1lDYswT+dzNobn+GLIQQPiMJsAmrvoEu6C47RSk3lG2ie5D8LitwXPYJmKyw+Sf47UFZKC9EU3FwHfx0J7id/o6kQZIE2MRV3UAXQHdGE5x1KwFqELsLNvBAys+4LpoOKPD3h7D4Rf8FLISoH+mb4fOLYN3n8OcL/o6mQZKF8FU0pYXwlbk1vdIGugGclhjJ2ozV3DrvVhyagws7XsjT5gSU3x4wLjjvNTjlOr/GLISoo8M74eNxUJgBrQbANT+BLdTfUfmELIQX1VTdQNekKpwadyovnvkiqqLy484fedVUAMPKEuCv98KWX/wbtBDi+GXvhc/ON5Jfi15w1ffNJvkdL0mAzdzINiN5atBTAHy86WM+iomH/teArsF318OeZf4NUIhmzq3pLNt5mJd+38ZLv29l2Y7DRy5ekZdqJL+8AxDdGa7+HwRG+DbgRkS6QKtoql2gx/LJxk94ec3LADw98EkuWvsDbPsVlyWUxUM/J7B1b05LjMSkKsd4JiFEfZm9IZUHv99AQanL63iI1cwLl/bmnN6Vavnmp8Gn4+HwdohoB9f9BmEtfRtwAyBdoOK4Te45met6GmN+T618hpdbjidJ6YbZmU+PBZN55MP/MfT5BVI7VAgfeW72Zm7/am215AdQ4HBx+1dreW72ZuNA7n5jzO/wdghrBdf83CyT3/GSBCg8pvSfwsWdLkbTNT7e/QJXKxexVUughZLD99aniMvbyG1frJUkKMRJNnvDQd5bnHyERzXPT+8tTmbhilVG8svaDeFt4LrZENHWN4E2cpIAhYeiKDx62uOYinuhqC701t8ySb2e9Vp7opR8vrI+y0h1LdNmbZYC2kKcJG5N54Hv1tf4mCVyCYEJn4BitArbKal0nXMF5KRARCJMnm10f4pakQQovKzdm0fO3stwFbZHMZVSmvANE9XrWejuQ6Di4H3Ly5xZMJtVyVn+DlWIJun1edspdGhVjupYo+YT0OJXzCHbMYduoKOyn6+tzxCvZFIU1sEY8wtP8EvMjZUkQOElI78EdAvF+6/BXdwK1VyI2vYTbrGO5xvXmZgUnf+zfEjEqhelYowQ9ey52Zt5Y+HOKkd1rDG/Y4udB0DpodH0yg/mO+s0Wig5bNUS+KTTmxAmm1sfL0mAwoungLYWQFHKTbgKOqKoDqwJX/BYSD9ed10EQNdt0+FnKbEkRH1wazqvzdtWw7ifhq3FLGzRiwAoST+XM7LC+cr6HOFKIeu0jkx0PEaRNdrnMTcFkgCFF68C2loAxfsm48zpj6JoBMT/wDvh4TxnvgVdUWHdFzBzEjgK/R22EI3WnI2pDH5uPq/Nr9ry07DF/Yg1cjkAJakXcmGum/csrxKoOFjg7sskx6NkE8agDlG+D7wJkAQovFQvoG2mJHUCpYdGAmCNmc/2vm5cEz4DcyDsmAufnAcFh/wWsxCN1ZyNqdz6xVrS80u9H1CcBLT6EmvEKnRdofjgpdySn8qLlvcxKxrfuoZxs/NeigkgPNDMwPaSAOtCEqCopnoBbQXH4THYci5HRWV15lzuPPALBVd+A4GRcHAt/Hc0ZO7ya9xCNCYOl8bdM9ZVf0AtIrDNh1jCNqFrJlwHLuP5or+53/ItAG+7zucB1y24MAPwf5f0lgIVdSSVYKporpVgalJTAe1lB5dw/5/3U+wqpmtkV97u9wCx390IOXshKBomfQOtB/g7dCEatDkbU/nX10mUOL1neyrmHALbfITJloHuDsC8/xI+cH3Pqep2XLrKU65r+cI9GoBgq8rLl/VlbE+Z/FLZ8XyGSwKsQhLgsW06vInb599OVkkW8cHxTB/8LB1mPQCpSWAJggmfQOez/R2mEA3SL0kHuHNmUrXjqu0ggQmfoFry0Jx2YveN4zP9YxLUQ+TpQdzuvIelWi8AQmxm1j4xGqtZOvGqklJo4qTqEd2DL875gnZh7UgtTOXqP//F3+c8Ax1HgbMIZkyEtZ/5O0whGhS3pnP7F6trTH7m0I0EtXsX1ZKHu6QF/VOG8jNvkqAeYo/Wgosc0zzJD+ClCb0l+dUDaQFWIS3A2sspyeGuBXeRdCgJi2rhuo4PcsGW32iT8qNxQv9rYez/gTXIr3EK4U9uTeetBTt4c8FOXNUqKOlYoxZii51rnFvQkRvSA7lP/RWAlVpXbnFMIQdjOyMFeHtSP87pLXU+j0S6QE+AJMDjU+Iq4bpfp7AxZ6lxP/0cbs9L5x7zj6joEN0FLv0I4nr6OVIhfKs88b375y6KnVUru2DM9Iz/DovdKHumZJ3CG1nbGG7aBMDHrrP5t+tKz2QXgHcm9ffeAUJUI12gwmcWbc3mrxXn4MgaAkBAi9m8F+tmkus+0vVwOLwNPhgJK9+XyjGi2ZizMZUBz87j1T921Jj8FHMuQW3fw2Jfj66rRKcO5becPxlu2kSRbuNux51Mc13rSX7hQRbevUqSX32TFmAV0gKsPbemM/T5BaTmlgBgiViKrcVsFEVDc0RiPTCet9TZDNHWGBd0HgcXvA3BsmZJNF1zNqZy2xdrOdIHqyl4BwEtZ6KaC9FdQYxI7chLzjnYFBe7tThudU5hu27U9OzTOowHz+7GwA5RstShlqQFKHxiVXKWJ/kBOLOHUrT3FjRHOKo1C2e7z7kucAC7BjwBJits/w3eHQLJi/0YtRAnj1vTmTZr8xGSn4Y1ej6BCR+hmgtRSlrw5H4zb7p+waa4+N19Chc4nvUkvxuGtuOnO89gSKdoSX4niSRAUWcZ+SXVjmnFbSlMvgdnXm8URcMWO4f7HBs4dPV3EN0Z8lPh0/Nh/tNSR1Q0KW5N55NlyV5fCj1MhQQmfIItZh6KohOZ05HfUrczQd9IiW7hced13OKcQj7GhLGbzkjkifN6+PgdND/mY58iRM08hbOr0gIpOTARd0EnbHE/s6tgHZf89QTPnvcfhm342VgiseRloyV4yYeyf5lo9OZsTOWpnzeTllc9+ZmCdhHQ8htUSy66ZmFURgteK14AwDatNXc57/K0+gDeuqIf5/WVWZ6+IGOAVcgYYO2VjwGm5ZbU2OWjALFRubTu8gPbs7cBcFW3q5gSkIj11/uhNBdsYWjnvsrK4BFeFWeky0c0FrM3HOT2r2ooaYYLa8wfWKP+RFF0LKV2/i8jizGuAwB87hrFs66rKMXquUKS34mTZRAnQBLg8Skf8Ae8kmB5+pp+VX9GdIvktTWv8cWWLwDoGtmVF/r+i8Tfn4L9qwD4xnUmT7qupZgA4u0BPDm+u5R4Eg3e7A2p3P7V2mrHFeshAlt+jSlwPwBdc6P4KGsDobg5pNt5xHkjf2jeJQNvGZbII+d090ncTZkkwBMgCfD4zdmYyrRZm73GPmpKYn/u+5Mnlj1Bdmk2geZAxre8Bfv8P7nT9DOqopOsteAp12QWa30AI3lKEhQNTXmN3D82p/HfZXuqPKphiViJLXY2iupEddv416ESriveB8BP7sE86bzWs7AdINhq4sVL+8gSh3oiCfAESAKsm5oKZ9fUjZlRlMGjSx5lZdpKAJy5vel5qCtvqh8Rr2QBMNc9gGdcV+MKa8PSh0ZKd6hoMGZvOMjjP20kq7D6BC7FcpiA+O8xBxub2iYUBfHhoZ201Fxk6qE85ryBOdppXtf866xO3HVWJ/kdr0eSAE+AJMCTz625mbb4bX7Y818URUN3B0LGCO4sSOEG0+9YFDcluoXprvMZfM0znN6llb9DFoLnZm+uYcd2AA1L5DJsMXONVp9m4tasIm7JT0fFaPU97byaTOyeK6Sb/+SRBHgCJAH6xk9JB5jy4ywC4n/AFJAKgLu4NTHpg/iPaw5DyspBFQa1Jvj8F6HLOFDkW7LwjyON9anWDALiv8MUlAJApyIzr2fuJcHlZo/Wgidc17FE6+05v09rOw+P6yYTvU4iSYAnQBKgb6zYlcnED/4C3Fgi/jK+PZtK0XUFZ86pDDsczTTTN7Qs6xal42gY9zxEdfBr3KL5cGs6y3ce5vu1+/l5/UG86lgrDqzRC7BGLUFR3FjcKvdlZTOpIBenbuJd93jedl3oNcPTZlbZ/PRYSXwnmSTAEyAJ0DeqLqFQTPnYYmdjCTemk+uuIELzx7Kku4L5r7dAcxrVZAbfBWfcB9Zg/74B0WSVF7F+Z+FOSt3Vd28wh27C1mIWqiUXgNOKXDx7OJ14t5u/tG485ryeXXr1bvt3ZVKXT0gCPAGSAH2npiUUpsDd2OJ+whSQDkDv6N481vUaui1/D2XXfABKg+Ixn/Mcph4XSreoOCHlk7fS8krIKihlf3YR36zZT2Gpu9q5iuUwAXE/Yw7ZDkC0E57IOsSIomIO6NH8xzmJ2drpVCwCMsh4n29JAjwBkgB9q6YlFHF2CyNP2878tM8pchWhoGAuGEyf1CieVr8mQT0EwOHYQURf+H/Qsq+foheNWU2/ezVSi7BFL8QSsRxFdWPS4frcXG7KyUPTrLztupD/usd5dXcCDO8czS1ndpTxPh+TBHgCJAH63pGWUGQUZXDfH8+SlL0QAM0VjHZoBDcWHuRO9VdsStlU9E5jYNiDkHCqH9+FaCzKuzhf/WPH0U9UXFgiVmCLXoBiKgZgUFExj2Zmk+B08717GC+6LuMQEdUuvemMRB47Vxa1+4MkwBMgCbDhKB8nzHBuNLpFbUbLT3PaCc48hQcLtnGR6S9MlO23lngmnPkgtBvqx6hFQ3a0mp0VNMyhG7HFzkG1GpOwOjic3J+VzZDiEn5zn8YrrkvZqbeudmWIzcwLl/SWRe1+JAnwBEgCbDgqZooCuLBErMQatQjVkg+A5ggnNHMA37fMo9Wen0BzAaC3GcSWTreyI+QUYsMCpQtKAEbyu/WL6ksZKhgTXKzRf2AKSAMgyuXmruwcLigoZJm7Ny+5LuMfvX21K4OsJm4Z1oE7R3aU3zU/O57PcNkNQjRY3tstmXFmD8GZcxqW8JVYo/9EteZQGD+fKywt+Nf5z3H+vk2Y1n2JmrKC7ikrKNU68qbrQu4NGcST5/eQSQjNmFvTefiHf47wqI4pZAu2mD8wBRwEIFjTuCY3n8m5eWx0d+ZK52Ws1LtVuzI80MJ1QxIl8TVS0gKsQlqADYd3C7AKxVmWCBehmgsAiLC2oGhPX24t3MtVpoUElI0RbtLa8pbrIi6YeDNje0lVmeakfHz5sxV7+G1jWpVHNUwh27BF/4Ep0NihIUjTuDIvn2tz89ng7M5brotYqXel6szOkV1juOmMDtK70ABJF+gJkATYcNRmu6UW4Sq3nneITzZ9RGZJJgCaIxLr4YHcWJjCZNN8gpVSAHYpCSSecy9qr0txW0NrVbtUNB5VJ1NlF5byzK9bapjl6cJsT8IWtRjVlgFAoKYxqSzxrXb24y3XBazXO9b4Ojed0Y7HzpXNahsqSYAnQBJgw1Kb7ZbG9oxn0fYD3PTjG1ijFntahJorBFNObybm53GHvpAwxZjJ5zIF8ps+mP8Wn0mS3gFQZK1WI1P7ZFeJWoIlfCWBkUvQLcbvSLCmcVleARNzilngHMpH7rE1LmIv9+bEfozvI/v1NWSSAE+AJMCGpzbbLf2UdIB7ZiaB4sAS8RfWyCWeyTK6rqLkd2J4roWppo3ElKZ4nmeLlsAM90h+dA8ln2DZgqkRqPX6vTKqLQ1r+Aps4WvQVGOiVKzLxZV5+ZyZa+IH5xi+co8kmyP/f5cvSI2HJMATIAmwYTrWdkvVxwvdmEM3YYn4C3Pw7orDzhhisxK5ofAgl/C3Zy1hiW7hV20gcwPG8s7Dt2MyqT56Z6K2ar1+DwAX5tBNhEYuxhV0wHO0g8PBtbn5ROW24Vv3WczRTsN5hLmAUcFWLujbktHd46SLvBGRBHgCJAE2TkcbL1St6VgiVmANXweqMR6oa1aU3J6clWviVvcquqr7POcX2TsSNPB66HUZhMT48F2II6nd+j1jd4ZQ+19YwldTanYAYNJ1RhYVc06ui92Fg5jpPovdevVuzLgwGy9P6MvhwlIZF27EJAGeAEmAjdexxguvGhzLzC0/YYlYgals8gOAu7glsfmtmVSYxlX63wSVTZrRFZX8mFPYGzsSR6dz6durl3wg+kDl1n50iI1VyZm8Pn/nEc9XTIUEh60mzL6C/MAcz/Fol5uL8wtIyGnDAscwftdOrVaurDIpVt00SAI8AZIAG7ejjRfaA61l3aQ6pqDdRvdo6CYURfOcqxclcEtsAucd2EBi1mav596mJKJ2G0+nMydCbDcpxH2CqnZrD2gbwfRFO/l42R5yiqvvuO5FcRIZspao8KUcCj6Eu+yfwqTrDC0uoU9eMPvzhjDbPYRDhB/9qRR4e2I/zuktk1uaAkmAJ0ASYON3pPHCmrpJFVMB5tCNmMPWYwrag6IYj+i6grkwgb4FAVxdvJ/h+jZMSqX/KpHtodt46DoeWg3AjXLE16zNcovantdU1PRFRVHgqJ9GSimtQv8iIvRv0kMOU1JpmLZbqYNB+SaceX353TH8qDM5q3pnUn8pXdaESAI8AZIAm7ajdZMq5lwuH57F7OTf0KwVM0V13YRa2JYuRVYuLk7jIm0LAVS0UEoCYljo6M7C0s6s1LqxV29BvD2Q8/vE8/P61KPOXi2P6VizXBuL2iTy8n+D2nzwtDClkBi6FC10B7uDiiit9FyxLhen5FtRcnvxd8mw40p60Hj/jsXRSQI8AZIAm77adJMqlkwsYRuMlmGAdwUR3RHO2RHtONdVwIBdK7E7C70eT9MjWKl14y+tGyu1buzW4ykfiay6fvFIyaDqeQ1V5YS353AhM1alkJZX6nm8/O91dPc4z757z/yyiazCmrs47eTSM2gZwSEbSQ/JZLfNO3m2crroWhBMaX5vVheO4BCRxx3z9UPayczOJkwS4AmQBNg8HKml4llPWIlqTccUshVzyA5MgckoaqXNUnWV4OJouheZGV2SyXhHMiGKy+v6DD2cVVpX/tK68Y+WyHY9gXC7nT8fGMGZLy484no2BYizB7D0oZF+/aA+0t9VbdbjKRgt7fAgCzlF3klPRaOTkkL7wHUEBm0nJyiTrQGQX2UJSmKJQkRhLHn5A9hcfDql2Or0PqTF1zxIAjwBkgCbt6PWHwVQSjEF7+ac03LZnP03GSUHvB7WNTPBJRF0KFUZWprDBaUptNJKvc5x6wrJejxqXE++OxDBZr0tm7W2ZBBO1ZqTADNuGsigDlH18O6OX01JLjLYSr8EO/O3Hqr18wRRQidlP11Mu4gI3I47MI39AYWsD7RSoHonvGC3TquiMNwFXdiVfwb57hbHHXe8PYAnzu1ORLC12YyrCoMkwBMgCbB5q0390fJW2S8bDvKv7//AHLIDc/B2TIF7UcxF1a6xOEJIKLHSr7SIQa7DDHDmEOXWqqW6w3oYW7Q27NJbsk+PZZ8ewz49lnFDT6dtq7hqH+I1tcyAE5pMU7VLs3aLzsveJy7ilUxaK4dIVNJoq+7DErCfooAs9ge42GS1ssdiRq8yezbADbElYWiF7Ugt7E9OSSfAdMzXiwuzMfW8HkQEW0nLKyGroJTIYCtxdtkCqzmTBHgCJAGK2tYfrd5a1FGshzEFppTd9qLa0j0zSyszuax0NIcSnlNCX2c+Ax2HaOd21pgYAbL1EPbpMRw2x5HYsRultii+3VJMclEAOXoIWYTiDoikgCCyiyu6aCt3+x0rYdY0hgc6ATgIpYhoJY9oJZdoco0/lVyilRxCzIfRrFnkWYrZYzWzx2Ih2WLhoNlULdkBhDgtBJREU1zUgcNFfXCVtAKOr/LOlFGdZQsiUSNJgCdAEqCA2s3MPFZrEQC1BFPAPkxBKai2g5hs6SjWzBqTIoCqqYS5LMQ4IcHloKOrkI7uIqLdbqLcbiLcGnZNO2K6cOkqOYRQrNsoxeK5RdnDOFigk+cy4ULFhI7NpGPGjeZ2o6JhQsOmOAmmhBClmFCKUJVScsyQZTJxyGQizWwm1WwitezPPRZLtS7MymwuG+biFhSVJFJY3B6tpBW6O6QW/wI1k3E8cSySAE+AJEBR7nim9AO1mtavAChOHr8oitioHObuSOKPXetRrekoltwjJkav59AhyK0S5ga7phGquQnTnYTqLoI0nUBdI0DXMenG66noqHpFC9ahKDgVBYcCTkWhVFEoVFUKFIUCVaVAVclXVbJMKsVHSW4eOpidYWiOGEpK49EcMWilMWiOGHR3aC3+VmoWHmRh8qB2nNouUsqTiVprkgmwXbt27N271+vYc889x8MPP+y5v2HDBu644w7+/vtvYmJiuOuuu3jwwQeP63UkAYrjdaTW4vGvAyxEseSgWrJRLNmoZTfFmo1qKkAxF6CYarcDQn3SNTO6KwTdHYrmDEd3hqM57eiucCPROaNAr7mg9PG6c0RHOrUIkWQn6ux4PsPr57fWR55++mluuukmz/3Q0Ipvl3l5eYwZM4ZRo0bx7rvv8s8//3D99dcTHh7OzTff7I9wRTMxtme8Z51b1dbig2O7HbMVWfX6Hen5vLVw1xFezY1iLkQxFaCYClFMRaA6UMpuqA4UxQGqExQNBR3Kb54qN2YjYekmdK38zwDQAtDdNnQtwLi5QozuSs1KTbNTayMiyEJ20THKmlUypGO032a8iuanUSXA0NBQ4uLianzsyy+/xOFw8NFHH2G1WunRowdJSUm88sorkgDFSWdSlRo/uI90/GjnrdiVeZQEaEJ3haG7GmbvRLw9gCtObUO76CBPwp+3Oe2YOzmUz64tn5gjhC80qi7QkpISnE4nbdq0YdKkSUyZMgWz2cjh11xzDXl5efz444+eaxYuXMjIkSPJysoiIiKixuctLS2ltLRi1lteXh4JCQnSBSr8plaTaxqI8oXux6qucrS9/BpL1RvROBxPF2ij2fXz7rvvZubMmSxcuJBbbrmF//znP17je2lpabRo4b1gtvx+Wpp3KavKnnvuOex2u+eWkJBwct6AELVkUhWeHN8dqN7xqBzh5yM50RE0pew2ZVRnbhjSjshgi9fjcfYA3r2qP1PH92BQh6gjjtmZVIV7RnXm3av68//t3W1MU9cfB/BvWcsVhQHDQqsoKZEVlcEQFtKxhTgYm9kL2YwjiyYQl0ylZIqaSVx82ItZ1Bij2wK4DUfiMiImZtOFKZuzRu2Y4IgiBhC7YCYPbwZW5El7/i+Q+7cIyKbjUu73kzSRe06bc39p/Ob0nnuPMXDaI5/B8CMlKDoDzM/Px65du8bsc+3aNURHRz9yvKSkBKtXr8adO3cgSRLS09NhMplQXFws96mvr8fChQtRX1+P+fPnj/j5nAHSZDXWrRgAHmkLnq6DADweOTa0GOfgWSeA8a1UfdhIt3486a4Vatv5giaW1yyC2bhxI7Kzs8fsExkZOeLxpKQk3Lt3D3/++SfMZjMMBgPa29s9+gz9Pdp1QwCQJAmS9O+eLUj0XxprcQ2AEduAkZ8EEz83eNyBOfwa3sPhNN5rmmN5Gp9B9DQoGoB6vR56vf5fvbe2thY+Pj4IDQ0FAFgsFnz88ccYGBiATjf4M01lZSXMZvOo1/+IJruxwmK0tpGOjRamwJM9Oo3Im3nFIhiHw4GqqiosXrwYAQEBcDgcyMvLw5IlS1BaWgoA6OrqgtlsRnp6OjZv3oy6ujqsWrUK+/bt+0erQHkfIBGR9/Kan0DHS5IklJWVYceOHejr64PJZEJeXh42bNgg9wkMDMSpU6dgtVqRkJCAmTNnYtu2bbwFgoiIRuQVM8CJxBkgEZH3mpK3QRARET1NDEAiIlIlBiAREakSA5CIiFSJAUhERKrEACQiIlViABIRkSp5xY3wE2notsjbt28rPBIiIvqnhv7vHs8t7gzAYVwuFwBwWyQiIi/mcrkQGBg4Zh8+CWYYt9uNW7duISAgAC6XC3PmzMHNmzf5VJhRDG0fxRqNjXV6PNZofFinsQkh4HK5MGvWLPj4jH2VjzPAYXx8fBAeHg4A0GgGn4r/7LPP8ov2GKzR+LBOj8cajQ/rNLrHzfyGcBEMERGpEgOQiIhUiQE4BkmSsH37du4YPwbWaHxYp8djjcaHdXp6uAiGiIhUiTNAIiJSJQYgERGpEgOQiIhUiQFIRESqpPoAtNlseOmllxAQEIDQ0FBkZGSgoaHBo09vby+sVitCQkLg7++PZcuWob29XaERK6OwsBCxsbHyzbcWiwUVFRVyO2v0qIKCAmg0Gqxfv14+xjoBO3bsgEaj8XhFR0fL7azRoL/++gsrV65ESEgI/Pz88MILL6C6ulpuF0Jg27ZtMBqN8PPzQ1paGpqamhQcsfdRfQDa7XZYrVb89ttvqKysxMDAANLT09Hd3S33ycvLw/Hjx1FeXg673Y5bt27hnXfeUXDUEy88PBwFBQWoqalBdXU1XnvtNSxduhRXr14FwBoNd/HiRRQXFyM2NtbjOOs0aOHChWhtbZVf586dk9tYI+Dvv/9GcnIydDodKioqUF9fj7179yI4OFjus3v3bhw4cABFRUWoqqrCjBkz8MYbb6C3t1fBkXsZQR46OjoEAGG324UQQnR2dgqdTifKy8vlPteuXRMAhMPhUGqYk0JwcLD46quvWKNhXC6XiIqKEpWVlSIlJUWsW7dOCMHv0pDt27eLuLi4EdtYo0GbN28Wr7zyyqjtbrdbGAwGsWfPHvlYZ2enkCRJfPfddxMxxClB9TPA4bq6ugAAzz33HACgpqYGAwMDSEtLk/tER0dj7ty5cDgcioxRaffv30dZWRm6u7thsVhYo2GsViveeustj3oA/C49rKmpCbNmzUJkZCRWrFiBlpYWAKzRkB9++AGJiYlYvnw5QkNDER8fjy+//FJudzqdaGtr86hTYGAgkpKSVFWnJ8UAfIjb7cb69euRnJyMmJgYAEBbWxt8fX0RFBTk0TcsLAxtbW0KjFI5V65cgb+/PyRJwpo1a3Ds2DEsWLCANXpIWVkZLl26BJvN9kgb6zQoKSkJ33zzDX766ScUFhbC6XTi1VdfhcvlYo0euHHjBgoLCxEVFYWTJ09i7dq1+PDDD1FaWgoAci3CwsI83qe2Oj0p7gbxEKvVirq6Oo/rEfR/ZrMZtbW16OrqwtGjR5GVlQW73a70sCaNmzdvYt26daisrMS0adOUHs6ktWTJEvnfsbGxSEpKQkREBI4cOQI/Pz8FRzZ5uN1uJCYmYufOnQCA+Ph41NXVoaioCFlZWQqPburgDPCB3NxcnDhxAr/++qu8HRIAGAwG9Pf3o7Oz06N/e3s7DAbDBI9SWb6+vpg3bx4SEhJgs9kQFxeH/fv3s0YP1NTUoKOjA4sWLYJWq4VWq4XdbseBAweg1WoRFhbGOo0gKCgIzz//PK5fv87v0gNGoxELFizwODZ//nz5p+KhWgxfHau2Oj0p1QegEAK5ubk4duwYTp8+DZPJ5NGekJAAnU6HX375RT7W0NCAlpYWWCyWiR7upOJ2u9HX18caPZCamoorV66gtrZWfiUmJmLFihXyv1mnR925cwfNzc0wGo38Lj2QnJz8yO1YjY2NiIiIAACYTCYYDAaPOt2+fRtVVVWqqtMTU3oVjtLWrl0rAgMDxZkzZ0Rra6v8unv3rtxnzZo1Yu7cueL06dOiurpaWCwWYbFYFBz1xMvPzxd2u104nU5x+fJlkZ+fLzQajTh16pQQgjUazcOrQIVgnYQQYuPGjeLMmTPC6XSK8+fPi7S0NDFz5kzR0dEhhGCNhBDi999/F1qtVnz66aeiqalJfPvtt2L69Oni8OHDcp+CggIRFBQkvv/+e3H58mWxdOlSYTKZRE9Pj4Ij9y6qD0AAI74OHTok9+np6RE5OTkiODhYTJ8+Xbz99tuitbVVuUErYNWqVSIiIkL4+voKvV4vUlNT5fATgjUazfAAZJ2EyMzMFEajUfj6+orZs2eLzMxMcf36dbmdNRp0/PhxERMTIyRJEtHR0eLgwYMe7W63W2zdulWEhYUJSZJEamqqaGhoUGi03onbIRERkSqp/hogERGpEwOQiIhUiQFIRESqxAAkIiJVYgASEZEqMQCJiEiVGIBERKRKDEAiIlIlBiARjSk7OxsZGRlKD4PoqWMAEnmx7OxsaDQaaDQa6HQ6mEwmfPTRR+jt7VV6aESTHvcDJPJyb775Jg4dOoSBgQHU1NQgKysLGo0Gu3btUnpoRJMaZ4BEXk6SJBgMBsyZMwcZGRlIS0tDZWUlgMEtq2w2G0wmE/z8/BAXF4ejR4/K771//z7ef/99ud1sNmP//v1KnQrRhOIMkGgKqaurw4ULF+R942w2Gw4fPoyioiJERUXh7NmzWLlyJfR6PVJSUuB2uxEeHo7y8nKEhITgwoUL+OCDD2A0GvHuu+8qfDZE/y0GIJGXO3HiBPz9/XHv3j309fXBx8cHn3/+Ofr6+rBz5078/PPP8iapkZGROHfuHIqLi5GSkgKdTodPPvlE/iyTyQSHw4EjR44wAGnKYwASebnFixejsLAQ3d3d2LdvH7RaLZYtW4arV6/i7t27eP311z369/f3Iz4+Xv77iy++QElJCVpaWtDT04P+/n68+OKLE3wWRBOPAUjk5WbMmIF58+YBAEpKShAXF4evv/4aMTExAIAff/wRs2fP9niPJEkAgLKyMmzatAl79+6FxWJBQEAA9uzZg6qqqok9CSIFMACJphAfHx9s2bIFGzZsQGNjIyRJQktLC1JSUkbsf/78ebz88svIycmRjzU3N0/UcIkUxVWgRFPM8uXL8cwzz6C4uBibNm1CXl4eSktL0dzcjEuXLuGzzz5DaWkpACAqKgrV1dU4efIkGhsbsXXrVly8eFHhMyCaGJwBEk0xWq0Wubm52L17N5xOJ/R6PWw2G27cuIGgoCAsWrQIW7ZsAQCsXr0af/zxBzIzM6HRaPDee+8hJycHFRUVCp8F0X9PI4QQSg+CiIhoovEnUCIiUiUGIBERqRIDkIiIVIkBSEREqsQAJCIiVWIAEhGRKjEAiYhIlRiARESkSgxAIiJSJQYgERGpEgOQiIhU6X+c2UgTpWeOjAAAAABJRU5ErkJggg==\n"
      },
+     "metadata": {},
      "output_type": "display_data"
     }
    ],
@@ -314,8 +296,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 207,
-   "metadata": {},
+   "execution_count": 8,
+   "metadata": {
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   },
    "outputs": [
     {
      "name": "stdout",
@@ -325,7 +311,7 @@
       "default initial guess used\n",
       "Resonator at 312.72 MHz\n",
       "     |                       Variables fit                       \u001B[1;30;42m|Derived variables|\u001B[0;0m\n",
-      "     | fr (MHz)|   Q    | amp | phi  | a   |   b0     |   b1     \u001B[1;30;42m|   Qi   |   Qc   |\u001B[0;0m\n",
+      "     | fr (MHz)|   Qr   | amp | phi  | a   |   b0     |   b1     \u001B[1;30;42m|   Qi   |   Qc   |\u001B[0;0m\n",
       "Guess| 312.7237|   21755| 0.61|  0.00| 0.00|  5.44E+03|  3.81E+05\u001B[1;30;42m|   55254|   35882|\u001B[0;0m\n",
       "Fit  | 312.7257|   21262| 0.60| -0.14| 0.10|  5.60E+03|  3.29E+04\u001B[1;30;42m|   53766|   35171|\u001B[0;0m\n"
      ]
@@ -337,7 +323,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 208,
+   "execution_count": 9,
    "metadata": {
     "collapsed": false,
     "jupyter": {
@@ -350,24 +336,18 @@
    "outputs": [
     {
      "data": {
-      "text/plain": [
-       "<matplotlib.legend.Legend at 0x148289fd0>"
-      ]
+      "text/plain": "<matplotlib.legend.Legend at 0x177a862dde0>"
      },
-     "execution_count": 208,
+     "execution_count": 9,
      "metadata": {},
      "output_type": "execute_result"
     },
     {
      "data": {
-      "image/png": "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\n",
-      "text/plain": [
-       "<Figure size 432x288 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
+      "text/plain": "<Figure size 640x480 with 1 Axes>",
+      "image/png": "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dFgSyNRj3rx5ZGdnB5L9jBkzhi+//LLe9lu3buWSSy6hT58+aJrGc889V6vNE088wa9+9StiY2NJTU3lwgsv5JdffqnVbvny5UycOJHo6Gji4uI4++yzqa6uDmrzn//8hzPOOIPIyEgSEhK48MILT/YtN0s4X58dO3YwY8YMkpOTiYuLY9y4cXz33Xet8r6bIxTXKDc3F03T6rx98MEHgXb79+/n/PPPJyoqitTUVO666y7cbnervv+mCNdrtHHjRi677DIyMjKIjIxk8ODBPP/8863+/hsTrtenpsLCQnr27ImmaZSUlLTG226ycL8+b731FtnZ2URERJCamspNN93Uau+9qcL5Gq1evZpJkyYRHx9PQkIC5557Lhs3bmz2e5RAph49e/bkySefZO3ataxZs4aJEycyY8YMtm7dWmf7qqoqTjnlFJ588knS0tLqbLN06VJuuukmVqxYweLFi3G5XEydOpXKyspAm+XLl5OTk8PUqVNZtWoVq1ev5uabbw5Kz/zRRx9x1VVXcc0117Bx40Z+/PFHLr/88ta9AI0I5+tzwQUX4Ha7+fbbb1m7di3Dhg3jggsuID8/v3UvQiNCcY0yMjLIy8sLuj388MPExMQwbdo0ADweD+effz5Op5OffvqJt99+m7feeosHHnigbS5EA8L1Gq1du5bU1FTeffddtm7dyl/+8hfmzp3Liy++2DYXoh7hen1qmj17NtnZ2a33ppshnK/P//zP//CXv/yFe++9l61bt/L1119z7rnntv5FaES4XqOKigpycnLo1asXK1euZNmyZcTGxnLuueficrma9yaVaLKEhAT1j3/8o9F2vXv3Vs8++2yj7QoKChSgli5dGjh2xhlnqPvuu6/e57hcLtWjR48m9aO9hcP1OXr0qALU999/HzhWVlamALV48eJGX7Ottcc1OtFpp52mrr322sD9L774QhkMBpWfnx84Nm/ePBUXF6ccDkejr9nWwuEa1eXGG29UEyZMaPT12lo4XZ+XX35ZnXPOOeqbb75RgCouLm709dpaOFyfoqIiFRkZqb7++usm9bm9hcM1Wr16tQLU/v37A8c2bdqkALVz585GX7MmGZFpAo/Hw4IFC6isrGTMmDGtdt7S0lIAEhMTASgoKGDlypWkpqYyduxYunXrxjnnnMOyZcsCz1m3bh2HDh3CYDAwfPhw0tPT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EB2WBDJCCCGE6LAkkBFCCCFEhyWBjBBCCCE6LAlkhBBCCNFhSSAjhBBCiA5LAhkhhBBCNNv333/P9OnT6d69O5qm8e9//7vZ51i0aBGjR48mNjaWlJQULrnkEnJzc5t1DglkhBCiBqfTSf/+/fnpp59C2o+FCxdy2mmnhUWNMCHqUllZybBhw3jppZda9Py9e/cyY8YMJk6cyIYNG1i0aBHHjh3j4osvbtZ5JJARohObNWsWmqbVuu3atSvUXQtbf//73+nbty9jx44NHPNftxUrVgS1dTgcJCUloWkaS5YsCWpf1/9OZ82axYUXXtikfuTk5GA2m3nvvfda8jaEaHPTpk3jscce46KLLqrzcYfDwZ133kmPHj2Ijo7mjDPOCPo9Wbt2LR6Ph8cee4x+/foxYsQI7rzzTjZs2IDL5WpyPySQEaKTy8nJIS8vL+hWV7Vap9MZgt6FF6UUL774IrNnz671WEZGBm+++WbQsU8++YSYmJg268+sWbN44YUX2uz8QrSlm2++meXLl7NgwQI2bdrEpZdeSk5ODjt37gRg5MiRGAwG3nzzTTweD6Wlpfzzn/9k8uTJmM3mJr+OBDJCdHJWq5W0tLSgm9FoZPz48dx8883cdtttJCcnc+655wKwZcsWpk2bRkxMDN26deOqq67i2LFjgfNVVlZy9dVXExMTQ3p6On/7298YP348t912W6BNXSMS8fHxvPXWW4H7Bw4c4Le//S3x8fEkJiYyY8aMoLlx/+jFM888Q3p6OklJSdx0001B/1NzOBzcc889ZGRkYLVa6d+/P6+//jpKKfr3788zzzwT1IcNGzY0OCK1du1adu/ezfnnn1/rsZkzZ7JgwQKqq6sDx9544w1mzpxZ77VvSG5ubp2jZePHjw+0mT59OmvWrGH37t0teg0hQmX//v28+eabfPDBB5x11ln069ePO++8k3HjxgX+Q9C3b1+++uor/vznP2O1WomPj+fgwYP861//atZrSSAjRBf29ttvY7FY+PHHH/n73/9OSUkJEydOZPjw4axZs4aFCxdy5MgRfvvb3waec9ddd7F06VI+/fRTvvrqK5YsWcK6deua9boul4tzzz2X2NhYfvjhB3788UdiYmLIyckJGhn67rvv2L17N9999x1vv/02b731VlAwdPXVVzN//nxeeOEFfv75Z1555RViYmLQNI1rr7221gjKm2++ydlnn03//v3r7NcPP/zAwIEDiY2NrfXYyJEj6dOnDx999BHg/aD+/vvvueqqq5r13v0yMjKCRsnWr19PUlISZ599dqBNr1696NatGz/88EOLXkOIUNm8eTMej4eBAwcSExMTuC1dujQQmOfn53P99dczc+ZMVq9ezdKlS7FYLPzmN7+hWfWsm10vWwjRYcycOVMZjUYVHR0duP3mN79RSil1zjnnqOHDhwe1f/TRR9XUqVODjh04cEAB6pdfflHl5eXKYrGof/3rX4HHCwsLVWRkpLr11lsDxwD1ySefBJ3HZrOpN998Uyml1D//+U81aNAgpet64HGHw6EiIyPVokWLAn3v3bu3crvdgTaXXnqp+t3vfqeUUuqXX35RgFq8eHGd7/3QoUPKaDSqlStXKqWUcjqdKjk5Wb311lv1Xq9bb71VTZw4sdZx//t57rnn1IQJE5RSSj388MPqoosuUsXFxQpQ3333XVD7iIiIoOseHR2tTCaTmjFjRq3zV1dXqzPOOENdcMEFyuPxBD02fPhw9dBDD9XbZyHCwYm/8wsWLFBGo1Ft375d7dy5M+iWl5enlFLqvvvuU6effnrQefyfN8uXL2/ya5taOQgTQoSZCRMmMG/evMD96OjowPcjR44Martx40a+++67Otd97N69m+rqapxOJ2eccUbgeGJiIoMGDWpWnzZu3MiuXbtqjXzY7fagaZQhQ4ZgNBoD99PT09m8eTPgnSYyGo2cc845db5G9+7dOf/883njjTcYNWoUn332GQ6Hg0svvbTeflVXVxMREVHv41deeSX33nsve/bs4a233mpw/cqzzz7L5MmTg47dc889eDyeWm2vvfZaysvLWbx4MQZD8EB5ZGQkVVVV9b6OEOFo+PDheDweCgoKOOuss+psU1VVVevn3f/73pzdehLICNHJRUdH1zuVUjOoAaioqGD69Ok89dRTtdqmp6c3ebeTpmm1hoZrrm2pqKhg5MiRde7ISUlJCXx/4oI/TdMCH3CRkZGN9uO6667jqquu4tlnn+XNN9/kd7/7HVFRUfW2T05ODgRKdUlKSuKCCy5g9uzZ2O12pk2bRnl5eZ1t09LSal332NhYSkpKgo499thjLFq0iFWrVtU5pVVUVBR0TYQIFxUVFUGfCXv37mXDhg0kJiYycOBArrjiCq6++mr+9re/MXz4cI4ePco333xDdnY2559/Pueffz7PPvssjzzyCJdddhnl5eX8+c9/pnfv3gwfPrzJ/ZA1MkKIgBEjRrB161b69OlD//79g27R0dH069cPs9nMypUrA88pLi5mx44dQedJSUkhLy8vcH/nzp1BowojRoxg586dpKam1nodm83WpL4OHToUXddZunRpvW3OO+88oqOjmTdvHgsXLuTaa69t8JzDhw9n+/btDc7PX3vttSxZsoSrr746aLSoJT766CMeeeQR/vWvf9GvX79aj/tHqJrzoS5Ee1mzZg3Dhw8P/HzecccdDB8+nAceeADwrkm7+uqr+dOf/sSgQYO48MILWb16Nb169QJg4sSJvP/++/z73/9m+PDh5OTkYLVaWbhwYZP+o+InIzJCiICbbrqJ1157jcsuu4y7776bxMREdu3axYIFC/jHP/5BTEwMs2fP5q677iIpKYnU1FT+8pe/1BoenjhxIi+++CJjxozB4/Fwzz33BI2uXHHFFfz1r39lxowZPPLII/Ts2ZN9+/bx8ccfc/fdd9OzZ89G+9qnTx9mzpzJtddeywsvvMCwYcPYt28fBQUFgcXJRqORWbNmMXfuXAYMGMCYMWMaPOeECROoqKhg69atZGVl1dkmJyeHo0ePEhcX12gfG7Jlyxauvvpq7rnnHoYMGUJ+fj4AFouFxMREAFasWIHVam2030KEwvjx4xsM+s1mMw8//DAPP/xwvW1+//vf8/vf//6k+iEjMkKIgO7du/Pjjz/i8XiYOnUqQ4cO5bbbbiM+Pj4QrPz1r3/lrLPOYvr06UyePJlx48bVWmvzt7/9jYyMDM466ywuv/xy7rzzzqApnaioKL7//nt69erFxRdfzODBgwPTNc0JEObNm8dvfvMbbrzxRk499VSuv/56Kisrg9rMnj0bp9PJNddc0+j5kpKSuOiiixpMQqdpGsnJyVgslib3sy5r1qyhqqqKxx57jPT09MCtZlbT+fPnc8UVVzQ4HSZEV6ephsIpIYRogvHjx3Paaafx3HPPhbortfzwww9MmjSJAwcO0K1bt0bbb9q0iSlTprB79+42TXbXmGPHjjFo0CDWrFlTZwJDIYSXjMgIITolh8PBwYMHeeihh7j00kubFMQAZGdn89RTT7F379427mHDcnNzefnllyWIEaIRskZGCNEpzZ8/n9mzZ3PaaafxzjvvNOu5s2bNaptONcPpp5/O6aefHupuCBH2ZGpJCCGEEB2WTC0JIYQQosOSQEYIIYQQHZYEMkIIIYTosCSQEUIIIUSHJYGMEEIIITosCWSEEEII0WFJICOEEEKIDksCGSGEEEJ0WP8fPGHtk3eiSJ0AAAAASUVORK5CYII=\n"
      },
+     "metadata": {},
      "output_type": "display_data"
     }
    ],
@@ -383,8 +363,12 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
+   "execution_count": 9,
+   "metadata": {
+    "pycharm": {
+     "name": "#%%\n"
+    }
+   },
    "outputs": [],
    "source": []
   }
diff --git a/submm/multitone_kidPy/analyze.py b/submm/multitone_kidPy/analyze.py
index 8182f58..859673c 100644
--- a/submm/multitone_kidPy/analyze.py
+++ b/submm/multitone_kidPy/analyze.py
@@ -3,223 +3,245 @@
 import matplotlib.pyplot as plt
 import numpy as np
 from scipy.stats import binned_statistic
-from scipy import interpolate
-from submm.KIDs import calibrate, resonance_fitting, PCA_implementation as PCA
+from scipy import interpolate, fftpack
+from submm.KIDs import calibrate, PCA_implementation as PCA
+from submm.KIDs.res.fitting import fit_nonlinear_mag_sep, fit_nonlinear_iq_sep
+from submm.KIDs.res.utils import amplitude_normalization_sep, guess_x0_mag_nonlinear_sep, guess_x0_iq_nonlinear_sep
 import pickle
 
 
-# this function fits a fine and gain scan combo produced by the ASU multitone system
+# this function fits a fine and gain scan combo produced by the ASU multi-tone system
 # and uses the error produced by the system to determine if the fit is good
-def fit_fine_gain_std(fine_name,gain_name,reduced_chi_squared_cutoff = 1000.,plot = True):
-
-        
-    fine = read_multitone.read_iq_sweep(fine_name, load_std = True)
-    gain = read_multitone.read_iq_sweep(gain_name, load_std = True)
+def fit_fine_gain_std(fine_name, gain_name, reduced_chi_squared_cutoff=1000., plot=True):
+    fine = read_multitone.read_iq_sweep(fine_name, load_std=True)
+    gain = read_multitone.read_iq_sweep(gain_name, load_std=True)
     outfile_dir = fine_name
-    center_freqs = fine['freqs'][fine['freqs'].shape[0]//2,:]
+    center_freqs = fine['freqs'][fine['freqs'].shape[0] // 2, :]
 
     if plot:
-        pdf_pages = PdfPages(outfile_dir+"/"+"fit_plots.pdf")
-
-    all_fits_mag = np.zeros((9,fine['freqs'].shape[1]))
-    all_fits_iq = np.zeros((10,fine['freqs'].shape[1]))
-
-    for i in range(0,fine['freqs'].shape[1]):
-        fine_f = fine['freqs'][:,i]*10**6
-        gain_f = gain['freqs'][:,i]*10**6
-        fine_z = fine['I'][:,i]+1.j*fine['Q'][:,i]
-        fine_z_err = fine['I_std'][:,i]+1.j*fine['Q_std'][:,i]
-        gain_z = gain['I'][:,i]+1.j*gain['Q'][:,i]
-        gain_z_err = gain['I_std'][:,i]+1.j*gain['Q_std'][:,i]
-
-        #flag data that is too close to other resonators              
-        distance = center_freqs-center_freqs[i]
-        if center_freqs[i] != np.min(center_freqs): #don't do if lowest frequency resonator
-            closest_lower_dist = -np.min(np.abs(distance[np.where(distance<0)]))
-            closest_lower_index = np.where(distance ==closest_lower_dist)[0][0]
-            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index])/2.
+        pdf_pages = PdfPages(outfile_dir + "/" + "fit_plots.pdf")
+
+    all_fits_mag = np.zeros((9, fine['freqs'].shape[1]))
+    all_fits_iq = np.zeros((10, fine['freqs'].shape[1]))
+
+    for i in range(0, fine['freqs'].shape[1]):
+        fine_f = fine['freqs'][:, i] * 10 ** 6
+        gain_f = gain['freqs'][:, i] * 10 ** 6
+        fine_z = fine['I'][:, i] + 1.j * fine['Q'][:, i]
+        fine_z_err = fine['I_std'][:, i] + 1.j * fine['Q_std'][:, i]
+        gain_z = gain['I'][:, i] + 1.j * gain['Q'][:, i]
+        gain_z_err = gain['I_std'][:, i] + 1.j * gain['Q_std'][:, i]
+
+        # flag data that is too close to other resonators
+        distance = center_freqs - center_freqs[i]
+        if center_freqs[i] != np.min(center_freqs):  # don't do if lowest frequency resonator
+            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
+            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
+            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index]) / 2.
         else:
             halfway_low = 0
 
-        if center_freqs[i] != np.max(center_freqs): #don't do if highest frequenct
-            closest_higher_dist = np.min(np.abs(distance[np.where(distance>0)]))
-            closest_higher_index = np.where(distance ==closest_higher_dist)[0][0]
-            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index])/2.
+        if center_freqs[i] != np.max(center_freqs):  # don't do if highest frequenct
+            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
+            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
+            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index]) / 2.
         else:
             halfway_high = np.inf
-           
-        use_index = np.where(((fine_f/10**6>halfway_low) & (fine_f/10**6<halfway_high)))
+
+        use_index = np.where(((fine_f / 10 ** 6 > halfway_low) & (fine_f / 10 ** 6 < halfway_high)))
         fine_f = fine_f[use_index]
         fine_z = fine_z[use_index]
         fine_z_err = fine_z_err[use_index]
 
-        #flag gain data that is to close to all of the resonators
-        fine_span = (fine_f[-1]-fine_f[0])/10**6
+        # flag gain data that is to close to all of the resonators
+        fine_span = (fine_f[-1] - fine_f[0]) / 10 ** 6
         use_boolean = np.zeros(len(gain_f))
-        for j in range(0,len(gain_f)):
-            if (np.abs(gain_f[j]/10**6-center_freqs)< fine_span/2.).any():
+        for j in range(0, len(gain_f)):
+            if (np.abs(gain_f[j] / 10 ** 6 - center_freqs) < fine_span / 2.).any():
                 use_boolean[j] = 1
 
         use_index_gain = np.where(use_boolean != 1)
-        if len(use_index_gain[0]>1):
+        if len(use_index_gain[0] > 1):
             gain_f = gain_f[use_index_gain]
             gain_z = gain_z[use_index_gain]
             gain_z_err = gain_z_err[use_index_gain]
 
         if plot:
-            fig = plt.figure(i,figsize = (16,10))
+            fig = plt.figure(i, figsize=(16, 10))
 
             ax1 = plt.subplot(231)
-            plt.title("Resonator Index "+str(i))
-            plt.plot(fine['freqs'][:,i],10*np.log10(fine['I'][:,i]**2+fine['Q'][:,i]**2),'o',label = "fine")
-            plt.plot(gain['freqs'][:,i],10*np.log10(gain['I'][:,i]**2+gain['Q'][:,i]**2),'o',label = "gain")
+            plt.title("Resonator Index " + str(i))
+            plt.plot(fine['freqs'][:, i], 10 * np.log10(fine['I'][:, i] ** 2 + fine['Q'][:, i] ** 2), 'o', label="fine")
+            plt.plot(gain['freqs'][:, i], 10 * np.log10(gain['I'][:, i] ** 2 + gain['Q'][:, i] ** 2), 'o', label="gain")
             plt.xlabel("Frequency (MHz)")
             plt.ylabel("Power (dB)")
 
             ax2 = plt.subplot(232)
-            plt.plot(fine['freqs'][:,i],10*np.log10(fine['I'][:,i]**2+fine['Q'][:,i]**2),'o')
-            plt.plot(gain['freqs'][:,i],10*np.log10(gain['I'][:,i]**2+gain['Q'][:,i]**2),'o')
+            plt.plot(fine['freqs'][:, i], 10 * np.log10(fine['I'][:, i] ** 2 + fine['Q'][:, i] ** 2), 'o')
+            plt.plot(gain['freqs'][:, i], 10 * np.log10(gain['I'][:, i] ** 2 + gain['Q'][:, i] ** 2), 'o')
             plt.xlabel("Frequency (MHz)")
             plt.ylabel("Power (dB)")
-            plt.xlim(np.min(fine['freqs'][:,i]),np.max(fine['freqs'][:,i]))
+            plt.xlim(np.min(fine['freqs'][:, i]), np.max(fine['freqs'][:, i]))
 
         # fit nonlinear magnitude
         try:
-            x0 = resonance_fitting.guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-            fit_dict_mag = resonance_fitting.fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err = fine_z_err, gain_z_err = gain_z_err, x0=x0)#,bounds =bounds)
-            all_fits_mag[0:8,i] = fit_dict_mag['fit'][0]
-            all_fits_mag[8,i] = fit_dict_mag['red_chi_sqr']
+            x0 = guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+            fit_dict_mag = fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err=fine_z_err,
+                                                         gain_z_err=gain_z_err, x0=x0)  # ,bounds =bounds)
+            all_fits_mag[0:8, i] = fit_dict_mag['fit'][0]
+            all_fits_mag[8, i] = fit_dict_mag['red_chi_sqr']
             if plot:
                 plt.subplot(231)
-                plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+",label = "fit")
-                plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x",label = "x0 guess")
-                plt.title("f ="+str(fit_dict_mag['fit'][0][0]/10**6)[0:7]+"MHz, a="+"{:.2f}".format(fit_dict_mag['fit'][0][4]))
+                plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+",
+                         label="fit")
+                plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x",
+                         label="x0 guess")
+                plt.title("f =" + str(fit_dict_mag['fit'][0][0] / 10 ** 6)[0:7] + "MHz, a=" + "{:.2f}".format(
+                    fit_dict_mag['fit'][0][4]))
                 plt.legend()
-                if fit_dict_mag['red_chi_sqr']>reduced_chi_squared_cutoff:
+                if fit_dict_mag['red_chi_sqr'] > reduced_chi_squared_cutoff:
                     ax1.set_facecolor('lightyellow')
                     ax2.set_facecolor('lightyellow')
-                
-            
+
                 plt.subplot(232)
-                plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+")
-                plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x")
-
-                plt.text(0.75, 0.9, "fr  = "+"{:.3f}".format(fit_dict_mag['fit'][0][0]/10**6)+" MHz", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.85, "Qr  = "+"{:.0f}".format(fit_dict_mag['fit'][0][1])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.8, "amp = "+"{:.2f}".format(fit_dict_mag['fit'][0][2])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.75, "phi = "+"{:.2f}".format(fit_dict_mag['fit'][0][3])+" radians", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.70, "a   = "+"{:.2f}".format(fit_dict_mag['fit'][0][4])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.65, "b0  = "+"{:.0f}".format(fit_dict_mag['fit'][0][5])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.6, "b1  = "+"{:.0f}".format(fit_dict_mag['fit'][0][6])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.55, "reduced chi squared  = "+"{:.2f}".format(fit_dict_mag['red_chi_sqr'])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            
+                plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+")
+                plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x")
+
+                plt.text(0.75, 0.9, "fr  = " + "{:.3f}".format(fit_dict_mag['fit'][0][0] / 10 ** 6) + " MHz",
+                         fontsize=14, transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.85, "Qr  = " + "{:.0f}".format(fit_dict_mag['fit'][0][1]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.8, "amp = " + "{:.2f}".format(fit_dict_mag['fit'][0][2]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.75, "phi = " + "{:.2f}".format(fit_dict_mag['fit'][0][3]) + " radians", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.70, "a   = " + "{:.2f}".format(fit_dict_mag['fit'][0][4]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.65, "b0  = " + "{:.0f}".format(fit_dict_mag['fit'][0][5]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.6, "b1  = " + "{:.0f}".format(fit_dict_mag['fit'][0][6]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.55, "reduced chi squared  = " + "{:.2f}".format(fit_dict_mag['red_chi_sqr']) + " ",
+                         fontsize=14, transform=plt.gcf().transFigure)
+
         except Exception as e:
             print(e)
             print("could not fit the resonator")
 
         if plot:
-            ax3 = plt.subplot(234,aspect ='equal')
-            plt.plot(fine['I'][:,i],fine['Q'][:,i],'o')
-            plt.plot(gain['I'][:,i],gain['Q'][:,i],'o')
+            ax3 = plt.subplot(234, aspect='equal')
+            plt.plot(fine['I'][:, i], fine['Q'][:, i], 'o')
+            plt.plot(gain['I'][:, i], gain['Q'][:, i], 'o')
             plt.xlabel("I")
             plt.ylabel("Q")
 
-            ax4 = plt.subplot(235,aspect ='equal')
-            plt.plot(fine['I'][:,i],fine['Q'][:,i],'o')
-            plt.plot(gain['I'][:,i],gain['Q'][:,i],'o')
+            ax4 = plt.subplot(235, aspect='equal')
+            plt.plot(fine['I'][:, i], fine['Q'][:, i], 'o')
+            plt.plot(gain['I'][:, i], gain['Q'][:, i], 'o')
             plt.xlabel("I")
             plt.ylabel("Q")
-            plt.xlim(np.min(fine['I'][:,i]),np.max(fine['I'][:,i]))
-            plt.ylim(np.min(fine['Q'][:,i]),np.max(fine['Q'][:,i]))
-
+            plt.xlim(np.min(fine['I'][:, i]), np.max(fine['I'][:, i]))
+            plt.ylim(np.min(fine['Q'][:, i]), np.max(fine['Q'][:, i]))
 
-        # fit nonlinear iq 
+        # fit nonlinear iq
         try:
-            x0 = resonance_fitting.guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-            fit_dict_iq = resonance_fitting.fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err = fine_z_err, gain_z_err = gain_z_err, x0=x0)
-            all_fits_iq[0:9,i] = fit_dict_iq['fit'][0]
-            all_fits_iq[9,i] = fit_dict_iq['red_chi_sqr']
+            x0 = guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+            fit_dict_iq = fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err=fine_z_err,
+                                                       gain_z_err=gain_z_err, x0=x0)
+            all_fits_iq[0:9, i] = fit_dict_iq['fit'][0]
+            all_fits_iq[9, i] = fit_dict_iq['red_chi_sqr']
             if plot:
-                plt.subplot(234,aspect ='equal')
-                plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-                plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-                plt.title("f ="+str(fit_dict_iq['fit'][0][0]/10**6)[0:7]+"MHz, a="+"{:.2f}".format(fit_dict_iq['fit'][0][4]))
-                plt.subplot(235,aspect ='equal')
-                plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-                plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-                plt.plot(fine['I'][:,i],fine['Q'][:,i])
-
-                if fit_dict_iq['red_chi_sqr']>reduced_chi_squared_cutoff:
+                plt.subplot(234, aspect='equal')
+                plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+                plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+                plt.title("f =" + str(fit_dict_iq['fit'][0][0] / 10 ** 6)[0:7] + "MHz, a=" + "{:.2f}".format(
+                    fit_dict_iq['fit'][0][4]))
+                plt.subplot(235, aspect='equal')
+                plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+                plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+                plt.plot(fine['I'][:, i], fine['Q'][:, i])
+
+                if fit_dict_iq['red_chi_sqr'] > reduced_chi_squared_cutoff:
                     ax3.set_facecolor('lightyellow')
                     ax4.set_facecolor('lightyellow')
 
-                plt.text(0.75, 0.45, "fr  = "+"{:.3f}".format(fit_dict_iq['fit'][0][0]/10**6)+" MHz", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.4, "Qr  = "+"{:.0f}".format(fit_dict_iq['fit'][0][1])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.35, "amp = "+"{:.2f}".format(fit_dict_iq['fit'][0][2])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.3, "phi = "+"{:.2f}".format(fit_dict_iq['fit'][0][3])+" radians", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.25, "a   = "+"{:.2f}".format(fit_dict_iq['fit'][0][4])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.2, "i0  = "+"{:.0f}".format(fit_dict_iq['fit'][0][5])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.15, "q0  = "+"{:.0f}".format(fit_dict_iq['fit'][0][6])+" ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.1, "tau = "+"{:.2f}".format(fit_dict_iq['fit'][0][7]*10**7)+" x 10^-7 ", fontsize=14, transform=plt.gcf().transFigure)
-                plt.text(0.75, 0.05, "reduced chi squared  = "+"{:.2f}".format(fit_dict_iq['red_chi_sqr'])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            
+                plt.text(0.75, 0.45, "fr  = " + "{:.3f}".format(fit_dict_iq['fit'][0][0] / 10 ** 6) + " MHz",
+                         fontsize=14, transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.4, "Qr  = " + "{:.0f}".format(fit_dict_iq['fit'][0][1]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.35, "amp = " + "{:.2f}".format(fit_dict_iq['fit'][0][2]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.3, "phi = " + "{:.2f}".format(fit_dict_iq['fit'][0][3]) + " radians", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.25, "a   = " + "{:.2f}".format(fit_dict_iq['fit'][0][4]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.2, "i0  = " + "{:.0f}".format(fit_dict_iq['fit'][0][5]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.15, "q0  = " + "{:.0f}".format(fit_dict_iq['fit'][0][6]) + " ", fontsize=14,
+                         transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.1, "tau = " + "{:.2f}".format(fit_dict_iq['fit'][0][7] * 10 ** 7) + " x 10^-7 ",
+                         fontsize=14, transform=plt.gcf().transFigure)
+                plt.text(0.75, 0.05, "reduced chi squared  = " + "{:.2f}".format(fit_dict_iq['red_chi_sqr']) + " ",
+                         fontsize=14, transform=plt.gcf().transFigure)
+
         except Exception as e:
             print(e)
             print("could not fit the resonator")
 
         if plot:
-            plt.suptitle("Resonator index = " +str(i) +", Frequency = "+str(center_freqs[i])[0:7])
-
-
+            plt.suptitle("Resonator index = " + str(i) + ", Frequency = " + str(center_freqs[i])[0:7])
 
             pdf_pages.savefig(fig)
             plt.close(fig)
     if plot:
         pdf_pages.close()
 
-    pdf_pages = PdfPages(outfile_dir+"/"+"fit_results.pdf")
+    pdf_pages = PdfPages(outfile_dir + "/" + "fit_results.pdf")
 
-    fig = plt.figure(1, figsize = (12,6))
+    fig = plt.figure(1, figsize=(12, 6))
     plt.title("Center frequency")
-    res_index = np.arange(0,all_fits_mag.shape[1])
-    
-    plt.plot(res_index,all_fits_mag[0,:]/10**6,'o',label = "Mag fit")
-    plt.plot(res_index,all_fits_iq[0,:]/10**6,'o',label = "IQ fit")
-    
-    bad_fit_mag = np.where(all_fits_mag[8,:]>reduced_chi_squared_cutoff)
-    failed_fit_mag = np.where(all_fits_mag[0,:]==0)
-    bad_fit_mag = np.append(bad_fit_mag,failed_fit_mag)
-    bad_fit_iq = np.where(all_fits_iq[9,:]>reduced_chi_squared_cutoff)
-    failed_fit_iq = np.where(all_fits_iq[0,:]==0)
-    bad_fit_iq = np.append(bad_fit_mag,failed_fit_iq)
-
-
-    plt.plot(res_index[bad_fit_mag],all_fits_mag[0,:][bad_fit_mag]/10**6,'o',label = "bad fit",color = 'k')
-    plt.plot(res_index[bad_fit_iq],all_fits_iq[0,:][bad_fit_iq]/10**6,'o',color = 'k')
-    
+    res_index = np.arange(0, all_fits_mag.shape[1])
+
+    plt.plot(res_index, all_fits_mag[0, :] / 10 ** 6, 'o', label="Mag fit")
+    plt.plot(res_index, all_fits_iq[0, :] / 10 ** 6, 'o', label="IQ fit")
+
+    bad_fit_mag = np.where(all_fits_mag[8, :] > reduced_chi_squared_cutoff)
+    failed_fit_mag = np.where(all_fits_mag[0, :] == 0)
+    bad_fit_mag = np.append(bad_fit_mag, failed_fit_mag)
+    bad_fit_iq = np.where(all_fits_iq[9, :] > reduced_chi_squared_cutoff)
+    failed_fit_iq = np.where(all_fits_iq[0, :] == 0)
+    bad_fit_iq = np.append(bad_fit_mag, failed_fit_iq)
+
+    plt.plot(res_index[bad_fit_mag], all_fits_mag[0, :][bad_fit_mag] / 10 ** 6, 'o', label="bad fit", color='k')
+    plt.plot(res_index[bad_fit_iq], all_fits_iq[0, :][bad_fit_iq] / 10 ** 6, 'o', color='k')
+
     plt.xlabel("resonator index")
     plt.ylabel("Resonator Frequency (MHz)")
-    plt.legend(loc = 4)
+    plt.legend(loc=4)
     pdf_pages.savefig(fig)
     plt.close()
 
-    fig = plt.figure(2,figsize = (12,6))
+    fig = plt.figure(2, figsize=(12, 6))
     plt.title("Resonator Qs")
-    plt.plot(res_index,all_fits_mag[1,:],'o',label = "Qr Mag",color = 'g')
-    plt.plot(res_index,all_fits_iq[1,:],'*',label = "Qr IQ",color = 'g')
-    plt.plot(res_index[bad_fit_mag],all_fits_mag[1,:][bad_fit_mag],'o',color = 'k')
-    plt.plot(res_index[bad_fit_iq],all_fits_iq[1,:][bad_fit_iq],'*',color = 'k')
-    
-    plt.plot(res_index,all_fits_mag[1,:]/all_fits_mag[2,:],'o',label = "Qc Mag",color = 'b')
-    plt.plot(res_index,all_fits_iq[1,:]/all_fits_mag[2,:],'*',label = "Qc IQ",color = 'b')
-    plt.plot(res_index[bad_fit_mag],all_fits_mag[1,:][bad_fit_mag]/all_fits_mag[2,:][bad_fit_mag],'o',color = 'k')
-    plt.plot(res_index[bad_fit_iq],all_fits_iq[1,:][bad_fit_iq]/all_fits_mag[2,:][bad_fit_iq],'*',color = 'k')
-    
-    plt.plot(res_index,1/(1/all_fits_mag[1,:]-1/(all_fits_mag[1,:]/all_fits_mag[2,:])),'o',label = "Qi Mag",color = 'r')
-    plt.plot(res_index,1/(1/all_fits_iq[1,:]-1/(all_fits_iq[1,:]/all_fits_iq[2,:])),'*',label = "Qi IQ",color = 'r')
-    plt.plot(res_index[bad_fit_mag],1/(1/all_fits_mag[1,:][bad_fit_mag]-1/(all_fits_mag[1,:][bad_fit_mag]/all_fits_mag[2,:][bad_fit_mag])),'o',color = 'k')
-    plt.plot(res_index[bad_fit_iq],1/(1/all_fits_iq[1,:][bad_fit_iq]-1/(all_fits_iq[1,:][bad_fit_iq]/all_fits_iq[2,:][bad_fit_iq])),'*',color = 'k')
-    
+    plt.plot(res_index, all_fits_mag[1, :], 'o', label="Qr Mag", color='g')
+    plt.plot(res_index, all_fits_iq[1, :], '*', label="Qr IQ", color='g')
+    plt.plot(res_index[bad_fit_mag], all_fits_mag[1, :][bad_fit_mag], 'o', color='k')
+    plt.plot(res_index[bad_fit_iq], all_fits_iq[1, :][bad_fit_iq], '*', color='k')
+
+    plt.plot(res_index, all_fits_mag[1, :] / all_fits_mag[2, :], 'o', label="Qc Mag", color='b')
+    plt.plot(res_index, all_fits_iq[1, :] / all_fits_mag[2, :], '*', label="Qc IQ", color='b')
+    plt.plot(res_index[bad_fit_mag], all_fits_mag[1, :][bad_fit_mag] / all_fits_mag[2, :][bad_fit_mag], 'o', color='k')
+    plt.plot(res_index[bad_fit_iq], all_fits_iq[1, :][bad_fit_iq] / all_fits_mag[2, :][bad_fit_iq], '*', color='k')
+
+    plt.plot(res_index, 1 / (1 / all_fits_mag[1, :] - 1 / (all_fits_mag[1, :] / all_fits_mag[2, :])), 'o',
+             label="Qi Mag", color='r')
+    plt.plot(res_index, 1 / (1 / all_fits_iq[1, :] - 1 / (all_fits_iq[1, :] / all_fits_iq[2, :])), '*', label="Qi IQ",
+             color='r')
+    plt.plot(res_index[bad_fit_mag], 1 / (1 / all_fits_mag[1, :][bad_fit_mag] - 1 / (
+                all_fits_mag[1, :][bad_fit_mag] / all_fits_mag[2, :][bad_fit_mag])), 'o', color='k')
+    plt.plot(res_index[bad_fit_iq], 1 / (1 / all_fits_iq[1, :][bad_fit_iq] - 1 / (
+                all_fits_iq[1, :][bad_fit_iq] / all_fits_iq[2, :][bad_fit_iq])), '*', color='k')
+
     plt.xlabel("Resonator index")
     plt.ylabel("Resonator Q")
     plt.yscale('log')
@@ -227,200 +249,210 @@ def fit_fine_gain_std(fine_name,gain_name,reduced_chi_squared_cutoff = 1000.,plo
     pdf_pages.savefig(fig)
     plt.close()
 
-    fig = plt.figure(3,figsize = (12,6))
+    fig = plt.figure(3, figsize=(12, 6))
     plt.title("Non linearity parameter a")
-    plt.plot(res_index,all_fits_mag[4,:],'o',label = "a Mag")
-    plt.plot(res_index,all_fits_iq[4,:],'o',label = "a IQ")
-    plt.plot(res_index[bad_fit_mag],all_fits_mag[4,:][bad_fit_mag],'o',color = 'k')
-    plt.plot(res_index[bad_fit_iq],all_fits_iq[4,:][bad_fit_iq],'o',color = 'k')
-    
+    plt.plot(res_index, all_fits_mag[4, :], 'o', label="a Mag")
+    plt.plot(res_index, all_fits_iq[4, :], 'o', label="a IQ")
+    plt.plot(res_index[bad_fit_mag], all_fits_mag[4, :][bad_fit_mag], 'o', color='k')
+    plt.plot(res_index[bad_fit_iq], all_fits_iq[4, :][bad_fit_iq], 'o', color='k')
+
     plt.xlabel("Resonator index")
     plt.ylabel("Non-linearity parameter a")
-    plt.ylim(0,1)
+    plt.ylim(0, 1)
     plt.legend()
     pdf_pages.savefig(fig)
     plt.close()
 
     pdf_pages.close()
 
-    np.save(outfile_dir+"/"+"all_fits_mag",all_fits_mag)
-    np.save(outfile_dir+"/"+"all_fits_iq",all_fits_iq)
-    np.savetxt(outfile_dir+"/"+"all_fits_mag.csv",all_fits_mag,delimiter = ',')
-    np.savetxt(outfile_dir+"/"+"all_fits_iq.csv",all_fits_iq,delimiter = ',')
-
-
+    np.save(outfile_dir + "/" + "all_fits_mag", all_fits_mag)
+    np.save(outfile_dir + "/" + "all_fits_iq", all_fits_iq)
+    np.savetxt(outfile_dir + "/" + "all_fits_mag.csv", all_fits_mag, delimiter=',')
+    np.savetxt(outfile_dir + "/" + "all_fits_iq.csv", all_fits_iq, delimiter=',')
 
 
 # this function fits a fine and gain scan combo produced by the ASU multitone system
-def fit_fine_gain(fine_name,gain_name):
-
-        
+def fit_fine_gain(fine_name, gain_name, fine_z_err=None, gain_z_err=None):
     fine = read_multitone.read_iq_sweep(fine_name)
     gain = read_multitone.read_iq_sweep(gain_name)
     outfile_dir = fine_name
-    center_freqs = fine['freqs'][fine['freqs'].shape[0]//2,:]
+    center_freqs = fine['freqs'][fine['freqs'].shape[0] // 2, :]
 
+    pdf_pages = PdfPages(outfile_dir + "/" + "fit_plots.pdf")
 
-    pdf_pages = PdfPages(outfile_dir+"/"+"fit_plots.pdf")
+    all_fits_mag = np.zeros((8, fine['freqs'].shape[1]))
+    all_fits_iq = np.zeros((9, fine['freqs'].shape[1]))
 
-    all_fits_mag = np.zeros((8,fine['freqs'].shape[1]))
-    all_fits_iq = np.zeros((9,fine['freqs'].shape[1]))
+    for i in range(0, fine['freqs'].shape[1]):
+        fine_f = fine['freqs'][:, i] * 10 ** 6
+        gain_f = gain['freqs'][:, i] * 10 ** 6
+        fine_z = fine['I'][:, i] + 1.j * fine['Q'][:, i]
+        gain_z = gain['I'][:, i] + 1.j * gain['Q'][:, i]
 
-    for i in range(0,fine['freqs'].shape[1]):
-        fine_f = fine['freqs'][:,i]*10**6
-        gain_f = gain['freqs'][:,i]*10**6
-        fine_z = fine['I'][:,i]+1.j*fine['Q'][:,i]
-        gain_z = gain['I'][:,i]+1.j*gain['Q'][:,i]
-
-        #flag data that is too close to other resonators              
-        distance = center_freqs-center_freqs[i]
-        if center_freqs[i] != np.min(center_freqs): #don't do if lowest frequency resonator
-            closest_lower_dist = -np.min(np.abs(distance[np.where(distance<0)]))
-            closest_lower_index = np.where(distance ==closest_lower_dist)[0][0]
-            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index])/2.
+        # flag data that is too close to other resonators
+        distance = center_freqs - center_freqs[i]
+        if center_freqs[i] != np.min(center_freqs):  # don't do if lowest frequency resonator
+            closest_lower_dist = -np.min(np.abs(distance[np.where(distance < 0)]))
+            closest_lower_index = np.where(distance == closest_lower_dist)[0][0]
+            halfway_low = (center_freqs[i] + center_freqs[closest_lower_index]) / 2.
         else:
             halfway_low = 0
 
-        if center_freqs[i] != np.max(center_freqs): #don't do if highest frequenct
-            closest_higher_dist = np.min(np.abs(distance[np.where(distance>0)]))
-            closest_higher_index = np.where(distance ==closest_higher_dist)[0][0]
-            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index])/2.
+        if center_freqs[i] != np.max(center_freqs):  # don't do if highest frequenct
+            closest_higher_dist = np.min(np.abs(distance[np.where(distance > 0)]))
+            closest_higher_index = np.where(distance == closest_higher_dist)[0][0]
+            halfway_high = (center_freqs[i] + center_freqs[closest_higher_index]) / 2.
         else:
             halfway_high = np.inf
-           
-        use_index = np.where(((fine_f/10**6>halfway_low) & (fine_f/10**6<halfway_high)))
+
+        use_index = np.where(((fine_f / 10 ** 6 > halfway_low) & (fine_f / 10 ** 6 < halfway_high)))
         fine_f = fine_f[use_index]
         fine_z = fine_z[use_index]
 
-        #flag gain data that is to close to all of the resonators
-        fine_span = (fine_f[-1]-fine_f[0])/10**6
+        # flag gain data that is to close to all of the resonators
+        fine_span = (fine_f[-1] - fine_f[0]) / 10 ** 6
         use_boolean = np.zeros(len(gain_f))
-        for j in range(0,len(gain_f)):
-            if (np.abs(gain_f[j]/10**6-center_freqs)< fine_span/2.).any():
+        for j in range(0, len(gain_f)):
+            if (np.abs(gain_f[j] / 10 ** 6 - center_freqs) < fine_span / 2.).any():
                 use_boolean[j] = 1
 
         use_index_gain = np.where(use_boolean != 1)
-        if len(use_index_gain[0]>1):
+        if len(use_index_gain[0] > 1):
             gain_f = gain_f[use_index_gain]
             gain_z = gain_z[use_index_gain]
 
-
-        fig = plt.figure(i,figsize = (16,10))
+        fig = plt.figure(i, figsize=(16, 10))
 
         plt.subplot(231)
-        plt.title("Resonator Index "+str(i))
-        plt.plot(fine['freqs'][:,i],10*np.log10(fine['I'][:,i]**2+fine['Q'][:,i]**2),'o',label = "fine")
-        plt.plot(gain['freqs'][:,i],10*np.log10(gain['I'][:,i]**2+gain['Q'][:,i]**2),'o',label = "gain")
+        plt.title("Resonator Index " + str(i))
+        plt.plot(fine['freqs'][:, i], 10 * np.log10(fine['I'][:, i] ** 2 + fine['Q'][:, i] ** 2), 'o', label="fine")
+        plt.plot(gain['freqs'][:, i], 10 * np.log10(gain['I'][:, i] ** 2 + gain['Q'][:, i] ** 2), 'o', label="gain")
         plt.xlabel("Frequency (MHz)")
         plt.ylabel("Power (dB)")
 
         plt.subplot(232)
-        plt.plot(fine['freqs'][:,i],10*np.log10(fine['I'][:,i]**2+fine['Q'][:,i]**2),'o')
-        plt.plot(gain['freqs'][:,i],10*np.log10(gain['I'][:,i]**2+gain['Q'][:,i]**2),'o')
+        plt.plot(fine['freqs'][:, i], 10 * np.log10(fine['I'][:, i] ** 2 + fine['Q'][:, i] ** 2), 'o')
+        plt.plot(gain['freqs'][:, i], 10 * np.log10(gain['I'][:, i] ** 2 + gain['Q'][:, i] ** 2), 'o')
         plt.xlabel("Frequency (MHz)")
         plt.ylabel("Power (dB)")
-        plt.xlim(np.min(fine['freqs'][:,i]),np.max(fine['freqs'][:,i]))
+        plt.xlim(np.min(fine['freqs'][:, i]), np.max(fine['freqs'][:, i]))
 
         # fit nonlinear magnitude
         try:
-            x0 = resonance_fitting.guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-            fit_dict_mag = resonance_fitting.fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_, fine_z_err = fine_z_err, gain_z_err = gain_z_errz, x0=x0)
-            #,bounds =bounds)
-            all_fits_mag[:,i] = fit_dict_mag['fit'][0]
+            x0 = guess_x0_mag_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+            fit_dict_mag = fit_nonlinear_mag_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err=fine_z_err,
+                                                 gain_z_err=gain_z_err, x0=x0)
+            # ,bounds =bounds)
+            all_fits_mag[:, i] = fit_dict_mag['fit'][0]
             plt.subplot(231)
-            plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+",label = "fit")
-            plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x",label = "x0 guess")
-            plt.title("f ="+str(fit_dict_mag['fit'][0][0]/10**6)[0:7]+"MHz, a="+"{:.2f}".format(fit_dict_mag['fit'][0][4]))
+            plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+", label="fit")
+            plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x",
+                     label="x0 guess")
+            plt.title("f =" + str(fit_dict_mag['fit'][0][0] / 10 ** 6)[0:7] + "MHz, a=" + "{:.2f}".format(
+                fit_dict_mag['fit'][0][4]))
             plt.legend()
             plt.subplot(232)
-            plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['fit_result']),"+")
-            plt.plot(fit_dict_mag['fit_freqs']/10**6,10*np.log10(fit_dict_mag['x0_result']),"x")
-
-            plt.text(0.75, 0.85, "fr  = "+"{:.3f}".format(fit_dict_mag['fit'][0][0]/10**6)+" MHz", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.80, "Qr  = "+"{:.0f}".format(fit_dict_mag['fit'][0][1])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.75, "amp = "+"{:.2f}".format(fit_dict_mag['fit'][0][2])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.70, "phi = "+"{:.2f}".format(fit_dict_mag['fit'][0][3])+" radians", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.65, "a   = "+"{:.2f}".format(fit_dict_mag['fit'][0][4])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.60, "b0  = "+"{:.0f}".format(fit_dict_mag['fit'][0][5])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.55, "b1  = "+"{:.0f}".format(fit_dict_mag['fit'][0][6])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            
+            plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['fit_result']), "+")
+            plt.plot(fit_dict_mag['fit_freqs'] / 10 ** 6, 10 * np.log10(fit_dict_mag['x0_result']), "x")
+
+            plt.text(0.75, 0.85, "fr  = " + "{:.3f}".format(fit_dict_mag['fit'][0][0] / 10 ** 6) + " MHz", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.80, "Qr  = " + "{:.0f}".format(fit_dict_mag['fit'][0][1]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.75, "amp = " + "{:.2f}".format(fit_dict_mag['fit'][0][2]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.70, "phi = " + "{:.2f}".format(fit_dict_mag['fit'][0][3]) + " radians", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.65, "a   = " + "{:.2f}".format(fit_dict_mag['fit'][0][4]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.60, "b0  = " + "{:.0f}".format(fit_dict_mag['fit'][0][5]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.55, "b1  = " + "{:.0f}".format(fit_dict_mag['fit'][0][6]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+
         except Exception as e:
             print(e)
             print("could not fit the resonator")
 
-
-        plt.subplot(234,aspect ='equal')
-        plt.plot(fine['I'][:,i],fine['Q'][:,i],'o')
-        plt.plot(gain['I'][:,i],gain['Q'][:,i],'o')
+        plt.subplot(234, aspect='equal')
+        plt.plot(fine['I'][:, i], fine['Q'][:, i], 'o')
+        plt.plot(gain['I'][:, i], gain['Q'][:, i], 'o')
         plt.xlabel("I")
         plt.ylabel("Q")
 
-        plt.subplot(235,aspect ='equal')
-        plt.plot(fine['I'][:,i],fine['Q'][:,i],'o')
-        plt.plot(gain['I'][:,i],gain['Q'][:,i],'o')
+        plt.subplot(235, aspect='equal')
+        plt.plot(fine['I'][:, i], fine['Q'][:, i], 'o')
+        plt.plot(gain['I'][:, i], gain['Q'][:, i], 'o')
         plt.xlabel("I")
         plt.ylabel("Q")
-        plt.xlim(np.min(fine['I'][:,i]),np.max(fine['I'][:,i]))
-        plt.ylim(np.min(fine['Q'][:,i]),np.max(fine['Q'][:,i]))
+        plt.xlim(np.min(fine['I'][:, i]), np.max(fine['I'][:, i]))
+        plt.ylim(np.min(fine['Q'][:, i]), np.max(fine['Q'][:, i]))
 
-
-        # fit nonlinear iq 
+        # fit nonlinear iq
         try:
-            x0 = resonance_fitting.guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose = True)
-            fit_dict_iq = resonance_fitting.fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err = fine_z_err, gain_z_err = gain_z_err, x0=x0)
-            all_fits_iq[:,i] = fit_dict_iq['fit'][0]
-            plt.subplot(234,aspect ='equal')
-            plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-            plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-            plt.title("f ="+str(fit_dict_iq['fit'][0][0]/10**6)[0:7]+"MHz, a="+"{:.2f}".format(fit_dict_iq['fit'][0][4]))
-            plt.subplot(235,aspect ='equal')
-            plt.plot(np.real(fit_dict_iq['fit_result']),np.imag(fit_dict_iq['fit_result']),"+")
-            plt.plot(np.real(fit_dict_iq['x0_result']),np.imag(fit_dict_iq['x0_result']),"x")
-            plt.plot(fine['I'][:,i],fine['Q'][:,i])
-
-            plt.text(0.75, 0.45, "fr  = "+"{:.3f}".format(fit_dict_iq['fit'][0][0]/10**6)+" MHz", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.4, "Qr  = "+"{:.0f}".format(fit_dict_iq['fit'][0][1])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.35, "amp = "+"{:.2f}".format(fit_dict_iq['fit'][0][2])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.3, "phi = "+"{:.2f}".format(fit_dict_iq['fit'][0][3])+" radians", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.25, "a   = "+"{:.2f}".format(fit_dict_iq['fit'][0][4])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.2, "i0  = "+"{:.0f}".format(fit_dict_iq['fit'][0][5])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.15, "q0  = "+"{:.0f}".format(fit_dict_iq['fit'][0][6])+" ", fontsize=14, transform=plt.gcf().transFigure)
-            plt.text(0.75, 0.1, "tau = "+"{:.2f}".format(fit_dict_iq['fit'][0][7]*10**7)+" x 10^-7 ", fontsize=14, transform=plt.gcf().transFigure)
-            
+            x0 = guess_x0_iq_nonlinear_sep(fine_f, fine_z, gain_f, gain_z, verbose=True)
+            fit_dict_iq = fit_nonlinear_iq_sep(fine_f, fine_z, gain_f, gain_z, fine_z_err=fine_z_err,
+                                               gain_z_err=gain_z_err, x0=x0)
+            all_fits_iq[:, i] = fit_dict_iq['fit'][0]
+            plt.subplot(234, aspect='equal')
+            plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+            plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+            plt.title("f =" + str(fit_dict_iq['fit'][0][0] / 10 ** 6)[0:7] + "MHz, a=" + "{:.2f}".format(
+                fit_dict_iq['fit'][0][4]))
+            plt.subplot(235, aspect='equal')
+            plt.plot(np.real(fit_dict_iq['fit_result']), np.imag(fit_dict_iq['fit_result']), "+")
+            plt.plot(np.real(fit_dict_iq['x0_result']), np.imag(fit_dict_iq['x0_result']), "x")
+            plt.plot(fine['I'][:, i], fine['Q'][:, i])
+
+            plt.text(0.75, 0.45, "fr  = " + "{:.3f}".format(fit_dict_iq['fit'][0][0] / 10 ** 6) + " MHz", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.4, "Qr  = " + "{:.0f}".format(fit_dict_iq['fit'][0][1]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.35, "amp = " + "{:.2f}".format(fit_dict_iq['fit'][0][2]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.3, "phi = " + "{:.2f}".format(fit_dict_iq['fit'][0][3]) + " radians", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.25, "a   = " + "{:.2f}".format(fit_dict_iq['fit'][0][4]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.2, "i0  = " + "{:.0f}".format(fit_dict_iq['fit'][0][5]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.15, "q0  = " + "{:.0f}".format(fit_dict_iq['fit'][0][6]) + " ", fontsize=14,
+                     transform=plt.gcf().transFigure)
+            plt.text(0.75, 0.1, "tau = " + "{:.2f}".format(fit_dict_iq['fit'][0][7] * 10 ** 7) + " x 10^-7 ",
+                     fontsize=14, transform=plt.gcf().transFigure)
+
         except Exception as e:
             print(e)
             print("could not fit the resonator")
 
-
-        plt.suptitle("Resonator index = " +str(i) +", Frequency = "+str(center_freqs[i])[0:7])
-
-
+        plt.suptitle("Resonator index = " + str(i) + ", Frequency = " + str(center_freqs[i])[0:7])
 
         pdf_pages.savefig(fig)
         plt.close(fig)
 
     pdf_pages.close()
 
-    pdf_pages = PdfPages(outfile_dir+"/"+"fit_results.pdf")
+    pdf_pages = PdfPages(outfile_dir + "/" + "fit_results.pdf")
 
-    fig = plt.figure(1, figsize = (12,6))
+    fig = plt.figure(1, figsize=(12, 6))
     plt.title("Center frequency")
-    plt.plot(all_fits_mag[0,:]/10**6,'o',label = "Mag fit")
-    plt.plot(all_fits_iq[0,:]/10**6,'o',label = "IQ fit")
+    plt.plot(all_fits_mag[0, :] / 10 ** 6, 'o', label="Mag fit")
+    plt.plot(all_fits_iq[0, :] / 10 ** 6, 'o', label="IQ fit")
     plt.xlabel("resonator index")
     plt.ylabel("Resonator Frequency (MHz)")
-    plt.legend(loc = 4)
+    plt.legend(loc=4)
     pdf_pages.savefig(fig)
     plt.close()
 
-    fig = plt.figure(2,figsize = (12,6))
+    fig = plt.figure(2, figsize=(12, 6))
     plt.title("Resonator Qs")
-    plt.plot(all_fits_mag[1,:],'o',label = "Qr Mag",color = 'g')
-    plt.plot(all_fits_iq[1,:],'*',label = "Qr IQ",color = 'g')
-    plt.plot(all_fits_mag[1,:]/all_fits_mag[2,:],'o',label = "Qc Mag",color = 'b')
-    plt.plot(all_fits_iq[1,:]/all_fits_mag[2,:],'*',label = "Qc IQ",color = 'b')
-    plt.plot(1/(1/all_fits_mag[1,:]-1/(all_fits_mag[1,:]/all_fits_mag[2,:])),'o',label = "Qi Mag",color = 'r')
-    plt.plot(1/(1/all_fits_iq[1,:]-1/(all_fits_iq[1,:]/all_fits_iq[2,:])),'*',label = "Qi IQ",color = 'r')
+    plt.plot(all_fits_mag[1, :], 'o', label="Qr Mag", color='g')
+    plt.plot(all_fits_iq[1, :], '*', label="Qr IQ", color='g')
+    plt.plot(all_fits_mag[1, :] / all_fits_mag[2, :], 'o', label="Qc Mag", color='b')
+    plt.plot(all_fits_iq[1, :] / all_fits_mag[2, :], '*', label="Qc IQ", color='b')
+    plt.plot(1 / (1 / all_fits_mag[1, :] - 1 / (all_fits_mag[1, :] / all_fits_mag[2, :])), 'o', label="Qi Mag",
+             color='r')
+    plt.plot(1 / (1 / all_fits_iq[1, :] - 1 / (all_fits_iq[1, :] / all_fits_iq[2, :])), '*', label="Qi IQ", color='r')
     plt.xlabel("Resonator index")
     plt.ylabel("Resonator Q")
     plt.yscale('log')
@@ -428,483 +460,480 @@ def fit_fine_gain(fine_name,gain_name):
     pdf_pages.savefig(fig)
     plt.close()
 
-    fig = plt.figure(3,figsize = (12,6))
+    fig = plt.figure(3, figsize=(12, 6))
     plt.title("Non linearity parameter a")
-    plt.plot(all_fits_mag[4,:],'o',label = "a Mag")
-    plt.plot(all_fits_iq[4,:],'o',label = "a IQ")
+    plt.plot(all_fits_mag[4, :], 'o', label="a Mag")
+    plt.plot(all_fits_iq[4, :], 'o', label="a IQ")
     plt.xlabel("Resonator index")
     plt.ylabel("Non-linearity parameter a")
-    plt.ylim(0,1)
+    plt.ylim(0, 1)
     plt.legend()
     pdf_pages.savefig(fig)
     plt.close()
 
     pdf_pages.close()
 
-    np.save(outfile_dir+"/"+"all_fits_mag",all_fits_mag)
-    np.save(outfile_dir+"/"+"all_fits_iq",all_fits_iq)
-    np.savetxt(outfile_dir+"/"+"all_fits_mag.csv",all_fits_mag,delimiter = ',')
-    np.savetxt(outfile_dir+"/"+"all_fits_iq.csv",all_fits_iq,delimiter = ',')
+    np.save(outfile_dir + "/" + "all_fits_mag", all_fits_mag)
+    np.save(outfile_dir + "/" + "all_fits_iq", all_fits_iq)
+    np.savetxt(outfile_dir + "/" + "all_fits_mag.csv", all_fits_mag, delimiter=',')
+    np.savetxt(outfile_dir + "/" + "all_fits_iq.csv", all_fits_iq, delimiter=',')
 
 
-def calibrate_list(fine_filename,gain_filename,stream_list,skip_beginning = 0,plot_period = 10,bin_num = 1,outfile_dir = "./",sample_rate = 488.28125):
-    #this is for batch fitting stream data in multiple dir files, mostly
-    #for the beam map separate
+def calibrate_list(fine_filename, gain_filename, stream_list, skip_beginning=0, bin_num=1, sample_rate=488.28125):
+    # this is for batch fitting stream data in multiple dir files, mostly
+    # for the beam map separate
     fine_dict = read_multitone.read_iq_sweep(fine_filename)
     gain_dict = read_multitone.read_iq_sweep(gain_filename)
     stream_dicts = [read_multitone.read_stream(stream_filename)
                     for stream_filename in stream_list]
 
-    gain_z = gain_dict['I'] +1.j*gain_dict['Q']
-    fine_z = fine_dict['I'] +1.j*fine_dict['Q']
-    stream_z = [stream_dict['I_stream'][skip_beginning:] +1.j*stream_dict['Q_stream'][skip_beginning:] for stream_dict in stream_dicts]
-    stream_time = [np.asarray(stream_dict['packet_count'])[skip_beginning:]*1/sample_rate
-            for stream_dict in stream_dicts]
+    gain_z = gain_dict['I'] + 1.j * gain_dict['Q']
+    fine_z = fine_dict['I'] + 1.j * fine_dict['Q']
+    stream_z = [stream_dict['I_stream'][skip_beginning:] + 1.j * stream_dict['Q_stream'][skip_beginning:] for
+                stream_dict in stream_dicts]
+    stream_time = [np.asarray(stream_dict['packet_count'])[skip_beginning:] * 1 / sample_rate
+                   for stream_dict in stream_dicts]
     stream_time = [time - time[0] for time in stream_time]
 
-
-    #bin the data if you like
-    if bin_num !=1:
-        for i in range(0,stream_z.shape[1]):
+    # bin the data if you like
+    if bin_num != 1:
+        for i in range(0, stream_z.shape[1]):
             if i == 0:
-                stream_z_downsamp = np.zeros((stream_z.shape[0]/bin_num,stream_z.shape[1]),dtype = 'complex')
-            stream_z_downsamp[:,i] = np.mean(stream_z[0:stream_z.shape[0]/bin_num*bin_num,i].reshape(-1,bin_num),axis = 1) #int math
-        stream_time_downsamp = np.mean(stream_time[0:stream_time.shape[0]/bin_num*bin_num].reshape(-1,bin_num),axis = 1) #int math 
+                stream_z_downsamp = np.zeros((stream_z.shape[0] / bin_num, stream_z.shape[1]), dtype='complex')
+            stream_z_downsamp[:, i] = np.mean(stream_z[0:stream_z.shape[0] / bin_num * bin_num, i].reshape(-1, bin_num),
+                                              axis=1)  # int math
+        stream_time_downsamp = np.mean(stream_time[0:stream_time.shape[0] / bin_num * bin_num].reshape(-1, bin_num),
+                                       axis=1)  # int math
         stream_z = stream_z_downsamp
         stream_time = stream_time_downsamp
-        
 
-    #initalize some arrays to hold the calibrated data
-    stream_corr_all = [np.zeros(set_z.shape,dtype = 'complex')
-            for set_z in stream_z]
-    gain_corr_all = np.zeros(gain_z.shape,dtype = 'complex')
-    fine_corr_all = np.zeros(fine_z.shape,dtype = 'complex')
+    # initalize some arrays to hold the calibrated data
+    stream_corr_all = [np.zeros(set_z.shape, dtype='complex')
+                       for set_z in stream_z]
+    gain_corr_all = np.zeros(gain_z.shape, dtype='complex')
+    fine_corr_all = np.zeros(fine_z.shape, dtype='complex')
     stream_df_over_f_all = [np.zeros(set_z.shape) for set_z in stream_z]
-    fit_vals = np.zeros((3,fine_z.shape[1]))
+    fit_vals = np.zeros((3, fine_z.shape[1]))
 
-
-    for k in range(0,min(fine_dict['I'].shape[1], stream_z[0].shape[1])):
+    for k in range(0, min(fine_dict['I'].shape[1], stream_z[0].shape[1])):
         print(k)
-       
-        f_stream = fine_dict['freqs'][len(fine_dict['freqs'][:,k])/2,k]*10**6
-        #normalize amplitude varation in gain scan
-        amp_norm_dict = [resonance_fitting.amplitude_normalization_sep(
-                gain_dict['freqs'][:,k]*10**6, gain_z[:,k],
-                fine_dict['freqs'][:,k]*10**6, fine_z[:,k], f_stream,
-                set_z[:,k]) for set_z in stream_z]
-
-
-        #fit the gain
-        gain_phase = np.arctan2(np.real(amp_norm_dict[0]['normalized_gain']),np.imag(amp_norm_dict[0]['normalized_gain']))
-        tau,fit_data_phase,gain_phase_rot = calibrate.fit_cable_delay(gain_dict['freqs'][:, k] * 10 ** 6, gain_phase)
-        
-        #remove cable delay
-        gain_corr = calibrate.remove_cable_delay(gain_dict['freqs'][:, k] * 10 ** 6, amp_norm_dict[0]['normalized_gain'], tau)
-        fine_corr = calibrate.remove_cable_delay(fine_dict['freqs'][:, k] * 10 ** 6, amp_norm_dict[0]['normalized_fine'], tau)
-        stream_corr = [calibrate.remove_cable_delay(f_stream, set_norm_dict['normalized_stream'], tau) for set_norm_dict in amp_norm_dict]
-        
+
+        f_stream = fine_dict['freqs'][len(fine_dict['freqs'][:, k]) / 2, k] * 10 ** 6
+        # normalize amplitude variation in gain scan
+        amp_norm_dict = [amplitude_normalization_sep(
+            gain_dict['freqs'][:, k] * 10 ** 6, gain_z[:, k],
+            fine_dict['freqs'][:, k] * 10 ** 6, fine_z[:, k], f_stream,
+            set_z[:, k]) for set_z in stream_z]
+
+        # fit the gain
+        gain_phase = np.arctan2(np.real(amp_norm_dict[0]['normalized_gain']),
+                                np.imag(amp_norm_dict[0]['normalized_gain']))
+        tau, fit_data_phase, gain_phase_rot = calibrate.fit_cable_delay(gain_dict['freqs'][:, k] * 10 ** 6, gain_phase)
+
+        # remove cable delay
+        gain_corr = calibrate.remove_cable_delay(gain_dict['freqs'][:, k] * 10 ** 6,
+                                                 amp_norm_dict[0]['normalized_gain'], tau)
+        fine_corr = calibrate.remove_cable_delay(fine_dict['freqs'][:, k] * 10 ** 6,
+                                                 amp_norm_dict[0]['normalized_fine'], tau)
+        stream_corr = [calibrate.remove_cable_delay(f_stream, set_norm_dict['normalized_stream'], tau) for set_norm_dict
+                       in amp_norm_dict]
+
         # fit a cicle to the data
-        xc, yc, R, residu  = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
-        fit_vals[0,k] = xc
-        fit_vals[1,k] = yc
-        fit_vals[2,k] = R
+        xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
+        fit_vals[0, k] = xc
+        fit_vals[1, k] = yc
+        fit_vals[2, k] = R
 
-        #move the data to the origin
+        # move the data to the origin
 
-        gain_corr = gain_corr - xc -1j*yc
-        fine_corr = fine_corr - xc -1j*yc
-        stream_corr = [set_corr  - xc -1j*yc for set_corr in stream_corr]
+        gain_corr = gain_corr - xc - 1j * yc
+        fine_corr = fine_corr - xc - 1j * yc
+        stream_corr = [set_corr - xc - 1j * yc for set_corr in stream_corr]
 
         # rotate so streaming data is at 0 pi
-        phase_stream = [np.arctan2(np.imag(set_corr),np.real(set_corr))
-                for set_corr in stream_corr]
+        phase_stream = [np.arctan2(np.imag(set_corr), np.real(set_corr))
+                        for set_corr in stream_corr]
         med_phase = np.median(phase_stream)
 
-        gain_corr_all[:,k]  = gain_corr = gain_corr*np.exp(-1j*med_phase) 
-        fine_corr_all[:,k] = fine_corr = fine_corr*np.exp(-1j*med_phase) 
+        gain_corr_all[:, k] = gain_corr = gain_corr * np.exp(-1j * med_phase)
+        fine_corr_all[:, k] = fine_corr = fine_corr * np.exp(-1j * med_phase)
         for i in range(len(stream_corr)):
-            stream_corr_all[i][:,k] = stream_corr[i] = stream_corr[i]*np.exp(
-                    -1j*med_phase)
+            stream_corr_all[i][:, k] = stream_corr[i] = stream_corr[i] * np.exp(
+                -1j * med_phase)
 
-        phase_fine = np.arctan2(np.imag(fine_corr),np.real(fine_corr))
-        use_index = np.where((-np.pi/2.<phase_fine) & (phase_fine<np.pi/2))
-        phase_stream = [np.arctan2(np.imag(set_corr),np.real(set_corr))
-                for set_corr in stream_corr]
+        phase_fine = np.arctan2(np.imag(fine_corr), np.real(fine_corr))
+        use_index = np.where((-np.pi / 2. < phase_fine) & (phase_fine < np.pi / 2))
+        phase_stream = [np.arctan2(np.imag(set_corr), np.real(set_corr))
+                        for set_corr in stream_corr]
 
-        #interp phase to frequency
-        f_interp = interpolate.interp1d(phase_fine, fine_dict['freqs'][:,k],kind = 'quadratic',bounds_error = False,fill_value = 0)
+        # interp phase to frequency
+        f_interp = interpolate.interp1d(phase_fine, fine_dict['freqs'][:, k], kind='quadratic', bounds_error=False,
+                                        fill_value=0)
 
-        phase_small = np.linspace(np.min(phase_fine),np.max(phase_fine),1000)
+        phase_small = np.linspace(np.min(phase_fine), np.max(phase_fine), 1000)
         for i in range(len(phase_stream)):
             freqs_stream = f_interp(phase_stream[i])
-            stream_df_over_f_all[i][:,k] = freqs_stream/np.mean(freqs_stream)-1.
+            stream_df_over_f_all[i][:, k] = freqs_stream / np.mean(freqs_stream) - 1.
 
-
-    #save everything to a dictionary
+    # save everything to a dictionary
     cal_dict = {
-    #                'fine_z': fine_z,
-    #                'gain_z': gain_z,
-    #                'stream_z': stream_z,
-    #                'fine_freqs':fine_dict['freqs'],
-    #                'gain_freqs':fine_dict['freqs'],
-    #                'stream_corr':stream_corr_all,
-                    'gain_corr':gain_corr_all,
-                    'fine_corr':fine_corr_all,
-    #                'stream_df_over_f':stream_df_over_f_all,
-    #                'time':stream_dict['time'],
-    #                'stream_time':stream_time}
-                     'fit_coords':fit_vals}
-
-    #save the dictionary
-    #pickle.dump( cal_dict, open(outfile_dir+ "cal.p", "wb" ),2 )
+        #                'fine_z': fine_z,
+        #                'gain_z': gain_z,
+        #                'stream_z': stream_z,
+        #                'fine_freqs':fine_dict['freqs'],
+        #                'gain_freqs':fine_dict['freqs'],
+        #                'stream_corr':stream_corr_all,
+        'gain_corr': gain_corr_all,
+        'fine_corr': fine_corr_all,
+        #                'stream_df_over_f':stream_df_over_f_all,
+        #                'time':stream_dict['time'],
+        #                'stream_time':stream_time}
+        'fit_coords': fit_vals}
+
+    # save the dictionary
+    # pickle.dump( cal_dict, open(outfile_dir+ "cal.p", "wb" ),2 )
     return stream_df_over_f_all, stream_time, cal_dict
 
 
 def calibrate_multi(fine_filename, gain_filename, stream_filename,
-        skip_beginning=0, plot_period=10, bin_num=1, outfile_dir="./",
-        sample_rate=488.28125, plot=True, **keywords):
-
-    #read in the scans
+                    skip_beginning=0, plot_period=10, bin_num=1, outfile_dir="./",
+                    sample_rate=488.28125, plot=True, **keywords):
+    # read in the scans
     fine_dict = read_multitone.read_iq_sweep(fine_filename)
     gain_dict = read_multitone.read_iq_sweep(gain_filename)
     stream_dict = read_multitone.read_stream(stream_filename)
 
-    #convert output to complex data
-    gain_z = gain_dict['I'] +1.j*gain_dict['Q']
-    fine_z = fine_dict['I'] +1.j*fine_dict['Q']
-    stream_z = stream_dict['I_stream'][skip_beginning:] +1.j*stream_dict['Q_stream'][skip_beginning:]
-    #generate relative packet times
-    stream_time = np.asarray(stream_dict['packet_count'])[skip_beginning:]*1/sample_rate
+    # convert output to complex data
+    gain_z = gain_dict['I'] + 1.j * gain_dict['Q']
+    fine_z = fine_dict['I'] + 1.j * fine_dict['Q']
+    stream_z = stream_dict['I_stream'][skip_beginning:] + 1.j * stream_dict['Q_stream'][skip_beginning:]
+    # generate relative packet times
+    stream_time = np.asarray(stream_dict['packet_count'])[skip_beginning:] * 1 / sample_rate
     stream_time = stream_time - stream_time[0]
 
-
-    #bin the data if you like
-    if bin_num !=1:
+    # bin the data if you like
+    if bin_num != 1:
         stream_z_downsamp = sum([stream_z
-            [:,i:bin_num * (stream_z.shape[1]//bin_num):bin_num]
-                for i in range(bin_num)]) / bin_num
+                                 [:, i:bin_num * (stream_z.shape[1] // bin_num):bin_num]
+                                 for i in range(bin_num)]) / bin_num
         stream_time_downsamp = sum([stream_time
-            [:,i:bin_num * (stream_time.shape[1]//bin_num):bin_num]
-                for i in range(bin_num)]) / bin_num
+                                    [:, i:bin_num * (stream_time.shape[1] // bin_num):bin_num]
+                                    for i in range(bin_num)]) / bin_num
         stream_z = stream_z_downsamp
         stream_time = stream_time_downsamp
-        
 
-    #initalize some arrays to hold the calibrated data
-    stream_corr_all = np.zeros(stream_z.shape,dtype = 'complex')
-    gain_corr_all = np.zeros(gain_z.shape,dtype = 'complex')
-    fine_corr_all = np.zeros(fine_z.shape,dtype = 'complex')
+    # initalize some arrays to hold the calibrated data
+    stream_corr_all = np.zeros(stream_z.shape, dtype='complex')
+    gain_corr_all = np.zeros(gain_z.shape, dtype='complex')
+    fine_corr_all = np.zeros(fine_z.shape, dtype='complex')
     stream_df_over_f_all = np.zeros(stream_z.shape)
-    circle_fit = np.ndarray((fine_dict['I'].shape[1],4))
+    circle_fit = np.ndarray((fine_dict['I'].shape[1], 4))
     amp_dicts = []
     cable_delay_data = []
 
-
-    for k in range(0,fine_dict['I'].shape[1]):
+    for k in range(0, fine_dict['I'].shape[1]):
         print(k)
-        
-        f_stream = fine_dict['freqs'][len(fine_dict['freqs'][:,k])/2,k]*10**6
-        #normalize amplitude varation in gain scan
-        amp_norm_dict = resonance_fitting.amplitude_normalization_sep(
-                gain_dict['freqs'][:,k]*1e6,
-                gain_z[:,k],
-                fine_dict['freqs'][:,k]*1e6,
-                fine_z[:,k],
-                f_stream,
-                stream_z[:,k])
+
+        f_stream = fine_dict['freqs'][len(fine_dict['freqs'][:, k]) / 2, k] * 10 ** 6
+        # normalize amplitude varation in gain scan
+        amp_norm_dict = amplitude_normalization_sep(
+            gain_dict['freqs'][:, k] * 1e6,
+            gain_z[:, k],
+            fine_dict['freqs'][:, k] * 1e6,
+            fine_z[:, k],
+            f_stream,
+            stream_z[:, k])
         amp_dicts.append(amp_norm_dict)
 
-        #fit the gain
+        # fit the gain
         gain_phase = np.arctan2(np.real(amp_norm_dict['normalized_gain']),
-                np.imag(amp_norm_dict['normalized_gain']))
-        tau,fit_data_phase,gain_phase_rot = calibrate.fit_cable_delay(
-                gain_dict['freqs'][:,k]*1e6,gain_phase)
+                                np.imag(amp_norm_dict['normalized_gain']))
+        tau, fit_data_phase, gain_phase_rot = calibrate.fit_cable_delay(
+            gain_dict['freqs'][:, k] * 1e6, gain_phase)
         cable_delay_data.append(
-                (gain_phase, tau, fit_data_phase, gain_phase_rot))
-        
-        #remove cable delay
+            (gain_phase, tau, fit_data_phase, gain_phase_rot))
+
+        # remove cable delay
         gain_corr = calibrate.remove_cable_delay(gain_dict['freqs'][:, k] * 1e6, amp_norm_dict['normalized_gain'], tau)
         fine_corr = calibrate.remove_cable_delay(fine_dict['freqs'][:, k] * 1e6, amp_norm_dict['normalized_fine'], tau)
         stream_corr = calibrate.remove_cable_delay(f_stream, amp_norm_dict['normalized_stream'], tau)
-        
+
         # fit a cicle to the data
-        xc, yc, R, residu  = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
-        circle_fit[k,0:3] = np.array([xc, yc, R])
+        xc, yc, R, residu = calibrate.leastsq_circle(np.real(fine_corr), np.imag(fine_corr))
+        circle_fit[k, 0:3] = np.array([xc, yc, R])
 
-        #move the data to the origin
-        gain_corr = gain_corr - xc -1j*yc
-        fine_corr = fine_corr - xc -1j*yc
-        stream_corr = stream_corr  - xc -1j*yc
+        # move the data to the origin
+        gain_corr = gain_corr - xc - 1j * yc
+        fine_corr = fine_corr - xc - 1j * yc
+        stream_corr = stream_corr - xc - 1j * yc
 
         # rotate so streaming data is at 0 pi
-        phase_stream = np.arctan2(np.imag(stream_corr),np.real(stream_corr))
-        if ("rotate_fine_first" in keywords): # if you have data that covers a large part of the iq loop
-            med_phase = np.arctan2(np.imag(fine_corr),np.real(fine_corr))[0]+np.pi
+        phase_stream = np.arctan2(np.imag(stream_corr), np.real(stream_corr))
+        if ("rotate_fine_first" in keywords):  # if you have data that covers a large part of the iq loop
+            med_phase = np.arctan2(np.imag(fine_corr), np.real(fine_corr))[0] + np.pi
         else:
             med_phase = np.median(phase_stream)
-        circle_fit[k,-1] = med_phase
-
-        gain_corr_all[:,k]  = gain_corr = gain_corr*np.exp(-1j*med_phase) 
-        fine_corr_all[:,k] = fine_corr = fine_corr*np.exp(-1j*med_phase) 
-        stream_corr_all[:,k] = stream_corr = stream_corr*np.exp(-1j*med_phase)
+        circle_fit[k, -1] = med_phase
 
+        gain_corr_all[:, k] = gain_corr = gain_corr * np.exp(-1j * med_phase)
+        fine_corr_all[:, k] = fine_corr = fine_corr * np.exp(-1j * med_phase)
+        stream_corr_all[:, k] = stream_corr = stream_corr * np.exp(-1j * med_phase)
 
-        phase_fine = np.arctan2(np.imag(fine_corr),np.real(fine_corr))
-        use_index = np.where((-np.pi/2.<phase_fine) & (phase_fine<np.pi/2))
-        phase_stream = np.arctan2(np.imag(stream_corr),np.real(stream_corr))
+        phase_fine = np.arctan2(np.imag(fine_corr), np.real(fine_corr))
+        use_index = np.where((-np.pi / 2. < phase_fine) & (phase_fine < np.pi / 2))
+        phase_stream = np.arctan2(np.imag(stream_corr), np.real(stream_corr))
 
-        #interp phase to frequency
-        f_interp = interpolate.interp1d(phase_fine, fine_dict['freqs'][:,k],kind = 'quadratic',bounds_error = False,fill_value = 0)
+        # interp phase to frequency
+        f_interp = interpolate.interp1d(phase_fine, fine_dict['freqs'][:, k], kind='quadratic', bounds_error=False,
+                                        fill_value=0)
 
-        phase_small = np.linspace(np.min(phase_fine),np.max(phase_fine),1000)
+        phase_small = np.linspace(np.min(phase_fine), np.max(phase_fine), 1000)
         freqs_stream = f_interp(phase_stream)
-        stream_df_over_f_all[:,k] = stream_df_over_f = freqs_stream/np.mean(freqs_stream)-1.
+        stream_df_over_f_all[:, k] = stream_df_over_f = freqs_stream / np.mean(freqs_stream) - 1.
 
-
-    #save everything to a dictionary
+    # save everything to a dictionary
     cal_dict = {'fine_z': fine_z,
-                    'gain_z': gain_z,
-                    'stream_z': stream_z,
-                    'fine_freqs':fine_dict['freqs'],
-                    'gain_freqs':gain_dict['freqs'],
-                    'stream_corr':stream_corr_all,
-                    'gain_corr':gain_corr_all,
-                    'fine_corr':fine_corr_all,
-                    'stream_df_over_f':stream_df_over_f_all,
-                    'time':stream_dict['time'],
-                    'stream_time':stream_time}
-
-    #plot the data if desired
+                'gain_z': gain_z,
+                'stream_z': stream_z,
+                'fine_freqs': fine_dict['freqs'],
+                'gain_freqs': gain_dict['freqs'],
+                'stream_corr': stream_corr_all,
+                'gain_corr': gain_corr_all,
+                'fine_corr': fine_corr_all,
+                'stream_df_over_f': stream_df_over_f_all,
+                'time': stream_dict['time'],
+                'stream_time': stream_time}
+
+    # plot the data if desired
     if plot:
         plot_calibrate(cal_dict, circle_fit, amp_dicts, cable_delay_data,
-        plot_period, outfile_dir)
+                       plot_period, outfile_dir)
 
-    #save the dictionary
-    pickle.dump( cal_dict, open(outfile_dir+ "cal.p", "wb" ),2 )
+    # save the dictionary
+    pickle.dump(cal_dict, open(outfile_dir + "cal.p", "wb"), 2)
     return cal_dict
 
 
 def plot_calibrate(cal_dict, circle_fit, amp_dicts, cable_delay_data,
-        plot_period, outfile_dir='./'):
-    pdf_pages = PdfPages(outfile_dir+"cal_plots.pdf")
+                   plot_period, outfile_dir='./'):
+    pdf_pages = PdfPages(outfile_dir + "cal_plots.pdf")
     for k in range(cal_dict['fine_z'].shape[1]):
-        fig = plt.figure(k,figsize = (16,10))
+        fig = plt.figure(k, figsize=(16, 10))
 
-        #plot the raw data
-        plt.subplot(241,aspect = 'equal')
+        # plot the raw data
+        plt.subplot(241, aspect='equal')
         plt.title("Raw data")
-        plt.plot(np.real(cal_dict['fine_z'][:,k]),
-                np.imag(cal_dict['fine_z'][:,k]),'o')
-        plt.plot(np.real(cal_dict['stream_z'][:,k][::plot_period]),
-                np.imag(cal_dict['stream_z'][:,k][::plot_period]),'.')
-        plt.plot(np.real(cal_dict['gain_z'])[:,k],
-                np.imag(cal_dict['gain_z'])[:,k],'o')
-
-        #plot fine and stream data
+        plt.plot(np.real(cal_dict['fine_z'][:, k]),
+                 np.imag(cal_dict['fine_z'][:, k]), 'o')
+        plt.plot(np.real(cal_dict['stream_z'][:, k][::plot_period]),
+                 np.imag(cal_dict['stream_z'][:, k][::plot_period]), '.')
+        plt.plot(np.real(cal_dict['gain_z'])[:, k],
+                 np.imag(cal_dict['gain_z'])[:, k], 'o')
+
+        # plot fine and stream data
         plt.subplot(242)
         plt.title("Raw data")
-        plt.plot(np.real(cal_dict['fine_z'])[:,k],
-                np.imag(cal_dict['fine_z'])[:,k],'o')
-        plt.plot(np.real(cal_dict['stream_z'][:,k][::plot_period]),
-                np.imag(cal_dict['stream_z'][:,k][::plot_period]),'.')
+        plt.plot(np.real(cal_dict['fine_z'])[:, k],
+                 np.imag(cal_dict['fine_z'])[:, k], 'o')
+        plt.plot(np.real(cal_dict['stream_z'][:, k][::plot_period]),
+                 np.imag(cal_dict['stream_z'][:, k][::plot_period]), '.')
 
-        #plot the fit of the gain amp/phase variation       
+        # plot the fit of the gain amp/phase variation
         plt.subplot(243)
         plt.title("Gain amplitude variation fit")
-        plt.plot(cal_dict['gain_freqs'][:,k]*1e6,
-                20.*np.log10(np.abs(cal_dict['gain_z'][:,k])),'o')
-        plt.plot(cal_dict['gain_freqs'][:,k]*1e6,
-                10.*np.log10(np.abs(amp_dicts[k]['normalized_gain'])**2),'o')
-        plt.plot(cal_dict['fine_freqs'][:,k]*1e6,
-                10.*np.log10(np.abs(amp_dicts[k]['normalized_fine'])**2),'o')
-        plt.plot(cal_dict['gain_freqs'][:,k]*1e6,
-                20.*np.log10(np.abs(amp_dicts[k]['poly_data'])))
-
-        #plot gain amp variation
+        plt.plot(cal_dict['gain_freqs'][:, k] * 1e6,
+                 20. * np.log10(np.abs(cal_dict['gain_z'][:, k])), 'o')
+        plt.plot(cal_dict['gain_freqs'][:, k] * 1e6,
+                 10. * np.log10(np.abs(amp_dicts[k]['normalized_gain']) ** 2), 'o')
+        plt.plot(cal_dict['fine_freqs'][:, k] * 1e6,
+                 10. * np.log10(np.abs(amp_dicts[k]['normalized_fine']) ** 2), 'o')
+        plt.plot(cal_dict['gain_freqs'][:, k] * 1e6,
+                 20. * np.log10(np.abs(amp_dicts[k]['poly_data'])))
+
+        # plot gain amp variation
         plt.subplot(244)
         plt.title("Data nomalized for gain amplitude variation")
         plt.plot(np.real(amp_dicts[k]['normalized_fine']),
-                np.imag(amp_dicts[k]['normalized_fine']),'o')
+                 np.imag(amp_dicts[k]['normalized_fine']), 'o')
         plt.plot(np.real(amp_dicts[k]['normalized_stream'][::plot_period]),
-                np.imag(amp_dicts[k]['normalized_stream'][::plot_period]),'.')
+                 np.imag(amp_dicts[k]['normalized_stream'][::plot_period]), '.')
 
         gain_phase, tau, fit_data_phase, gain_phase_rot = cable_delay_data[k]
-        #plot gain phase fit
+        # plot gain phase fit
         plt.subplot(245)
         plt.title("Gain phase fit")
-        plt.plot(cal_dict['gain_freqs'][:,k],gain_phase_rot,'o')
-        plt.plot(cal_dict['gain_freqs'][:,k],fit_data_phase)
+        plt.plot(cal_dict['gain_freqs'][:, k], gain_phase_rot, 'o')
+        plt.plot(cal_dict['gain_freqs'][:, k], fit_data_phase)
         plt.xlabel("Frequency (MHz)")
         plt.ylabel("Phase")
 
-        #unpack corr data       
-        gain_corr = cal_dict['gain_corr'][:,k]
-        fine_corr = cal_dict['fine_corr'][:,k]
-        stream_corr = cal_dict['stream_corr'][:,k]
-        #reverse the circle offset and rotation
-        med_phase = circle_fit[k,-1]
-        xc = circle_fit[k,0]
-        yc = circle_fit[k,1]
-        R = circle_fit[k,2]
-        gain_corr0 = gain_corr * np.exp(1.j*med_phase) + xc + 1.j * yc
-        fine_corr0 = fine_corr * np.exp(1.j*med_phase) + xc + 1.j * yc
-        stream_corr0 = stream_corr * np.exp(1.j*med_phase) + xc + 1.j * yc
-        
+        # unpack corr data
+        gain_corr = cal_dict['gain_corr'][:, k]
+        fine_corr = cal_dict['fine_corr'][:, k]
+        stream_corr = cal_dict['stream_corr'][:, k]
+        # reverse the circle offset and rotation
+        med_phase = circle_fit[k, -1]
+        xc = circle_fit[k, 0]
+        yc = circle_fit[k, 1]
+        R = circle_fit[k, 2]
+        gain_corr0 = gain_corr * np.exp(1.j * med_phase) + xc + 1.j * yc
+        fine_corr0 = fine_corr * np.exp(1.j * med_phase) + xc + 1.j * yc
+        stream_corr0 = stream_corr * np.exp(1.j * med_phase) + xc + 1.j * yc
 
         plt.subplot(246)
         plt.title("Cable delay removed")
-        plt.plot(np.real(gain_corr0),np.imag(gain_corr0),'o')
-        plt.plot(np.real(fine_corr0),np.imag(fine_corr0),'o')
+        plt.plot(np.real(gain_corr0), np.imag(gain_corr0), 'o')
+        plt.plot(np.real(fine_corr0), np.imag(fine_corr0), 'o')
         plt.plot(np.real(stream_corr0)[10:-10][::plot_period],
-                np.imag(stream_corr0)[10:-10][::plot_period],'.')
+                 np.imag(stream_corr0)[10:-10][::plot_period], '.')
 
-        #center and rotate IQ circle
+        # center and rotate IQ circle
         plt.subplot(247)
         plt.title("Moved to 0,0 and rotated")
         plt.plot(np.real(stream_corr)[2:-1][::plot_period],
-                np.imag(stream_corr)[2:-1][::plot_period],'.')
-        plt.plot(np.real(gain_corr),np.imag(gain_corr),'o')
-        plt.plot(np.real(fine_corr),np.imag(fine_corr),'o')
+                 np.imag(stream_corr)[2:-1][::plot_period], '.')
+        plt.plot(np.real(gain_corr), np.imag(gain_corr), 'o')
+        plt.plot(np.real(fine_corr), np.imag(fine_corr), 'o')
         calibrate.plot_data_circle(np.real(fine_corr) - xc, np.imag(fine_corr) - yc,
                                    0, 0, R)
 
-        #redo the phase fitting
-        phase_fine = np.arctan2(np.imag(fine_corr),np.real(fine_corr))
-        use_index = np.where((-np.pi/2.<phase_fine) & (phase_fine<np.pi/2))
-        phase_stream = np.arctan2(np.imag(stream_corr),np.real(stream_corr))
+        # redo the phase fitting
+        phase_fine = np.arctan2(np.imag(fine_corr), np.real(fine_corr))
+        use_index = np.where((-np.pi / 2. < phase_fine) & (phase_fine < np.pi / 2))
+        phase_stream = np.arctan2(np.imag(stream_corr), np.real(stream_corr))
 
-        #interp phase to frequency
-        f_interp = interpolate.interp1d(phase_fine, cal_dict['fine_freqs'][:,k],
-                kind = 'quadratic',bounds_error = False,fill_value = 0)
+        # interp phase to frequency
+        f_interp = interpolate.interp1d(phase_fine, cal_dict['fine_freqs'][:, k],
+                                        kind='quadratic', bounds_error=False, fill_value=0)
 
-        phase_small = np.linspace(np.min(phase_fine),np.max(phase_fine),1000)
+        phase_small = np.linspace(np.min(phase_fine), np.max(phase_fine), 1000)
         freqs_stream = f_interp(phase_stream)
 
-        #plot the stream phase
+        # plot the stream phase
         plt.subplot(248)
-        plt.plot(phase_fine,cal_dict['fine_freqs'][:,k],'o')
-        plt.plot(phase_small,f_interp(phase_small),'--')
-        plt.plot(phase_stream[::plot_period],freqs_stream[::plot_period],'.')
-        plt.ylim(np.min(freqs_stream)-(np.max(freqs_stream)-np.min(freqs_stream))*3,np.max(freqs_stream)+(np.max(freqs_stream)-np.min(freqs_stream))*3)
-        plt.xlim(np.min(phase_stream)-np.pi/4,np.max(phase_stream)+np.pi/4)
+        plt.plot(phase_fine, cal_dict['fine_freqs'][:, k], 'o')
+        plt.plot(phase_small, f_interp(phase_small), '--')
+        plt.plot(phase_stream[::plot_period], freqs_stream[::plot_period], '.')
+        plt.ylim(np.min(freqs_stream) - (np.max(freqs_stream) - np.min(freqs_stream)) * 3,
+                 np.max(freqs_stream) + (np.max(freqs_stream) - np.min(freqs_stream)) * 3)
+        plt.xlim(np.min(phase_stream) - np.pi / 4, np.max(phase_stream) + np.pi / 4)
         plt.xlabel("phase")
         plt.ylabel("Frequency")
 
-
-
         pdf_pages.savefig(fig)
         plt.close(fig)
 
     pdf_pages.close()
 
 
-def fft_noise(z_stream,df_over_f,sample_rate):
-    npts_fft = int(2**(np.floor(np.log2(df_over_f.size)))) 
-    Sxx = 2*fftpack.fft(df_over_f,n = npts_fft)*np.conj(fftpack.fft(df_over_f,n = npts_fft))/sample_rate*npts_fft/npts_fft**2
-    #perpendicular should be radial on the circle
+def fft_noise(z_stream, df_over_f, sample_rate):
+    npts_fft = int(2 ** (np.floor(np.log2(df_over_f.size))))
+    Sxx = 2 * fftpack.fft(df_over_f, n=npts_fft) * np.conj(
+        fftpack.fft(df_over_f, n=npts_fft)) / sample_rate * npts_fft / npts_fft ** 2
+    # perpendicular should be radial on the circle
     per_stream = np.abs(z_stream)
-    #radius times angle should be distance along the circle and should work if 
-    #noise ball is not small
+    # radius times angle should be distance along the circle and should work if
+    # noise ball is not small
     par_stream = np.mean(per_stream) * np.arctan2(np.imag(z_stream), np.real(z_stream))
-    S_per = 2*fftpack.fft(per_stream,n = npts_fft)*np.conj(
-            fftpack.fft(per_stream,n = npts_fft)
-            )/sample_rate*npts_fft/npts_fft**2
-    S_par = 2*fftpack.fft(par_stream,n = npts_fft)*np.conj(
-            fftpack.fft(par_stream,n = npts_fft))/sample_rate*npts_fft/npts_fft**2
-    fft_freqs = fftpack.fftfreq(npts_fft,1./sample_rate)
-    return fft_freqs,Sxx,S_per,S_par
+    S_per = 2 * fftpack.fft(per_stream, n=npts_fft) * np.conj(
+        fftpack.fft(per_stream, n=npts_fft)
+    ) / sample_rate * npts_fft / npts_fft ** 2
+    S_par = 2 * fftpack.fft(par_stream, n=npts_fft) * np.conj(
+        fftpack.fft(par_stream, n=npts_fft)) / sample_rate * npts_fft / npts_fft ** 2
+    fft_freqs = fftpack.fftfreq(npts_fft, 1. / sample_rate)
+    return fft_freqs, Sxx, S_per, S_par
 
 
-def noise_multi(cal_dict, sample_rate = 488.28125,outfile_dir = "./",n_comp_PCA = 0):
-
-    if n_comp_PCA >0:
+def noise_multi(cal_dict, sample_rate=488.28125, outfile_dir="./", n_comp_PCA=0):
+    if n_comp_PCA > 0:
         do_PCA = True
-        #do PCA on the data
-        cleaned, removed = PCA.PCA_SVD(cal_dict['stream_df_over_f'],n_comp_PCA,
-                plot=True)
+        # do PCA on the data
+        cleaned, removed = PCA.PCA_SVD(cal_dict['stream_df_over_f'], n_comp_PCA,
+                                       plot=True)
     else:
         do_PCA = False
 
-    for k in range(0,cal_dict['fine_corr'].shape[1]):
+    for k in range(0, cal_dict['fine_corr'].shape[1]):
         print(k)
 
-
-        #lets fourier transfer that crap
-        fft_freqs,Sxx,S_per,S_par = fft_noise(cal_dict['stream_corr'][:,k],cal_dict['stream_df_over_f'][:,k],sample_rate)
+        # lets fourier transfer that crap
+        fft_freqs, Sxx, S_per, S_par = fft_noise(cal_dict['stream_corr'][:, k], cal_dict['stream_df_over_f'][:, k],
+                                                 sample_rate)
         if do_PCA:
-            fft_freqs_2,Sxx_clean,S_per_2,S_par_2 = fft_noise(cal_dict['stream_corr'][:,k],cleaned[:,k], sample_rate)
+            fft_freqs_2, Sxx_clean, S_per_2, S_par_2 = fft_noise(cal_dict['stream_corr'][:, k], cleaned[:, k],
+                                                                 sample_rate)
         if k == 0:
-            #intialize some arrays
-            Sxx_all = np.zeros((Sxx.shape[0],cal_dict['fine_corr'].shape[1]))
-            Sxx_all_clean = np.zeros((Sxx.shape[0],cal_dict['fine_corr'].shape[1]))
-            S_per_all = np.zeros((S_per.shape[0],cal_dict['fine_corr'].shape[1]))
-            S_par_all = np.zeros((S_par.shape[0],cal_dict['fine_corr'].shape[1]))
+            # intialize some arrays
+            Sxx_all = np.zeros((Sxx.shape[0], cal_dict['fine_corr'].shape[1]))
+            Sxx_all_clean = np.zeros((Sxx.shape[0], cal_dict['fine_corr'].shape[1]))
+            S_per_all = np.zeros((S_per.shape[0], cal_dict['fine_corr'].shape[1]))
+            S_par_all = np.zeros((S_par.shape[0], cal_dict['fine_corr'].shape[1]))
 
-        Sxx_all[:,k] = np.abs(Sxx)
+        Sxx_all[:, k] = np.abs(Sxx)
         if do_PCA:
-            Sxx_all_clean[:,k] = np.abs(Sxx_clean)
-        S_per_all[:,k] = np.abs(S_per)
-        S_par_all[:,k] = np.abs(S_par)
+            Sxx_all_clean[:, k] = np.abs(Sxx_clean)
+        S_per_all[:, k] = np.abs(S_per)
+        S_par_all[:, k] = np.abs(S_par)
 
         # bin it for ploting
-        plot_bins = np.logspace(-3,np.log10(250),100)
-        binnedfreq =  binned_statistic(fft_freqs, fft_freqs, bins=plot_bins)[0] #bin the frequecy against itself
+        plot_bins = np.logspace(-3, np.log10(250), 100)
+        binnedfreq = binned_statistic(fft_freqs, fft_freqs, bins=plot_bins)[0]  # bin the frequecy against itself
         binnedpsd = binned_statistic(fft_freqs, np.abs(Sxx), bins=plot_bins)[0]
         if do_PCA:
             binnedpsd_clean = binned_statistic(fft_freqs, np.abs(Sxx_clean), bins=plot_bins)[0]
         binnedper = binned_statistic(fft_freqs, np.abs(S_per), bins=plot_bins)[0]
         binnedpar = binned_statistic(fft_freqs, np.abs(S_par), bins=plot_bins)[0]
-        amp_subtracted = np.abs(binnedpsd)*(binnedpar-binnedper)/binnedpar
+        amp_subtracted = np.abs(binnedpsd) * (binnedpar - binnedper) / binnedpar
         if k == 0:
-            Sxx_binned_all = np.zeros((binnedfreq.shape[0],cal_dict['fine_corr'].shape[1]))
-            Sxx_binned_all_clean = np.zeros((binnedfreq.shape[0],cal_dict['fine_corr'].shape[1]))
-            S_per_binned_all = np.zeros((binnedfreq.shape[0],cal_dict['fine_corr'].shape[1]))
-            S_par_binned_all = np.zeros((binnedfreq.shape[0],cal_dict['fine_corr'].shape[1]))
-            amp_subtracted_all = np.zeros((binnedfreq.shape[0],cal_dict['fine_corr'].shape[1]))
+            Sxx_binned_all = np.zeros((binnedfreq.shape[0], cal_dict['fine_corr'].shape[1]))
+            Sxx_binned_all_clean = np.zeros((binnedfreq.shape[0], cal_dict['fine_corr'].shape[1]))
+            S_per_binned_all = np.zeros((binnedfreq.shape[0], cal_dict['fine_corr'].shape[1]))
+            S_par_binned_all = np.zeros((binnedfreq.shape[0], cal_dict['fine_corr'].shape[1]))
+            amp_subtracted_all = np.zeros((binnedfreq.shape[0], cal_dict['fine_corr'].shape[1]))
 
-        Sxx_binned_all[:,k] = binnedpsd
+        Sxx_binned_all[:, k] = binnedpsd
         if do_PCA:
-             Sxx_binned_all_clean[:,k] = binnedpsd_clean
-        S_per_binned_all[:,k] = binnedper
-        S_par_binned_all[:,k] = binnedpar
-        amp_subtracted_all[:,k] = amp_subtracted
-
-    #make a psd dictionary
-    psd_dict = {'fft_freqs':fft_freqs,
-                    'Sxx':Sxx_all,
-                    'S_per':S_per_all,
-                    'S_par':S_par_all,
-                    'binned_freqs':binnedfreq,
-                    'Sxx_binned':Sxx_binned_all,
-                    'S_per_binned':S_per_binned_all,
-                    'S_par_binned':S_par_binned_all,
-                    'amp_subtracted':amp_subtracted_all,
-                    'Sxx_clean':Sxx_all_clean,
-                    'Sxx_binned_clean':Sxx_binned_all_clean}
-
-    #plot the stuff
-    plot_noise_multi(psd_dict, N_PCA=n_comp_PCA, outfile_dir=outfile_dir) 
-    #save the psd dictionary
-    pickle.dump( psd_dict, open( outfile_dir+"psd.p", "wb" ),2 )
+            Sxx_binned_all_clean[:, k] = binnedpsd_clean
+        S_per_binned_all[:, k] = binnedper
+        S_par_binned_all[:, k] = binnedpar
+        amp_subtracted_all[:, k] = amp_subtracted
+
+    # make a psd dictionary
+    psd_dict = {'fft_freqs': fft_freqs,
+                'Sxx': Sxx_all,
+                'S_per': S_per_all,
+                'S_par': S_par_all,
+                'binned_freqs': binnedfreq,
+                'Sxx_binned': Sxx_binned_all,
+                'S_per_binned': S_per_binned_all,
+                'S_par_binned': S_par_binned_all,
+                'amp_subtracted': amp_subtracted_all,
+                'Sxx_clean': Sxx_all_clean,
+                'Sxx_binned_clean': Sxx_binned_all_clean}
+
+    # plot the stuff
+    plot_noise_multi(psd_dict, N_PCA=n_comp_PCA, outfile_dir=outfile_dir)
+    # save the psd dictionary
+    pickle.dump(psd_dict, open(outfile_dir + "psd.p", "wb"), 2)
 
     return psd_dict
 
 
-def plot_noise_multi(psd_dict, white_avg=100., N_PCA=0, outfile_dir = "./"):
-    #create the PDF file
-    pdf_pages = PdfPages(outfile_dir+"psd_plots.pdf")
-    #was there a PCA analysis
+def plot_noise_multi(psd_dict, white_avg=100., N_PCA=0, outfile_dir="./"):
+    # create the PDF file
+    pdf_pages = PdfPages(outfile_dir + "psd_plots.pdf")
+    # was there a PCA analysis
     do_PCA = (N_PCA > 0)
-    #calculate white noise levels and plot them
+    # calculate white noise levels and plot them
     freq_mask = psd_dict['fft_freqs'] > white_avg
     N_res = psd_dict['Sxx'].shape[1]
     Sxx_avg = np.ndarray((N_res,))
     par_per_ratio = np.ndarray((N_res,))
     for i in range(N_res):
-        Sxx_avg[i] = np.mean(psd_dict['Sxx'][:,i][freq_mask])
-        par_per_ratio[i] = np.mean(psd_dict['S_par'][:,i][freq_mask]
-                ) / np.mean(psd_dict['S_per'][:,i][freq_mask])
-    fig = plt.figure(9000,figsize = (16,6))
+        Sxx_avg[i] = np.mean(psd_dict['Sxx'][:, i][freq_mask])
+        par_per_ratio[i] = np.mean(psd_dict['S_par'][:, i][freq_mask]
+                                   ) / np.mean(psd_dict['S_per'][:, i][freq_mask])
+    fig = plt.figure(9000, figsize=(16, 6))
     plt.subplot(122)
     plt.title("White Noise Levels")
     plt.semilogy(np.arange(N_res), Sxx_avg, 'bo')
@@ -917,40 +946,40 @@ def plot_noise_multi(psd_dict, white_avg=100., N_PCA=0, outfile_dir = "./"):
     plt.xlabel("Resonator Index")
     pdf_pages.savefig(fig)
     plt.close(fig)
-    #loop over the resonators
+    # loop over the resonators
     for k in range(N_res):
-        fig = plt.figure(k,figsize = (16,6))
-        #plot Sxx raw and with amplifier subtracted
+        fig = plt.figure(k, figsize=(16, 6))
+        # plot Sxx raw and with amplifier subtracted
         plt.subplot(122)
         plt.title("Sxx")
         plt.loglog(psd_dict['binned_freqs'],
-                np.abs(psd_dict['Sxx_binned'][:,k]),linewidth = 2,
-                label = "Sxx raw")
+                   np.abs(psd_dict['Sxx_binned'][:, k]), linewidth=2,
+                   label="Sxx raw")
         if do_PCA:
             plt.loglog(psd_dict['binned_freqs'],
-                    np.abs(psd_dict['Sxx_binned_clean'][:,k]),linewidth = 2,
-                    label = "PCA {0} comps".format(N_PCA))
+                       np.abs(psd_dict['Sxx_binned_clean'][:, k]), linewidth=2,
+                       label="PCA {0} comps".format(N_PCA))
         plt.loglog(psd_dict['binned_freqs'],
-                psd_dict['amp_subtracted'][:,k],
-                linewidth = 2, label="raw amp subtracted")
+                   psd_dict['amp_subtracted'][:, k],
+                   linewidth=2, label="raw amp subtracted")
         plt.ylabel("Sxx (1/Hz)")
         plt.xlabel("Frequency (Hz)")
         plt.legend()
 
-        #plot noise independant quadratures
+        # plot noise independant quadratures
         plt.subplot(121)
-        plt.title("Res indx = "+str(k))
+        plt.title("Res indx = " + str(k))
 
-        plt.loglog(psd_dict['binned_freqs'],psd_dict['S_per_binned'][:,k],
-                label = "amp noise")
-        plt.loglog(psd_dict['binned_freqs'],psd_dict['S_par_binned'][:,k],
-                label = "detect noise")
+        plt.loglog(psd_dict['binned_freqs'], psd_dict['S_per_binned'][:, k],
+                   label="amp noise")
+        plt.loglog(psd_dict['binned_freqs'], psd_dict['S_par_binned'][:, k],
+                   label="detect noise")
         plt.legend()
         plt.xlabel("Frequency (Hz)")
 
-        #save and close the figure
+        # save and close the figure
         pdf_pages.savefig(fig)
         plt.close(fig)
 
-    #close the pdf file so everything gets flushed to the disk
+    # close the pdf file so everything gets flushed to the disk
     pdf_pages.close()
diff --git a/submm/sample_data/abs_paths.py b/submm/sample_data/abs_paths.py
index 7d126b2..b9a94c5 100644
--- a/submm/sample_data/abs_paths.py
+++ b/submm/sample_data/abs_paths.py
@@ -3,9 +3,11 @@
 abs_path_parent_dir = dir_this_file.rsplit("submm", 1)[0]
 abs_path_submm = os.path.join(abs_path_parent_dir, "submm")
 abs_path_sample_data = os.path.join(abs_path_submm, "sample_data")
+abs_path_output_dir_default = os.path.join(abs_path_submm, "output")
 
 
 if __name__ == "__main__":
     print(f'abs_path_parent_dir:               {abs_path_parent_dir}')
     print(f'The absolute path for submm:       {abs_path_submm}')
     print(f'The absolute path for sample_data: {abs_path_sample_data}')
+    print(f'The absolute path for output_dir:  {abs_path_output_dir_default}')
diff --git a/submm/utils/plotting.py b/submm/utils/plotting.py
index 12f424c..3e3b4fc 100644
--- a/submm/utils/plotting.py
+++ b/submm/utils/plotting.py
@@ -33,7 +33,7 @@ def presentation_plot():
 # adds in the ability to grab cursur info from screen
 # adds in the ability to find mins and maximums 
 def activate_interactive_plotting(fig,ax,zoom_factor = 0.1,lim_shift_factor = 0.1,show_pts = True):   
-    class interactive_plot(object): #must pass fig to this command
+    class InteractivePlot(object): #must pass fig to this command
     
         def __init__(self,fig,ax,zoom_factor,lim_shift_factor,show_pts):
             #matplotlib.use("TkAgg")
@@ -205,7 +205,7 @@ def find_max(self):
     
             
 
-    ip = interactive_plot(fig,ax,zoom_factor = zoom_factor,lim_shift_factor = lim_shift_factor,show_pts = show_pts)
+    ip = InteractivePlot(fig,ax,zoom_factor = zoom_factor,lim_shift_factor = lim_shift_factor,show_pts = show_pts)
     return ip
 
 


Test patch:
diff --git a/submm/KIDs/test_fit.py b/submm/KIDs/test_fit.py
index f4e6515..9d21545 100644
--- a/submm/KIDs/test_fit.py
+++ b/submm/KIDs/test_fit.py
@@ -1,36 +1,34 @@
 import numpy as np
 import matplotlib.pyplot as plt
 from submm.multitone_mako import read_multitone
-from submm.KIDs import resonance_fitting
+from submm.KIDs.res.fitting import fit_nonlinear_iq_with_err
 
-#change log
-#JDW 2017-08-17 changed to include amplitude normalization option
+# change log
+# JDW 2017-08-17 changed to include amplitude normalization option
 
 res_num = 0
 
-
 cal = read_multitone.readcal("mako20161007_223744Cal.fits")
 gain = read_multitone.readcal("mako20161007_224502Cal.fits")
 
-all_i = np.vstack((cal['I'],gain['I']))
-all_q = -np.vstack((cal['Q'],gain['Q'])) # notice the negative for the Q the mako multitone seems to have the wrong sign on Q
-all_freqs = np.vstack((cal['freqs'],gain['freqs']))
-
+all_i = np.vstack((cal['I'], gain['I']))
+all_q = -np.vstack(
+    (cal['Q'], gain['Q']))  # notice the negative for the Q the mako multitone seems to have the wrong sign on Q
+all_freqs = np.vstack((cal['freqs'], gain['freqs']))
 
-x = all_freqs[:,res_num]
-z = all_i[:,res_num] + 1.0j*all_q[:,res_num]
+x = all_freqs[:, res_num]
+z = all_i[:, res_num] + 1.0j * all_q[:, res_num]
 
-#multitone glitches
-x[30] = np.nan 
+# multitone glitches
+x[30] = np.nan
 x[34] = np.nan
 x[50] = np.nan
 x[34] = np.nan
-z[30] = np.nan 
+z[30] = np.nan
 z[34] = np.nan
 z[50] = np.nan
 z[34] = np.nan
 
-
 # fitter does not like nans
 z_nonan = z[~np.isnan(z)]
 x_nonan = x[~np.isnan(z)]
@@ -38,32 +36,29 @@
 f0_guess = x_nonan[np.argmin(np.abs(z_nonan))]
 
 # try with or without these
-x0 = [f0_guess,10000.,0.37,np.pi*-0.1,.6,np.real(z_nonan[60]),np.imag(z_nonan[60]),3*10**-7,f0_guess]
-bounds = ([np.min(x_nonan),2000,.01,-4.0*np.pi,0,-5,-5,1*10**-9,np.min(x_nonan)],[np.max(x_nonan),200000,100,4.0*np.pi,5,5,5,1*10**-6,np.max(x_nonan)])
+x0 = [f0_guess, 10000., 0.37, np.pi * -0.1, .6, np.real(z_nonan[60]), np.imag(z_nonan[60]), 3 * 10 ** -7, f0_guess]
+bounds = ([np.min(x_nonan), 2000, .01, -4.0 * np.pi, 0, -5, -5, 1 * 10 ** -9, np.min(x_nonan)],
+          [np.max(x_nonan), 200000, 100, 4.0 * np.pi, 5, 5, 5, 1 * 10 ** -6, np.max(x_nonan)])
 
-fit_dict = resonance_fitting.fit_nonlinear_iq_with_err(x_nonan, z_nonan, x0 = x0, bounds = bounds, amp_norm = True) # with defined bounds
-#fit_dict = resonance_fitting.fit_nonlinear_iq_with_err( x_nonan, z_nonan) #with out defined bounds
+fit_dict = fit_nonlinear_iq_with_err(x_nonan, z_nonan, x0=x0, bounds=bounds, amp_norm=True)  # with defined bounds
+# fit_dict = resonance_fitting.fit_nonlinear_iq_with_err( x_nonan, z_nonan) #with out defined bounds
 
 fit = fit_dict['fit']
 fit_result = fit_dict['fit_result']
 x0_result = fit_dict['x0_result']
 
-
 plt.figure(1)
-plt.plot(np.real(x0_result),np.imag(x0_result),'+',label = "x0")
-plt.plot(np.real(z_nonan),np.imag(z_nonan),'o',label = "data")
-plt.plot(np.real(fit_dict['z']),np.imag(fit_dict['z']),'o',label = "data after amp_norm")
-plt.plot(np.real(fit_result),np.imag(fit_result),'*',label = "fit")
-plt.legend(loc = 4)
+plt.plot(np.real(x0_result), np.imag(x0_result), '+', label="x0")
+plt.plot(np.real(z_nonan), np.imag(z_nonan), 'o', label="data")
+plt.plot(np.real(fit_dict['z']), np.imag(fit_dict['z']), 'o', label="data after amp_norm")
+plt.plot(np.real(fit_result), np.imag(fit_result), '*', label="fit")
+plt.legend(loc=4)
 
 plt.figure(2)
-plt.plot(x_nonan,np.sqrt(np.real(z_nonan)**2+np.imag(z_nonan)**2),'o',label = "data")
-plt.plot(x_nonan,np.sqrt(np.real(fit_dict['z'])**2+np.imag(fit_dict['z'])**2),'o',label = "data after amp norm")
-plt.plot(x_nonan,np.sqrt(np.real(x0_result)**2+np.imag(x0_result)**2),'+',label = "x0")
-plt.plot(x_nonan,np.sqrt(np.real(fit_result)**2+np.imag(fit_result)**2),'*',label = "fit")
+plt.plot(x_nonan, np.sqrt(np.real(z_nonan) ** 2 + np.imag(z_nonan) ** 2), 'o', label="data")
+plt.plot(x_nonan, np.sqrt(np.real(fit_dict['z']) ** 2 + np.imag(fit_dict['z']) ** 2), 'o', label="data after amp norm")
+plt.plot(x_nonan, np.sqrt(np.real(x0_result) ** 2 + np.imag(x0_result) ** 2), '+', label="x0")
+plt.plot(x_nonan, np.sqrt(np.real(fit_result) ** 2 + np.imag(fit_result) ** 2), '*', label="fit")
 plt.legend()
 
-
 plt.show()
-
-