def chooseplot(self, plot_range): ''' switch for single (A1), sequential (B1), ... # multi_groups suite.single userpars multigroup_in_components userlocals # A1 False True False False False * # A20 True True False False False # A21 True True True True False * # B1 False False False False False # B20 True False False False False does not exist # B21 True False True True False # C1 False False True False True * # C2 True False True True True * ''' from mujpy.aux.aux import multigroup_in_components, userpars, userlocals if self.suite.single(): # A1, A20, A21 if self.suite.multi_groups(): # A20 A21 self.suite.console( 'Multigroup fit animation: toggle pause/resume by clicking on the plot' ) if sum(multigroup_in_components(self.dashboard)): # A21 ok = self.plot_singlerun_multigroup_userpar(plot_range) else: # A20 ok = self.plot_singlerun_multigroup_sequential(plot_range) else: # A1 ok = self.plot_singlerun(plot_range) else: # B1, B2, C1, C2, no calib in this lot self.suite.console( 'Multirun fit animation: toggle pause/resume by clicking on the plot' ) if self.suite.multi_groups(): # B2, C2 self.suite.console( 'No B2, C2 yet. Exiting mufitplot without a plot') if userlocals(self.dashboard): # C2 pass else: # B2 (means B21 group global, B20 group sequential does not exist) pass else: # B1, C1 if userpars(self.dashboard): # C1 self.suite.console( 'No B2, C2 yet. Exiting mufitplot without a plot') pass else: # B1 ok = self.plot_multirun_singlegroup_sequential(plot_range) if not ok: self.suite.console('Exiting mufitplot without a plot')
def single_chi(self): ''' output: True if chi_1 is required (single cost function) False if chi_2 is required (multi cost finctions) ''' # multi_groups suite.single userpars multigroup_in_components userlocals # A1 False True False False False * # A20 True True False False False # A21 True True True True False * # B1 False False False False False # B20 True False False False False # B21 True False True True False # C1 False False True False True * # C2 True False True True True * # True : A1 1d, A21 2d multigroup userpar, C1 2d userpar, C2 3d multgrup userpar # False: B1 2d, A20, B20 2d multigroup, B21 2d multigroup userpar from mujpy.aux.aux import userlocals, userpars return (userlocals(self.dashboard) or (self.suite.single() and (not self.multigroup or userpars(self.dashboard))))
def plot_fft(self, fft_range, pars, asymm, asyme, real): ''' input: fft_range start,stop,sigma MHz pars list (single, calib) or list of lists (sequence) asymm, asyme 1d (single, calib) or 2d (sequence) uses data as dictated by self.dashboard["fit_range"] calls either self.chi_fft (only for model function) set_single_fft or set_sequence_fft, from aux.plot first version single only (produces actual figures using aux.plot functions) ''' from mujpy.aux.aux import derange, rebin, autops, ps from mujpy.aux.aux import get_run_title, userpars from mujpy.aux.plot import set_figure_fft from copy import deepcopy from numpy import ones, exp, linspace, sqrt, mean, fft from numpy import hstack, linspace, zeros, mgrid # print('plot_fft muplotfit debug: pars = {}'.format(pars)) run_title = get_run_title(self.suite) # always a list, even for single string = 'global ' if userpars(self.dashboard) else '' if len(self.suite.groups) > 1: strgrps = [ groups['forward'] + '-' + groups['backward'] for groups in self.suite.groups ] else: strgrps = self.suite.groups['forward'] + '-' + self.suite.groups[ 'backward'] if self.guess: if len(run_title) == len(self.suite.groups): run_title = [ runtitle + " (" + string + "guess) group" + strgrp for runtitle, strgrp in zip(run_title, strgrps) ] else: run_title = [ runtitle + " (" + string + "guess)" for runtitle in run_title ] else: if len(run_title) == len(self.suite.groups): run_title = [ runtitle + " (" + string + "fit) group" + strgrp for runtitle, strgrp in zip(run_title, strgrps) ] else: run_title = [ runtitle + " (" + string + "fit)" for runtitle in run_title ] ############################# # rebinning of data as in fit # this works for single # and for sequential ############################# fittup = derange(self.dashboard["fit_range"], self.suite.histoLength) # range as tuple fit_pack = 1 if len(fittup) == 3: # plot start stop pack fit_start, fit_stop, fit_pack = fittup[0], fittup[1], fittup[2] elif len(fittup) == 2: # plot start stop fit_start, fit_stop = fittup[0], fittup[1] t_fit, y_fit, ey_fit = rebin(self.suite.time, asymm, [fit_start, fit_stop], fit_pack, e=asyme) f_fit_res, f_fit = self.chi_fft( t_fit, y_fit, *pars) # returns both partial and full model fgroup = [ self.suite.groups[k]['forward'] for k in range(len(self.suite.groups)) ] bgroup = [ self.suite.groups[k]['backward'] for k in range(len(self.suite.groups)) ] alpha = [ self.suite.groups[k]['alpha'] for k in range(len(self.suite.groups)) ] group = [fgroup, bgroup, alpha] dt = t_fit[1] - t_fit[0] # time bin fmax = 0.5 / dt # max frequancy available l = (fit_stop - fit_start) // fit_pack # floor division, dimension of data df = 1 / (dt * l) n = 2 * l # not a power of 2, but surely even nf = hstack((linspace(0, l, l + 1, dtype=int), linspace(-l + 1, -1, l - 2, dtype=int))) dfa = 1 / n / dt # digital frequency resolution f = nf * dfa # all frequencies, l+1 >=0 followed by l-1 <0 fstart, fstop, fsigma = float(fft_range[0]), float( fft_range[1]), float(fft_range[2]) start, stop = int(round(fstart / dfa)), int(round(fstop / dfa)) f = deepcopy(f[start:stop]) # selected slice # asymmetry has 1,2,3 dimensions to distinguish run from group # here they are on same par: the data are reshaped into a 2 d array if len(asymm.shape) == 1: y = zeros(n) # for data zero padded to n yf = zeros(n) # fit function for rephasing, zero padded to n ey = zeros(n) y[0:l] = y_fit[ fit_start:fit_stop] - f_fit_res # zero padded partial residues yf[0:l] = f_fit ey[0:l] = ey_fit[fit_start:fit_stop] # slice of time stds t = dt * linspace(0, n - 1, n) elif len(asymm.shape) == 2: # print('mufitplot plot_fft debug: nruns/ngroups {}, nbins {}'.format(asymm.shape[0],y_fit.shape[-1])) y = zeros((y_fit.shape[0], n)) # for data zero padded to n yf = zeros((y_fit.shape[0], n)) # fit function for rephasing, zero padded to n ey = zeros((ey_fit.shape[0], n)) # print('mufitplot plot_fft debug: shapes y {}, asymm {}, f_fit_res {}'.format(y[:,0:l].shape,y_fit[:,fit_start:fit_stop].shape,f_fit_res.shape)) y[:, 0: l] = y_fit[:, fit_start: fit_stop] - f_fit_res # zero padded partial residues yf[:, 0:l] = f_fit ey[:, 0:l] = ey_fit[:, fit_start:fit_stop] # slice of time stds _, t = dt * mgrid[0:asymm.shape[0], 0:n] else: # 3 is reshaped to 2d nruns, ngroups = asymm.shape[0], asymm.shape[1] y = zeros((nruns * ngroups, n)) # for data zero padded to n yf = zeros((nruns * ngroups, n)) # fit function for rephasing, zero padded to n ey = zeros((nruns * ngroups, n)) y[:, :, 0: l] = y_fit[:, :, fit_start: fit_stop] - f_fit_res # zero padded partial residues yf[:, :, 0:l] = f_fit # zero padded full fit function ey[:, :, 0:l] = ey_fit[:, :, fit_start:fit_stop] # slice of time stds y = y.reshape(nruns * ngroups, n) # reshaped to 2d yf = yf.reshape(nruns * ngroups, n) # reshaped to 2d ey = ey.reshape(nruns * ngroups, n) # reshaped to 2d _, t = dt * mgrid[0:nruns * ngroups, 0:n] # time for zero padded data # print('mufitplot plot_fft debug: t.min t.max = {},{}'.format(t.min(),t.max())) filter_apo = exp(-(t * fsigma)**3) # hypergaussian filter mask # is applied as if first good bin were t=0 filter_apo = filter_apo / filter_apo.sum( axis=1)[0] / dt # approx normalization dfa = 1 / n / dt # digital frequency resolution y *= filter_apo # zero padded, filtered partial residues yf *= filter_apo # zero padded, filtered full fit function ey *= filter_apo # filteres fft_e = ( sqrt(mean(fft.fft(ey)**2, axis=-1)) ).real #.reshape(ey.shape[0],1)*ones(y.shape) # one per asymmetry fft_amplitude = fft.fft( y) # amplitudes (complex), matrix with rows fft of each run fftf_amplitude = fft.fft( yf) # amplitudes (complex), same for fit function if real: ######################## # REAL PART # APPLY PHASE CORRECTION # try acme ######################## if len(y_fit.shape) == 1: fftf_amplitude[start:stop], p0, p1, out = autops( fftf_amplitude[start:stop], 'acme') # fix phase on theory out = out[:out.index('\n')] self.suite.console('Autophase: ' + out) fft_amplitude[start:stop] = ps(fft_amplitude[start:stop], p0=p0, p1=p1).real ap = deepcopy(fft_amplitude[start:stop].real) apf = deepcopy(fftf_amplitude[start:stop].real) else: for k in range(fftf_amplitude.shape[0]): fftf_amplitude[k, start:stop], p0, p1, out = autops( fftf_amplitude[k, start:stop], 'acme') # fix phase on theory out = out[:out.index('\n')] self.suite.console('Autophase {}: '.format(k) + out) # fft_amplitude[k,start:stop], p0, p1, out = autops(fft_amplitude[k,start:stop],'acme') # fix phase on theory fft_amplitude[k, start:stop] = ps( fft_amplitude[k, start:stop], p0=p0, p1=p1).real # same correction as theory ap = deepcopy(fft_amplitude[:, start:stop].real) apf = deepcopy(fftf_amplitude[:, start:stop].real) ylabel = 'FFT Real part [arb. units]' else: ################## # POWER ################## if len(asymm.shape) == 1: ap = fft_amplitude.real[start:stop]**2 + fft_amplitude.imag[ start:stop]**2 apf = fftf_amplitude.real[start:stop]**2 + fftf_amplitude.imag[ start:stop]**2 else: ap = fft_amplitude.real[:, start: stop]**2 + fft_amplitude.imag[:, start: stop]**2 apf = fftf_amplitude.real[:, start: stop]**2 + fftf_amplitude.imag[:, start: stop]**2 ylabel = 'FFT Power [arb. units]' self.fig_fft = set_figure_fft(self.fig_fft, self.model_name(), ylabel, f, ap, apf, fft_e, group, run_title)
def choosefftplot(self, fft_range, real): ''' distinguishes single-multi run single-multi group sequential-global ''' from mujpy.aux.aux import multigroup_in_components, userlocals from mujpy.aux.aux import get_nruns, int2min, int2min_multigroup from numpy import array # single - multi run sequential A1 B1 both produce list of pars # single - multi group sequential A1 A20 both produce list of pars # multi run sequential multi group global B2 produces list of pars # multi group global A21 produces par # multi run global C1 produces par # multi run multi group global C2 produces par if self.suite.single(): if self.suite.multi_groups(): # A2 # print('mufitplot choosefftplot debug: A2') self.suite.console( 'Multigroup fft animation: toggle pause/resume by clicking on the plot' ) if sum(multigroup_in_components( self.dashboard)): # A21 single chi2 userpars = "userpardicts_guess" if self.guess else "userpardicts_results" pardicts = self.dashboard[userpars] pars, _, _, _, _ = int2min_multigroup(pardicts) # ok = self.single_fft_plot_multi_global(fft_range,pars,real) else: # A20 as many chi2 as groups now results are saved in single group dashboards if self.model == "model_result": pars = [ array(lastfit.values) for lastfit in self.lastfits ] # print('mufitplot choosefftplot debug: A20 fit pars = {}'.format(pars)) else: par, _, _, _, _ = int2min(self.dashboard[self.model]) pars = [ array(par) for k in range(len(self.suite.groups)) ] # print('mufitplot choosefftplot debug: A20 guess pars = {}'.format(pars)) # ok = self.single_fft_plot_multi_sequential(fft_range,pars,real) asymm, asyme = self.suite.asymmetry_multigroup() else: # A1 simple single plot pars, _, _, _, _ = int2min(self.dashboard[self.model]) # ok = self.single_fft_plot(fft_range,pars,real) asymm, asyme = self.suite.asymmetry_single( self.suite._the_runs_[0], 0) else: if userpars(self.dashboard): if not self.suite.multi_groups( ): # C1, userpardicts no multigroup self.suite.console( 'Multirun fft animation: toggle pause/resume by clicking on the plot' ) pass # not yet else: self.suite.console( 'Multi group and run fft animation: toggle pause/resume by clicking on the plot' ) if userlocals(self.dashboard): # C2 pass # not yet else: # B21 userpardicts, multigroup_in_components no tilde_incomponents pars = [] # not yet # for run in get_nruns(self.suite): # par = # pars.append(par) else: pars = [] if self.suite.multi_groups(): for run in get_nruns(self.suite): # B1 no multigroup for group in self.suite.groups: # or B20 no userpardicts multigroup par, _, _, _, _ = int2min( self.dashboard[self.model]) pars.append(par) asymm, asyme = self.suite.asymmetry_multirun_multigroup( ) else: for run in get_nruns(self.suite): # B1 no multigroup par, _, _, _, _ = int2min(self.dashboard[self.model]) pars.append(par) asymm, asyme = self.suite.asymmetry_multirun(0) # ok = self.sequential_fft_plot(fft_rangepars,real) # print('mufitplot choosefftplot debug: pars = {}'.format(pars)) self.plot_fft(fft_range, pars, asymm, asyme, real)
def plot_run(self, plot_range, pars, asymm, asyme): ''' input : plot_range (start,stop) (start,stop,pack) (start_early,stop_early,pack_early,stop_late,pack_late) pars list (single, calib) or list of lists (sequence) asymm, asyme 1d (single, calib) or 2d (sequence) calls either self.chi_1 or self.chi_2 (stats and model function, deals also with plotting model function) set_single_fit or set_sequence_fit, from aux.plot (produces actual figures) Draws either static or anim figures using aux.plot functions ''' from mujpy.aux.aux import derange, rebin, multigroup_in_components from mujpy.aux.aux import get_run_title, userpars, mixer from mujpy.aux.plot import set_single_fit, set_sequence_fit from iminuit import Minuit from numpy import ones # print('plot_run muplotfit debug: pars = {}'.format(pars)) # chi_1: single chisquare, different asymm.shape, # chi_2: many chisquare, different asymm.shape, chi = self.chi_1 if self.single_chi() else self.chi_2 # print('plot_run mufitplot debug: single chi is {}'.format(self.single_chi())) run_title = get_run_title(self.suite) # always a list, even for single string = 'global ' if userpars(self.dashboard) else '' if self.guess: run_title = [ title + ": " + string + "guess values" for title in run_title ] else: run_title = [ title + ": " + string + "fit results" for title in run_title ] plottup = derange(plot_range, self.suite.histoLength) ############################# # rebinning of data as in fit # this works for single # and for sequential ############################# fittup = derange(self.dashboard["fit_range"], self.suite.histoLength) # range as tuple fit_pack = 1 if len(fittup) == 3: # plot start stop pack fit_start, fit_stop, fit_pack = fittup[0], fittup[1], fittup[2] elif len(fittup) == 2: # plot start stop fit_start, fit_stop = fittup[0], fittup[1] # load modules and reproduce fit t_fit, y_fit, ey_fit = rebin(self.suite.time, asymm, [fit_start, fit_stop], fit_pack, e=asyme) # single slices as in fit # print('muplotfit plot_run debug: calling chi for f_fit') nu_fit, f_fit, chi_fit = chi(t_fit, y_fit, ey_fit, pars) if self.rotating_frame_frequencyMHz: # (t_fit,y_fit,f_fit,ey_fit) the last three must be transformed to rrf _, y_fit, ey_fit = rebin(self.suite.time, self.rrf_asymm, [fit_start, fit_stop], fit_pack, e=self.rrf_asyme) f_fit = mixer(t_fit, f_fit, self.rotating_frame_frequencyMHz) if not nu_fit: return False # function as in fit if len(plottup) == 5: ################### # double range plot ################### early_late = True start, stop, pack, last, packlate = plottup t_late, y_late, ey_late = rebin(self.suite.time, asymm, [stop, last], packlate, e=asyme) # rebinned late slices packfit = int(packlate / 2) tfl, dum = rebin(self.suite.time, asymm, [stop, last], packfit) # late time slice for function # tfl,fl for late plot curve _, f_late_res, _ = chi( t_late, None, None, pars) # for f_late_res calculating residues (on data points) _, fl, _ = chi(tfl, None, None, pars) # t_late,fls for plotting residues if self.rotating_frame_frequencyMHz: # (t_late,y_late,f_late_res,ey_late) the last three must be transformed to rrf # (tfl,fl) non rebinned, the last must be transformed to rrf _, y_late, ey_late = rebin(self.suite.time, self.rrf_asymm, [start, stop], packlate, e=self.rrf_asyme) f_late_res = mixer(t_late, f_late_res, self.rotating_frame_frequencyMHz) fl = mixer(tfl, fl, self.rotating_frame_frequencyMHz) fit_late_start = int( stop / packlate * fit_pack) # divides fit_range in early and late # redo the same with the original fit binning fit_pack, only for histo and chi2 t_fit_late, y_fit_late, ey_fit_late = rebin( self.suite.time, asymm, [fit_late_start, fit_stop], fit_pack, e=asyme) # no rotating frame version for this! nu_fit_late, f_fit_late, chi_fit_late = chi( t_fit_late, y_fit_late, ey_fit_late, pars) if self.rotating_frame_frequencyMHz: # (t_fit_late,y_fit_late,f_fit_late,ey_fit_late) the last three must be transformed to rrf _, y_fit_late, ey_fit_late = rebin(self.suite.time, self.rrf_asymm, [fit_start, fit_late_start], fit_pack, e=self.rrf_asyme) f_fit_late = mixer(t_fit_late, f_fit_late, self.rotating_frame_frequencyMHz) # print('mufitplot plot_run debug: y_fit_late ey_fit_late f_fit_late shape = {}, {}, {}'.format(y_fit_late.shape, ey_fit_late.shape, f_fit_late.shape)) if not nu_fit_late: return False # function as in fit t_fit_early, y_fit_early, ey_fit_early = rebin( self.suite.time, asymm, [fit_start, fit_late_start], fit_pack, e=asyme) # single slices as in fit nu_fit_early, f_fit_early, chi_fit_early = chi( t_fit_early, y_fit_early, ey_fit_early, pars) if self.rotating_frame_frequencyMHz: _, y_fit_early, ey_fit_early = rebin( self.suite.time, self.rrf_asymm, [fit_start, fit_late_start], fit_pack, e=self.rrf_asyme) f_fit_early = mixer(t_fit_early, f_fit_early, self.rotating_frame_frequencyMHz) if not nu_fit_early: return False # function as in fit else: ################### # single range plot ################### early_late = False pack = 1 chi_fit_late, nu_fit_late, chi_fit_early, nu_fit_early = None, None, None, None if len(plottup) == 3: # plot start stop pack start, stop, pack = plottup elif len(plottup) == 2: # plot start stop start, stop = plottup # self.suite.console('plot_range= {}'.format(plot_range)) # self.suite.console('start, stop, pack = {},{},{}'.format(start, stop, pack)) t, y, ey = rebin(self.suite.time, asymm, [start, stop], pack, e=asyme) # rebinned single or early slices # print('muplotfit plot_run debug: calling chi for f_res') nudum, f_res, _ = chi(t, None, None, pars) packfit = int(pack / 2) tf, dum = rebin(self.suite.time, asymm, [start, stop], packfit) # single or early time slice for plot function # print('muplotfit plot_run debug: calling chi for f (None)') _, f, _ = chi(tf, None, None, pars) # print('mufitplot plot_run debug: min max f_res {}, min max f {}'.format([f_res.min(),f_res.max()],[f.min(),f.max()])) if self.rotating_frame_frequencyMHz: # (t,y,f_res,ey) the last three must be transformed to rrf # (tf,f) non rebinned, the last must be transformed to rrf _, y, ey = rebin(self.suite.time, self.rrf_asymm, [start, stop], pack, e=self.rrf_asyme) f_res = mixer(t, f_res, self.rotating_frame_frequencyMHz) f = mixer(tf, f, self.rotating_frame_frequencyMHz) if not nudum: return False # print('nu = {}, chi_res = {}'.format(nu,chi_res)) # t,fres calculated on plot points for residues # assume self.suite.single() # prepare figure fgroup = [ self.suite.groups[k]['forward'] for k in range(len(self.suite.groups)) ] bgroup = [ self.suite.groups[k]['backward'] for k in range(len(self.suite.groups)) ] alpha = [ self.suite.groups[k]['alpha'] for k in range(len(self.suite.groups)) ] group = [fgroup, bgroup, alpha] dy_fit = (y_fit - f_fit) / ey_fit data = [t, y, ey, f_res, tf, f, dy_fit] chi_dof = [nu_fit, chi_fit] if self.suite.single() and not self.multigroup: set_figure_fit = set_single_fit else: set_figure_fit = set_sequence_fit # single draws a static plot, many runs are dealt by animation # invoke ploting of dat, fit and residues if early_late: dy_fit_early = (y_fit_early - f_fit_early) / ey_fit_early dy_fit_late = (y_fit_late - f_fit_late) / ey_fit_late w_early = nu_fit * ones(t_fit_early.shape[0]) / nu_fit_early w_late = nu_fit * ones(t_fit_late.shape[0]) / nu_fit_late data_late = [ t_late, y_late, ey_late, f_late_res, tfl, fl, dy_fit_early, dy_fit_late ] chi_dof_late = [nu_fit_early,nu_fit_late,\ chi_fit_early,chi_fit_late, w_early,w_late] else: data_late, chi_dof_late = None, None # self.suite.console('Debug-mufitplot: set_figure = {}'.format(set_figure_fit)) self.fig = set_figure_fit(self.fig, self.model_name(), early_late, data, group, run_title, chi_dof, data_late, chi_dof_late, rrf=self.rotating_frame_frequencyMHz) return True