import argparse, logging
import itertools
from scipy.optimize import fmin
import numpy as np
import os
import allensdk.core.json_utilities as ju
import allensdk.internal.model.glif.find_sweeps as fs
from allensdk.internal.model.data_access import load_sweeps
from allensdk.internal.model.glif.MLIN import MLIN
from allensdk.internal.model.glif.ASGLM import ASGLM_pairwise
from allensdk.internal.model.glif.rc import least_squares_RCEl_calc_tested
from allensdk.internal.model.glif.threshold_adaptation import calc_spike_component_of_threshold_from_multiblip
from allensdk.internal.model.glif.spike_cutting import calc_spike_cut_and_v_reset_via_expvar_residuals
from allensdk.internal.model.glif.find_spikes import find_spikes_list, find_spikes_ssq_list
from allensdk.internal.model.glif.threshold_adaptation import fit_avoltage_bvoltage_th, fit_avoltage_bvoltage
import allensdk.ephys.ephys_extractor as efex
import allensdk.ephys.ephys_features as ft
from allensdk.model.glif.glif_neuron_methods import spike_component_of_threshold_exact
import matplotlib.pyplot as plt
import allensdk.internal.model.glif.plotting as plotting

RESTING_POTENTIAL = 'slow_vm_mv'
DEFAULT_DT = 5e-05
DEFAULT_CUT = 0
DEFAULT_BESSEL = { 'N': 4, 'freq': 10000 }
MAKE_PLOT = True
SHOW_PLOT = False
SAVE_FIG =True
SHORT_RUN = False

class MissingSpikeException(Exception): pass

RESTING_POTENTIAL = 'slow_vm_mv'

def find_first_spike_voltage(voltage, dt, ssq=False, MAKE_PLOT=False, SHOW_PLOT=False, BLOCK=False,
                             dv_cutoff=20.0, thresh_frac=0.05):
    '''calculate voltage at threshold of first spike
    Parameters
    ----------
    voltage: numpy array
        voltage trace
    dt: float
        sampling time step
    ssq: Boolean
        whether there is or is not a subrathreshold short square pulse (note that if thes
    MAKE_PLOT: Boolean
        specifies whether or not a plot should be made
    SHOW_PLOT: Boolean
        specifies if a visualization should be made
    BLOCK: Boolean
        if a plot is made this specifies weather to stop the code until the plot is closed
    dv_cutoff: float
        specifies cut off of the derivative of the voltage
    thresh_frac: float
        variable that goes into feature extractor
    
    Returns
    -------
    :float
        voltage of threshold of first spike
    '''
    
    if ssq:
        spike_time_steps, _ = find_spikes_ssq_list([voltage], dt, dv_cutoff=dv_cutoff, thresh_frac=thresh_frac)
    else:
        spike_time_steps, _ = find_spikes_list([voltage], dt)

    if MAKE_PLOT:
        plotting.plotSpikes([voltage], spike_time_steps, dt, blockME=False, method='dvdt_v2')
    if SHOW_PLOT:
        plt.show(block=BLOCK)

    if len(spike_time_steps[0]) == 0:
        raise MissingSpikeException('No spike detected.')
    
    return voltage[spike_time_steps[0][0]]

def tag_plot(tag, fs=9):
    plt.annotate(tag, xy=(0.98, .01),
                 xycoords='figure fraction',
                 horizontalalignment='right', 
                 verticalalignment='bottom',
                 fontsize=fs)
    
def estimate_dv_cutoff(voltage_list, dt, start_t, end_t):
    v_set = [ v * 1e3 for v in voltage_list ]
    t_set = [ np.arange(0, len(v)) * dt for v in voltage_list ]
    
    dv_cutoff, thresh_frac = ft.estimate_adjusted_detection_parameters(v_set, t_set,
                                                                       start_t, end_t,
                                                                       filter=None)
    
    return dv_cutoff, thresh_frac

def preprocess_neuron(nwb_file, sweep_list, cell_properties=None,
                      dt=None, cut=None, bessel=None, save_figure_path=None):
    if dt is None:
        dt = DEFAULT_DT  
    if cut is None:
        cut = DEFAULT_CUT  
    if bessel is None:
        bessel = DEFAULT_BESSEL

    sweep_index = { s['sweep_number']: s for s in sweep_list }

    noise_sweeps = fs.find_noise_sweeps(sweep_index)
    noise1_sweeps = noise_sweeps['noise1']
    noise2_sweeps = noise_sweeps['noise2']

    ssq_sweeps = fs.find_short_square_sweeps(sweep_index) 
    all_ssq_data = load_sweeps(nwb_file, ssq_sweeps['all'], dt, cut, bessel)
    ssq_dv_cutoff, ssq_thresh_frac = estimate_dv_cutoff(all_ssq_data['voltage'], dt, 
                                                        efex.SHORT_SQUARES_WINDOW_START,
                                                        efex.SHORT_SQUARES_WINDOW_END)
    
    ssq_triple_sweeps = ssq_sweeps['triple']
    
    ramp_sweeps = fs.find_ramp_sweeps(sweep_index)['suprathreshold']
    R2R_sweeps = fs.find_ramp_to_rheo_sweeps(sweep_index)['all']
    
    noise1_data = load_sweeps(nwb_file, noise1_sweeps, dt, cut, bessel)
    noise2_data = load_sweeps(nwb_file, noise2_sweeps, dt, cut, bessel)

    maximum_subthreshold_short_square_sweeps = ssq_sweeps['maximum_subthreshold']
    maximum_subthreshold_short_square_data = load_sweeps(nwb_file, [maximum_subthreshold_short_square_sweeps[0]], dt, cut, bessel)
    minimum_suprathreshold_short_square_sweeps = ssq_sweeps['minimum_suprathreshold']
    minimum_suprathreshold_short_square_data = load_sweeps(nwb_file, [minimum_suprathreshold_short_square_sweeps[0]], dt, cut, bessel)

    dt = noise1_data['dt'][0]  #getting subsampled dt returned for ease of use

    subthresh_noise_current_list=[]
    subthresh_noise_voltage_list=[]
    noise_El_list=[]
    for ss in range(0, len(noise1_data['current'])):
        #--subthreshold noise has first epoch of noise with a region of no stimulation before and after (note the selection of end point is hard coded)
        subthresh_noise_current_list.append(noise1_data['current'][ss][noise1_data['start_idx'][ss]:int(6./dt)])
        subthresh_noise_voltage_list.append(noise1_data['voltage'][ss][noise1_data['start_idx'][ss]:int(6./dt)])
        noise_El_list.append(sweep_index[noise1_sweeps[ss]][RESTING_POTENTIAL]*1e-3)  

    # Els calculated from QC
    El_noise=np.mean(noise_El_list)
    El_subthreshold_blip=sweep_index[maximum_subthreshold_short_square_sweeps[0]][RESTING_POTENTIAL]*1e-3
    El_suprathreshold_blip=sweep_index[minimum_suprathreshold_short_square_sweeps[0]][RESTING_POTENTIAL]*1e-3

    if len(ramp_sweeps):
        logging.info('has ramp')
        ramp_data = load_sweeps(nwb_file, ramp_sweeps, dt, cut, bessel)
        El_ramp=sweep_index[ramp_sweeps[0]][RESTING_POTENTIAL]*1e-3
    else:
        ramp_sweeps=None
        ramp_data=None
        El_ramp=None
        logging.info("No ramp")

    if len(ssq_triple_sweeps):
        logging.info('has multi ss')
        multi_ssq_data = load_sweeps(nwb_file, ssq_triple_sweeps, dt, cut, bessel)
        El_multi_ssq_data=sweep_index[ssq_triple_sweeps[0]][RESTING_POTENTIAL]*1e-3
        multi_ssq_dv_cutoff, multi_ssq_thresh_frac = estimate_dv_cutoff(multi_ssq_data['voltage'], dt, 
                                                                        efex.SHORT_SQUARE_TRIPLE_WINDOW_START,
                                                                        efex.SHORT_SQUARE_TRIPLE_WINDOW_END)
        print "*************************"
        print "ssq", ssq_dv_cutoff, ssq_thresh_frac
        print "triple",multi_ssq_dv_cutoff, multi_ssq_thresh_frac
    else:
        ssq_triple_sweeps=None
        multi_ssq_data = None
        El_multi_ssq_data = None
        logging.info("No multi short square")

    # Needed for MLIN
    long_square_config = fs.find_long_square_sweeps(sweep_index)
    long_square_sweeps = long_square_config['all']
    subthreshold_long_square_sweeps = long_square_config['subthreshold']
    maximum_subthreshold_long_square_sweeps = long_square_config['maximum_subthreshold']
    #TODO: Here you are loading just one sweep: probably should load all
    maximum_subthreshold_long_square_data = load_sweeps(nwb_file, [maximum_subthreshold_long_square_sweeps[0]], dt, cut, bessel)
    El_max_subth_long_square=sweep_index[maximum_subthreshold_long_square_sweeps[0]][RESTING_POTENTIAL]*1e-3  

    #---------------------------------------------------------------        
    #---------find spiking indicies of spikes in noise--------------
    #---------------------------------------------------------------

    # note that when using find_spikes_list without removing the testpulse a warning will result from calculating feature_data['base_v'] in the feature extractor (line 375) this not relavent here
    noise1_ind_wo_test_pulse_removed, _ = find_spikes_list(noise1_data['voltage'], dt)
    noise2_ind_wo_test_pulse_removed, _ = find_spikes_list(noise2_data['voltage'], dt)
    #Put all ISI ind in a 
    ISI_length=np.array([])
    for ii in range(len(noise1_ind_wo_test_pulse_removed)):
        ISI_length=np.append(ISI_length,noise1_ind_wo_test_pulse_removed[ii][1:]-noise1_ind_wo_test_pulse_removed[ii][:-1])
    for ii in range(len(noise2_ind_wo_test_pulse_removed)):
        ISI_length=np.append(ISI_length,noise2_ind_wo_test_pulse_removed[ii][1:]-noise2_ind_wo_test_pulse_removed[ii][:-1])
    min_ISI_len=np.min(ISI_length)


    #-------------------------------------------------------------------------------------------------------------------
    #---------------------Compute R, C and EL via least squares-------------------------------------------------
    #------------------------------------------------------------------------------------------------------------------- 

    #--compute R, C, and El via least squares tested in verify_RCEl_GLM_vs_lssq_and_smooth.py
    (R_test_list, C_test_list, El_test_list)=least_squares_RCEl_calc_tested(subthresh_noise_voltage_list, subthresh_noise_current_list, dt)
    R_test_list_mean=np.mean(R_test_list)
    C_test_list_mean=np.mean(C_test_list)
    El_test_list_mean=np.mean(El_test_list)
    
    #-----------------------------------------------------------------------------------------        
    #------------------------ compute spike cut length----------------------------------------
    #-----------------------------------------------------------------------------------------

    #TODO: I should disentangle this function so I can get rid of the deltaV dependency 
    (spike_cut_length_NODELTAV, slope_at_min_expVar_list_NODELTAV, intercept_at_min_expVar_list_NODELTAV) \
        = calc_spike_cut_and_v_reset_via_expvar_residuals(noise1_data['current'], noise1_data['voltage'], 
                                                          dt, El_noise, 0, 
                                                          max_spike_cut_time=min_ISI_len*dt,
                                                          MAKE_PLOT=MAKE_PLOT, 
                                                          SHOW_PLOT=SHOW_PLOT, 
                                                          BLOCK=False)
    if SAVE_FIG:
        tag='spikeCutting_noDeltaV_regression.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close()
        tag='spikeCutting_noDeltaV_spike_wave_form.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close()
    logging.info('spike cut length: %d', spike_cut_length_NODELTAV)

    #-----------------------------------------------------------------------------------------        
    #------------------------ compute ASC amplitudes------------------------------------------
    #-----------------------------------------------------------------------------------------

    #***Hack: k's are being hard coded into this function and are not necessarily consistent with what is in the setting of AS currents!!!
    k_asc_possible=np.array([3, 10., 30., 100., 300.]) 
    if SHORT_RUN:  #THIS IS JUST FOR DEBUGGING SO THAT YOU DONT HAVE TO WAIT FOR THE ENTIRE MODULE TO RUN
        (best_k_pair_fit_ascR, best_asc_amp_fit_ascR, best_R_fit_ascR, best_llh_fit_ascR)=ASGLM_pairwise(k_asc_possible, 
                            noise1_data['current'], noise1_data['voltage'], noise1_ind_wo_test_pulse_removed, 
                            C_test_list_mean, C_test_list_mean*R_test_list_mean, spike_cut_length_NODELTAV, dt, El_noise,
                            SHORT_RUN=True, MAKE_PLOT=MAKE_PLOT, SHOW_PLOT=SHOW_PLOT, BLOCK=False)
        asc_amp_from_ASGLM=np.mean(best_asc_amp_fit_ascR, axis=0)
        R_from_ASGLM=np.mean(best_R_fit_ascR)

    else:
        (best_k_pair_fit_ascR, best_asc_amp_fit_ascR, best_R_fit_ascR, best_llh_fit_ascR)=ASGLM_pairwise(k_asc_possible, 
                            noise1_data['current'], noise1_data['voltage'], noise1_ind_wo_test_pulse_removed, 
                            C_test_list_mean, C_test_list_mean*R_test_list_mean, spike_cut_length_NODELTAV, dt, El_noise,
                            SHORT_RUN=False, MAKE_PLOT=MAKE_PLOT, SHOW_PLOT=SHOW_PLOT, BLOCK=False)            
        asc_amp_from_ASGLM=np.mean(best_asc_amp_fit_ascR, axis=0)
        R_from_ASGLM=np.mean(best_R_fit_ascR) 

    if SAVE_FIG:
        tag='GLM_fit_ascR_basis.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close()
        tag='GLM_fit_ascR_sumASC.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close()
        tag='GLM_fit_ascR_individualASC.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close()

    logging.info('Output of ASC fitting GLM')
    logging.info('R out_of_GLM_Rfit_Cfixed %f %s', R_from_ASGLM/1e6, "MOhms")
    logging.info('ASC amplitudes at the time of cut spike %s', str(asc_amp_from_ASGLM*1e12))
    logging.info("ks used %s", str(best_k_pair_fit_ascR))

    #-----------------------------------------------------------------------------------------        
    #------------------------ calculate thresholds-----------------------------------------
    #-----------------------------------------------------------------------------------------

    # ---extract instantaneous threshold from suprathreshold blip 
    try:
        th_inf_via_Vmeasure = find_first_spike_voltage(minimum_suprathreshold_short_square_data['voltage'][0][minimum_suprathreshold_short_square_data['start_idx'][0]:], 
                                                           dt,         
                                                           ssq=True,                                    
                                                           MAKE_PLOT=MAKE_PLOT, 
                                                           SHOW_PLOT=SHOW_PLOT, 
                                                           BLOCK=False,
                                                           dv_cutoff=ssq_dv_cutoff,
                                                           thresh_frac=ssq_thresh_frac)
        th_inf_via_Vmeasure_from0=th_inf_via_Vmeasure-El_suprathreshold_blip
        if SAVE_FIG:
            tag='th_inf_from_blip.png'
            tag_plot(tag)
            plt.savefig(os.path.join(save_figure_path, tag), format='png')
            plt.close()
    except MissingSpikeException as e:
        raise MissingSpikeException("The suprathreshold short square sweep must have a spike, but no spike was detected. This means that feature extraction and GLIF spike detection are inconsistent.")

    #-----------------------------------------------------------------------------------------------------
    #-----------------find spike and voltage component of the threshold---------------------------
    #-----------------------------------------------------------------------------------------------------

    # If a multishort square stimulus exists calculate spike component of threshold..
    if multi_ssq_data:
        (a_spike_component_of_threshold, b_spike_component_of_threshold, 
         mean_voltage_first_spike_of_blip) = calc_spike_component_of_threshold_from_multiblip(multi_ssq_data, 
                                                                     dt, 
                                                                     multi_ssq_dv_cutoff,
                                                                     multi_ssq_thresh_frac,
                                                                     MAKE_PLOT=MAKE_PLOT, 
                                                                     SHOW_PLOT=False, 
                                                                     BLOCK=False,
                                                                     PUBLICATION_PLOT=False)
        #adjust values to be after spike cutting
        if a_spike_component_of_threshold is not None and b_spike_component_of_threshold is not None:
            a_spike_component_of_threshold=spike_component_of_threshold_exact(a_spike_component_of_threshold, b_spike_component_of_threshold, spike_cut_length_NODELTAV*dt)

        if SAVE_FIG:
            tag='multiblip_fit.png'
            tag_plot(tag)
            plt.savefig(os.path.join(save_figure_path, tag), format='png')
            plt.close() 

            tag='multiblip_data.png'
            tag_plot(tag, fs=9)
            plt.savefig(os.path.join(save_figure_path,tag), format='png')
            plt.close() 

        #---calculate voltage componet of threshold 
        if a_spike_component_of_threshold is None or b_spike_component_of_threshold is None:
            logging.warning("spike component of threshold could not be calculated from the multiblip data")
            a_voltage_comp_of_thr_from_fitab=None
            b_voltage_comp_of_thr_from_fitab=None
            a_voltage_comp_of_thr_from_fitabth=None
            b_voltage_comp_of_thr_from_fitabth=None
            th_inf_fit_w_v_comp_of_th=None
            th_inf_fit_w_v_comp_of_th_from0=None
        else:
            #TODO:this function needs to be changed to use experimental change of reference
            b_voltage_guess = 5.0         
            a_voltage_guess = 0.1*b_voltage_guess
            fit_ab_vcomp_from_noise = fmin(func=fit_avoltage_bvoltage, 
                                           args=(noise1_data['voltage'], 
                                                 noise_El_list, 
                                                 spike_cut_length_NODELTAV, 
                                                 noise1_ind_wo_test_pulse_removed, #NOTE THAT IF YOU WANT TO USE THIS TO GET A VOLTAGE WITHIN THE FUNCTION YOU NEED TO SUBTRACT OFF AND INDICIE BECAUSE THIS IS THE VALUE SET TO NAN AS THE SPIKE WAS INITIATED IN THE PREVIOUS TIME STEP. 
                                                 th_inf_via_Vmeasure,
                                                 dt, 
                                                 a_spike_component_of_threshold, 
                                                 b_spike_component_of_threshold),
                                           x0=[a_voltage_guess,b_voltage_guess])

            a_voltage_comp_of_thr_from_fitab=fit_ab_vcomp_from_noise[0]
            b_voltage_comp_of_thr_from_fitab=fit_ab_vcomp_from_noise[1]

            logging.info("spike components %s %s", str(a_spike_component_of_threshold), str(b_spike_component_of_threshold))
            logging.info("voltage components %s %s", str(a_voltage_comp_of_thr_from_fitab), str(b_voltage_comp_of_thr_from_fitab))

            fit_ab_vcomp_th_from_thr_from_noise = fmin(func=fit_avoltage_bvoltage_th, 
                                                       args=(noise1_data['voltage'], 
                                                             noise_El_list, 
                                                             spike_cut_length_NODELTAV, 
                                                             noise1_ind_wo_test_pulse_removed, #NOTE THAT IF YOU WANT TO USE THIS TO GET A VOLTAGE WITHIN THE FUNCTION YOU NEED TO SUBTRACT OFF AND INDICIE BECAUSE THIS IS THE VALUE SET TO NAN AS THE SPIKE WAS INITIATED IN THE PREVIOUS TIME STEP. 
                                                             dt, 
                                                             a_spike_component_of_threshold, 
                                                             b_spike_component_of_threshold),
                                                       x0=[a_voltage_guess,b_voltage_guess, th_inf_via_Vmeasure])

            a_voltage_comp_of_thr_from_fitabth=fit_ab_vcomp_th_from_thr_from_noise[0]
            b_voltage_comp_of_thr_from_fitabth=fit_ab_vcomp_th_from_thr_from_noise[1]
            th_inf_fit_w_v_comp_of_th=fit_ab_vcomp_th_from_thr_from_noise[2]    
            th_inf_fit_w_v_comp_of_th_from0=th_inf_fit_w_v_comp_of_th-El_noise
            logging.info("spike components %s %s", str(a_spike_component_of_threshold), str(b_spike_component_of_threshold))
            logging.info("voltage components %s %s %s %s", str(a_voltage_comp_of_thr_from_fitabth), str(b_voltage_comp_of_thr_from_fitabth), 'fit threshold', str(th_inf_fit_w_v_comp_of_th))


    else:
        a_spike_component_of_threshold=None
        b_spike_component_of_threshold=None
        a_voltage_comp_of_thr_from_fitab=None
        b_voltage_comp_of_thr_from_fitab=None 
        a_voltage_comp_of_thr_from_fitabth=None
        b_voltage_comp_of_thr_from_fitabth=None
        th_inf_fit_w_v_comp_of_th_from0=None
        th_inf_fit_w_v_comp_of_th=None

    #--------------------------------------------------------------------------     
    #------------------------ MLIN calculations--------------------------------
    #--------------------------------------------------------------------------

    #TODO: probably want to use more than just one square pulse for this distribution
    STLS_voltage=maximum_subthreshold_long_square_data['voltage'][0][maximum_subthreshold_long_square_data['start_idx'][0]:]
    STLS_current=maximum_subthreshold_long_square_data['current'][0][maximum_subthreshold_long_square_data['start_idx'][0]:]
    (var_of_section, sv_for_expsymm, tau_from_AC)=MLIN(STLS_voltage, STLS_current, R_test_list_mean, C_test_list_mean, dt, 
                                                       MAKE_PLOT=MAKE_PLOT, 
                                                       SHOW_PLOT=SHOW_PLOT, 
                                                       BLOCK=False, 
                                                       PUBLICATION_PLOT=False)
    if SAVE_FIG:
        tag='MLIN.png'
        tag_plot(tag)
        plt.savefig(os.path.join(save_figure_path,tag), format='png')
        plt.close() 

    #--------------------------------------------------------------------------     
    #------------------------ make output dictionaries-------------------------
    #--------------------------------------------------------------------------

    #TODO: find out how many are the max number of all_passing_sweeps. 
    El_noise_1=[None, None, None, None, None]
    WFS_noise_1=[None, None, None, None, None]
    RTP_noise_1=[None, None, None, None, None]
    sweep_noise_1=[None, None, None, None, None]
    spike_ind_noise_1=[None, None, None, None, None]

    def fill_in_lists(out_list, data_list):
        '''note since the input is a list shouldnt need to return anything (pass by reference)'''
        for ii in range(len(data_list)):
            out_list[ii]=data_list[ii] 
    fill_in_lists(El_noise_1, noise_El_list)
    fill_in_lists(sweep_noise_1, noise1_sweeps)
    fill_in_lists(spike_ind_noise_1, noise1_ind_wo_test_pulse_removed)

    #--initialize output dictionaries
    for_reference_dict={}
    for_use_dict={}

    for_reference_dict['dt_used_for_preprocessor_calculations']=dt
    #for_reference_dict['optional_methods']=self.optional_methods
    for_reference_dict['sweep_properties']={'noise1': 
                                                {'1':{'El': El_noise_1[0], 'sweep_num':sweep_noise_1[0], 'spike_ind': spike_ind_noise_1[0]},
                                                 '2':{'El': El_noise_1[1], 'sweep_num':sweep_noise_1[1], 'spike_ind': spike_ind_noise_1[1]},
                                                 '3':{'El': El_noise_1[2], 'sweep_num':sweep_noise_1[2], 'spike_ind': spike_ind_noise_1[2]},
                                                 '4':{'El': El_noise_1[3], 'sweep_num':sweep_noise_1[3], 'spike_ind': spike_ind_noise_1[3]},
                                                 '5':{'El': El_noise_1[4], 'sweep_num':sweep_noise_1[4], 'spike_ind': spike_ind_noise_1[4]}},
                                            'ramp': {'sweep_num':ramp_sweeps},
                                            'subthreshold_short_square': {'sweep_num':maximum_subthreshold_short_square_sweeps},
                                            'suprathreshold_short_square': {'R_testpulsesweep_num':minimum_suprathreshold_short_square_sweeps},
                                            'max_subthresh_long_square': {'sweep_num':maximum_subthreshold_long_square_sweeps},
                                            'multi_short_square': {'sweep_num':ssq_triple_sweeps}}

    for_reference_dict['El']={'El_noise': {'measured': {'mean':El_noise, 'list':noise_El_list, 'dependencies':None}},
                              'El_ramp': {'value':El_ramp, 'dependencies': None},
                              'El_subthreshold_blip': {'value':El_subthreshold_blip, 'dependencies':None}, 
                              'El_suprathreshold_blip': {'value':El_suprathreshold_blip, 'dependencies':None},
                              'El_max_subth_long_square': {'value':El_max_subth_long_square, 'dependencies':None}} 

    for_reference_dict['resistance']={#'R_lssq_Wrest':{'mean': R_lssq_wrest_mean, 'list': R_lssq_wrest_list, 'dependencies': 'from subthreshold (no spike cutting) noise'},        
                                      'R_from_lims':{'value':cell_properties['ri']*1e6},
                                      'R_test_list': {'mean':R_test_list_mean, 'list': R_test_list},
                                      'R_fit_ASC_and_R':{'mean':R_from_ASGLM, 'list': best_R_fit_ascR}}

    for_reference_dict['capacitance']={#'C_lssq_Wrest': {'mean':C_lssq_wrest_mean, 'list':C_lssq_wrest_list, 'dependencies': 'from subthreshold (no spike cutting) noise'},
                                       'C_from_lims':{'value': (cell_properties['tau']*1e-3)/(cell_properties['ri']*1e6)},
                                       'C_test_list': {'mean':C_test_list_mean, 'list': C_test_list}}
    
    for_reference_dict['spike_cut_length']={'no deltaV shift':{'length':spike_cut_length_NODELTAV, 
                                                               'slope':slope_at_min_expVar_list_NODELTAV, 
                                                               'intercept':intercept_at_min_expVar_list_NODELTAV, 
                                                               'dependencies':None}}

    for_reference_dict['spike_cutting']={'NOdeltaV': {'cut_length':spike_cut_length_NODELTAV, 'slope':slope_at_min_expVar_list_NODELTAV, 'intercept':intercept_at_min_expVar_list_NODELTAV, 'dependencies': None}}

    for_reference_dict['asc']={'k': best_k_pair_fit_ascR, 'amp':asc_amp_from_ASGLM, 'dependencies': 'Cap and res from least squares'}

    for_reference_dict['th_inf']={'via_Vmeasure':{'value':th_inf_via_Vmeasure, 'from_zero':th_inf_via_Vmeasure_from0, 'dependencies':'measured from suprathreshold blip'},
                                  'fit_with_v_comp_of_th':{'value':th_inf_fit_w_v_comp_of_th, 'from_zero':th_inf_fit_w_v_comp_of_th_from0}}

    for_reference_dict['threshold_adaptation']={'a_spike_component_of_threshold':a_spike_component_of_threshold,
                                                'b_spike_component_of_threshold':b_spike_component_of_threshold,
                                                'a_voltage_comp_of_thr_from_fitab':a_voltage_comp_of_thr_from_fitab,
                                                'b_voltage_comp_of_thr_from_fitab':b_voltage_comp_of_thr_from_fitab,
                                                'a_voltage_comp_of_thr_from_fitabth':a_voltage_comp_of_thr_from_fitabth,
                                                'b_voltage_comp_of_thr_from_fitabth':b_voltage_comp_of_thr_from_fitabth}
    for_reference_dict['MLIN']={'var_of_section':var_of_section,
                                'sv_for_expsymm':sv_for_expsymm,
                                'tau_from_AC':tau_from_AC}
    logging.info("finished")

    return for_reference_dict

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("nwb_file")
    parser.add_argument("sweep_list_file")
    parser.add_argument("output_json")
    parser.add_argument("--dt", default=DEFAULT_DT)
    parser.add_argument("--bessel", default=DEFAULT_BESSEL)
    parser.add_argument("--cut", default=DEFAULT_CUT)

    args = parser.parse_args()

    sweep_list = ju.read(args.sweep_list_file)
    
    values = preprocess_neuron(args.nwb_file, sweep_list)

    ju.write(args.output_json, values)
    

if __name__ == "__main__": main()
