Esempio n. 1
0
def compare_gainControl(fitBase, normType, lossType, expInd, conSteps=11):
  ''' given a fitBase (str) with associated norm/loss indices, and experiment indices, get the RVC for all cells
  '''
  _, _, _, _, nCells, dir = hf.get_exp_params(expInd);

  if expInd == 1:
    dir = str(dir+'Structures/');
  else:
    dir = str(dir+'structures/');

  dataList = hf.np_smart_load(str(dir + 'dataList.npy'));

  fl_str = hf.fitList_name(fitBase, normType, lossType);
  fitList = hf.np_smart_load(str(dir + fl_str));

  rvcs = np.nan * np.zeros((nCells, conSteps));

  for i in range(nCells):
    print('cell %d' % i);
    cellStr = hf.np_smart_load(str(dir + dataList['unitName'][i] + '_sfm.npy'));
    currParams = fitList[i]['params'];

    rvcs[i, :] = evaluate_RVC(cellStr, currParams, normType=normType, expInd=expInd, conSteps=conSteps);

  if expInd == 1:
    np.save(str('rvcV1_' + fl_str), rvcs);
  elif expInd == 3:
    np.save(str('rvcLGN_' + fl_str), rvcs);

  return rvcs;
Esempio n. 2
0
def batch_phase_by_cond(cell_num,
                        disp,
                        cons=[],
                        sfs=[],
                        dir=-1,
                        dp=dataPath,
                        expName=expName):
    ''' must specify dispersion (one value)
      if cons = [], then get/plot all valid contrasts for the given dispersion
      if sfs = [], then get/plot all valid contrasts for the given dispersion
  '''
    dataList = hf.np_smart_load(str(dp + expName))
    fileName = dataList['unitName'][cell_num - 1]

    cellStruct = hf.np_smart_load(str(dp + fileName + '_sfm.npy'))
    data = cellStruct['sfm']['exp']['trial']
    # prepare the valid stim parameters by condition in case needed
    resp, stimVals, val_con_by_disp, validByStimVal, mdRsp = hf.tabulate_responses(
        data)

    # gather the sf indices in case we need - this is a dictionary whose keys are the valid sf indices
    valSf = validByStimVal[2]

    if cons == []:  # then get all valid cons for this dispersion
        cons = val_con_by_disp[disp]
    if sfs == []:  # then get all valid sfs for this dispersion
        sfs = list(valSf.keys())

    for c in cons:
        for s in sfs:
            print('analyzing cell %d, dispersion %d, contrast %d, sf %d\n' %
                  (cell_num, disp, c, s))
            phase_by_cond(cell_num, data, disp, c, s, dir=dir)
Esempio n. 3
0
def writeCellTxt(cellNum, load_path, save_loc):

  dataList = np_smart_load(load_path + 'sachData.npy');
  data = dataList[cellNum-1]['data'];

  resps, conds, _ = tabulateResponses(data);
  f1 = resps[1];
  all_cons = conds[0];
  all_sfs = conds[1];
  
  for i in range(len(all_cons)):
    writeDataTxt(cellNum, f1, all_sfs, i, save_loc);
Esempio n. 4
0
def fit_descr(cell_num, data_loc, n_repeats = 4, loss_type = 1):

    nParam = 5;
    
    if loss_type == 1:
      loss_str = '_lsq.npy';    
    elif loss_type == 2:
      loss_str = '_sqrt.npy';    
    elif loss_type == 3:
      loss_str = '_poiss.npy';

    # load cell information
    dataList = hfunc.np_smart_load(data_loc + 'dataList.npy');
    if os.path.isfile(data_loc + 'descrFits' +  loss_str):
        descrFits = hfunc.np_smart_load(data_loc + 'descrFits' + loss_str);
    else:
        descrFits = dict();
    data = hfunc.np_smart_load(data_loc + dataList['unitName'][cell_num-1] + '_sfm.npy');
    
    print('Doing the work, now');

    to_unpack = hfunc.tabulate_responses(data);
    [respMean, respVar, predMean, predVar] = to_unpack[0];
    [all_disps, all_cons, all_sfs] = to_unpack[1];
    val_con_by_disp = to_unpack[2];
    
    nDisps = len(all_disps);
    nCons = len(all_cons);

    if cell_num-1 in descrFits:
        bestNLL = descrFits[cell_num-1]['NLL'];
        currParams = descrFits[cell_num-1]['params'];
    else: # set values to NaN...
        bestNLL = np.ones((nDisps, nCons)) * np.nan;
        currParams = np.ones((nDisps, nCons, nParam)) * np.nan;
    
    for family in range(nDisps):
        for con in range(nCons):    
            
            if con not in val_con_by_disp[family]:
                continue;

            print('.');           
            # set initial parameters - a range from which we will pick!
            base_rate = hfunc.blankResp(data)[0];
            if base_rate <= 3:
                range_baseline = (0, 3);
            else:
                range_baseline = (0.5 * base_rate, 1.5 * base_rate);

            valid_sf_inds = ~np.isnan(respMean[family, :, con]);
            max_resp = np.amax(respMean[family, valid_sf_inds, con]);
            range_amp = (0.5 * max_resp, 1.5);
            
            theSfCents = all_sfs[valid_sf_inds];
            
            max_sf_index = np.argmax(respMean[family, valid_sf_inds, con]); # what sf index gives peak response?
            mu_init = theSfCents[max_sf_index];
            
            if max_sf_index == 0: # i.e. smallest SF center gives max response...
                range_mu = (mu_init/2,theSfCents[max_sf_index + 3]);
            elif max_sf_index+1 == len(theSfCents): # i.e. highest SF center is max
                range_mu = (theSfCents[max_sf_index-2], mu_init);
            else:
                range_mu = (theSfCents[max_sf_index-1], theSfCents[max_sf_index+1]); # go +-1 indices from center
                
            log_bw_lo = 0.75; # 0.75 octave bandwidth...
            log_bw_hi = 2; # 2 octave bandwidth...
            denom_lo = hfunc.bw_log_to_lin(log_bw_lo, mu_init)[0]; # get linear bandwidth
            denom_hi = hfunc.bw_log_to_lin(log_bw_hi, mu_init)[0]; # get lin. bw (cpd)
            range_denom = (denom_lo, denom_hi); # don't want 0 in sigma 
                
            # set bounds for parameters
            min_bw = 1/4; max_bw = 10; # ranges in octave bandwidth

            bound_baseline = (0, max_resp);
            bound_range = (0, 1.5*max_resp);
            bound_mu = (0.01, 10);
            bound_sig = (np.maximum(0.1, min_bw/(2*np.sqrt(2*np.log(2)))), max_bw/(2*np.sqrt(2*np.log(2)))); # Gaussian at half-height
            all_bounds = (bound_baseline, bound_range, bound_mu, bound_sig, bound_sig);

            for n_try in range(n_repeats):
                
                # pick initial params
                init_base = hfunc.random_in_range(range_baseline);
                init_amp = hfunc.random_in_range(range_amp);
                init_mu = hfunc.random_in_range(range_mu);
                init_sig_left = hfunc.random_in_range(range_denom);
                init_sig_right = hfunc.random_in_range(range_denom);
                         
                init_params = [init_base, init_amp, init_mu, init_sig_left, init_sig_right];
                         
                # choose optimization method
                if np.mod(n_try, 2) == 0:
                    methodStr = 'L-BFGS-B';
                else:
                    methodStr = 'TNC';
                
                obj = lambda params: descr_loss(params, data, family, con, loss_type);
                wax = opt.minimize(obj, init_params, method=methodStr, bounds=all_bounds);
                
                # compare
                NLL = wax['fun'];
                params = wax['x'];

                if np.isnan(bestNLL[family, con]) or NLL < bestNLL[family, con] or invalid(currParams[family, con, :], all_bounds):
                    bestNLL[family, con] = NLL;
                    currParams[family, con, :] = params;

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + 'descrFits' + loss_str):
        print('reloading descrFits...');
        descrFits = hfunc.np_smart_load(data_loc + 'descrFits' + loss_str);
    if cell_num-1 not in descrFits:
      descrFits[cell_num-1] = dict();
    descrFits[cell_num-1]['NLL'] = bestNLL;
    descrFits[cell_num-1]['params'] = currParams;

    np.save(data_loc + 'descrFits' + loss_str, descrFits);
    print('saving for cell ' + str(cell_num));
Esempio n. 5
0
save_loc = str(save_loc + subDir + '/')
if not os.path.exists(save_loc):
    os.makedirs(save_loc)

rpt_fit = 1
# i.e. take the multi-start result
if rpt_fit:
    is_rpt = '_rpt'
else:
    is_rpt = ''

conDig = 3
# round contrast to the 3rd digit

dataList = np.load(str(data_loc + expName), encoding='latin1').item()
fitList_fl = hf.np_smart_load(data_loc + fitName_fl)
fitList_wg = hf.np_smart_load(data_loc + fitName_wg)

cellName = dataList['unitName'][cellNum - 1]
try:
    cellType = dataList['unitType'][cellNum - 1]
except:
    # TODO: note, this is dangerous; thus far, only V1 cells don't have 'unitType' field in dataList, so we can safely do this
    cellType = 'V1'

expData = np.load(str(data_loc + cellName + '_sfm.npy'),
                  encoding='latin1').item()
expInd = hf.get_exp_ind(data_loc, cellName)[0]

# #### Load model fits
Esempio n. 6
0
        from functools import partial
        import multiprocessing as mp
        nCpu = mp.cpu_count()

        # to avoid race conditions, load the previous fits beforehand; and the datalist
        rvcNameFinal = hf.rvc_fit_name(rvcName, rvc_mod, None, vecF1=1)
        # DEFAULT is vecF1 adjustment
        modStr = hf.descrMod_name(sf_mod)
        sfNameFinal = hf.descrFit_name(loss_type,
                                       descrBase=sfName,
                                       modelName=modStr,
                                       joint=jointSf)
        # descrLoss order is lsq/sqrt/poiss/sach

        pass_rvc = hf.np_smart_load(
            '%s%s%s' %
            (basePath, data_suff, rvcNameFinal)) if fit_rvc else None
        pass_sf = hf.np_smart_load(
            '%s%s%s' % (basePath, data_suff, sfNameFinal)) if fit_sf else None

        dataList = hf.np_smart_load(
            '%s%s%s' % (basePath, data_suff, hf.get_datalist('V1_BB/')))

        if nBoots > 1:
            n_repeats = 3 if jointSf > 0 else 5
            # fewer if repeat
        else:
            n_repeats = 20 if jointSf > 0 else 15
            # was previously be 3, 15, then 7, 15

        with mp.Pool(processes=nCpu) as pool:
Esempio n. 7
0
        fL_suffix1 = '_c50'
    # lossType
    if lossType == 1:
        fL_suffix2 = '_sqrt.npy'
    elif lossType == 2:
        fL_suffix2 = '_poiss.npy'
    elif lossType == 3:
        fL_suffix2 = '_modPoiss.npy'

    save_name = '%s%s%s' % (save_base, fL_suffix1, fL_suffix2)
    save_loc = '/home/pl1465/SF_diversity/Analysis/Structures/'
    # Prince cluster
    #save_loc = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/Analysis/Structures/

    if os.path.isfile(save_loc + save_name):
        fits = np_smart_load(str(save_loc + save_name))
        if cellNum - 1 in fits:
            fits_curr = fits[cellNum - 1]
        else:
            fits_curr = None
    else:
        fits = dict()
        fits_curr = None

    if fits_curr is None:
        nDisps = 5
        nCons = 2
        nSfs = 11

        if collapseSF == 1:
            NLLs = numpy.nan * numpy.empty((nDisps, nCons))
Esempio n. 8
0
#rvcBase = 'rvcFits_200507'; # direc flag & '.npy' are added
#rvcBase = 'rvcFits_191023'; # direc flag & '.npy' are adde
#rvcBase = 'rvcFits_200714'; # direc flag & '.npy' are adde
#rvcBase = 'rvcFits_200507';
rvcBase = 'rvcFits_210517'
# -- rvcAdj = -1 means, yes, load the rvcAdj fits, but with vecF1 correction rather than ph fit; so, we'll
rvcAdjSigned = rvcAdj
rvcAdj = np.abs(rvcAdj)

##################
### Spatial frequency
##################

modStr = hf.descrMod_name(descrMod)
fLname = hf.descrFit_name(descrLoss, descrBase=descrBase, modelName=modStr)
descrFits = hf.np_smart_load(data_loc + fLname)
pause_tm = 2.5 * np.random.rand()
time.sleep(pause_tm)
# set the save directory to save_loc, then create the save directory if needed
subDir = fLname.replace('Fits', '').replace('.npy', '')
save_loc = str(save_loc + subDir + '/')

if not os.path.exists(save_loc):
    os.makedirs(save_loc)

dataList = hf.np_smart_load(data_loc + expName)

cellName = dataList['unitName'][cellNum - 1]
try:
    cellType = dataList['unitType'][cellNum - 1]
except:
Esempio n. 9
0
def fit_all_CRF_boot(cell_num,
                     data_loc,
                     each_c50,
                     loss_type,
                     n_boot_iter=1000):
    np = numpy
    conDig = 3
    # round contrast to the thousandth
    n_params = 5
    # 4 for NR, 1 for varGain

    if each_c50 == 1:
        fit_key = 'fits_each'
    else:
        fit_key = 'fits'

    if loss_type == 1:
        loss_str = '-lsq'
    if loss_type == 2:
        loss_str = '-sqrt'
    if loss_type == 1:
        loss_str = '-poiss'
    if loss_type == 1:
        loss_str = '-poissMod'
    fits_name = 'crfFits' + loss_str + '.npy'

    dataList = hf.np_smart_load(str(data_loc + 'dataList.npy'))
    if os.path.isfile(data_loc + fits_name):
        crfFits = hf.np_smart_load(str(data_loc + fits_name))
    else:
        crfFits = dict()

    cellStruct = hf.np_smart_load(
        str(data_loc + dataList['unitName'][cell_num - 1] + '_sfm.npy'))
    data = cellStruct['sfm']['exp']['trial']

    all_cons = np.unique(np.round(data['total_con'], conDig))
    all_cons = all_cons[~np.isnan(all_cons)]

    all_sfs = np.unique(data['cent_sf'])
    all_sfs = all_sfs[~np.isnan(all_sfs)]

    all_disps = np.unique(data['num_comps'])
    all_disps = all_disps[all_disps > 0]
    # ignore zero...

    nCons = len(all_cons)
    nSfs = len(all_sfs)
    nDisps = len(all_disps)

    nk_ru = dict()
    nk_ru_boot = dict()
    all_data = dict()

    for d in range(nDisps):
        valid_disp = data['num_comps'] == all_disps[d]
        cons = []
        resps = []

        nk_ru[d] = dict()
        nk_ru_boot[d] = dict()
        all_data[d] = dict()
        v_sfs = []
        # keep track of valid sfs

        for sf in range(nSfs):

            valid_sf = data['cent_sf'] == all_sfs[sf]

            valid_tr = valid_disp & valid_sf
            if np.all(np.unique(valid_tr) ==
                      False):  # did we not find any trials?
                continue

            v_sfs.append(sf)

            nk_ru[d][sf] = dict()
            # create dictionary here; thus, only valid sfs have valid keys
            nk_ru_boot[d][sf] = dict()
            # create dictionary here; thus, only valid sfs have valid keys
            # for unpacking loss/parameters later...
            nk_ru[d][sf]['params'] = np.nan * np.zeros((n_params, 1))
            nk_ru[d][sf]['loss'] = np.nan
            nk_ru_boot[d][sf]['params'] = np.nan * np.zeros(
                (n_boot_iter, n_params))
            nk_ru_boot[d][sf]['loss'] = np.nan * np.zeros((n_boot_iter, 1))

            resps.append(data['spikeCount'][valid_tr])
            cons.append(data['total_con'][valid_tr])

# save data for later use
        all_data[d]['resps'] = resps
        all_data[d]['cons'] = cons
        all_data[d]['valid_sfs'] = v_sfs

        maxResp = np.max(np.max(resps))
        n_v_sfs = len(v_sfs)

        if each_c50 == 1:
            n_c50s = n_v_sfs
            # separate for each SF...
        else:
            n_c50s = 1

        init_base = 0.1
        bounds_base = (0.01, maxResp)
        init_gain = np.max(resps) - np.min(resps)
        bounds_gain = (0, 10 * maxResp)
        init_expn = 2
        bounds_expn = (1, 10)
        init_c50 = 0.1
        #geomean(all_cons);
        bounds_c50 = (0.01, 10 * max(all_cons))
        # contrast values are b/t [0, 1]
        init_varGain = 1
        bounds_varGain = (0.01, None)

        base_inits = np.repeat(init_base, 1)
        # only one baseline per SF
        base_constr = [tuple(x) for x in np.broadcast_to(bounds_base, (1, 2))]

        gain_inits = np.repeat(init_gain, n_v_sfs)
        # ...and gain
        gain_constr = [
            tuple(x) for x in np.broadcast_to(bounds_gain, (n_v_sfs, 2))
        ]

        c50_inits = np.repeat(init_c50, n_c50s)
        # repeat n_v_sfs times if c50 separate for each SF; otherwise, 1
        c50_constr = [
            tuple(x) for x in np.broadcast_to(bounds_c50, (n_c50s, 2))
        ]

        init_params = np.hstack(
            (c50_inits, init_expn, gain_inits, base_inits, init_varGain))
        boundsAll = np.vstack((c50_constr, bounds_expn, gain_constr,
                               base_constr, bounds_varGain))
        boundsAll = [tuple(x) for x in boundsAll]
        # turn the (inner) arrays into tuples...

        expn_ind = n_c50s
        gain_ind = n_c50s + 1
        base_ind = gain_ind + n_v_sfs
        # only one baseline per dispersion...
        varGain_ind = base_ind + 1

        # first, fit original dataset
        obj = lambda params: hf.fit_CRF(cons, resps, params[0:n_c50s], params[
            expn_ind], params[gain_ind:gain_ind + n_v_sfs], params[base_ind],
                                        params[varGain_ind], loss_type)
        opts_full = opt.minimize(obj, init_params, bounds=boundsAll)

        # now unpack...
        params = opts_full['x']
        for sf_in in range(n_v_sfs):
            if n_c50s == 1:
                c50_ind = 0
            else:
                c50_ind = sf_in

            nk_ru[d][v_sfs[sf_in]]['params'][0] = params[base_ind]
            nk_ru[d][v_sfs[sf_in]]['params'][1] = params[gain_ind + sf_in]
            nk_ru[d][v_sfs[sf_in]]['params'][2] = params[expn_ind]
            nk_ru[d][v_sfs[sf_in]]['params'][3] = params[c50_ind]
            # params (to match naka_rushton) are: baseline, gain, expon, c50
            nk_ru[d][v_sfs[sf_in]]['params'][4] = params[varGain_ind]
            nk_ru[d][v_sfs[sf_in]]['loss'] = opts_full['fun']

# then, bootstrap resample
        for boot_i in range(n_boot_iter):
            resamp_resps = []
            resamp_cons = []

            # resample the data
            for sf_i in range(len(resps)):
                resamp_inds = numpy.random.randint(0, len(resps[sf_i]),
                                                   len(resps[sf_i]))
                resamp_resps.append(resps[sf_i][resamp_inds])
                resamp_cons.append(cons[sf_i][resamp_inds])

            obj = lambda params: hf.fit_CRF(
                resamp_cons, resamp_resps, params[0:n_c50s], params[expn_ind],
                params[gain_ind:gain_ind + n_v_sfs], params[base_ind], params[
                    varGain_ind], loss_type)
            opts = opt.minimize(obj, init_params, bounds=boundsAll)

            # now unpack...
            params = opts['x']
            for sf_in in range(n_v_sfs):
                if n_c50s == 1:
                    c50_ind = 0
                else:
                    c50_ind = sf_in
                nk_ru_boot[d][v_sfs[sf_in]]['params'][boot_i,
                                                      0] = params[base_ind]
                nk_ru_boot[d][v_sfs[sf_in]]['params'][boot_i,
                                                      1] = params[gain_ind +
                                                                  sf_in]
                nk_ru_boot[d][v_sfs[sf_in]]['params'][boot_i,
                                                      2] = params[expn_ind]
                nk_ru_boot[d][v_sfs[sf_in]]['params'][boot_i,
                                                      3] = params[c50_ind]
                # params (to match naka_rushton) are: baseline, gain, expon, c50
                nk_ru_boot[d][v_sfs[sf_in]]['params'][boot_i,
                                                      4] = params[varGain_ind]
                nk_ru_boot[d][v_sfs[sf_in]]['loss'][boot_i] = opts['fun']

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + fits_name):
        print('reloading CRF Fits...')
        crfFits = hf.np_smart_load(str(data_loc + fits_name))
    if cell_num - 1 not in crfFits:
        crfFits[cell_num - 1] = dict()
    crfFits[cell_num - 1][fit_key] = nk_ru
    crfFits[cell_num - 1]['data'] = all_data
    crfFits[cell_num - 1][str(fit_key + '_boot')] = nk_ru_boot

    np.save(data_loc + fits_name, crfFits)
    print('saving for cell ' + str(cell_num))

    return nk_ru
Esempio n. 10
0
if len(inhAsym) == 1:
    inhAsyms = inhAsym * nRecov

# get the directory, set up the dataList
loc_base = os.getcwd() + '/'
# ensure there is a "/" after the final directory
dL_mr = dict()
# set up the datalist components
mr_names = []
mr_unitArea = []
mr_expType = []

for param, nm, dl, expDr, cellNum, inhAsym in zip(params, recovName, dataLists,
                                                  expDirs, cellNums, inhAsyms):
    loc_data = loc_base + expDr + 'structures/'
    dl_in = hf.np_smart_load(loc_data + dl)
    regFileName = dl_in['unitName'][cellNum - 1] + '_sfm.npy'
    mrFileName = ('mr%s_' % nm) + regFileName
    # copy that whole data structure, but add "mr_" at the beginning
    if not os.path.isfile(loc_data + mrFileName) or overwriteMR:
        print('moving %s to %s...' % (regFileName, mrFileName))
        mvStr = 'cp %s %s' % (loc_data + regFileName, loc_data + mrFileName)
        os.system(mvStr)
        print('...done!\n')
        curr = hf.np_smart_load(loc_data + mrFileName)
        # add a model recovery section
        curr['sfm']['mod']['recovery'] = dict()
        curr['sfm']['mod']['recovery']['paramsWght'] = param
        baseParams = param[0:len(param) - 2]
        # all params except the two relating to normalization tuning
        baseParams.append(inhAsym)
Esempio n. 11
0
binWidth = 1e-3; # in seconds
stimDur = 1; # in seconds

# at CNS
# dataPath = '/arc/2.2/p1/plevy/SF_diversity/sfDiv-OriModel/sfDiv-python/altExp/recordings/';
# savePath = '/arc/2.2/p1/plevy/SF_diversity/sfDiv-OriModel/sfDiv-python/altExp/analysis/';
# personal mac
#dataPath = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/LGN/analysis/structures/';
#save_loc = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/LGN/analysis/figures/';
# prince cluster
dataPath = '/home/pl1465/SF_diversity/LGN/analysis/structures/';
save_loc = '/home/pl1465/SF_diversity/LGN/analysis/figures/';

expName = 'dataList.npy'

dataList = hf.np_smart_load(str(dataPath + expName));
loadName = str(dataPath + dataList['unitName'][which_cell-1] + '_sfm.npy');
cellStruct = hf.np_smart_load(loadName);
data = cellStruct['sfm']['exp']['trial'];

allSpikes = data['spikeTimes'];

# Create PSTH, spectrum for all cells
psth_all, _ = hf.make_psth(allSpikes, binWidth, stimDur);
spect_all, _, _ = hf.spike_fft(psth_all);

# now for valid trials (i.e. non-blanks), compute the stimulus-relevant power
n_stim_comp = np.max(data['num_comps']);
n_tr = len(psth_all);
stim_power = np.array(np.nan*np.zeros(n_tr, ), dtype='O'); # object dtype; more flexible
Esempio n. 12
0
if fitType == 1:
    fitSuf = '_flat'
elif fitType == 2:
    fitSuf = '_wght'
# then the loss type
if lossType == 1:
    lossSuf = '_sqrt_details.npy'
elif lossType == 2:
    lossSuf = '_poiss_details.npy'
elif lossType == 3:
    lossSuf = '_modPoiss_details.npy'
elif lossType == 4:
    lossSuf = '_chiSq_details.npy'
# load fit details
fitName = str(fitBase + fitSuf + lossSuf)
fitDetails = hf.np_smart_load(dataPath + fitName)
fitDet = fitDetails[which_cell - 1]
# load rvc/ph fits, if applicable
rvcFits = hf.get_rvc_fits(dataPath, expInd, which_cell)
phFits = hf.get_rvc_fits(dataPath,
                         expInd,
                         which_cell,
                         rvcName='phaseAdvanceFits')
# load cell structure
cellStruct = hf.np_smart_load(dataPath + dataList['unitName'][which_cell - 1] +
                              '_sfm.npy')
data = cellStruct['sfm']['exp']['trial']

# also, get save directory
compDir = str(fitBase + '_anim' + lossSuf.replace('details', ''))
subDir = compDir.replace('fitList', 'fits').replace('.npy', '')
Esempio n. 13
0
def setModel(cellNum, stopThresh, lr, lossType = 1, fitType = 1, subset_frac = 1, initFromCurr = 1, holdOutCondition = None):
    # Given just a cell number, will fit the Robbe-inspired V1 model to the data
    #
    # stopThresh is the value (in NLL) at which we stop the fitting (i.e. if the difference in NLL between two full steps is < stopThresh, stop the fitting
    #
    # LR is learning rate
    #
    # lossType
    #   1 - loss := square(sqrt(resp) - sqrt(pred))
    #   2 - loss := poissonProb(spikes | modelRate)
    #   3 - loss := modPoiss model (a la Goris, 2014)
    #   4 - loss := chi squared (a la Cavanaugh, 2002)
    #
    # fitType - what is the model formulation?
    #   1 := flat normalization
    #   2 := gaussian-weighted normalization responses
    #   3 := gaussian-weighted c50/norm "constant"
    #
    # holdOutCondition - [d, c, sf] or None
    #   which condition should we hold out from the dataset
 
    ########
    # Load cell
    ########
    #loc_data = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/altExp/analysis/structures/'; # personal mac
    #loc_data = '/home/pl1465/SF_diversity/altExp/analysis/structures/'; # Prince cluster 
    loc_data = '/arc/2.2/p1/plevy/SF_diversity/sfDiv-OriModel/sfDiv-python/altExp/analysis/structures/'; # CNS
    fL_name = 'fitListSP_181202c'

    np = numpy;

    # fitType
    if fitType == 1:
      fL_suffix1 = '_flat';
    elif fitType == 2:
      fL_suffix1 = '_wght';
    elif fitType == 3:
      fL_suffix1 = '_c50';
    # lossType
    if lossType == 1:
      fL_suffix2 = '_sqrt.npy';
    elif lossType == 2:
      fL_suffix2 = '_poiss.npy';
    elif lossType == 3:
      fL_suffix2 = '_modPoiss.npy';
    elif lossType == 4:
      fL_suffix2 = '_chiSq.npy';
    fitListName = str(fL_name + fL_suffix1 + fL_suffix2);

    if os.path.isfile(loc_data + fitListName):
      fitList = np_smart_load(str(loc_data + fitListName));
    else:
      fitList = dict();

    dataList = np_smart_load(str(loc_data + 'dataList.npy'));
    dataNames = dataList['unitName'];

    print('loading data structure...');
    S = np_smart_load(str(loc_data + dataNames[cellNum-1] + '_sfm.npy')); # why -1? 0 indexing...
    print('...finished loading');
    trial_inf = S['sfm']['exp']['trial'];
    prefSfEst = gmean(trial_inf['sf'][0][~numpy.isnan(trial_inf['sf'][0])]); # avoid NaN trials...
    
    ########

    # 00 = preferred spatial frequency   (cycles per degree)
    # 01 = derivative order in space
    # 02 = normalization constant        (log10 basis)
    # 03 = response exponent
    # 04 = response scalar
    # 05 = early additive noise
    # 06 = late additive noise
    # 07 = variance of response gain - only used if lossType = 3
    # if fitType == 2
    # 08 = mean of (log)gaussian for normalization weights
    # 09 = std of (log)gaussian for normalization weights
    # if fitType == 3
    # 08 = the offset of the c50 tuning curve which is bounded between [v_sigOffset, 1] || [0, 1]
    # 09 = standard deviation of the gaussian to the left of the peak || >0.1
    # 10 = "" to the right "" || >0.1
    # 11 = peak of offset curve
    
    if cellNum-1 in fitList:
      curr_params = fitList[cellNum-1]['params']; # load parameters from the fitList! this is what actually gets updated...
    else: # set up basic fitList structure...
      curr_params = [];
      initFromCurr = 0; # override initFromCurr so that we just go with default parameters
      fitList[cellNum-1] = dict();
      fitList[cellNum-1]['NLL'] = 1e4; # large initial value...

    if numpy.any(numpy.isnan(curr_params)): # if there are nans, we need to ignore...
      curr_params = [];
      initFromCurr = 0;

    pref_sf = float(prefSfEst) if initFromCurr==0 else curr_params[0];
    dOrdSp = np.random.uniform(1, 3) if initFromCurr==0 else curr_params[1];
    normConst = -0.8 if initFromCurr==0 else curr_params[2]; # why -0.8? Talked with Tony, he suggests starting with lower sigma rather than higher/non-saturating one
    #normConst = np.random.uniform(-1, 0) if initFromCurr==0 else curr_params[2];
    respExp = np.random.uniform(1, 3) if initFromCurr==0 else curr_params[3];
    respScalar = np.random.uniform(10, 1000) if initFromCurr==0 else curr_params[4];
    noiseEarly = np.random.uniform(0.001, 0.1) if initFromCurr==0 else curr_params[5];
    noiseLate = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[6];
    varGain = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[7];
    if fitType == 1:
      inhAsym = 0; 
    if fitType == 2:
      normMean = np.random.uniform(-1, 1) if initFromCurr==0 else curr_params[8];
      normStd = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[9];
    if fitType == 3:
      sigOffset = np.random.uniform(0, 0.05) if initFromCurr==0 else curr_params[8];
      stdLeft = np.random.uniform(1, 5) if initFromCurr==0 else curr_params[9];
      stdRight = np.random.uniform(1, 5) if initFromCurr==0 else curr_params[10];
      sigPeak = float(prefSfEst) if initFromCurr==0 else curr_params[11];

    print('Initial parameters:\n\tsf: ' + str(pref_sf)  + '\n\td.ord: ' + str(dOrdSp) + '\n\tnormConst: ' + str(normConst));
    print('\n\trespExp ' + str(respExp) + '\n\trespScalar ' + str(respScalar));
    
    #########
    # Now get all the data we need
    #########    
    # stimulus information
    
    # vstack to turn into array (not array of arrays!)
    stimOr = np.vstack(trial_inf['ori']);

    #purge of NaNs...
    mask = np.isnan(np.sum(stimOr, 0)); # sum over all stim components...if there are any nans in that trial, we know
    objWeight = np.ones((stimOr.shape[1]));    

    ''' For now, let's ignore holdout in /altExp/functions/model_responses.py
    # hold out a condition if we have specified, and adjust the mask accordingly
    if holdOutCondition is not None:
      # first, get all of the conditions... - blockIDs by condition known from Robbe code
      dispInd = holdOutCondition[0];
      conInd = holdOutCondition[1];
      sfInd = holdOutCondition[2];

      StimBlockIDs  = np.arange(((dispInd-1)*(13*2)+1)+(conInd-1), ((dispInd)*(13*2)-5)+(conInd-1)+1, 2); # +1 to include the last block ID
      currBlockID = StimBlockIDs[sfInd-1];
      holdOutTr = np.where(trial_inf['blockID'] == currBlockID)[0];
      mask[holdOutTr.astype(np.int64)] = True; # as in, don't include those trials either!
    '''
      
    # Set up model here - get the parameters and parameter bounds
    if fitType == 1:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, inhAsym);
    elif fitType == 2:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, normMean, normStd);
    elif fitType == 3:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, sigOffset, stdLeft, stdRight, sigPeak);
    all_bounds = getConstraints(fitType);
   
    # now set up the optimization
    obj = lambda params: SFMGiveBof(params, structureSFM=S, normType=fitType, lossType=lossType, maskIn=~mask)[0];
    tomin = opt.minimize(obj, param_list, bounds=all_bounds);
    #tomin = opt.minimize(obj, param_list, method='SLSQP', bounds=all_bounds);
    #minimizer_kwargs = dict(method='L-BFGS-B', bounds=all_bounds)
    #tomin = opt.basinhopping(obj, param_list, minimizer_kwargs=minimizer_kwargs);

    opt_params = tomin['x'];
    NLL = tomin['fun'];

    currNLL = fitList[cellNum-1]['NLL']; # exists - either from real fit or as placeholder

    if NLL < currNLL:
      # reload fitlist in case changes have been made with the file elsewhere!
      if os.path.exists(loc_data + fitListName):
        fitList = np_smart_load(str(loc_data + fitListName));
      # else, nothing to reload!!!
      # but...if we reloaded fitList and we don't have this key (cell) saved yet, recreate the key entry...
      if cellNum-1 not in fitList:
        fitList[cellNum-1] = dict();
      fitList[cellNum-1]['NLL'] = NLL;
      fitList[cellNum-1]['params'] = opt_params;
      # NEW: Also save whether or not fit was success, exit message (18.12.01)
      fitList[cellNum-1]['success'] = tomin['success'];
      fitList[cellNum-1]['message'] = tomin['message'];
      numpy.save(loc_data + fitListName, fitList);   

    ''' Again, ignoring holdoutNLL for now
    if holdOutCondition is not None:
      holdoutNLL, _, = SFMGiveBof(opt_params, structureSFM=S, normType=fitType, lossType=lossType, trialSubset=holdOutTr);
    else:
      holdoutNLL = [];
    '''
    holdoutNLL = [];

    return NLL, opt_params, holdoutNLL;
Esempio n. 14
0
def setModel(cellNum, stopThresh, lr, lossType = 1, fitType=1, subset_frac = 1, initFromCurr = 1):
    # Given just a cell number, will fit the Robbe V1 model to the data
    # stopThresh is the value (in NLL) at which we stop the fitting (i.e. if the difference in NLL between two full steps is < stopThresh, stop the fitting
    # LR is learning rate
    # lossType
    #   1 - loss := square(sqrt(resp) - sqrt(pred))
    #   2 - loss := poissonProb(spikes | modelRate)
    #   3 - loss := modPoiss model (a la Goris, 2014)
    # fitType - what is the model formulation?
    #   1 := flat normalization
    #   2 := gaussian-weighted normalization responses
    #   3 := gaussian-weighted c50/norm "constant"

    ########
    # Load cell
    ########
    loc_data = '/home/pl1465/SF_diversity/LGN/analysis/structures/'; # Prince cluster
    #loc_data = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/LGN/analysis/structures/'; # Personal mac

    fL_name = 'fitList_181129';
    # fitType
    if fitType == 1:
      fL_suffix1 = '_flat';
    elif fitType == 2:
      fL_suffix1 = '_wght';
    elif fitType == 3:
      fL_suffix1 = '_c50';
    # lossType
    if lossType == 1:
      fL_suffix2 = '_sqrt.npy';
    elif lossType == 2:
      fL_suffix2 = '_poiss.npy';
    elif lossType == 3:
      fL_suffix2 = '_modPoiss.npy';
    fitListName = str(fL_name + fL_suffix1 + fL_suffix2);

    if os.path.exists(loc_data + fitListName):
      fitList = np_smart_load(str(loc_data + fitListName));
    else:
      fitList = dict();
    dataList = np_smart_load(str(loc_data + 'dataList.npy'));
    dataNames = dataList['unitName'];

    S = np_smart_load(str(loc_data + dataNames[cellNum-1] + '_sfm.npy')); # why -1? 0 indexing...
    data = S['sfm']['exp']['trial'];
    rvcFits = np_smart_load(str(loc_data + 'rvcFits_pos.npy'));
    trial_inf = S['sfm']['exp']['trial'];
    #prefOrEst = mode(trial_inf['ori'][1]).mode;
    prefSfEst = gmean(trial_inf['sf'][0][~numpy.isnan(trial_inf['sf'][0])]); # avoid NaN trials...

    ########
    # Set up model parameters - i.e. trainable variables!
    ########

    # 00 = preferred spatial frequency   (cycles per degree)
    # 01 = derivative order in space
    # 02 = normalization constant        (log10 basis)
    # 03 = response exponent
    # 04 = response scalar
    # 05 = early additive noise
    # 06 = late additive noise
    # 07 = variance of response gain - only used if lossType = 3
    # if fitType == 2
    # 08 = mean of (log)gaussian for normalization weights
    # 09 = std of (log)gaussian for normalization weights
    # if fitType == 3
    # 08 = the offset of the c50 tuning curve which is bounded between [v_sigOffset, 1] || [0, 1]
    # 09 = standard deviation of the gaussian to the left of the peak || >0.1
    # 10 = "" to the right "" || >0.1
    # 11 = peak of offset curve

    if cellNum-1 in fitList:
      curr_params = fitList[cellNum-1]['params']; # load parameters from the fitList! this is what actually gets updated...
    else: # set up basic fitList structure...
      curr_params = [];
      initFromCurr = 0; # override initFromCurr so that we just go with default parameters
      fitList[cellNum-1] = dict();
      fitList[cellNum-1]['NLL'] = 1e4; # large initial value...

    if numpy.any(numpy.isnan(curr_params)): # if there are nans, we need to ignore...
      curr_params = [];
      initFromCurr = 0;

    pref_sf = float(prefSfEst) if initFromCurr==0 else curr_params[0];
    dOrdSp = numpy.random.uniform(1, 3) if initFromCurr==0 else curr_params[1];
    normConst = -0.8 if initFromCurr==0 else curr_params[2]; # why -0.8? Talked with Tony, he suggests starting with lower sigma rather than higher/non-saturating one
    #normConst = numpy.random.uniform(-1, 0) if initFromCurr==0 else curr_params[2];
    respExp = numpy.random.uniform(1, 3) if initFromCurr==0 else curr_params[3];
    respScal = numpy.random.uniform(10, 1000) if initFromCurr==0 else curr_params[4];
    noiseEarly = numpy.random.uniform(0.001, 0.1) if initFromCurr==0 else curr_params[5];
    noiseLate = numpy.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[6];
    varGain = numpy.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[7];
    if fitType == 2:
      normMean = numpy.random.uniform(-1, 1) if initFromCurr==0 else curr_params[8];
      normStd = numpy.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[9];
    if fitType == 3:
      sigOffset = numpy.random.uniform(0, 0.05) if initFromCurr==0 else curr_params[8];
      stdLeft = numpy.random.uniform(1, 5) if initFromCurr==0 else curr_params[9];
      stdRight = numpy.random.uniform(1, 5) if initFromCurr==0 else curr_params[10];
      sigPeak = float(prefSfEst) if initFromCurr==0 else curr_params[11];

    print('Initial parameters:\n\tsf: ' + str(pref_sf)  + '\n\td.ord: ' + str(dOrdSp) + '\n\tnormConst: ' + str(normConst));
    print('\n\trespExp ' + str(respExp) + '\n\trespScalar ' + str(respScal));
    
    v_prefSf = tf.Variable(pref_sf, dtype=tf.float32);
    v_dOrdSp = tf.Variable(dOrdSp, dtype=tf.float32);
    v_normConst = tf.Variable(normConst, dtype=tf.float32);
    v_respExp = tf.Variable(respExp, dtype=tf.float32);
    v_respScalar = tf.Variable(respScal, dtype=tf.float32);
    v_noiseEarly = tf.Variable(noiseEarly, dtype=tf.float32);
    v_noiseLate = tf.Variable(noiseLate, dtype=tf.float32);
    v_varGain = tf.Variable(varGain, dtype=tf.float32);
    if fitType == 2:
      v_normMean = tf.Variable(normMean, dtype=tf.float32);
      v_normStd = tf.Variable(normStd, dtype=tf.float32);
    if fitType == 3:
      v_sigOffset = tf.Variable(sigOffset, dtype=tf.float32);
      v_stdLeft = tf.Variable(stdLeft, dtype=tf.float32);
      v_stdRight = tf.Variable(stdRight, dtype=tf.float32);
      v_sigPeak = tf.Variable(sigPeak, dtype=tf.float32);
 
    #########
    # Now get all the data we need for tf_placeholders 
    #########    
    # stimulus information
    
    # vstack to turn into array (not array of arrays!)
    stimOr = numpy.vstack(trial_inf['ori']);
    stimTf = numpy.vstack(trial_inf['tf']);
    stimCo = numpy.vstack(trial_inf['con']);
    stimSf = numpy.vstack(trial_inf['sf']);
    stimPh = numpy.vstack(trial_inf['ph']);
    
    #purge of NaNs...
    mask = numpy.isnan(numpy.sum(stimOr, 0)); # sum over all stim components...if there are any nans in that trial, we know

    objWeight = numpy.ones((stimOr.shape[1]));    

    fixedOr = stimOr[:,~mask];
    fixedTf = stimTf[:,~mask];
    fixedCo = stimCo[:,~mask];
    fixedSf = stimSf[:,~mask];
    fixedPh = stimPh[:,~mask];
    
    # cell responses
    _, spks, _, _ = organize_adj_responses(data, rvcFits[cellNum-1]);
    spikes = spks[~mask];
    #spikes = [numpy.sum(x) for x in trial_inf['power_f1'][~mask]];
    stim_dur = trial_inf['duration'][~mask];
    objWeight = objWeight[~mask];        

    #########
    # Now set up our normalization pool information (also placeholder)
    #########
    # Get the normalization response (nTrials x nFilters [27] x nFrames [120])
    normResp = S['sfm']['mod']['normalization']['normResp'][~mask,:,:];
    
    # Put all of the filter prefSf into one vector (should be length 12+15=27)
    muCenterPref = [];
    normWeight = [];
    normPrefSf = S['sfm']['mod']['normalization']['pref']['sf'];
    for iP in range(len(normPrefSf)):
        muCenterPref = numpy.append(muCenterPref, numpy.log(normPrefSf[iP])); # TODO: Change name if works (4/26/18)
        #muCenterPref = numpy.append(muCenterPref, numpy.log(normPrefSf[iP]) - numpy.mean(numpy.log(normPrefSf[iP])));
    
    normCentSf = muCenterPref;
    
    #########
    # Set up the network!
    #########
    subsetShape = [fixedTf.shape[0], int(round(fixedTf.shape[-1]*subset_frac))];
    
    ph_stimOr = tf.placeholder(tf.float32);
    if subset_frac < 1:
      ph_stimTf = tf.placeholder(tf.float32, shape=subsetShape);
    else:
      ph_stimTf = tf.placeholder(tf.float32, shape=fixedTf.shape);
    ph_stimCo = tf.placeholder(tf.float32);
    ph_stimSf = tf.placeholder(tf.float32);
    ph_stimPh = tf.placeholder(tf.float32);
    
    ph_spikeCount = tf.placeholder(tf.float32);
    ph_stimDur = tf.placeholder(tf.float32);
    ph_objWeight = tf.placeholder(tf.float32);
        
    ph_normResp = tf.placeholder(tf.float32);
    ph_normCentSf = tf.placeholder(tf.float32);

    print('Setting network');

    if fitType == 1:
      param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar, v_noiseEarly, v_noiseLate, v_varGain);
    elif fitType == 2:
      param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar, v_noiseEarly, v_noiseLate, v_varGain, v_normMean, v_normStd);
    elif fitType == 3:
      param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar, v_noiseEarly, v_noiseLate, v_varGain, v_sigOffset, v_stdLeft, v_stdRight, v_sigPeak);
    # now make the call
    okok = SFMGiveBof(ph_stimOr, ph_stimTf, ph_stimCo, ph_stimSf, ph_stimPh, ph_spikeCount, ph_stimDur, ph_objWeight, \
                        ph_normResp, ph_normCentSf, lossType, fitType, *param_list);

    if subset_frac < 1:  # then we also need to create a network which can handle the full dataset
      ph_stimTfFull = tf.placeholder(tf.float32, shape=fixedTf.shape);
      full = SFMGiveBof(ph_stimOr, ph_stimTfFull, ph_stimCo, ph_stimSf, ph_stimPh, ph_spikeCount, ph_stimDur, ph_objWeight, \
                ph_normResp, ph_normCentSf, lossType, fitType, *param_list);
    
    print('Setting optimizer');
    optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(okok);

    m = tf.Session();
    init = tf.global_variables_initializer();
    m.run(init);

    # compute initial loss
    NLL = m.run(okok, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                ph_stimDur: stim_dur, ph_objWeight:objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf});
    print('\n\n*** Initial loss: %.3f ***\n' % NLL);
    
    # guaranteed to have NLL for this cell by now (even if just placeholder)
    currNLL = fitList[cellNum-1]['NLL'];
    prevNLL = numpy.nan;
    diffNLL = 1e4; # just pick a large value
    iter = 1;

    if subset_frac < 1: # do the subsampling ONCE
      trialsToPick = numpy.random.randint(0, fixedOr.shape[-1], subsetShape[-1]);
      subsetOr = fixedOr[:,trialsToPick];
      subsetTf = fixedTf[:,trialsToPick];
      subsetCo = fixedCo[:,trialsToPick];
      subsetSf = fixedSf[:,trialsToPick];
      subsetPh = fixedPh[:,trialsToPick];
      subsetSpikes = spikes[trialsToPick];
      subsetDur = stim_dur[trialsToPick];
      subsetWeight = objWeight[trialsToPick];
      subsetNormResp = normResp[trialsToPick,:,:];

    while (abs(diffNLL) > stopThresh):

        if subset_frac < 1: # pass in the subsampled data
          opt = m.run(optimizer, feed_dict={ph_stimOr: subsetOr, ph_stimTf: subsetTf, ph_stimCo: subsetCo, \
                          ph_stimSf: subsetSf, ph_stimPh: subsetPh, ph_spikeCount: subsetSpikes, ph_stimDur: subsetDur, ph_objWeight: subsetWeight, \
                          ph_normResp: subsetNormResp, ph_normCentSf: normCentSf});

          if (iter/500.0) == round(iter/500.0):
            NLL = m.run(full, feed_dict={ph_stimOr: fixedOr, ph_stimTfFull: fixedTf, ph_stimCo: fixedCo, \
                        ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                        ph_stimDur: stim_dur, ph_objWeight: objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf});

        else:
          opt = \
                m.run(optimizer, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                            ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                            ph_stimDur: stim_dur, ph_objWeight: objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf});

        
          if (iter/500.0) == round(iter/500.0):
            NLL = m.run(okok, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                        ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                        ph_stimDur: stim_dur, ph_objWeight:objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf});

        if (iter/500.0) == round(iter/500.0): # save every once in a while!!!

          real_params = m.run(applyConstraints(fitType, *param_list));
          
          print('iteration ' + str(iter) + '...NLL is ' + str(NLL) + ' and params are ' + str(curr_params));
          print('\tparams in current optimization are: ' + str(real_params));

          if numpy.isnan(prevNLL):
            diffNLL = NLL;
          else:
            diffNLL = prevNLL - NLL;
          prevNLL = NLL;

          print('Difference in NLL is : ' + str(diffNLL));

          if NLL < currNLL or numpy.any(numpy.isnan(curr_params)): # if the saved params are NaN, overwrite them

            if numpy.any(numpy.isnan(real_params)): # don't save a fit with NaN!
              print('.nanParam.');
              iter = iter+1;
              continue;

            print('.update.');
            print('.params.'); print(real_params);
            print('.NLL|fullData.'); print(NLL);
            currNLL = NLL;
            currParams = real_params;
	    # reload fitlist in case changes have been made with the file elsewhere!
            if os.path.exists(loc_data + fitListName):
              fitList = np_smart_load(str(loc_data + fitListName));
            # else, nothing to reload!!!
      	    # but...if we reloaded fitList and we don't have this key (cell) saved yet, recreate the key entry...
            if cellNum-1 not in fitList:
              fitList[cellNum-1] = dict();
            fitList[cellNum-1]['NLL'] = NLL;
            fitList[cellNum-1]['params'] = real_params;
            numpy.save(loc_data + fitListName, fitList);   
            curr_params = real_params; # update for when you print/display

        iter = iter+1;

    # Now the fitting is done    
    # Now get "true" model parameters and NLL
    if subset_frac < 1:
      NLL = m.run(okok, feed_dict={ph_stimOr: subsetOr, ph_stimTf: subsetTf, ph_stimCo: subsetCo, \
                          ph_stimSf: subsetSf, ph_stimPh: subsetPh, ph_spikeCount: subsetSpikes, ph_stimDur: subsetDur, ph_objWeight: subsetWeight, \
                          ph_normResp: subsetNormResp, ph_normCentSf: normCentSf});
    else:
      NLL = m.run(okok, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                            ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                            ph_stimDur: stim_dur, ph_objWeight: objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf});


    x = m.run(applyConstraints(fitType, *param_list));

    # Put those into fitList and save...ONLY if better than before
    if NLL < currNLL:
      # reload (as above) to avoid overwriting changes made with the file elsewhere
      if os.path.exists(loc_data + fitListName):
        fitList = np_smart_load(str(loc_data + fitListName));
      # else, nothing to reload...
      # but...if we reloaded fitList and we don't have this key (cell) saved yet, recreate the key entry...
      if cellNum-1 not in fitList:
        fitList[cellNum-1] = dict();
      fitList[cellNum-1]['NLL'] = NLL;
      fitList[cellNum-1]['params'] = x;

      numpy.save(loc_data + fitListName, fitList);

    if cellNum-1 in fitList:
      print('Final parameters are ' + str(fitList[cellNum-1]['params']));
    else:
      print('Optimization failed: no parameter set');
    
    return NLL, x;
Esempio n. 15
0
def measure_chiSq(lossType, expInd=1, date='181121'):

  _, nDisps, _, nCons, nCells, dataLoc = hf.get_exp_params(expInd);
  if expInd == 1: # main V1 branch
    dataLoc = dataLoc + 'Structures/';
  else:
    dataLoc = dataLoc + 'structures/';
  dataList = hf.np_smart_load(str(dataLoc + 'dataList.npy'));

  # then the loss type
  if lossType == 1:
    lossSuf = '_sqrt.npy';
  elif lossType == 2:
    lossSuf = '_poiss.npy';
  elif lossType == 3:
    lossSuf = '_modPoiss.npy';

  chi_wght = np.nan * np.zeros((nCells, ));
  chi_flat = np.nan * np.zeros((nCells, ));

  flat   = hf.np_smart_load(dataLoc + 'fitList_%s_flat%s' % (date, lossSuf));
  weight = hf.np_smart_load(dataLoc + 'fitList_%s_wght%s' % (date, lossSuf));

  for i in range(nCells):
    print('cell %d' % i);
    S = hf.np_smart_load(str(dataLoc + dataList['unitName'][i] + '_sfm.npy'));

    # first, the data
    _, _, sfmixExpResp, allSfMixExp = hf.organize_modResp(S['sfm']['exp']['trial']['spikeCount'], S['sfm']['exp']['trial'])    
    exp_responses = [sfmixExpResp, np.nanvar(allSfMixExp, axis=3)];

    ## then, the model
    # flat normalization
    if i in flat:
      flat_params = flat[i]['params'];
      ignore, modResp = SFMGiveBof(flat_params, S, normType=1, lossType=lossType, expInd=expInd);
      _, _, sfmixModResp, allSfMixMod = hf.organize_modResp(modResp, S['sfm']['exp']['trial'])
      mod_responses = [sfmixModResp, np.nanvar(allSfMixMod)];

      chi_flat[i] = hf.chiSq(exp_responses, mod_responses);
      print('chi: %.1f' % chi_flat[i]);

    # weighted normalization
    if i in weight:
      wght_params = weight[i]['params'];
      ignore, modResp = SFMGiveBof(wght_params, S, normType=2, lossType=lossType, expInd=expInd);
      _, _, sfmixModResp, allSfMixMod = hf.organize_modResp(modResp, S['sfm']['exp']['trial'])
      mod_responses = [sfmixModResp, np.nanvar(allSfMixMod)];

      chi_wght[i] = hf.chiSq(exp_responses, mod_responses);
      print('\tchi: %.1f' % chi_wght[i]);

  n_flat_params = len(flat[0]['params']);
  n_wght_params = len(weight[0]['params']);    

  chiNorm_flat = np.divide(chi_flat, n_flat_params);
  chiNorm_wght = np.divide(chi_flat, n_wght_params);

  chiAnalysis = dict();
  chiAnalysis['flat_norm'] = chiNorm_flat;
  chiAnalysis['wght_norm'] = chiNorm_wght;
  chiAnalysis['flat'] = chi_flat;
  chiAnalysis['wght'] = chi_wght;

  np.save('chiAnalysis', chiAnalysis);

  return chiNorm_flat, chiNorm_wght, chi_flat, chi_wght;
Esempio n. 16
0
def phase_advance_fit(cell_num,
                      data_loc=dataPath,
                      phAdvName=phAdvName,
                      to_save=1,
                      disp=0,
                      dir=-1):
    ''' Given the FFT-derived response amplitude and phase, determine the response phase relative
      to the stimulus by taking into account the stimulus phase. 
      Then, make a simple linear model fit (line + constant offset) of the response phase as a function
      of response amplitude.
      vSAVES loss/optimized parameters/and phase advance (if default "to_save" value is kept)
      RETURNS phAdv_model, all_opts

      Do ONLY for single gratings
  '''

    dataList = hf.np_smart_load(data_loc + 'dataList.npy')
    cellStruct = hf.np_smart_load(data_loc +
                                  dataList['unitName'][cell_num - 1] +
                                  '_sfm.npy')
    data = cellStruct['sfm']['exp']['trial']
    phAdvName = hf.fit_name(phAdvName, dir)

    # first, get the set of stimulus values:
    _, stimVals, valConByDisp, _, _ = hf.tabulate_responses(data,
                                                            expInd=expInd)
    allCons = stimVals[1]
    allSfs = stimVals[2]

    # for all con/sf values for this dispersion, compute the mean amplitude/phase per condition
    allAmp, allPhi, allTf, _, _ = hf.get_all_fft(data, disp, dir=dir)

    # now, compute the phase advance
    conInds = valConByDisp[disp]
    conVals = allCons[conInds]
    nConds = len(allAmp)
    # this is how many conditions are present for this dispersion
    # recall that nConds = nCons * nSfs
    allCons = [conVals] * nConds
    # repeats list and nests
    phAdv_model, all_opts, all_phAdv, all_loss = hf.phase_advance(
        allAmp, allPhi, conVals, allTf)

    if os.path.isfile(data_loc + phAdvName):
        phFits = hf.np_smart_load(data_loc + phAdvName)
    else:
        phFits = dict()

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + phAdvName):
        print('reloading phAdvFits...')
        phFits = hf.np_smart_load(data_loc + phAdvName)
    if cell_num - 1 not in phFits:
        phFits[cell_num - 1] = dict()
    phFits[cell_num - 1]['loss'] = all_loss
    phFits[cell_num - 1]['params'] = all_opts
    phFits[cell_num - 1]['phAdv'] = all_phAdv

    if to_save:
        np.save(data_loc + phAdvName, phFits)
        print('saving phase advance fit for cell ' + str(cell_num))

    return phAdv_model, all_opts
Esempio n. 17
0
#descrBase = 'descrFits%s_220410' % hpc_str;
### RVCFITS
rvcBase = 'rvcFits%s_220718' % hpc_str
#rvcBase = 'rvcFits%s_220609' % hpc_str;

##################
### Spatial frequency
##################

modStr = hf.descrMod_name(descrMod)
fLname = hf.descrFit_name(descrLoss,
                          descrBase=descrBase,
                          modelName=modStr,
                          joint=joint,
                          phAdj=1 if phAdjSigned == 1 else None)
descrFits = hf.np_smart_load(data_loc + fLname)
pause_tm = 2.0 * np.random.rand()
time.sleep(pause_tm)
# set the save directory to save_loc, then create the save directory if needed
subDir = fLname.replace('Fits', '').replace('.npy', '')
save_loc = str(save_loc + subDir + '/')

if not os.path.exists(save_loc):
    os.makedirs(save_loc)

dataList = hf.np_smart_load(data_loc + expName)

cellName = dataList['unitName'][cellNum - 1]
try:
    cellType = dataList['unitType'][cellNum - 1]
except:
Esempio n. 18
0
def plot_phase_advance(which_cell,
                       disp,
                       sv_loc=save_loc,
                       dir=-1,
                       dp=dataPath,
                       expName=expName,
                       phAdvStr=phAdvName,
                       rvcStr=rvcName,
                       date_suffix=''):
    ''' RVC, resp-X-phase, phase advance model split by SF within each cell/dispersion condition
      1. response-versus-contrast; shows original and adjusted response
      2. polar plot of response amplitude and phase with phase advance model fit
      3. response amplitude (x) vs. phase (y) with the linear phase advance model fit
  '''

    # basics
    dataList = hf.np_smart_load(str(dp + expName))
    cellName = dataList['unitName'][which_cell - 1]
    expInd = hf.get_exp_ind(dp, cellName)[0]
    cellStruct = hf.np_smart_load(str(dp + cellName + '_sfm.npy'))

    rvcFits = hf.np_smart_load(str(dp + hf.phase_fit_name(rvcStr, dir)))
    rvcFits = rvcFits[which_cell - 1]
    rvc_model = hf.get_rvc_model()

    phAdvFits = hf.np_smart_load(str(dp + hf.phase_fit_name(phAdvStr, dir)))
    phAdvFits = phAdvFits[which_cell - 1]
    phAdv_model = hf.get_phAdv_model()

    save_base = sv_loc + 'phasePlots_%s/' % date_suffix

    # gather/compute everything we need
    data = cellStruct['sfm']['exp']['trial']
    _, stimVals, val_con_by_disp, validByStimVal, _ = hf.tabulate_responses(
        data, expInd)

    valDisp = validByStimVal[0]
    valCon = validByStimVal[1]
    valSf = validByStimVal[2]

    allDisps = stimVals[0]
    allCons = stimVals[1]
    allSfs = stimVals[2]

    con_inds = val_con_by_disp[disp]

    # now get ready to plot
    fPhaseAdv = []

    # we will summarize for all spatial frequencies for a given cell!
    for j in range(len(allSfs)):
        # first, get the responses and phases that we need:
        amps = []
        phis = []
        sf = j
        for i in con_inds:
            val_trials = np.where(valDisp[disp] & valCon[i] & valSf[sf])

            # get the phase of the response relative to the stimulus (ph_rel_stim)
            ph_rel_stim, stim_ph, resp_ph, all_tf = hf.get_true_phase(
                data, val_trials, expInd, dir=dir)
            phis.append(ph_rel_stim)
            # get the relevant amplitudes (i.e. the amplitudes at the stimulus TF)
            stimDur = hf.get_exp_params(expInd).stimDur
            psth_val, _ = hf.make_psth(data['spikeTimes'][val_trials],
                                       stimDur=stimDur)
            _, rel_amp, _ = hf.spike_fft(psth_val, all_tf, stimDur=stimDur)
            amps.append(rel_amp)

        r, th, _, _ = hf.polar_vec_mean(amps, phis)
        # mean amp/phase (outputs 1/2); std/var for amp/phase (outputs 3/4)
        # get the models/fits that we need:
        con_values = allCons[con_inds]
        ## phase advance
        opt_params_phAdv = phAdvFits['params'][sf]
        ph_adv = phAdvFits['phAdv'][sf]
        ## rvc
        opt_params_rvc = rvcFits[disp]['params'][sf]
        con_gain = rvcFits[disp]['conGain'][sf]
        adj_means = rvcFits[disp]['adjMeans'][sf]
        if disp == 1:  # then sum adj_means (saved by component)
            adj_means = [np.sum(x, 1) if x else [] for x in adj_means]
        # (Above) remember that we have to project the amp/phase vector onto the "correct" phase for estimate of noiseless response
        ## now get ready to plot!
        f, ax = plt.subplots(2, 2, figsize=(20, 10))
        fPhaseAdv.append(f)

        n_conds = len(r)
        colors = cm.viridis(np.linspace(0, 0.95, n_conds))

        #####
        ## 1. now for plotting: first, response amplitude (with linear contrast)
        #####
        plot_cons = np.linspace(0, 1, 100)
        mod_fit = rvc_model(opt_params_rvc[0], opt_params_rvc[1],
                            opt_params_rvc[2], plot_cons)

        ax = plt.subplot(2, 2, 1)
        plot_amp = adj_means
        plt_measured = ax.scatter(allCons[con_inds],
                                  plot_amp,
                                  s=100,
                                  color=colors,
                                  label='ph. corr')
        plt_og = ax.plot(allCons[con_inds],
                         r,
                         linestyle='None',
                         marker='o',
                         markeredgecolor='k',
                         markerfacecolor='None',
                         alpha=0.5,
                         label='vec. mean')
        plt_fit = ax.plot(plot_cons,
                          mod_fit,
                          linestyle='--',
                          color='k',
                          label='rvc fit')
        ax.set_xlabel('contrast')
        ax.set_ylabel('response (f1)')
        ax.set_title('response versus contrast')
        ax.legend(loc='upper left')

        # also summarize the model fit on this plot
        ymax = np.maximum(np.max(r), np.max(mod_fit))
        plt.text(0.8,
                 0.30 * ymax,
                 'b: %.2f' % (opt_params_rvc[0]),
                 fontsize=12,
                 horizontalalignment='center',
                 verticalalignment='center')
        plt.text(0.8,
                 0.20 * ymax,
                 'slope:%.2f' % (opt_params_rvc[1]),
                 fontsize=12,
                 horizontalalignment='center',
                 verticalalignment='center')
        plt.text(0.8,
                 0.10 * ymax,
                 'c0: %.2f' % (opt_params_rvc[2]),
                 fontsize=12,
                 horizontalalignment='center',
                 verticalalignment='center')
        plt.text(0.8,
                 0.0 * ymax,
                 'con gain: %.2f' % (con_gain),
                 fontsize=12,
                 horizontalalignment='center',
                 verticalalignment='center')

        #####
        ## 3. then the fit/plot of phase as a function of ampltude
        #####
        plot_amps = np.linspace(0, np.max(r), 100)
        mod_fit = phAdv_model(opt_params_phAdv[0], opt_params_phAdv[1],
                              plot_amps)

        ax = plt.subplot(2, 1, 2)
        plt_measured = ax.scatter(r,
                                  th,
                                  s=100,
                                  color=colors,
                                  clip_on=False,
                                  label='vec. mean')
        plt_fit = ax.plot(plot_amps,
                          mod_fit,
                          linestyle='--',
                          color='k',
                          clip_on=False,
                          label='phAdv model')
        ax.set_xlabel('response amplitude')
        if phAdv_set_ylim:
            ax.set_ylim([0, 360])
        ax.set_ylabel('response phase')
        ax.set_title('phase advance with amplitude')
        ax.legend(loc='upper left')

        ## and again, summarize the model fit on the plot
        xmax = np.maximum(np.max(r), np.max(plot_amps))
        ymin = np.minimum(np.min(th), np.min(mod_fit))
        ymax = np.maximum(np.max(th), np.max(mod_fit))
        yrange = ymax - ymin
        if phAdv_set_ylim:
            if mod_fit[-1] > 260:  # then start from ymin and go dwn
                start, sign = mod_fit[-1] - 30, -1
            else:
                start, sign = mod_fit[-1] + 30, 1
            plt.text(0.9 * xmax,
                     start + 1 * 30 * sign,
                     'phi0: %.2f' % (opt_params_phAdv[0]),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')
            plt.text(0.9 * xmax,
                     start + 2 * 30 * sign,
                     'slope:%.2f' % (opt_params_phAdv[1]),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')
            plt.text(0.9 * xmax,
                     start + 3 * 30 * sign,
                     'phase advance: %.2f ms' % (ph_adv),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')
        else:
            plt.text(0.8 * xmax,
                     ymin + 0.25 * yrange,
                     'phi0: %.2f' % (opt_params_phAdv[0]),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')
            plt.text(0.8 * xmax,
                     ymin + 0.15 * yrange,
                     'slope:%.2f' % (opt_params_phAdv[1]),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')
            plt.text(0.8 * xmax,
                     ymin + 0.05 * yrange,
                     'phase advance: %.2f ms' % (ph_adv),
                     fontsize=12,
                     horizontalalignment='center',
                     verticalalignment='center')

        #center_phi = lambda ph1, ph2: np.arcsin(np.sin(np.deg2rad(ph1) - np.deg2rad(ph2)));

        #####
        ## 2. now the polar plot of resp/phase together
        #####
        ax = plt.subplot(2, 2, 2, projection='polar')
        th_center = np.rad2deg(np.radians(-90) + np.radians(th[np.argmax(r)]))
        # "anchor" to the phase at the highest amplitude response
        #data_centered = center_phi(th, th_center);
        #model_centered = center_phi(mod_fit, th_center);
        #ax.scatter(data_centered, r, s=50, color=colors);
        #ax.plot(model_centered, plot_amps, linestyle='--', color='k');
        data_centered = np.mod(th - th_center, 360)
        model_centered = np.mod(mod_fit - th_center, 360)
        ax.scatter(np.deg2rad(data_centered), r, s=50, color=colors)
        ax.plot(np.deg2rad(model_centered),
                plot_amps,
                linestyle='--',
                color='k')
        ax.set_ylim(0, 1.25 * np.max(r))
        ax.set_title('phase advance')

        # overall title
        f.subplots_adjust(wspace=0.2, hspace=0.25)
        f1f0_ratio = hf.compute_f1f0(data,
                                     which_cell,
                                     expInd,
                                     dp,
                                     descrFitName_f0=descrFit_f0)[0]
        try:
            f.suptitle('%s (%.2f) #%d: disp %d, sf %.2f cpd' %
                       (dataList['unitType'][which_cell - 1], f1f0_ratio,
                        which_cell, allDisps[disp], allSfs[sf]))
        except:
            f.suptitle('%s (%.2f) #%d: disp %d, sf %.2f cpd' %
                       (dataList['unitArea'][which_cell - 1], f1f0_ratio,
                        which_cell, allDisps[disp], allSfs[sf]))

    saveName = "/cell_%03d_d%d_phaseAdv.pdf" % (which_cell, disp)
    save_loc = save_base + 'summary/'
    full_save = os.path.dirname(str(save_loc))
    if not os.path.exists(full_save):
        os.makedirs(full_save)
    pdfSv = pltSave.PdfPages(full_save + saveName)
    for f in fPhaseAdv:
        pdfSv.savefig(f)
        plt.close(f)
    pdfSv.close()
Esempio n. 19
0
def fit_all_CRF(cell_num,
                data_loc,
                each_c50,
                loss_type,
                n_iter=1,
                each_expn=0,
                each_base=0,
                each_gain=1):
    ''' Given cell#, data loc, load the data. Other inputs:
          each_c50/expn/base/gain : separate c50/expn/base/gain for each condition?
          n_iter                  : how many iterations to fit?
          
    '''
    print(str(n_iter) + ' fit attempts')
    np = numpy
    conDig = 3
    # round contrast to the thousandth
    n_params = 5
    # 4 for NR, 1 for varGain

    if each_c50 == 1:
        fit_key = 'fits_each_rpt'
    else:
        fit_key = 'fits_rpt'

    if loss_type == 1:
        loss_str = '-lsq'
    if loss_type == 2:
        loss_str = '-sqrt'
    if loss_type == 3:
        loss_str = '-poiss'
    if loss_type == 4:
        loss_str = '-poissMod'
    fits_name = 'crfFitsCom' + loss_str + '.npy'
    dataList = hf.np_smart_load(str(data_loc + 'dataList.npy'))
    if os.path.isfile(data_loc + fits_name):
        crfFits = hf.np_smart_load(str(data_loc + fits_name))
    else:
        crfFits = dict()

    # load cell information
    cellStruct = hf.np_smart_load(
        str(data_loc + dataList['unitName'][cell_num - 1] + '_sfm.npy'))
    data = cellStruct['sfm']['exp']['trial']

    all_cons = np.unique(np.round(data['total_con'], conDig))
    all_cons = all_cons[~np.isnan(all_cons)]

    all_sfs = np.unique(data['cent_sf'])
    all_sfs = all_sfs[~np.isnan(all_sfs)]

    all_disps = np.unique(data['num_comps'])
    all_disps = all_disps[all_disps > 0]
    # ignore zero...

    nCons = len(all_cons)
    nSfs = len(all_sfs)
    nDisps = len(all_disps)

    nk_ru = dict()
    all_data = dict()

    # for use in fitting SF functions...
    _, _, blankResps = hf.blankResp(cellStruct)
    blankCons = np.zeros_like(blankResps)

    for d in range(nDisps):
        valid_disp = data['num_comps'] == all_disps[d]
        cons = []
        resps = []

        nk_ru[d] = dict()
        v_sfs = []
        # keep track of valid sfs
        all_data[d] = dict()

        for sf in range(nSfs):

            valid_sf = data['cent_sf'] == all_sfs[sf]

            valid_tr = valid_disp & valid_sf
            if np.all(np.unique(valid_tr) ==
                      False):  # did we not find any trials?
                continue

            v_sfs.append(sf)
            nk_ru[d][sf] = dict()
            # create dictionary here; thus, only valid sfs have valid keys
            # for unpacking loss/parameters later...
            nk_ru[d][sf]['params'] = np.nan * np.zeros((n_params, 1))
            nk_ru[d][sf]['loss'] = np.nan

            resps.append(np.hstack((blankResps, data['spikeCount'][valid_tr])))
            cons.append(np.hstack((blankCons, data['total_con'][valid_tr])))

        # save data for later use
        all_data[d]['resps'] = resps
        all_data[d]['cons'] = cons
        all_data[d]['valid_sfs'] = v_sfs

        maxResp = np.max(np.max(resps))
        n_v_sfs = len(v_sfs)

        each_list = (each_base, each_gain, each_expn, each_c50)

        n_per_param = [1 if i == 0 else n_v_sfs for i in each_list]
        '''
    	if each_c50 == 1:
    	  n_c50s = n_v_sfs; # separate for each SF...
    	else:
	  n_c50s = 1;	
        '''
        init_base = 0.1
        #bounds_base = (0, 0);
        bounds_base = (0.1, maxResp)
        init_gain = np.max(resps) - np.min(resps)
        bounds_gain = (0, 10 * maxResp)
        init_expn = 2
        bounds_expn = (0.5, 10)
        init_c50 = 0.1
        #geomean(all_cons);
        bounds_c50 = (0.01, 10 * max(all_cons))
        # contrast values are b/t [0, 1]
        init_varGain = 1
        bounds_varGain = (0.01, None)

        base_inits = np.repeat(init_base, n_per_param[0])
        # default is only one baseline per SF
        base_constr = [
            tuple(x) for x in np.broadcast_to(bounds_base, (n_per_param[0], 2))
        ]

        gain_inits = np.repeat(init_gain, n_per_param[1])
        # gain is always separate for each SF
        gain_constr = [
            tuple(x) for x in np.broadcast_to(bounds_gain, (n_per_param[1], 2))
        ]

        expn_inits = np.repeat(init_expn, n_per_param[2])
        # exponent can be either, like baseline
        expn_constr = [
            tuple(x) for x in np.broadcast_to(bounds_expn, (n_per_param[2], 2))
        ]

        c50_inits = np.repeat(init_c50, n_per_param[3])
        # repeat n_v_sfs times if c50 separate for each SF; otherwise, 1
        c50_constr = [
            tuple(x) for x in np.broadcast_to(bounds_c50, (n_per_param[3], 2))
        ]

        init_params = np.hstack(
            (c50_inits, expn_inits, gain_inits, base_inits, init_varGain))
        boundsAll = np.vstack((c50_constr, expn_constr, gain_constr,
                               base_constr, bounds_varGain))
        boundsAll = [tuple(x) for x in boundsAll]
        # turn the (inner) arrays into tuples...

        c50_ind = 0
        expn_ind = n_per_param[3]
        # the number of c50s...
        gain_ind = expn_ind + n_per_param[2]
        # the number of exponents
        base_ind = gain_ind + n_per_param[1]
        # always n_v_sfs gain parameters
        varGain_ind = base_ind + n_per_param[0]

        obj = lambda params: hf.fit_CRF(cons, resps, params[c50_ind:c50_ind+n_per_param[3]], params[expn_ind:expn_ind+n_per_param[2]], params[gain_ind:gain_ind+n_per_param[1]], \
                                            params[base_ind:base_ind+n_per_param[0]], params[varGain_ind], loss_type)
        opts = opt.minimize(obj, init_params, bounds=boundsAll)

        curr_params = opts['x']
        curr_loss = opts['fun']

        for iter in range(n_iter - 1):  # now, extra iterations if chosen...
            init_params = np.hstack(
                (hf.random_in_range(bounds_c50,
                                    n_c50s), hf.random_in_range(bounds_expn),
                 hf.random_in_range(bounds_gain,
                                    n_v_sfs), hf.random_in_range(bounds_base),
                 hf.random_in_range((bounds_varGain[0], 1))))

            # choose optimization method
            if np.mod(iter, 2) == 0:
                methodStr = 'L-BFGS-B'
            else:
                methodStr = 'TNC'

            opt_iter = opt.minimize(obj,
                                    init_params,
                                    bounds=boundsAll,
                                    method=methodStr)

            if opt_iter['fun'] < curr_loss:
                print('improve.')
                curr_loss = opt_iter['fun']
                curr_params = opt_iter['x']

        # now unpack...
        for sf_in in range(n_v_sfs):
            param_ind = [0 if i == 1 else sf_in for i in n_per_param]

            nk_ru[d][v_sfs[sf_in]]['params'][0] = curr_params[base_ind +
                                                              param_ind[0]]
            nk_ru[d][v_sfs[sf_in]]['params'][1] = curr_params[gain_ind +
                                                              param_ind[1]]
            nk_ru[d][v_sfs[sf_in]]['params'][2] = curr_params[expn_ind +
                                                              param_ind[2]]
            nk_ru[d][v_sfs[sf_in]]['params'][3] = curr_params[c50_ind +
                                                              param_ind[3]]
            # params (to match naka_rushton) are: baseline, gain, expon, c50
            nk_ru[d][v_sfs[sf_in]]['params'][4] = curr_params[varGain_ind]
            nk_ru[d][v_sfs[sf_in]]['loss'] = curr_loss

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + fits_name):
        print('reloading CRF Fits...')
        crfFits = hf.np_smart_load(str(data_loc + fits_name))
    if cell_num - 1 not in crfFits:
        crfFits[cell_num - 1] = dict()
    crfFits[cell_num - 1][fit_key] = nk_ru
    crfFits[cell_num - 1]['data'] = all_data
    crfFits[cell_num - 1]['blankResps'] = blankResps

    np.save(data_loc + fits_name, crfFits)
    print('saving for cell ' + str(cell_num))

    return nk_ru
Esempio n. 20
0
def phase_by_cond(which_cell,
                  data,
                  expInd,
                  disp,
                  con,
                  sf,
                  sv_loc=save_loc,
                  dir=-1,
                  cycle_fold=2,
                  n_bins_fold=8,
                  dp=dataPath,
                  expName=expName,
                  date_suffix=''):
    ''' Given a cell and the disp/con/sf indices, plot the spike raster for each trial, a folded PSTH,
      and finally the response phase - first relative to trial onset, and finally relative to the stimulus phase 
      
      dir = -1 or +1 (i.e. stimulus moving left or right?)
      cycle_fold = over how many stimulus cycles to fold when creating folded psth?
      n_bins_fold = how many bins per stimulus period when folding?
  '''
    dataList = hf.np_smart_load(str(dp + expName))
    save_base = sv_loc + 'phasePlots_%s/' % date_suffix

    val_trials, allDisps, allCons, allSfs = hf.get_valid_trials(
        data, disp, con, sf, expInd)

    if not np.any(
            val_trials[0]
    ):  # val_trials[0] will be the array of valid trial indices --> if it's empty, leave!
        warnings.warn('this condition is not valid')
        return

    ### SINGLE GRATINGS
    if disp == 0:

        # get the phase relative to the stimulus
        ph_rel_stim, stim_ph, resp_ph, all_tf = hf.get_true_phase(
            data, val_trials, expInd, dir)
        # compute the fourier amplitudes
        stimDur = hf.get_exp_params(expInd).stimDur
        psth_val, _ = hf.make_psth(data['spikeTimes'][val_trials],
                                   stimDur=stimDur)
        _, rel_amp, full_fourier = hf.spike_fft(psth_val, all_tf, stimDur)

        # now plot!
        f, ax = plt.subplots(3, 2, figsize=(20, 30))

        relSpikes = data['spikeTimes'][val_trials]
        colors = cm.rainbow(np.linspace(0, 1, len(val_trials[0])))

        #####
        # plot spike raster - trial-by-trial
        #####
        # only works for SINGLE GRATINGS
        # draw the beginning of each cycle for each trial
        ax = plt.subplot(3, 1, 1)
        for i in range(len(relSpikes)):
            ax.scatter(relSpikes[i],
                       i * np.ones_like(relSpikes[i]),
                       s=45,
                       color=colors[i])
            stimPh = stim_ph[i]
            stimPeriod = np.divide(1.0, all_tf[i])
            stimDur = hf.get_exp_params(expInd).stimDur
            # i.e. at what point during the trial (in s) does the stimulus component first begin a cycle?
            firstPh0 = hf.first_ph0(stimPh, all_tf[i])[1]

            for j in range(len(all_tf[i])):
                allPh0 = [
                    stimPeriod[j] * np.arange(-1, stimDur * all_tf[i][j]) +
                    firstPh0[j]
                ]
                allPh90 = allPh0 + stimPeriod[j] / 4
                allPh180 = allPh90 + stimPeriod[j] / 4
                allPh270 = allPh180 + stimPeriod[j] / 4
            ax.errorbar(allPh0[0],
                        i * np.ones_like(allPh0[0]),
                        0.25,
                        linestyle='none',
                        color='k',
                        linewidth=1)
            ax.errorbar(allPh90[0],
                        i * np.ones_like(allPh0[0]),
                        0.05,
                        linestyle='none',
                        color='k',
                        linewidth=1)
            ax.errorbar(allPh180[0],
                        i * np.ones_like(allPh0[0]),
                        0.05,
                        linestyle='none',
                        color='k',
                        linewidth=1)
            ax.errorbar(allPh270[0],
                        i * np.ones_like(allPh0[0]),
                        0.05,
                        linestyle='none',
                        color='k',
                        linewidth=1)
        ax.set_xlabel('time (s)')
        ax.set_ylabel('repetition #')
        ax.set_title('Spike rasters')

        #####
        # plot PSTH - per trial, but folded over N cycles
        #####
        # only works for SINGLE GRATINGS
        ax = plt.subplot(3, 1, 2)

        for i in range(len(relSpikes)):
            _, bin_edges, psth_norm = hf.fold_psth(relSpikes[i],
                                                   all_tf[i],
                                                   stim_ph[i],
                                                   cycle_fold,
                                                   n_bins_fold,
                                                   dir=dir)
            plt.plot(bin_edges[0:-1], i - 0.5 + psth_norm, color=colors[i])
            stimPeriod = np.divide(1.0, all_tf[i])
            for j in range(cycle_fold):
                cycStart = plt.axvline(j * stimPeriod[0])
                cycHalf = plt.axvline((j + 0.5) * stimPeriod[0],
                                      linestyle='--')
        ax.set_xlabel('time (s)')
        ax.set_ylabel('spike count (normalized by trial)')
        ax.set_title('PSTH folded')
        ax.set_xlim(
            [-stimPeriod[0] / 4.0, (cycle_fold + 0.25) * stimPeriod[0]])
        ax.legend((cycStart, cycHalf), ('ph = 0', 'ph = 180'))

        #####
        # plot response phase - without accounting for stimulus phase
        #####
        ax = plt.subplot(3, 2, 5, projection='polar')
        ax.scatter(np.radians(resp_ph),
                   rel_amp,
                   s=60,
                   color=colors,
                   clip_on=False)
        ax.set_title('Stimulus-blind')
        ax.set_ylim(auto='True')
        polar_ylim = ax.get_ylim()

        # now, compute the average amplitude/phase over all trials
        [avg_r, avg_ph, _, _] = hf.polar_vec_mean([rel_amp], [ph_rel_stim])
        avg_r = avg_r[0]
        # just get it out of the array!
        avg_ph = avg_ph[0]
        # just get it out of the array!

        #####
        # plot response phase - relative to stimulus phase
        #####
        ax = plt.subplot(3, 2, 6, projection='polar')
        ax.scatter(np.radians(ph_rel_stim),
                   rel_amp,
                   s=60,
                   color=colors,
                   clip_on=False)
        ax.plot([0, np.radians(avg_ph)], [0, avg_r],
                color='k',
                linestyle='--',
                clip_on=False)
        ax.set_ylim(polar_ylim)
        ax.set_title('Stimulus-accounted')

    ### MIXTURE STIMULI
    elif disp > 0:
        nComp = hf.get_exp_params(expInd).nStimComp
        # a useful function for swapping inside/outside of nested list...
        switch_inner_outer = lambda arr: [[x[i] for x in arr]
                                          for i in range(len(arr[0]))]

        ### first, gather the isolated component responses from the mixture
        val_trials, allDisp, allCons, allSfs = hf.get_valid_trials(
            data, disp, con, sf, expInd)
        # outer-most list (for ph_rel_stim, stim_phase, resp_phase) is trial/repetition, inner lists are by component
        ph_rel_stim, stim_phase, resp_phase, all_tf = hf.get_true_phase(
            data, val_trials, expInd, dir=dir)
        # f1all is nComp lists, each with nReps/nTrials values
        _, _, _, f1all, conByComp, sfByComp = hf.get_isolated_response(
            data, val_trials)
        # need to switch ph_rel_stim (and resp_phase) to be lists of phases by component (rather than list of phases by trial)
        ph_rel_stim = switch_inner_outer(ph_rel_stim)
        resp_phase = switch_inner_outer(resp_phase)
        # compute vector means
        r_comp, th_comp, _, _ = hf.polar_vec_mean(f1all, ph_rel_stim)

        nrow = 1 + nComp
        ncol = 2
        f, ax = plt.subplots(nrow, ncol, figsize=(ncol * 10, nrow * 10))

        # in-mixture response phase - NOT stimulus-aligned; just demonstrate for 1st component
        colors = cm.rainbow(np.linspace(0, 1, len(val_trials[0])))
        ax = plt.subplot(
            nrow, 1, 1, projection='polar'
        )  # pretend only one column, i.e. take up whole top row
        ax.scatter(np.radians(resp_phase[0]),
                   hf.flatten(f1all[0]),
                   s=45,
                   color=colors,
                   clip_on=False)
        ax.set_ylim([0, 1.1 * np.max(hf.flatten(f1all[0]))])
        ax.set_title('Stimulus-blind (compound; comp #1)')

        for i in range(nComp):

            # compute the isolated response
            # Then, pick one of the components and get the response (when presented in isolation)
            # phases/amplitudes and align relative to the stimulus phase
            isolConInd = np.where(allCons == conByComp[i])[0][0]
            # unwrap fully (will be only one value...)
            isolSfInd = np.where(allSfs == sfByComp[i])[0][0]
            val_trials_isol, _, _, _ = hf.get_valid_trials(data,
                                                           disp=0,
                                                           con=isolConInd,
                                                           sf=isolSfInd,
                                                           expInd=expInd)

            ph_rel_stim_isol, stim_phase_isol, resp_phase_isol, all_tf_isol = hf.get_true_phase(
                data, val_trials_isol, expInd, dir=dir)
            stimDur = hf.get_exp_params(expInd).stimDur
            psth_val, _ = hf.make_psth(data['spikeTimes'][val_trials_isol],
                                       stimDur=stimDur)
            _, rel_amp_isol, _ = hf.spike_fft(psth_val, all_tf_isol, stimDur)
            # and compute vector mean
            r_isol, th_isol, _, _ = hf.polar_vec_mean([rel_amp_isol],
                                                      [ph_rel_stim_isol])

            # isolated response phase - relative to stimulus phase
            colors = cm.rainbow(np.linspace(0, 1, len(val_trials[0])))
            ax = plt.subplot(nrow, ncol, 2 * (i + 1) + 1, projection='polar')
            ax.scatter(np.radians(ph_rel_stim_isol),
                       rel_amp_isol,
                       s=45,
                       color=colors,
                       clip_on=False)
            ax.plot([0, np.radians(th_isol[0])], [0, r_isol[0]],
                    ls='--',
                    color='k')
            ax.set_ylim([0, 1.1 * np.max(rel_amp_isol)])
            ax.set_title('isolated (r, phi) = (%.2f, %.2f)' %
                         (r_isol[0], th_isol[0]))

            # in-mixture response phase - relative to stimulus phase
            colors = cm.rainbow(np.linspace(0, 1, len(val_trials[0])))
            ax = plt.subplot(nrow, ncol, 2 * (i + 2), projection='polar')
            ax.scatter(np.radians(ph_rel_stim[i]),
                       hf.flatten(f1all[i]),
                       s=45,
                       color=colors,
                       clip_on=False)
            ax.plot([0, np.radians(th_comp[i])], [0, r_comp[i]],
                    ls='--',
                    color='k')
            ax.set_ylim([0, 1.1 * np.max(rel_amp_isol)])
            ax.set_title('compound (r, phi) = (%.2f, %.2f)' %
                         (r_comp[i], th_comp[i]))

    ## Common to all
    f.subplots_adjust(wspace=0.2, hspace=0.25)
    f1f0_ratio = hf.compute_f1f0(data,
                                 which_cell,
                                 expInd,
                                 dp,
                                 descrFitName_f0=descrFit_f0)[0]
    try:  # not always exists
        cell_label = dataList['unitType'][which_cell - 1]
    except:  # always works
        cell_label = dataList['unitArea'][which_cell - 1]
    f.suptitle('%s (f1f0: %.2f) #%d: disp %d, con %.2f, sf %.2f' %
               (cell_label, f1f0_ratio, which_cell, allDisps[disp],
                allCons[con], allSfs[sf]))

    saveName = "/cell_%03d_d%dsf%dcon%d_phase.pdf" % (which_cell, disp, sf,
                                                      con)
    save_loc = save_base + "cell_%03d/" % which_cell
    full_save = os.path.dirname(str(save_loc))
    if not os.path.exists(full_save):
        os.makedirs(full_save)
    pdfSv = pltSave.PdfPages(full_save + saveName)
    pdfSv.savefig(f)
    plt.close(f)
    pdfSv.close()
Esempio n. 21
0
elif onsetMethod == 1:
    onsStr = '_zeros'

### Directories
loc_base = os.getcwd() + '/'

data_loc = loc_base + expDir + 'structures/'
save_loc = loc_base + expDir + 'figures/onset%s/' % onsStr

### Load datalist, cell, and "onset list"
expName = hf.get_datalist(expDir)
onsetName = 'onset_transients%s.npy' % onsStr

# auto...
path = '%sstructures/' % expDir
dataList = hf.np_smart_load(path + expName)
expName = 'sfBB_core'
unitNm = dataList['unitName'][cellNum - 1]
cell = hf.np_smart_load('%s%s_sfBB.npy' % (path, unitNm))
expInfo = cell[expName]
byTrial = expInfo['trial']

# we're enforcing expInd = -1 for now...
expInd = -1
stimDur = hf.get_exp_params(expInd).stimDur

msTenthToS = 1e-4
# the spike times are in 1/10th ms, so multiply by 1e-4 to convert to S
nonBlank = np.where(np.logical_or(byTrial['maskOn'], byTrial['maskOn']))[0]
nTrials = len(nonBlank)
# print('%d non-blank trials considered' % nTrials);
Esempio n. 22
0
def fit_descr(cell_num,
              data_loc,
              n_repeats=4,
              fromModelSim=0,
              fitLossType=1,
              baseStr=None,
              normType=None,
              lossType=None):

    nFam = 5
    nCon = 2
    nParam = 5

    # get base descrFit name (including loss str)
    if fitLossType == 1:
        floss_str = '_lsq'
    elif fitLossType == 2:
        floss_str = '_sqrt'
    elif fitLossType == 3:
        floss_str = '_poiss'
    descrFitBase = 'descrFits%s' % floss_str

    # load cell information
    dataList = hfunc.np_smart_load(data_loc + 'dataList.npy')
    if fromModelSim:
        # get model fit name
        fL_name = baseStr

        # normType
        if normType == 1:
            fL_suffix1 = '_flat'
        elif normType == 2:
            fL_suffix1 = '_wght'
        elif normType == 3:
            fL_suffix1 = '_c50'
        # lossType
        if lossType == 1:
            fL_suffix2 = '_sqrt.npy'
        elif lossType == 2:
            fL_suffix2 = '_poiss.npy'
        elif lossType == 3:
            fL_suffix2 = '_modPoiss.npy'
        elif lossType == 4:
            fL_suffix2 = '_chiSq.npy'
        fitListName = str(fL_name + fL_suffix1 + fL_suffix2)

        dfModelName = '%s_%s' % (descrFitBase, fitListName)

        if os.path.isfile(data_loc + dfModelName):
            descrFits = hfunc.np_smart_load(data_loc + dfModelName)
        else:
            descrFits = dict()
    else:
        dfModelName = '%s.npy' % descrFitBase
        if os.path.isfile(data_loc + dfModelName):
            descrFits = hfunc.np_smart_load(data_loc + dfModelName)
        else:
            descrFits = dict()
    data = hfunc.np_smart_load(data_loc + dataList['unitName'][cell_num - 1] +
                               '_sfm.npy')

    if fromModelSim:  # then we'll 'sneak' in the model responses in the place of the real data
        modFits = hfunc.np_smart_load(data_loc + fitListName)
        modFit = modFits[cell_num - 1]['params']
        a, modResp = mod_resp.SFMGiveBof(modFit,
                                         data,
                                         normType=normType,
                                         lossType=lossType)
        # spike count must be integers! Simply round
        data['sfm']['exp']['trial']['spikeCount'] = np.round(
            modResp * data['sfm']['exp']['trial']['duration'])

    if cell_num - 1 in descrFits:
        bestNLL = descrFits[cell_num - 1]['NLL']
        currParams = descrFits[cell_num - 1]['params']
    else:  # set values to NaN...
        bestNLL = np.ones((nFam, nCon)) * np.nan
        currParams = np.ones((nFam, nCon, nParam)) * np.nan

    print('Doing the work, now')
    for family in range(nFam):
        for con in range(nCon):

            print('.')
            # set initial parameters - a range from which we will pick!
            base_rate = data['sfm']['exp']['sponRateMean']
            if base_rate <= 3:
                range_baseline = (0, 3)
            else:
                range_baseline = (0.5 * base_rate, 1.5 * base_rate)

            max_resp = np.amax(data['sfm']['exp']['sfRateMean'][family][con])
            range_amp = (0.5 * max_resp, 1.5)

            theSfCents = data['sfm']['exp']['sf'][family][con]

            max_sf_index = np.argmax(
                data['sfm']['exp']['sfRateMean'][family][con])
            # what sf index gives peak response?
            mu_init = theSfCents[max_sf_index]

            if max_sf_index == 0:  # i.e. smallest SF center gives max response...
                range_mu = (mu_init / 2, theSfCents[max_sf_index + 3])
            elif max_sf_index + 1 == len(
                    theSfCents):  # i.e. highest SF center is max
                range_mu = (theSfCents[max_sf_index - 3], mu_init)
            else:
                range_mu = (theSfCents[max_sf_index - 1],
                            theSfCents[max_sf_index + 1])
                # go +-1 indices from center

            log_bw_lo = 0.75
            # 0.75 octave bandwidth...
            log_bw_hi = 2
            # 2 octave bandwidth...
            denom_lo = hfunc.bw_log_to_lin(log_bw_lo, mu_init)[0]
            # get linear bandwidth
            denom_hi = hfunc.bw_log_to_lin(log_bw_hi, mu_init)[0]
            # get lin. bw (cpd)
            range_denom = (denom_lo, denom_hi)
            # don't want 0 in sigma

            # set bounds for parameters
            min_bw = 1 / 4
            max_bw = 10
            # ranges in octave bandwidth

            bound_baseline = (0, max_resp)
            bound_range = (0, 1.5 * max_resp)
            bound_mu = (0.01, 10)
            bound_sig = (np.maximum(0.1,
                                    min_bw / (2 * np.sqrt(2 * np.log(2)))),
                         max_bw / (2 * np.sqrt(2 * np.log(2))))
            # Gaussian at half-height

            all_bounds = (bound_baseline, bound_range, bound_mu, bound_sig,
                          bound_sig)

            for n_try in range(n_repeats):

                # pick initial params
                init_base = hfunc.random_in_range(range_baseline)
                init_amp = hfunc.random_in_range(range_amp)
                init_mu = hfunc.random_in_range(range_mu)
                init_sig_left = hfunc.random_in_range(range_denom)
                init_sig_right = hfunc.random_in_range(range_denom)

                init_params = [
                    init_base, init_amp, init_mu, init_sig_left, init_sig_right
                ]

                # choose optimization method
                if np.mod(n_try, 2) == 0:
                    methodStr = 'L-BFGS-B'
                else:
                    methodStr = 'TNC'

                obj = lambda params: descr_loss(params, data, family, con)
                wax = opt.minimize(obj,
                                   init_params,
                                   method=methodStr,
                                   bounds=all_bounds)

                # compare
                NLL = wax['fun']
                params = wax['x']

                if np.isnan(
                        bestNLL[family,
                                con]) or NLL < bestNLL[family, con] or invalid(
                                    currParams[family, con, :], all_bounds):
                    bestNLL[family, con] = NLL
                    currParams[family, con, :] = params

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + dfModelName):
        print('reloading descrFitsModel...')
        descrFits = hfunc.np_smart_load(data_loc + dfModelName)
    if cell_num - 1 not in descrFits:
        descrFits[cell_num - 1] = dict()
    descrFits[cell_num - 1]['NLL'] = bestNLL
    descrFits[cell_num - 1]['params'] = currParams

    np.save(data_loc + dfModelName, descrFits)
    print('saving for cell ' + str(cell_num))
Esempio n. 23
0
#            'm678p7r03_c72_sfm.mat', 'm678p7r03_c32_sfm.mat', 'm678p7r03_c36_sfm.mat', 'm678p7r03_c27_sfm.mat', 'm678p7r03_c39_sfm.mat', 'm678p7r03_c69_sfm.mat'];
# or generate the list
matFiles = None
if matFiles is None:  # then, let's build a list of files that we need
    allFiles = os.listdir(loc_matData)
    matFiles = []
    for f in allFiles:
        if f.startswith('m681') and f.endswith('_sfm.mat'):
            if os.path.exists(loc_pyData + f.replace('.mat', '.npy')):
                continue
            else:
                matFiles.append(f)

for f in matFiles:
    matData = makeStimulus.loadmat(loc_matData + f)
    S = matData.get('S')
    # the actual data structure

    print("now saving...%s" % f.replace('.mat', '.npy'))
    saveName = loc_pyData + f.replace('.mat', '.npy')
    np.save(saveName, S)

    # if move spikes
    if moveGLXspikes:
        pyDat = hf.np_smart_load(saveName)
        pyDat['sfm']['exp']['trial']['spikeCount'] = pyDat['sfm']['exp'][
            'trial']['spikeTimesGLX']['spikeCount']
        pyDat['sfm']['exp']['trial']['spikeTimes'] = pyDat['sfm']['exp'][
            'trial']['spikeTimesGLX']['spikeTimes']
        np.save(saveName, pyDat)
Esempio n. 24
0
import helper_fcns as hf
import re
import glob
import os

import pdb

#dirs = ['LGN/'];
#dirs = ['V1/', 'V1_orig/', 'altExp/']; # which experiments are we grabbing from?
to_check = ['structures/', 'recordings/']
# which subdirs are we looking in for files to copy?
file_ending = ['*.npy', '*sfMix*.xml']
# in structures/, we copy .npy; in recordings/, we copy .xml
splits = ['_sfm', '_|#']
# for structures/, split just based on _sfm; for recordings, first "_" or "#"

output_name = 'scp_list_200507.txt'

with open(output_name, 'w') as f:  # overwite any existing file...
    for dr in dirs:
        pth = '%sstructures/' % dr
        dl = hf.np_smart_load(pth + hf.get_datalist(dr))

        names = dl['unitName']
        for nm in names:
            for subdir, ending, to_split in zip(to_check, file_ending, splits):
                splt = re.split('%s' % to_split, nm)[0]
                # split the string on _ OR # to get the root of the file (i.e. animal#, penetration#, cell#)
                to_add = glob.glob('%s%s%s%s' % (dr, subdir, splt, ending))
                [f.write(x + '\n') for x in to_add]
Esempio n. 25
0
def setModel(cellNum,
             stopThresh,
             lr,
             lossType=1,
             fitType=1,
             subset_frac=1,
             initFromCurr=1,
             holdOutCondition=None):
    # Given just a cell number, will fit the Robbe-inspired V1 model to the data
    #
    # stopThresh is the value (in NLL) at which we stop the fitting (i.e. if the difference in NLL between two full steps is < stopThresh, stop the fitting
    #
    # LR is learning rate
    #
    # lossType
    #   1 - loss := square(sqrt(resp) - sqrt(pred))
    #   2 - loss := poissonProb(spikes | modelRate)
    #   3 - loss := modPoiss model (a la Goris, 2014)
    #
    # fitType - what is the model formulation?
    #   1 := flat normalization
    #   2 := gaussian-weighted normalization responses
    #   3 := gaussian-weighted c50/norm "constant"
    #
    # holdOutCondition - [d, c, sf] or None
    #   which condition should we hold out from the dataset

    ########
    # Load cell
    ########
    #loc_data = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/Analysis/Structures/'; # personal mac
    #loc_data = '/home/pl1465/SF_diversity/Analysis/Structures/'; # Prince cluster
    loc_data = '/arc/2.2/p1/plevy/SF_diversity/sfDiv-OriModel/sfDiv-python/Analysis/Structures/'
    # CNS

    # fitType
    if fitType == 1:
        fL_suffix1 = '_flat'
    elif fitType == 2:
        fL_suffix1 = '_wght'
    elif fitType == 3:
        fL_suffix1 = '_c50'
    # lossType
    if lossType == 1:
        fL_suffix2 = '_sqrt.npy'
    elif lossType == 2:
        fL_suffix2 = '_poiss.npy'
    elif lossType == 3:
        fL_suffix2 = '_modPoiss.npy'

    dataList = np_smart_load(str(loc_data + 'dataList.npy'))
    dataNames = dataList['unitName']

    print('loading data structure...')
    S = np_smart_load(str(loc_data + dataNames[cellNum - 1] + '_sfm.npy'))
    # why -1? 0 indexing...
    print('...finished loading')
    trial_inf = S['sfm']['exp']['trial']
    prefOrEst = mode(trial_inf['ori'][1]).mode
    trialsToCheck = trial_inf['con'][0] == 0.01
    prefSfEst = mode(trial_inf['sf'][0][trialsToCheck == True]).mode

    ########

    # 00 = preferred spatial frequency   (cycles per degree)
    # 01 = derivative order in space
    # 02 = normalization constant        (log10 basis)
    # 03 = response exponent
    # 04 = response scalar
    # 05 = early additive noise
    # 06 = late additive noise
    # 07 = variance of response gain - only used if lossType = 3
    # if fitType == 2
    # 08 = mean of (log)gaussian for normalization weights
    # 09 = std of (log)gaussian for normalization weights
    # if fitType == 3
    # 08 = the offset of the c50 tuning curve which is bounded between [v_sigOffset, 1] || [0, 1]
    # 09 = standard deviation of the gaussian to the left of the peak || >0.1
    # 10 = "" to the right "" || >0.1
    # 11 = peak of offset curve

    curr_params = []
    initFromCurr = 0
    # override initFromCurr so that we just go with default parameters

    if numpy.any(numpy.isnan(
            curr_params)):  # if there are nans, we need to ignore...
        curr_params = []
        initFromCurr = 0

    pref_sf = float(prefSfEst) if initFromCurr == 0 else curr_params[0]
    dOrdSp = numpy.random.uniform(1,
                                  3) if initFromCurr == 0 else curr_params[1]
    normConst = -0.8 if initFromCurr == 0 else curr_params[2]
    # why -0.8? Talked with Tony, he suggests starting with lower sigma rather than higher/non-saturating one
    #normConst = numpy.random.uniform(-1, 0) if initFromCurr==0 else curr_params[2];
    respExp = numpy.random.uniform(1,
                                   3) if initFromCurr == 0 else curr_params[3]
    respScal = numpy.random.uniform(
        10, 1000) if initFromCurr == 0 else curr_params[4]
    noiseEarly = numpy.random.uniform(
        0.001, 0.1) if initFromCurr == 0 else curr_params[5]
    noiseLate = numpy.random.uniform(
        0.1, 1) if initFromCurr == 0 else curr_params[6]
    varGain = numpy.random.uniform(0.1,
                                   1) if initFromCurr == 0 else curr_params[7]
    if fitType == 2:
        normMean = numpy.random.uniform(
            -1, 1) if initFromCurr == 0 else curr_params[8]
        normStd = numpy.random.uniform(
            0.1, 1) if initFromCurr == 0 else curr_params[9]
    if fitType == 3:
        sigOffset = numpy.random.uniform(
            0, 0.05) if initFromCurr == 0 else curr_params[8]
        stdLeft = numpy.random.uniform(
            1, 5) if initFromCurr == 0 else curr_params[9]
        stdRight = numpy.random.uniform(
            1, 5) if initFromCurr == 0 else curr_params[10]
        sigPeak = float(prefSfEst) if initFromCurr == 0 else curr_params[11]

    print('Initial parameters:\n\tsf: ' + str(pref_sf) + '\n\td.ord: ' +
          str(dOrdSp) + '\n\tnormConst: ' + str(normConst))
    print('\n\trespExp ' + str(respExp) + '\n\trespScalar ' + str(respScal))

    v_prefSf = tf.Variable(pref_sf, dtype=tf.float32)
    v_dOrdSp = tf.Variable(dOrdSp, dtype=tf.float32)
    v_normConst = tf.Variable(normConst, dtype=tf.float32)
    v_respExp = tf.Variable(respExp, dtype=tf.float32)
    v_respScalar = tf.Variable(respScal, dtype=tf.float32)
    v_noiseEarly = tf.Variable(noiseEarly, dtype=tf.float32)
    v_noiseLate = tf.Variable(noiseLate, dtype=tf.float32)
    v_varGain = tf.Variable(varGain, dtype=tf.float32)
    if fitType == 2:
        v_normMean = tf.Variable(normMean, dtype=tf.float32)
        v_normStd = tf.Variable(normStd, dtype=tf.float32)
    if fitType == 3:
        v_sigOffset = tf.Variable(sigOffset, dtype=tf.float32)
        v_stdLeft = tf.Variable(stdLeft, dtype=tf.float32)
        v_stdRight = tf.Variable(stdRight, dtype=tf.float32)
        v_sigPeak = tf.Variable(sigPeak, dtype=tf.float32)

    #########
    # Now get all the data we need for tf_placeholders
    #########
    # stimulus information

    # vstack to turn into array (not array of arrays!)
    stimOr = numpy.vstack(trial_inf['ori'])
    stimTf = numpy.vstack(trial_inf['tf'])
    stimCo = numpy.vstack(trial_inf['con'])
    stimSf = numpy.vstack(trial_inf['sf'])
    stimPh = numpy.vstack(trial_inf['ph'])

    #purge of NaNs...
    mask = numpy.isnan(numpy.sum(stimOr, 0))
    # sum over all stim components...if there are any nans in that trial, we know
    objWeight = numpy.ones((stimOr.shape[1]))

    # and get rid of orientation tuning curve trials
    oriBlockIDs = numpy.hstack(
        (numpy.arange(131, 155 + 1, 2), numpy.arange(132, 136 + 1, 2)))
    # +1 to include endpoint like Matlab

    oriInds = numpy.empty((0, ))
    for iB in oriBlockIDs:
        indCond = numpy.where(trial_inf['blockID'] == iB)
        if len(indCond[0]) > 0:
            oriInds = numpy.append(oriInds, indCond)

    # get rid of CRF trials, too? Not yet...
    conBlockIDs = numpy.arange(138, 156 + 1, 2)
    conInds = numpy.empty((0, ))
    for iB in conBlockIDs:
        indCond = numpy.where(trial_inf['blockID'] == iB)
        if len(indCond[0]) > 0:
            conInds = numpy.append(conInds, indCond)

    objWeight[conInds.astype(numpy.int64)] = 1
    # for now, yes it's a "magic number"

    mask[oriInds.astype(numpy.int64)] = True
    # as in, don't include those trials either!
    # hold out a condition if we have specified
    if holdOutCondition is not None:
        # dispInd: [1, 5]...conInd: [1, 2]...sfInd: [1, 11]
        # first, get all of the conditions... - blockIDs by condition known from Robbe code
        dispInd = holdOutCondition[0]
        conInd = holdOutCondition[1]

        StimBlockIDs = numpy.arange(
            ((dispInd - 1) * (13 * 2) + 1) + (conInd - 1),
            ((dispInd) * (13 * 2) - 5) + (conInd - 1) + 1, 2)
        # +1 to include the last block ID

        if len(numpy.shape(holdOutCondition)) == 3:
            sfInd = holdOutCondition[2]
            currBlockID = StimBlockIDs[sfInd - 1]
            holdOutTr = numpy.where(trial_inf['blockID'] == currBlockID)[0]
        else:
            holdOutTr = []
            for i in StimBlockIDs:
                newTr = numpy.where(trial_inf['blockID'] == i)[0]
                holdOutTr.append(newTr)
            holdOutTr = numpy.array(holdOutTr).flatten()

        mask[holdOutTr.astype(numpy.int64)] = True
        # as in, don't include those trials either!

    fixedOr = stimOr[:, ~mask]
    fixedTf = stimTf[:, ~mask]
    fixedCo = stimCo[:, ~mask]
    fixedSf = stimSf[:, ~mask]
    fixedPh = stimPh[:, ~mask]

    # cell responses
    spikes = trial_inf['spikeCount'][~mask]
    stim_dur = trial_inf['duration'][~mask]
    objWeight = objWeight[~mask]

    #########
    # Now set up our normalization pool information (also placeholder)
    #########
    # Get the normalization response (nTrials x nFilters [27] x nFrames [120])
    normResp = S['sfm']['mod']['normalization']['normResp'][~mask, :, :]

    # Put all of the filter prefSf into one vector (should be length 12+15=27)
    normFilterSF = []
    normPrefSf = S['sfm']['mod']['normalization']['pref']['sf']
    for iP in range(len(normPrefSf)):
        normFilterSF = numpy.append(normFilterSF, numpy.log(normPrefSf[iP]))
        #muCenterPref = numpy.append(muCenterPref, numpy.log(normPrefSf[iP]) - numpy.mean(numpy.log(normPrefSf[iP])));

    normCentSf = normFilterSF

    #########
    # Set up the network!
    #########
    subsetShape = [
        fixedTf.shape[0],
        int(round(fixedTf.shape[-1] * subset_frac))
    ]

    ph_stimOr = tf.placeholder(tf.float32)
    if subset_frac < 1:
        ph_stimTf = tf.placeholder(tf.float32, shape=subsetShape)
    else:
        ph_stimTf = tf.placeholder(tf.float32, shape=fixedTf.shape)
    ph_stimCo = tf.placeholder(tf.float32)
    ph_stimSf = tf.placeholder(tf.float32)
    ph_stimPh = tf.placeholder(tf.float32)

    ph_spikeCount = tf.placeholder(tf.float32)
    ph_stimDur = tf.placeholder(tf.float32)
    ph_objWeight = tf.placeholder(tf.float32)

    ph_normResp = tf.placeholder(tf.float32)
    ph_normCentSf = tf.placeholder(tf.float32)

    print('Setting network')

    # Set up model here - we return the NLL
    if fitType == 1:
        param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar,
                      v_noiseEarly, v_noiseLate, v_varGain)
    elif fitType == 2:
        param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar,
                      v_noiseEarly, v_noiseLate, v_varGain, v_normMean,
                      v_normStd)
    elif fitType == 3:
        param_list = (v_prefSf, v_dOrdSp, v_normConst, v_respExp, v_respScalar,
                      v_noiseEarly, v_noiseLate, v_varGain, v_sigOffset,
                      v_stdLeft, v_stdRight, v_sigPeak)
    # now make the call
    okok = SFMGiveBof(ph_stimOr, ph_stimTf, ph_stimCo, ph_stimSf, ph_stimPh, ph_spikeCount, ph_stimDur, ph_objWeight, \
                        ph_normResp, ph_normCentSf, lossType, fitType, *param_list)

    if subset_frac < 1:  # then we also need to create a network which can handle the full dataset
        ph_stimTfFull = tf.placeholder(tf.float32, shape=fixedTf.shape)
        full = SFMGiveBof(ph_stimOr, ph_stimTfFull, ph_stimCo, ph_stimSf, ph_stimPh, ph_spikeCount, ph_stimDur, ph_objWeight, \
                  ph_normResp, ph_normCentSf, lossType, fitType, *param_list)

    print('Setting optimizer')
    optimizer = tf.train.AdamOptimizer(learning_rate=lr).minimize(okok)

    m = tf.Session()
    init = tf.global_variables_initializer()
    m.run(init)

    # guaranteed to have NLL for this cell by now (even if just placeholder)
    currNLL = 1e4
    prevNLL = numpy.nan
    diffNLL = 1e4
    # just pick a large value
    iter = 1

    if subset_frac < 1:  # do the subsampling ONCE
        trialsToPick = numpy.random.randint(0, fixedOr.shape[-1],
                                            subsetShape[-1])
        subsetOr = fixedOr[:, trialsToPick]
        subsetTf = fixedTf[:, trialsToPick]
        subsetCo = fixedCo[:, trialsToPick]
        subsetSf = fixedSf[:, trialsToPick]
        subsetPh = fixedPh[:, trialsToPick]
        subsetSpikes = spikes[trialsToPick]
        subsetDur = stim_dur[trialsToPick]
        subsetWeight = objWeight[trialsToPick]
        subsetNormResp = normResp[trialsToPick, :, :]

    while (abs(diffNLL) > stopThresh):

        if subset_frac < 1:  # pass in the subsampled data
            opt = m.run(optimizer, feed_dict={ph_stimOr: subsetOr, ph_stimTf: subsetTf, ph_stimCo: subsetCo, \
                            ph_stimSf: subsetSf, ph_stimPh: subsetPh, ph_spikeCount: subsetSpikes, ph_stimDur: subsetDur, ph_objWeight: subsetWeight, \
                            ph_normResp: subsetNormResp, ph_normCentSf: normCentSf})

            if (iter / 500.0) == round(iter / 500.0):
                NLL = m.run(full, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                           ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                           ph_stimDur: stim_dur, ph_objWeight:objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf})

        else:  # pass in the full dataset
            opt = \
                  m.run(optimizer, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                              ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                              ph_stimDur: stim_dur, ph_objWeight: objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf})

            if (iter / 500.0) == round(iter / 500.0):
                NLL = m.run(okok, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                           ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                           ph_stimDur: stim_dur, ph_objWeight:objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf})

        if (iter / 500.0) == round(iter /
                                   500.0):  # save every once in a while!!!

            real_params = m.run(applyConstraints(fitType, *param_list))
            print('iteration ' + str(iter) + '...NLL is ' + str(NLL) +
                  ' and saved params are ' + str(curr_params))
            print('\tparams in current optimization are: ' + str(real_params))

            if numpy.isnan(prevNLL):
                diffNLL = NLL
            else:
                diffNLL = prevNLL - NLL
            prevNLL = NLL

            print('Difference in NLL is : ' + str(diffNLL))

            if NLL < currNLL or numpy.any(
                    numpy.isnan(curr_params)
            ):  # if the saved params are NaN, overwrite them

                if numpy.any(numpy.isnan(
                        real_params)):  # don't save a fit with NaN!
                    print('.nanParam.')
                    iter = iter + 1
                    continue

                print('.update.')
                print('.params.')
                print(real_params)
                print('.NLL|fullData.')
                print(NLL)
                currNLL = NLL
                currParams = real_params
                curr_params = real_params
                # update for when you print/display

        iter = iter + 1

    # Now the fitting is done
    # Now get "true" model parameters and NLL
    if subset_frac < 1:
        NLL = m.run(okok, feed_dict={ph_stimOr: subsetOr, ph_stimTf: subsetTf, ph_stimCo: subsetCo, \
                            ph_stimSf: subsetSf, ph_stimPh: subsetPh, ph_spikeCount: subsetSpikes, ph_stimDur: subsetDur, ph_objWeight: subsetWeight, \
                            ph_normResp: subsetNormResp, ph_normCentSf: normCentSf})
    else:
        NLL = m.run(okok, feed_dict={ph_stimOr: fixedOr, ph_stimTf: fixedTf, ph_stimCo: fixedCo, \
                              ph_stimSf: fixedSf, ph_stimPh: fixedPh, ph_spikeCount: spikes, \
                              ph_stimDur: stim_dur, ph_objWeight: objWeight, ph_normResp: normResp, ph_normCentSf: normCentSf})

    x = m.run(applyConstraints(fitType, *param_list))

    if holdOutCondition is not None:
        holdoutNLL, _, = nllEval(params=x,
                                 structureSFM=S,
                                 normType=fitType,
                                 lossType=lossType,
                                 trialSubset=holdOutTr)
    else:
        holdoutNLL = []

    print('Final parameters are ' + str(x))

    return NLL, x, holdoutNLL
Esempio n. 26
0
def rvc_adjusted_fit(cell_num,
                     data_loc=dataPath,
                     rvcName=rvcName,
                     to_save=1,
                     disp=0,
                     dir=-1):
    ''' Piggy-backing off of phase_advance_fit above, get prepare to project the responses onto the proper phase to get the correct amplitude
      Then, with the corrected response amplitudes, fit the RVC model
  '''
    dataList = hf.np_smart_load(data_loc + 'dataList.npy')
    cellStruct = hf.np_smart_load(data_loc +
                                  dataList['unitName'][cell_num - 1] +
                                  '_sfm.npy')
    data = cellStruct['sfm']['exp']['trial']
    rvcNameFinal = hf.fit_name(rvcName, dir)

    # first, get the set of stimulus values:
    _, stimVals, valConByDisp, _, _ = hf.tabulate_responses(data,
                                                            expInd=expInd)
    allCons = stimVals[1]
    allSfs = stimVals[2]
    valCons = allCons[valConByDisp[disp]]

    # calling phase_advance fit, use the phAdv_model and optimized paramters to compute the true response amplitude
    # given the measured/observed amplitude and phase of the response
    # NOTE: We always call phase_advance_fit with disp=0 (default), since we don't make a fit
    # for the mixtrue stimuli - instead, we use the fits made on single gratings to project the
    # individual-component-in-mixture responses
    phAdv_model, all_opts = phase_advance_fit(cell_num, dir=dir, to_save=0)
    # don't save
    allAmp, allPhi, _, allCompCon, allCompSf = hf.get_all_fft(data,
                                                              disp,
                                                              dir=dir,
                                                              all_trials=1)
    # get just the mean amp/phi and put into convenient lists
    allAmpMeans = [[x[0] for x in sf] for sf in allAmp]
    # mean is in the first element; do that for each [mean, std] pair in each list (split by sf)
    allAmpTrials = [[x[2] for x in sf] for sf in allAmp]
    # trial-by-trial is third element

    allPhiMeans = [[x[0] for x in sf] for sf in allPhi]
    # mean is in the first element; do that for each [mean, var] pair in each list (split by sf)
    allPhiTrials = [[x[2] for x in sf] for sf in allPhi]
    # trial-by-trial is third element

    adjMeans = hf.project_resp(allAmpMeans, allPhiMeans, phAdv_model, all_opts,
                               disp, allCompSf, allSfs)
    adjByTrial = hf.project_resp(allAmpTrials, allPhiTrials, phAdv_model,
                                 all_opts, disp, allCompSf, allSfs)
    consRepeat = [valCons] * len(adjMeans)

    if disp == 1:  # then we need to sum component responses and get overall std measure (we'll fit to sum, not indiv. comp responses!)
        adjSumResp = [np.sum(x, 1) if x else [] for x in adjMeans]
        adjSemTr = [[sem(np.sum(hf.switch_inner_outer(x), 1)) for x in y]
                    for y in adjByTrial]
        adjSemCompTr = [[sem(hf.switch_inner_outer(x)) for x in y]
                        for y in adjByTrial]
        rvc_model, all_opts, all_conGains, all_loss = hf.rvc_fit(
            adjSumResp, consRepeat, adjSemTr)
    elif disp == 0:
        adjSemTr = [[sem(x) for x in y] for y in adjByTrial]
        adjSemCompTr = adjSemTr
        # for single gratings, there is only one component!
        rvc_model, all_opts, all_conGains, all_loss = hf.rvc_fit(
            adjMeans, consRepeat, adjSemTr)

    if os.path.isfile(data_loc + rvcNameFinal):
        rvcFits = hf.np_smart_load(data_loc + rvcNameFinal)
    else:
        rvcFits = dict()

    # update stuff - load again in case some other run has saved/made changes
    if os.path.isfile(data_loc + rvcNameFinal):
        print('reloading rvcFits...')
        rvcFits = hf.np_smart_load(data_loc + rvcNameFinal)
    if cell_num - 1 not in rvcFits:
        rvcFits[cell_num - 1] = dict()
        rvcFits[cell_num - 1][disp] = dict()
    else:  # cell_num-1 is a key in rvcFits
        if disp not in rvcFits[cell_num - 1]:
            rvcFits[cell_num - 1][disp] = dict()

    rvcFits[cell_num - 1][disp]['loss'] = all_loss
    rvcFits[cell_num - 1][disp]['params'] = all_opts
    rvcFits[cell_num - 1][disp]['conGain'] = all_conGains
    rvcFits[cell_num - 1][disp]['adjMeans'] = adjMeans
    rvcFits[cell_num - 1][disp]['adjByTr'] = adjByTrial
    rvcFits[cell_num - 1][disp]['adjSem'] = adjSemTr
    rvcFits[cell_num - 1][disp]['adjSemComp'] = adjSemCompTr

    if to_save:
        np.save(data_loc + rvcNameFinal, rvcFits)
        print('saving rvc fit for cell ' + str(cell_num))

    return rvc_model, all_opts, all_conGains, adjMeans
Esempio n. 27
0
def make_descr_fits(cellNum,
                    data_path=basePath + data_suff,
                    fit_rvc=1,
                    fit_sf=1,
                    rvcMod=1,
                    sfMod=0,
                    loss_type=2,
                    vecF1=1,
                    onsetCurr=None,
                    rvcName=rvcName,
                    sfName=sfName,
                    toSave=1,
                    fracSig=1,
                    nBoots=0,
                    n_repeats=25,
                    jointSf=0,
                    resp_thresh=(-1e5, 0),
                    veThresh=-1e5,
                    sfModRef=1,
                    phAdvCorr=True):
    ''' Separate fits for DC, F1 
      -- for DC: [maskOnly, mask+base]
      -- for F1: [maskOnly, mask+base {@mask TF}] 
      For asMulti fits (i.e. when done in parallel) we do the following to reduce multiple loading of files/race conditions
      --- we'll pass in the previous fits as fit_rvc and/or fit_sf
      --- we'll pass in [cellNum, cellName] as cellNum
  '''
    rvcFits_curr_toSave = None
    sfFits_curr_toSave = None
    # default to None, in case we don't actually do those fits
    expName = 'sfBB_core'

    if not isinstance(cellNum, int):
        cellNum, unitNm = cellNum
        print('cell %d {%s}' % (cellNum, unitNm))
    else:
        dlName = hf.get_datalist('V1_BB/')
        dataList = hf.np_smart_load(data_path + dlName)
        unitNm = dataList['unitName'][cellNum - 1]
    print('loading cell')
    cell = hf.np_smart_load('%s%s_sfBB.npy' % (data_path, unitNm))
    expInfo = cell[expName]
    byTrial = expInfo['trial']

    if fit_rvc == 1 or fit_rvc is not None:  # load existing rvcFits, if there
        rvcNameFinal = hf.rvc_fit_name(rvcName, rvcMod, None, vecF1)
        if fit_rvc == 1:
            if os.path.isfile(data_path + rvcNameFinal):
                rvcFits = hf.np_smart_load(data_path + rvcNameFinal)
            else:
                rvcFits = dict()
        else:  # otherwise, we have passed it in as fit_sf to avoid race condition during multiprocessing (i.e. multiple threads trying to load the same file)
            rvcFits = fit_rvc
        try:
            rvcFits_curr_toSave = rvcFits[cellNum - 1]
        except:
            rvcFits_curr_toSave = dict()

    if fit_sf == 1 or fit_sf is not None:
        modStr = hf.descrMod_name(sfMod)
        sfNameFinal = hf.descrFit_name(loss_type,
                                       descrBase=sfName,
                                       modelName=modStr,
                                       joint=jointSf)
        # descrLoss order is lsq/sqrt/poiss/sach
        if fit_sf == 1:
            if os.path.isfile(data_path + sfNameFinal):
                sfFits = hf.np_smart_load(data_path + sfNameFinal)
            else:
                sfFits = dict()
        else:  # otherwise, we have passed it in as fit_sf to avoid race condition during multiprocessing (i.e. multiple threads trying to load the same file)
            sfFits = fit_sf
        try:
            sfFits_curr_toSave = sfFits[cellNum - 1]
            print('---prev sf!')
        except:
            sfFits_curr_toSave = dict()
            print('---NO PREV sf!')

    # Set up whether we will bootstrap straight away
    resample = False if nBoots <= 0 else True
    if cross_val is not None:
        # we also set to True if cross_val is not None
        resample = True
    nBoots = 1 if nBoots <= 0 else nBoots
    if nBoots > 1:
        ftol = 5e-9
        #ftol = 1e-6;
    else:
        ftol = 2.220446049250313e-09
        # the default value, per scipy guide (scipy.optimize, for L-BFGS-B)

    #########
    ### Get the responses - base only, mask+base [base F1], mask only (mask F1)
    ### _____ MAKE THIS A FUNCTION???
    #########
    # 1. Get the mask only response (f1 at mask TF)
    _, _, gt_respMatrixDC_onlyMask, gt_respMatrixF1_onlyMask = hf_sf.get_mask_resp(
        expInfo,
        withBase=0,
        maskF1=1,
        vecCorrectedF1=vecF1,
        onsetTransient=onsetCurr,
        returnByTr=1,
        phAdvCorr=phAdvCorr)
    # i.e. get the maskONLY response
    # 2f1. get the mask+base response (but f1 at mask TF)
    _, _, _, gt_respMatrixF1_maskTf = hf_sf.get_mask_resp(
        expInfo,
        withBase=1,
        maskF1=1,
        vecCorrectedF1=vecF1,
        onsetTransient=onsetCurr,
        returnByTr=1,
        phAdvCorr=phAdvCorr)
    # i.e. get the maskONLY response
    # 2dc. get the mask+base response (f1 at base TF)
    _, _, gt_respMatrixDC, _ = hf_sf.get_mask_resp(expInfo,
                                                   withBase=1,
                                                   maskF1=0,
                                                   vecCorrectedF1=vecF1,
                                                   onsetTransient=onsetCurr,
                                                   returnByTr=1,
                                                   phAdvCorr=phAdvCorr)
    # i.e. get the base response for F1

    if cross_val == 2.0:
        nBoots = np.multiply(*gt_respMatrixDC_onlyMask.shape[0:2], )
        print('# boots is %03d' % nBoots)
        resample = False
        # then we DO NOT want to resample

    for boot_i in range(nBoots):
        ######
        # 3a. Ensure we have the right responses (incl. resampling, taking mean)
        ######
        # --- Note that all hf_sf.resample_all_cond(resample, arr, axis=X) calls are X=2, because all arrays are [nSf x nCon x respPerTrial x ...]
        # - o. DC responses are easy - simply resample, then take the mean/s.e.m. across all trials of a given condition
        respMatrixDC_onlyMask_resample = hf_sf.resample_all_cond(
            resample, np.copy(gt_respMatrixDC_onlyMask), axis=2)
        respMatrixDC_onlyMask = np.stack(
            (np.nanmean(respMatrixDC_onlyMask_resample, axis=-1),
             sem(respMatrixDC_onlyMask_resample, axis=-1, nan_policy='omit')),
            axis=-1)
        respMatrixDC_resample = hf_sf.resample_all_cond(
            resample, np.copy(gt_respMatrixDC), axis=2)
        respMatrixDC = np.stack(
            (np.nanmean(respMatrixDC_resample, axis=-1),
             sem(respMatrixDC_resample, axis=-1, nan_policy='omit')),
            axis=-1)
        # - F1 responses are different - vector math (i.e. hf.polar_vec_mean call)
        # --- first, resample the data, then do the vector math
        # - i. F1, only mask
        respMatrixF1_onlyMask_resample = hf_sf.resample_all_cond(
            resample, np.copy(gt_respMatrixF1_onlyMask), axis=2)
        # --- however, polar_vec_mean must be computed by condition, to handle NaN (which might be unequal across conditions):
        respMatrixF1_onlyMask = np.empty(
            respMatrixF1_onlyMask_resample.shape[0:2] +
            respMatrixF1_onlyMask_resample.shape[3:])
        respMatrixF1_onlyMask_phi = np.copy(respMatrixF1_onlyMask)
        for conds in itertools.product(
                *[range(x)
                  for x in respMatrixF1_onlyMask_resample.shape[0:2]]):
            r_mean, phi_mean, r_sem, phi_sem = hf.polar_vec_mean(
                [
                    hf.nan_rm(respMatrixF1_onlyMask_resample[conds +
                                                             (slice(None), 0)])
                ], [
                    hf.nan_rm(respMatrixF1_onlyMask_resample[conds +
                                                             (slice(None), 1)])
                ],
                sem=1)  # return s.e.m. rather than std (default)
            # - and we only care about the R value (after vec. avg.)
            respMatrixF1_onlyMask[conds] = [r_mean[0], r_sem[0]]
            # r...[0] to unpack (it's nested inside array, since f is vectorized
            respMatrixF1_onlyMask_phi[conds] = [phi_mean[0], phi_sem[0]]
        if phAdvCorr and vecF1:
            maskCon, maskSf = expInfo['maskCon'], expInfo['maskSF']
            opt_params, phAdv_model = hf_sf.phase_advance_fit_core(
                respMatrixF1_onlyMask, respMatrixF1_onlyMask_phi, maskCon,
                maskSf)
            for msI, mS in enumerate(maskSf):
                curr_params = opt_params[msI]
                # the phAdv model applies per-SF
                for mcI, mC in enumerate(maskCon):
                    curr_r, curr_phi = respMatrixF1_onlyMask[
                        mcI, msI, 0], respMatrixF1_onlyMask_phi[mcI, msI, 0]
                    refPhi = phAdv_model(*curr_params, curr_r)
                    new_r = np.multiply(
                        curr_r,
                        np.cos(np.deg2rad(refPhi) - np.deg2rad(curr_phi)))
                    respMatrixF1_onlyMask[mcI, msI, 0] = new_r

        # - ii. F1, both (@ maskTF)
        respMatrixF1_maskTf_resample = hf_sf.resample_all_cond(
            resample, np.copy(gt_respMatrixF1_maskTf), axis=2)
        # --- however, polar_vec_mean must be computed by condition, to handle NaN (which might be unequal across conditions):
        respMatrixF1_maskTf = np.empty(
            respMatrixF1_maskTf_resample.shape[0:2] +
            respMatrixF1_maskTf_resample.shape[3:])
        respMatrixF1_maskTf_phi = np.copy(respMatrixF1_maskTf)
        for conds in itertools.product(
                *[range(x) for x in respMatrixF1_maskTf_resample.shape[0:2]]):
            r_mean, phi_mean, r_sem, phi_var = hf.polar_vec_mean(
                [
                    hf.nan_rm(respMatrixF1_maskTf_resample[conds +
                                                           (slice(None), 0)])
                ], [
                    hf.nan_rm(respMatrixF1_maskTf_resample[conds +
                                                           (slice(None), 1)])
                ],
                sem=1)  # return s.e.m. rather than std (default)
            # - and we only care about the R value (after vec. avg.)
            respMatrixF1_maskTf[conds] = [r_mean[0], r_sem[0]]
            # r...[0] is to unpack (it's nested inside array, since func is vectorized
            respMatrixF1_maskTf_phi[conds] = [phi_mean[0], phi_sem[0]]
        if phAdvCorr and vecF1:
            maskCon, maskSf = expInfo['maskCon'], expInfo['maskSF']
            opt_params, phAdv_model = hf_sf.phase_advance_fit_core(
                respMatrixF1_maskTf, respMatrixF1_maskTf_phi, maskCon, maskSf)
            for msI, mS in enumerate(maskSf):
                curr_params = opt_params[msI]
                # the phAdv model applies per-SF
                for mcI, mC in enumerate(maskCon):
                    curr_r, curr_phi = respMatrixF1_maskTf[
                        mcI, msI, 0], respMatrixF1_maskTf_phi[mcI, msI, 0]
                    refPhi = phAdv_model(*curr_params, curr_r)
                    new_r = np.multiply(
                        curr_r,
                        np.cos(np.deg2rad(refPhi) - np.deg2rad(curr_phi)))
                    respMatrixF1_maskTf[mcI, msI, 0] = new_r

        if cross_val == 2.0:
            n_sfs, n_cons = gt_respMatrixF1_maskTf.shape[
                0], gt_respMatrixF1_maskTf.shape[1]
            con_ind, sf_ind = np.floor(np.divide(boot_i,
                                                 n_sfs)).astype('int'), np.mod(
                                                     boot_i,
                                                     n_sfs).astype('int')
            print('holding out con/sf indices %02d/%02d' % (con_ind, sf_ind))

        for measure in [0, 1]:
            if measure == 0:
                baseline = np.nanmean(
                    hf.resample_array(resample, expInfo['blank']['resps']))
                if cross_val == 2.0:
                    # --- so, "nan" out that condition in all of the responses
                    mask_only_ref = np.copy(respMatrixDC_onlyMask)
                    mask_base_ref = np.copy(respMatrixDC)
                    # the above establish the reference values; below, we nan out the current condition
                    mask_only = np.copy(respMatrixDC_onlyMask)
                    mask_base = np.copy(respMatrixDC)
                    mask_only[sf_ind, con_ind] = np.nan
                    mask_base[sf_ind, con_ind] = np.nan
                else:
                    mask_only = respMatrixDC_onlyMask
                    mask_base = respMatrixDC
                mask_only_all = None
                # as of 22.06.15
                fix_baseline = False
            elif measure == 1:
                baseline = 0
                if cross_val == 2.0:
                    # --- so, "nan" out that condition in all of the responses
                    mask_only_ref = np.copy(respMatrixF1_onlyMask)
                    mask_base_ref = np.copy(respMatrixF1_maskTf)
                    # the above establish the reference values; below, we nan out the current condition
                    mask_only = np.copy(respMatrixF1_onlyMask)
                    mask_base = np.copy(respMatrixF1_maskTf)
                    mask_only[sf_ind, con_ind] = np.nan
                    mask_base[sf_ind, con_ind] = np.nan
                else:
                    mask_only = respMatrixF1_onlyMask
                    mask_base = respMatrixF1_maskTf
                mask_only_all = None
                # as of 22.06.15; ignore the above line
                fix_baseline = True
            resp_str = hf_sf.get_resp_str(respMeasure=measure)

            if cross_val is not None:  # set up what is the test data!
                nan_val = -1e3
                # make sure we nan out any existing NaN values in the reference data
                mask_only_ref[np.isnan(mask_only_ref)] = nan_val
                # make sure we nan out any NaN values in the training data
                mask_only_tr = np.copy(mask_only)
                mask_only_tr[np.isnan(mask_only_tr)] = nan_val
                heldout = np.abs(
                    mask_only_tr - mask_only_ref
                ) > 1e-6  # if the idff. is g.t. this, it means they are different values
                test_mask_only = np.nan * np.zeros_like(mask_only_tr)
                test_mask_base = np.nan * np.zeros_like(mask_only_tr)
                test_mask_only[heldout] = mask_only_ref[heldout]
                test_mask_base[heldout] = mask_base_ref[heldout]
                heldouts = [test_mask_only]
                # update to include ...base IF below lines (which*) include both
            else:
                heldouts = [None]

            whichAll = [mask_only_all]
            whichResp = [mask_only]  #, mask_base];
            whichKey = ['mask']  #, 'both'];

            if fit_rvc == 1 or fit_rvc is not None:
                ''' Fit RVCs responses (see helper_fcns.rvc_fit for details) for:
            --- F0: mask alone (7 sfs)
                    mask + base together (7 sfs)
            --- F1: mask alone (7 sfs; at maskTf)
                    mask+ + base together (7 sfs; again, at maskTf)
            NOTE: Assumes only sfBB_core
        '''
                if resp_str not in rvcFits_curr_toSave:
                    rvcFits_curr_toSave[resp_str] = dict()

                cons = expInfo['maskCon']
                # first, mask only; then mask+base
                for wR, wK, wA in zip(whichResp, whichKey, whichAll):
                    # create room for an empty dict, if not already present
                    if wK not in rvcFits_curr_toSave[resp_str]:
                        rvcFits_curr_toSave[resp_str][wK] = dict()

                    adjMeans = np.transpose(wR[:, :, 0])
                    # just the means
                    # --- in new version of code [to allow boot], we can get masked array; do the following to save memory
                    adjMeans = adjMeans.data if isinstance(
                        adjMeans, np.ma.MaskedArray) else adjMeans
                    consRepeat = [cons] * len(adjMeans)

                    # get a previous fit, if present
                    try:
                        rvcFit_curr = rvcFits_curr_toSave[resp_str][
                            wK] if not resample else None
                    except:
                        rvcFit_curr = None
                    # do the fitting!
                    _, all_opts, all_conGains, all_loss = hf.rvc_fit(
                        adjMeans,
                        consRepeat,
                        var=None,
                        mod=rvcMod,
                        fix_baseline=fix_baseline,
                        prevFits=rvcFit_curr,
                        n_repeats=n_repeats)

                    # compute variance explained!
                    varExpl = [
                        hf.var_explained(
                            hf.nan_rm(dat),
                            hf.nan_rm(hf.get_rvcResp(prms, cons, rvcMod)),
                            None) for dat, prms in zip(adjMeans, all_opts)
                    ]
                    # now, package things
                    if resample:
                        if boot_i == 0:  # i.e. first time around
                            # - then we create empty lists to which we append the result of each success iteration
                            # --- note that we do not include adjMeans here (don't want nBoots iterations of response means saved!)
                            rvcFits_curr_toSave[resp_str][wK][
                                'boot_loss'] = []
                            rvcFits_curr_toSave[resp_str][wK][
                                'boot_params'] = []
                            rvcFits_curr_toSave[resp_str][wK][
                                'boot_conGain'] = []
                            rvcFits_curr_toSave[resp_str][wK][
                                'boot_varExpl'] = []
                        # then -- append!
                        rvcFits_curr_toSave[resp_str][wK]['boot_loss'].append(
                            all_loss)
                        rvcFits_curr_toSave[resp_str][wK][
                            'boot_params'].append(all_opts)
                        rvcFits_curr_toSave[resp_str][wK][
                            'boot_conGain'].append(all_conGains)
                        rvcFits_curr_toSave[resp_str][wK][
                            'boot_varExpl'].append(varExpl)
                    else:  # we will never be here more than once, since if not resample, then nBoots = 1
                        rvcFits_curr_toSave[resp_str][wK]['loss'] = all_loss
                        rvcFits_curr_toSave[resp_str][wK]['params'] = all_opts
                        rvcFits_curr_toSave[resp_str][wK][
                            'conGain'] = all_conGains
                        rvcFits_curr_toSave[resp_str][wK][
                            'adjMeans'] = adjMeans
                        rvcFits_curr_toSave[resp_str][wK]['varExpl'] = varExpl
                ########
                # END of rvc fit (for this measure, boot iteration)
                ########

            if fit_sf == 1 or fit_sf is not None:
                ''' Fit SF tuning responses (see helper_fcns.dog_fit for details) for:
            --- F0: mask alone (7 cons)
                    mask + base together (7 cons)
            --- F1: mask alone (7 cons; at maskTf)
                    mask+ + base together (7 cons; again, at maskTf)
            NOTE: Assumes only sfBB_core
        '''
                if resp_str not in sfFits_curr_toSave:
                    sfFits_curr_toSave[resp_str] = dict()

                cons, sfs = expInfo['maskCon'], expInfo['maskSF']
                stimVals = [[0], cons, sfs]
                valConByDisp = [np.arange(0, len(cons))]
                # all cons are valid in sfBB experiment

                for wR, wK, wA, heldout in zip(whichResp, whichKey, whichAll,
                                               heldouts):
                    if wK not in sfFits_curr_toSave[resp_str]:
                        sfFits_curr_toSave[resp_str][wK] = dict()

                    # get a previous fit, if present
                    try:
                        sfFit_curr = sfFits_curr_toSave[resp_str][
                            wK] if not resample else None
                    except:
                        sfFit_curr = None

                    # try to load isolated fits...
                    if jointSf > 0:
                        try:  # load non_joint fits as a reference (see hf.dog_fit or S. Sokol thesis for details)
                            modStr = hf.descrMod_name(sfMod)
                            ref_fits = hf.np_smart_load(
                                data_path + hf.descrFit_name(loss_type,
                                                             descrBase=sfName,
                                                             modelName=modStr,
                                                             joint=0))
                            isolFits = ref_fits[cellNum -
                                                1][resp_str][wK]['params']
                            if sfMod == sfModRef:
                                ref_varExpl = ref_fits[
                                    cellNum - 1][resp_str][wK]['varExpl']
                            else:
                                # otherwise, load the DoG
                                vExp_ref_fits = hf.np_smart_load(
                                    data_path + hf.descrFit_name(
                                        loss_type,
                                        descrBase=sfName,
                                        modelName=hf.descrMod_name(sfModRef),
                                        joint=0))
                                ref_varExpl = vExp_ref_fits[
                                    cellNum - 1][resp_str][wK]['varExpl']
                        except:
                            isolFits = None
                            ref_varExpl = None
                    else:
                        isolFits = None
                        ref_varExpl = None

                    allCurr = np.expand_dims(
                        np.transpose(
                            wA, [1, 0, 2]), axis=0) if wA is not None else None
                    # -- by default, loss_type=2 (meaning sqrt loss); why expand dims and transpose? dog fits assumes the data is in [disp,sf,con] and we just have [con,sf]
                    nll, prms, vExp, pSf, cFreq, totNLL, totPrm, success = hf.dog_fit(
                        [
                            np.expand_dims(np.transpose(wR[:, :, 0]),
                                           axis=0), allCurr,
                            np.expand_dims(np.transpose(wR[:, :, 1]), axis=0),
                            baseline
                        ],
                        sfMod,
                        loss_type=2,
                        disp=0,
                        expInd=None,
                        stimVals=stimVals,
                        validByStimVal=None,
                        valConByDisp=valConByDisp,
                        prevFits=sfFit_curr,
                        noDisp=1,
                        fracSig=fracSig,
                        n_repeats=n_repeats,
                        isolFits=isolFits,
                        ref_varExpl=ref_varExpl,
                        veThresh=veThresh,
                        joint=jointSf,
                        ftol=ftol,
                        resp_thresh=resp_thresh
                    )  # noDisp=1 means that we don't index dispersion when accessins prevFits

                    if resample or cross_val is not None:
                        if boot_i == 0:  # i.e. first time around
                            if cross_val is not None:
                                # first, pre-define empty lists for all of the needed results, if they are not yet defined
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_NLL_cv_test'] = np.empty(
                                        (nBoots, ) + nll.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_vExp_cv_test'] = np.empty(
                                        (nBoots, ) + vExp.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_NLL_cv_train'] = np.empty(
                                        (nBoots, ) + nll.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_vExp_cv_train'] = np.empty(
                                        (nBoots, ) + vExp.shape,
                                        dtype=np.float32)
                                # --- these are all implicitly based on training data
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_cv_params'] = np.empty(
                                        (nBoots, ) + prms.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_cv_prefSf'] = np.empty(
                                        (nBoots, ) + pSf.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_cv_charFreq'] = np.empty(
                                        (nBoots, ) + cFreq.shape,
                                        dtype=np.float32)
                            else:  # otherwise, the things we put only if we didn't have cross-validation
                                # - pre-allocate empty array of length nBoots (save time over appending each time around)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_loss'] = np.empty(
                                        (nBoots, ) + nll.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_params'] = np.empty(
                                        (nBoots, ) + prms.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_varExpl'] = np.empty(
                                        (nBoots, ) + vExp.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_prefSf'] = np.empty(
                                        (nBoots, ) + pSf.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_charFreq'] = np.empty(
                                        (nBoots, ) + cFreq.shape,
                                        dtype=np.float32)
                            # and the below apply whether or not we did cross-validation!
                            if jointSf > 0:
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_totalNLL'] = np.empty(
                                        (nBoots, ) + totNLL.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_paramList'] = np.empty(
                                        (nBoots, ) + totPrm.shape,
                                        dtype=np.float32)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_success'] = np.empty((nBoots, ),
                                                               dtype=np.bool_)
                            else:  # only if joint=0 will success be an array (and not just one value)
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_success'] = np.empty(
                                        (nBoots, ) + success.shape,
                                        dtype=np.bool_)

                        # then -- put in place (we reach here for all boot_i)
                        if cross_val is not None:
                            ### then, we need to compute test loss/vExp!
                            test_nlls = np.nan * np.zeros_like(nll)
                            test_vExps = np.nan * np.zeros_like(vExp)
                            # set up ref_params, ref_rc_val; will only be used IF applicable
                            ref_params = None
                            ref_rc_val = None
                            if sfMod == 3:
                                try:
                                    all_xc = prms[:, 1]
                                    # xc
                                    ref_params = [np.nanmin(all_xc), 1]
                                except:
                                    pass
                            else:
                                try:
                                    ref_params = prms[-1]
                                    # high contrast condition
                                    ref_rc_val = totPrm[
                                        2] if jointSf > 0 else None
                                    # even then, only used for jointSf==5
                                except:
                                    pass

                            for ii, prms_curr in enumerate(prms):
                                # we'll iterate over the parameters, which are fit for each contrast (the final dimension of test_mn)
                                if np.any(np.isnan(prms_curr)):
                                    continue
                                non_nans = np.where(~np.isnan(heldout[:, ii,
                                                                      0]))[0]
                                # check -- from the heldout data at contrast ii, which sfs are not NaN
                                curr_sfs = stimVals[2][non_nans]
                                # get those sf values
                                resps_curr = heldout[non_nans, ii, 0]
                                # and get those responses, to pass into DoG_loss
                                test_nlls[ii] = hf.DoG_loss(
                                    prms_curr,
                                    resps_curr,
                                    curr_sfs,
                                    resps_std=None,
                                    loss_type=loss_type,
                                    DoGmodel=sfMod,
                                    dir=dir,
                                    joint=0,
                                    baseline=baseline,
                                    ref_params=ref_params,
                                    ref_rc_val=ref_rc_val
                                )  # why not enforce max? b/c fewer resps means more varied range of max, don't want to wrongfully penalize
                                test_vExps[ii] = hf.var_explained(
                                    resps_curr,
                                    prms_curr,
                                    curr_sfs,
                                    sfMod,
                                    baseline=baseline,
                                    ref_params=ref_params,
                                    ref_rc_val=ref_rc_val)

                            ### done with computing test loss, so save everything
                            sfFits_curr_toSave[resp_str][wK][
                                'boot_NLL_cv_test'][boot_i] = test_nlls
                            sfFits_curr_toSave[resp_str][wK][
                                'boot_vExp_cv_test'][boot_i] = test_vExps
                            sfFits_curr_toSave[resp_str][wK][
                                'boot_NLL_cv_train'][boot_i] = nll
                            sfFits_curr_toSave[resp_str][wK][
                                'boot_vExp_cv_train'][boot_i] = vExp
                            # --- these are all implicitly based on training data
                            sfFits_curr_toSave[resp_str][wK]['boot_cv_params'][
                                boot_i] = prms
                            sfFits_curr_toSave[resp_str][wK]['boot_cv_prefSf'][
                                boot_i] = pSf
                            sfFits_curr_toSave[resp_str][wK][
                                'boot_cv_charFreq'][boot_i] = cFreq
                        else:
                            sfFits_curr_toSave[resp_str][wK]['boot_loss'][
                                boot_i] = nll
                            sfFits_curr_toSave[resp_str][wK]['boot_params'][
                                boot_i] = prms
                            sfFits_curr_toSave[resp_str][wK]['boot_charFreq'][
                                boot_i] = cFreq
                            sfFits_curr_toSave[resp_str][wK]['boot_varExpl'][
                                boot_i] = vExp
                            sfFits_curr_toSave[resp_str][wK]['boot_prefSf'][
                                boot_i] = pSf
                        # these apply regardless of c-v or not
                        sfFits_curr_toSave[resp_str][wK]['boot_success'][
                            boot_i] = success
                        if jointSf > 0:
                            try:
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_totalNLL'][boot_i] = totNLL
                                sfFits_curr_toSave[resp_str][wK][
                                    'boot_paramList'][boot_i] = totPrm
                            except:
                                pass
                    else:  # otherwise, we'll only be here once
                        sfFits_curr_toSave[resp_str][wK]['NLL'] = nll.astype(
                            np.float32)
                        sfFits_curr_toSave[resp_str][wK][
                            'params'] = prms.astype(np.float32)
                        sfFits_curr_toSave[resp_str][wK][
                            'varExpl'] = vExp.astype(np.float32)
                        sfFits_curr_toSave[resp_str][wK][
                            'prefSf'] = pSf.astype(np.float32)
                        sfFits_curr_toSave[resp_str][wK][
                            'charFreq'] = cFreq.astype(np.float32)
                        sfFits_curr_toSave[resp_str][wK][
                            'success'] = success  #.astype(np.bool_);
                        if jointSf > 0:
                            try:
                                sfFits_curr_toSave[resp_str][wK][
                                    'totalNLL'] = totNLL.astype(np.float32)
                            except:
                                sfFits_curr_toSave[resp_str][wK][
                                    'totalNLL'] = totNLL
                                # if it's None, or [], or...
                            try:
                                sfFits_curr_toSave[resp_str][wK][
                                    'paramList'] = totPrm.astype(np.float32)
                            except:
                                sfFits_curr_toSave[resp_str][wK][
                                    'paramList'] = totPrm
                                # if it's None, or [], or...
                ########
                # END of sf fit (for this measure, boot iteration)
                ########

        ########
        # END of measure (i.e. handled both measures, go back for more boot_iter, if specified)
        ########
    ########
    # END of all boot iters (i.e. handled both measures, go back for more boot_iter, if specified)
    ########

    ###########
    # NOW, save (if saving); otherwise, we return the values
    ###########
    # if we are saving, save; otherwise, return the curr_rvc, curr_sf fits
    if toSave:
        if fit_rvc:
            # load fits again in case some other run has saved/made changes
            if os.path.isfile(data_path + rvcNameFinal):
                print('reloading rvcFits...')
                rvcFits = hf.np_smart_load(data_path + rvcNameFinal)
            if cellNum - 1 not in rvcFits:
                rvcFits[cellNum - 1] = dict()

            # now save
            rvcFits[cellNum - 1] = rvcFits_curr_toSave
            np.save(data_path + rvcNameFinal, rvcFits)
            print('Saving %s, %s @ %s' % (resp_str, wK, rvcNameFinal))

        if fit_sf:

            pass_check = False
            while not pass_check:  # keep saving/reloading until the fit has properly saved everything...

                # load fits again in case some other run has saved/made changes
                if os.path.isfile(data_path + sfNameFinal):
                    print('reloading sfFits...')
                    sfFits = hf.np_smart_load(data_path + sfNameFinal)
                if cellNum - 1 not in sfFits:
                    sfFits[cellNum - 1] = dict()

                sfFits[cellNum - 1] = sfFits_curr_toSave

                # now save
                np.save(data_path + sfNameFinal, sfFits)
                print('Saving %s, %s @ %s' % (resp_str, wK, sfNameFinal))

                # now check...
                check = hf.np_smart_load(data_path + sfNameFinal)
                if resample:  # check that the boot stuff is there
                    if 'boot_params' in check[cellNum -
                                              1]['dc']['mask'].keys():
                        pass_check = True
                else:
                    if 'NLL' in check[cellNum - 1]['dc']['mask'].keys(
                    ):  # just check that any relevant key is there
                        pass_check = True
                # --- and if neither pass_check was triggered, then we go back and reload, etc

        ### End of saving (both RVC and SF)
    else:
        return rvcFits_curr_toSave, sfFits_curr_toSave
Esempio n. 28
0
def fit_descr_DoG(cell_num,
                  data_loc=dataPath,
                  n_repeats=1000,
                  loss_type=3,
                  DoGmodel=1,
                  disp=0,
                  rvcName=rvcName,
                  dir=-1,
                  gain_reg=0,
                  fLname=dogName):

    nParam = 4

    # load cell information
    dataList = hf.np_smart_load(data_loc + 'dataList.npy')
    assert dataList != [], "data file not found!"

    if loss_type == 1:
        loss_str = '_poiss'
    elif loss_type == 2:
        loss_str = '_sqrt'
    elif loss_type == 3:
        loss_str = '_sach'
    elif loss_type == 4:
        loss_str = '_varExpl'
    if DoGmodel == 1:
        mod_str = '_sach'
    elif DoGmodel == 2:
        mod_str = '_tony'
    fLname = str(data_loc + fLname + loss_str + mod_str + '.npy')
    if os.path.isfile(fLname):
        descrFits = hf.np_smart_load(fLname)
    else:
        descrFits = dict()

    cellStruct = hf.np_smart_load(data_loc +
                                  dataList['unitName'][cell_num - 1] +
                                  '_sfm.npy')
    data = cellStruct['sfm']['exp']['trial']
    rvcNameFinal = hf.phase_fit_name(rvcName, dir)
    rvcFits = hf.np_smart_load(data_loc + rvcNameFinal)
    adjResps = rvcFits[cell_num - 1][disp]['adjMeans']
    adjSem = rvcFits[cell_num - 1][disp]['adjSem']
    if 'adjByTr' in rvcFits[cell_num - 1][disp]:
        adjByTr = rvcFits[cell_num - 1][disp]['adjByTr']
    if disp == 1:
        adjResps = [np.sum(x, 1) if x else [] for x in adjResps]
        if adjByTr:
            adjByTr = [np.sum(x, 1) if x else [] for x in adjByTr]
    adjResps = np.array(adjResps)
    # indexing multiple SFs will work only if we convert to numpy array first
    adjSem = np.array([np.array(x) for x in adjSem])
    # make each inner list an array, and the whole thing an array

    print('Doing the work, now')

    # first, get the set of stimulus values:
    resps, stimVals, valConByDisp, _, _ = hf.tabulate_responses(data,
                                                                expInd=expInd)
    # LGN is expInd=3
    all_disps = stimVals[0]
    all_cons = stimVals[1]
    all_sfs = stimVals[2]

    nDisps = len(all_disps)
    nCons = len(all_cons)

    if cell_num - 1 in descrFits:
        bestNLL = descrFits[cell_num - 1]['NLL']
        currParams = descrFits[cell_num - 1]['params']
        varExpl = descrFits[cell_num - 1]['varExpl']
        prefSf = descrFits[cell_num - 1]['prefSf']
        charFreq = descrFits[cell_num - 1]['charFreq']
    else:  # set values to NaN...
        bestNLL = np.ones((nDisps, nCons)) * np.nan
        currParams = np.ones((nDisps, nCons, nParam)) * np.nan
        varExpl = np.ones((nDisps, nCons)) * np.nan
        prefSf = np.ones((nDisps, nCons)) * np.nan
        charFreq = np.ones((nDisps, nCons)) * np.nan

    # set bounds
    if DoGmodel == 1:
        bound_gainCent = (1e-3, None)
        bound_radiusCent = (1e-3, None)
        bound_gainSurr = (1e-3, None)
        bound_radiusSurr = (1e-3, None)
        allBounds = (bound_gainCent, bound_radiusCent, bound_gainSurr,
                     bound_radiusSurr)
    elif DoGmodel == 2:
        bound_gainCent = (1e-3, None)
        bound_gainFracSurr = (1e-2, 1)
        bound_freqCent = (1e-3, None)
        bound_freqFracSurr = (1e-2, 1)
        allBounds = (bound_gainCent, bound_freqCent, bound_gainFracSurr,
                     bound_freqFracSurr)

    for d in range(
            1
    ):  # should be nDisps - just setting to 1 for now (i.e. fitting single gratings and mixtures separately)
        for con in range(nCons):
            if con not in valConByDisp[disp]:
                continue

            valSfInds = hf.get_valid_sfs(data, disp, con, expInd)
            valSfVals = all_sfs[valSfInds]

            print('.')
            # adjResponses (f1) in the rvcFits are separate by sf, values within contrast - so to get all responses for a given SF,
            # access all sfs and get the specific contrast response
            respConInd = np.where(np.asarray(valConByDisp[disp]) == con)[0]
            pdb.set_trace()
            ### interlude...
            spks = hf.get_spikes(data,
                                 rvcFits=rvcFits[cell_num - 1],
                                 expInd=expInd)
            _, _, mnResp, alResp = hf.organize_resp(spks, data, expInd)
            ###
            resps = flatten([x[respConInd] for x in adjResps[valSfInds]])
            resps_sem = [x[respConInd] for x in adjSem[valSfInds]]
            if isinstance(resps_sem[0],
                          np.ndarray):  # i.e. if it's still array of arrays...
                resps_sem = flatten(resps_sem)
            #resps_sem = None;
            maxResp = np.max(resps)
            freqAtMaxResp = all_sfs[np.argmax(resps)]

            for n_try in range(n_repeats):
                # pick initial params
                if DoGmodel == 1:
                    init_gainCent = hf.random_in_range(
                        (maxResp, 5 * maxResp))[0]
                    init_radiusCent = hf.random_in_range((0.05, 2))[0]
                    init_gainSurr = init_gainCent * hf.random_in_range(
                        (0.1, 0.8))[0]
                    init_radiusSurr = hf.random_in_range((0.5, 4))[0]
                    init_params = [
                        init_gainCent, init_radiusCent, init_gainSurr,
                        init_radiusSurr
                    ]
                elif DoGmodel == 2:
                    init_gainCent = maxResp * hf.random_in_range((0.9, 1.2))[0]
                    init_freqCent = np.maximum(
                        all_sfs[2],
                        freqAtMaxResp * hf.random_in_range((1.2, 1.5))[0])
                    # don't pick all_sfs[0] -- that's zero (we're avoiding that)
                    init_gainFracSurr = hf.random_in_range((0.7, 1))[0]
                    init_freqFracSurr = hf.random_in_range((.25, .35))[0]
                    init_params = [
                        init_gainCent, init_freqCent, init_gainFracSurr,
                        init_freqFracSurr
                    ]

                # choose optimization method
                if np.mod(n_try, 2) == 0:
                    methodStr = 'L-BFGS-B'
                else:
                    methodStr = 'TNC'

                obj = lambda params: DoG_loss(params,
                                              resps,
                                              valSfVals,
                                              resps_std=resps_sem,
                                              loss_type=loss_type,
                                              DoGmodel=DoGmodel,
                                              dir=dir,
                                              gain_reg=gain_reg)
                wax = opt.minimize(obj,
                                   init_params,
                                   method=methodStr,
                                   bounds=allBounds)

                # compare
                NLL = wax['fun']
                params = wax['x']

                if np.isnan(bestNLL[disp, con]) or NLL < bestNLL[disp, con]:
                    bestNLL[disp, con] = NLL
                    currParams[disp, con, :] = params
                    varExpl[disp,
                            con] = hf.var_explained(resps, params, valSfVals)
                    prefSf[disp, con] = hf.dog_prefSf(params, DoGmodel,
                                                      valSfVals)
                    charFreq[disp, con] = hf.dog_charFreq(params, DoGmodel)

        # update stuff - load again in case some other run has saved/made changes
        if os.path.isfile(fLname):
            print('reloading descrFits...')
            descrFits = hf.np_smart_load(fLname)
        if cell_num - 1 not in descrFits:
            descrFits[cell_num - 1] = dict()
        descrFits[cell_num - 1]['NLL'] = bestNLL
        descrFits[cell_num - 1]['params'] = currParams
        descrFits[cell_num - 1]['varExpl'] = varExpl
        descrFits[cell_num - 1]['prefSf'] = prefSf
        descrFits[cell_num - 1]['charFreq'] = charFreq
        descrFits[cell_num - 1]['gainRegFactor'] = gain_reg

        np.save(fLname, descrFits)
        print('saving for cell ' + str(cell_num))
Esempio n. 29
0
def setModel(cellNum, stopThresh, lr, lossType = 1, fitType = 1, subset_frac = 1, initFromCurr = 1, holdOutCondition = None):
    # Given just a cell number, will fit the Robbe-inspired V1 model to the data
    #
    # stopThresh is the value (in NLL) at which we stop the fitting (i.e. if the difference in NLL between two full steps is < stopThresh, stop the fitting
    #
    # LR is learning rate
    #
    # lossType
    #   1 - loss := square(sqrt(resp) - sqrt(pred))
    #   2 - loss := poissonProb(spikes | modelRate)
    #   3 - loss := modPoiss model (a la Goris, 2014)
    #
    # fitType - what is the model formulation?
    #   1 := flat normalization
    #   2 := gaussian-weighted normalization responses
    #   3 := gaussian-weighted c50/norm "constant"
    #
    # holdOutCondition - [d, c, sf] or None
    #   which condition should we hold out from the dataset
 
    ########
    # Load cell
    ########
    #loc_data = '/Users/paulgerald/work/sfDiversity/sfDiv-OriModel/sfDiv-python/Analysis/Structures/'; # personal mac
    loc_data = '/home/pl1465/SF_diversity/Analysis/Structures/'; # Prince cluster 

    # fitType
    if fitType == 1:
      fL_suffix1 = '_flat';
    elif fitType == 2:
      fL_suffix1 = '_wght';
    elif fitType == 3:
      fL_suffix1 = '_c50';
    # lossType
    if lossType == 1:
      fL_suffix2 = '_sqrt.npy';
    elif lossType == 2:
      fL_suffix2 = '_poiss.npy';
    elif lossType == 3:
      fL_suffix2 = '_modPoiss.npy';

    dataList = hf.np_smart_load(str(loc_data + 'dataList.npy'));
    dataNames = dataList['unitName'];

    print('loading data structure...');
    S = hf.np_smart_load(str(loc_data + dataNames[cellNum-1] + '_sfm.npy')); # why -1? 0 indexing...
    print('...finished loading');
    trial_inf = S['sfm']['exp']['trial'];
    prefOrEst = mode(trial_inf['ori'][1]).mode;
    trialsToCheck = trial_inf['con'][0] == 0.01;
    prefSfEst = mode(trial_inf['sf'][0][trialsToCheck==True]).mode;
    
    ########

    # 00 = preferred spatial frequency   (cycles per degree)
    # 01 = derivative order in space
    # 02 = normalization constant        (log10 basis)
    # 03 = response exponent
    # 04 = response scalar
    # 05 = early additive noise
    # 06 = late additive noise
    # 07 = variance of response gain - only used if lossType = 3
    # if fitType == 2
    # 08 = mean of (log)gaussian for normalization weights
    # 09 = std of (log)gaussian for normalization weights
    # if fitType == 3
    # 08 = the offset of the c50 tuning curve which is bounded between [v_sigOffset, 1] || [0, 1]
    # 09 = standard deviation of the gaussian to the left of the peak || >0.1
    # 10 = "" to the right "" || >0.1
    # 11 = peak of offset curve
    
    curr_params = [];
    initFromCurr = 0; # override initFromCurr so that we just go with default parameters

    if np.any(np.isnan(curr_params)): # if there are nans, we need to ignore...
      curr_params = [];
      initFromCurr = 0;

    pref_sf = float(prefSfEst) if initFromCurr==0 else curr_params[0];
    dOrdSp = np.random.uniform(1, 3) if initFromCurr==0 else curr_params[1];
    normConst = -0.8 if initFromCurr==0 else curr_params[2]; # why -0.8? Talked with Tony, he suggests starting with lower sigma rather than higher/non-saturating one
    #normConst = np.random.uniform(-1, 0) if initFromCurr==0 else curr_params[2];
    respExp = np.random.uniform(1, 3) if initFromCurr==0 else curr_params[3];
    respScalar = np.random.uniform(10, 1000) if initFromCurr==0 else curr_params[4];
    noiseEarly = np.random.uniform(0.001, 0.1) if initFromCurr==0 else curr_params[5];
    noiseLate = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[6];
    varGain = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[7];
    if fitType == 1:
      inhAsym = 0; 
    if fitType == 2:
      normMean = np.random.uniform(-1, 1) if initFromCurr==0 else curr_params[8];
      normStd = np.random.uniform(0.1, 1) if initFromCurr==0 else curr_params[9];
    if fitType == 3:
      sigOffset = np.random.uniform(0, 0.05) if initFromCurr==0 else curr_params[8];
      stdLeft = np.random.uniform(1, 5) if initFromCurr==0 else curr_params[9];
      stdRight = np.random.uniform(1, 5) if initFromCurr==0 else curr_params[10];
      sigPeak = float(prefSfEst) if initFromCurr==0 else curr_params[11];

    print('Initial parameters:\n\tsf: ' + str(pref_sf)  + '\n\td.ord: ' + str(dOrdSp) + '\n\tnormConst: ' + str(normConst));
    print('\n\trespExp ' + str(respExp) + '\n\trespScalar ' + str(respScalar));
    
    #########
    # Now get all the data we need
    #########    
    # stimulus information
    
    # vstack to turn into array (not array of arrays!)
    stimOr = np.vstack(trial_inf['ori']);

    #purge of NaNs...
    mask = np.isnan(np.sum(stimOr, 0)); # sum over all stim components...if there are any nans in that trial, we know
    objWeight = np.ones((stimOr.shape[1]));    

    # and get rid of orientation tuning curve trials
    oriBlockIDs = np.hstack((np.arange(131, 155+1, 2), np.arange(132, 136+1, 2))); # +1 to include endpoint like Matlab

    oriInds = np.empty((0,));
    for iB in oriBlockIDs:
        indCond = np.where(trial_inf['blockID'] == iB);
        if len(indCond[0]) > 0:
            oriInds = np.append(oriInds, indCond);

    # get rid of CRF trials, too? Not yet...
    conBlockIDs = np.arange(138, 156+1, 2);
    conInds = np.empty((0,));
    for iB in conBlockIDs:
       indCond = np.where(trial_inf['blockID'] == iB);
       if len(indCond[0]) > 0:
           conInds = np.append(conInds, indCond);

    objWeight[conInds.astype(np.int64)] = 1; # for now, yes it's a "magic number"    

    mask[oriInds.astype(np.int64)] = True; # as in, don't include those trials either!
    # hold out a condition if we have specified, and adjust the mask accordingly
    if holdOutCondition is not None:
      # dispInd: [1, 5]...conInd: [1, 2]...sfInd: [1, 11]
      # first, get all of the conditions... - blockIDs by condition known from Robbe code
      dispInd = holdOutCondition[0];
      conInd = holdOutCondition[1];
      sfInd = holdOutCondition[2];

      StimBlockIDs  = np.arange(((dispInd-1)*(13*2)+1)+(conInd-1), ((dispInd)*(13*2)-5)+(conInd-1)+1, 2); # +1 to include the last block ID
      currBlockID = StimBlockIDs[sfInd-1];
      holdOutTr = np.where(trial_inf['blockID'] == currBlockID)[0];
      mask[holdOutTr.astype(np.int64)] = True; # as in, don't include those trials either!
      
    # Set up model here - get the parameters and parameter bounds
    if fitType == 1:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, inhAsym);
    elif fitType == 2:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, normMean, normStd);
    elif fitType == 3:
      param_list = (pref_sf, dOrdSp, normConst, respExp, respScalar, noiseEarly, noiseLate, varGain, sigOffset, stdLeft, stdRight, sigPeak);
    all_bounds = hf.getConstraints(fitType);
   
    # now set up the optimization
    obj = lambda params: mod_resp.SFMGiveBof(params, structureSFM=S, normType=fitType, lossType=lossType, maskIn=~mask)[0];
    tomin = opt.minimize(obj, param_list, bounds=all_bounds);

    opt_params = tomin['x'];
    NLL = tomin['fun'];

    if holdOutCondition is not None:
      holdoutNLL, _, = mod_resp.SFMGiveBof(opt_params, structureSFM=S, normType=fitType, lossType=lossType, trialSubset=holdOutTr);
    else:
      holdoutNLL = [];

    return NLL, opt_params, holdoutNLL;
Esempio n. 30
0
nFam = 5
nCon = 2
plotSteps = 100
# how many steps for plotting descriptive functions?
sfPlot = np.logspace(-1, 1, plotSteps)

# for bandwidth/prefSf descriptive stuff
muLoc = 2
# mu is in location '2' of parameter arrays
height = 1 / 2.
# measure BW at half-height
sf_range = [0.01, 10]
# allowed values of 'mu' for fits - see descr_fit.py for details

dL = np_smart_load(data_loc + expName)
fitList_fl = np_smart_load(data_loc + fitName_fl)
fitList_wg = np_smart_load(data_loc + fitName_wg)
descrExpFits = np_smart_load(data_loc + descrExpName)
descrModFits = np_smart_load(data_loc + descrModName)

# #### Load data

expData = np_smart_load(
    str(data_loc + dL['unitName'][cellNum - 1] + '_sfm.npy'))
expResp = expData

modFit_fl = fitList_fl[cellNum - 1]['params']
#
modFit_wg = fitList_wg[cellNum - 1]['params']
#