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;
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)
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);
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));
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
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:
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))
#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:
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
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)
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
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', '')
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;
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;
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;
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
#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:
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()
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
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()
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);
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))
# '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)
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]
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
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
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
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))
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;
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'] #