From c880092b1bbd323e843c40a5154af6000ad757de Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 21 Aug 2023 13:53:26 -0300 Subject: [PATCH 001/108] 1st_commit --- functions.py | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 functions.py diff --git a/functions.py b/functions.py new file mode 100644 index 00000000..69fbb2d4 --- /dev/null +++ b/functions.py @@ -0,0 +1,556 @@ +import pymodels as _pymodels +import pyaccel as _pyaccel +import matplotlib.pyplot as _plt +import numpy as _np +import scipy.integrate as _scyint +import scipy.special as _special +from mathphys.beam_optics import beam_rigidity as _beam_rigidity + + +def calc_amp(acc,energy_offsets, hmax, hmin): + a_def = _np.zeros(energy_offsets.size) + indices = _np.zeros(energy_offsets.size) + try: + for idx,delta in enumerate(energy_offsets): + twi,*_ = _pyaccel.optics.calc_twiss(accelerator=acc, + energy_offset=delta, + indices='closed') + if _np.any(_np.isnan(twi[0].betax)): + raise _pyaccel.optics.OpticsException('error') + rx = twi.rx + betax = twi.betax + + a_sup = (hmax - rx)**2 /betax + a_inf = (hmin - rx)**2 /betax + + a_max = _np.minimum(a_sup,a_inf) + idx_min = _np.argmin(a_max) + indices[idx] = idx_min + a_def[idx] = a_max[idx_min] + except (_pyaccel.optics.OpticsException, _pyaccel.tracking.TrackingException): + pass + return _np.sqrt(a_def), indices + +# Função criada em outro programa utilizando tracking + +# --------------------- +def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): + + # pos_x and pos_y have default values but it can be varied + # here we define the initial conditions for the simulation + + orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) + orb = orb[:, 1] + + rin = _np.zeros((6, deltas.size)) + rin += orb[:, None] + rin[0] += pos_x + rin[2] += pos_y + rin[4] += deltas + + track = _pyaccel.tracking.ring_pass( + model, rin, nr_turns=n_turn, turn_by_turn=True, + element_offset=element_idx, parallel=True) + + par_out, flag, turn_lost, element_lost, plane_lost = track + + turnl_element = [] + + for i,item in enumerate(turn_lost): + if item == n_turn and element_lost[i] == element_idx: # ignora elétrons que não foram perdidos + pass + else: + turnl_element.append((item, element_lost[i], deltas[i])) + + return turnl_element + +# This function will calculate where the electrons are lost using tracking + +# The function recives an array containing all the s positions along the ring + +def trackm_elec(acc,deltas, n_turn, lspos): + results = [] + ind = [] + spos = _pyaccel.lattice.find_spos(acc) + + for k, iten in enumerate(lspos): + + el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to calculate the lost positions + turnl = track_eletrons(deltas, n_turn, el_idx, acc, pos_x=1e-5, pos_y=3e-6) + results.append(turnl) # + ind.append(el_idx) + + return results, ind + + +# function returns the desired element index of dipoles, quadrupoles, sextupoles and any other +# element that is desired, the only thing that is needed is to pass a string + +def el_idx_collector(acc, lname): + all_index = [] + fam_data = _pymodels.si.get_family_data(acc) + + for string in lname: + element_index = [] + array_idx = _np.array(fam_data[string]['index'], dtype=object) + + for k, lista in enumerate(array_idx): + length = len(lista) + + if length % 2 != 0: + ind = int((length-1)/2) + element_index.append(lista[ind]) + + else: + try: + ind = int(length/2 + 1) + element_index.append(lista[ind]) + + except IndexError: + ind = int(length/2 - 1) + element_index.append(lista[ind]) + + all_index.append(element_index) + + return all_index + + +def plot_track(lista_resul, lista_idx, lista_off, param, element_idx, accep): + # ---------------- + + acc= _pymodels.si.create_accelerator() + acc.cavity_on = False + acc.radiation_on= False + acc.vchamber_on = False + twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') + betax = twi0.betax + betax = betax*(1/5) + + spos = _pyaccel.lattice.find_spos(acc) + + fig, (a1, a2) = _plt.subplots(1, 2, figsize=(10, 5), sharey=True, gridspec_kw={'width_ratios': [1, 3]}) + + a1.grid(True, alpha=0.5, ls='--', color='k') + a1.tick_params(axis='both', labelsize=12) + a2.grid(True, alpha=0.5, ls='--', color='k') + a2.tick_params(axis='both', labelsize=12) + a2.xaxis.grid(False) + a1.xaxis.grid(False) + + a1.set_title(r'$\delta \times$ lost turn', fontsize=16) + if 'pos' in param: + for item in lista_resul: + a1.plot(item[0], item[2]*1e2, 'k.', label = '') + a1.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + + elif 'neg' in param: + for item in lista_resul: + a1.plot(item[0], -item[2]*1e2, 'k.', label = '') + a1.set_ylabel(r'negative $\delta$ [%]', fontsize=14) + + a1.set_xlabel(r'n de voltas', fontsize=14) + + + a2.set_title(r'tracking ', fontsize=16) + + # Tracking graphics + # ---------------- + +# defining the acceptance given a point s of the ring + + acp_s = accep[element_idx] + ind = _np.argmin(_np.abs(lista_off-acp_s)) + a2.plot(spos[lista_idx][:ind], lista_off[:ind]*1e2,'b.', label=r'accep. limit', alpha=0.25) + + if 'pos' in param: + a2.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + for item in lista_resul: + a2.plot(spos[int(item[1])], item[2]*1e2, 'r.') + + elif 'neg' in param: + a2.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + for item in lista_resul: + a2.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + +# plotting acceptances with _plt.hlines + + _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) + + # linear model graphic + # ---------------- + + # plotting beta function + a2.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') + + # plotting magnetic lattice + _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) + + # initial position that tracking begins + + a2.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( + acc[element_idx].fam_name, "%.2f" % spos[element_idx])) + + # setting configurations of the graphic + a2.set_xlabel(r'$s$ [m]', fontsize=14) + a2.legend(loc='best', ncol=2) + + fig.tight_layout() + fig.show() + +def select_idx(list_, param1, param2): + arr = _np.array(list_) + + n_arr = arr[param1:param2+1] + + return n_arr + +def f_function_arg_mod(kappa, kappam, b1_, b2_): + tau = (_np.tan(kappa)**2)[:, None] + taum = (_np.tan(kappam)**2) + beta = _beam_rigidity(energy=3)[2] + ratio = tau/taum/(1+tau) + arg = (2*tau+1)**2 * (ratio - 1)/tau + arg += tau - _np.sqrt(tau*taum*(1+tau)) + arg -= (2+1/(2*tau))*_np.log(ratio) + arg *= _np.sqrt(1+tau) +# arg *= beta* _np.cos(kappa)[:, None]**2 + arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) + arg *= 2* beta* _np.sqrt(tau) + + bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + return arg * bessel + +def f_integral_simps_l_mod(taum, b1_, b2_): + kappam = _np.arctan(_np.sqrt(taum)) + _npts = int(9*1000) + dkappa = (_np.pi/2-kappam)/_npts + kappa = _np.linspace(kappam, _np.pi/2, _npts+1) + func = f_function_arg_mod(kappa, kappam, b1_, b2_) + + # Simpson's 3/8 Rule - N must be mod(N, 3) = 0 + val1 = func[0:-1:3, :] + func[3::3, :] + val2 = func[1::3, :] + func[2::3, :] + f_int = 3*dkappa/8*_np.sum(val1 + 3*val2, axis=0) + + # # Simpson's 1/3 Rule - N must be mod(N, 2) = 0 + # val1 = func[0::2, :] + func[2::2, :] + # val2 = func[1::2, :] + # f_int = dkappa/3*_np.sum(val1+4*val2, axis=0) + f_int *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum + return f_int + +def get_dis(lsps, _npt, accep, norm): + model = _pymodels.si.create_accelerator() + model = _pymodels.si.fitted_models.vertical_dispersion_and_coupling(model) + + spos = _pyaccel.lattice.find_spos(model, indices='closed') + _npoints = int((spos[-1]-spos[0])/0.1) + scalc= _np.linspace(spos[0],spos[-1], _npoints) + + daccp = _np.interp(scalc, spos, accep[1]) + daccn = _np.interp(scalc, spos, accep[0]) + + beta = _beam_rigidity(energy=3)[2] + taum_p = (beta*daccp)**2 + taum_n = (beta*daccn)**2 + + kappam_p = _np.arctan(_np.sqrt(taum_p)) + kappam_n = _np.arctan(_np.sqrt(taum_n)) + + ltime = _pyaccel.lifetime.Lifetime(model) + b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + + calc_dp, calc_dn = [], [] + deltasp, deltasn = [], [] + indices, indices_model= [], [] + + for indx, s in enumerate(lsps): + + dif = _np.abs(scalc - s) + idx = _np.argmin(dif) + indices.append(idx) + + dif1 = _np.abs(spos - s) + idx_model = _np.argmin(dif1) + +# kappam_p0 = kappam_p[idx] +# kappam_n0 = kappam_n[idx] + + kappam_p0 = 0.00001 # teste sugerido pelo ximenes + kappam_n0 = 0.00001 + + + if norm: + kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) + deltap = 1/beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) + deltan = 1/beta * _np.tan(kappan) + + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx]) + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx]) + y_p = y_p.squeeze() + y_n = y_n.squeeze() + + norm_facp = _scyint.trapz(y_p, deltap) + norm_facn = _scyint.trapz(y_n, deltan) + + # Normalizing the probability density function + + y_p /= (norm_facp) + y_n /= (norm_facn) + + calc_dp.append(y_p) + calc_dn.append(y_n) + deltasp.append(deltap) + deltasn.append(deltan) + indices_model.append(idx_model) + + else: + kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) + deltap = 1/beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) + deltan = 1/beta * _np.tan(kappan) + + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx]) + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx]) + y_p = y_p.squeeze() + y_n = y_n.squeeze() + + calc_dp.append(y_p) + calc_dn.append(y_n) + deltasp.append(deltap) + deltasn.append(deltan) + indices_model.append(idx_model) + + + calc_dp = _np.array(calc_dp) + calc_dn = _np.array(calc_dn) + deltasp = _np.array(deltasp) + deltasn = _np.array(deltasn) + indices = _np.array(indices) + indices_model = _np.array(indices_model) + + + return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model + + +def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): + + fig, axis = _plt.subplots(1,l_index.squeeze().size, figsize=(10,6)) + _plt.suptitle('Comparação entre densidade de probabilidade analítica e de M.C.', fontsize=15) + spos = _pyaccel.lattice.find_spos(acc, indices='closed') + nb = int((spos[-1] - spos[0])/0.1) + scalc = _np.linspace(spos[0],spos[-1], nb) + + for c,iten in enumerate(l_index): + ax = axis[c] + + if c == 0: + ax.set_ylabel(r'PDF normalizada', fontsize=15) + + idx = _np.argmin(_np.abs(spos[iten] - scalc)) + + ax.set_title('{}'.format(acc[iten].fam_name)) + ax.plot(deltp[idx], f_densp[idx], color='blue', label='Analytic ({:.2f} [m])'.format(scalc[idx])) + + ax.tick_params(axis='both', labelsize=14) + + ax.hist(hn[idx], density=True, bins=200, color='lightgrey', label='Monte-Carlo') + ax.plot(-deltn[idx], f_densn[idx], color='blue') + # ax.set_yscale('log') + + ax.hist(hp[idx],density=True, bins=200,color='lightgrey') + # ax.set_ylim(1e-1,1e3) + ax.set_xlim(-0.3,0.3) + + ax.set_xlabel(r'$\delta$ [%]', fontsize=15) + ax.legend() + + ax.grid(axis='y', ls='--', alpha=0.5) + # fig.tight_layout() + _plt.show + + return idx + +def create_particles(cov_matrix, num_part): + + # permute indices to change the order of the columns: + # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T + idcs = [1, 3, 4, 0, 2, 5] + # [px, py, de, rx, ry, dl]^T -> [rx, px, ry, py, de, dl]^T + idcs_r = [3, 0, 4, 1, 2, 5] + + cov_matrix = cov_matrix[:, idcs][idcs, :] + + sig_xx = cov_matrix[:3, :3] + sig_xy = cov_matrix[:3, 3:] + sig_yx = cov_matrix[3:, :3] + sig_yy = cov_matrix[3:, 3:] + inv_yy = _np.linalg.inv(sig_yy) + + part1 = _np.random.multivariate_normal(_np.zeros(6), cov_matrix, num_part).T + # changing the matrices' columns order + part2 = part1.copy() + + vec_a = part2[3:] + new_mean = (sig_xy @ inv_yy) @ vec_a + new_cov = sig_xx - sig_xy @ inv_yy @ sig_yx + + part2[:3] = _np.random.multivariate_normal(_np.zeros(3), new_cov, num_part).T + part2[:3] += new_mean + + part2 = part2[idcs_r, :] + part1 = part1[idcs_r, :] + + return part1, part2 + + +def get_cross_section_distribution(psim, _npts=3000): + beta_bar = 0 + psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) + psi = _np.pi/2 - psi + psi = psi[::-1] # this step is necessary to reverse the order of psi + cpsi = _np.cos(psi) + cross = _np.zeros(cpsi.size) + if beta_bar > 1e-19: # I think it maybe will be related to the relativistic regime + cross += (1 + 1/beta_bar**2)**2 * (2*(1 + cpsi**2)/cpsi**3 - 3/cpsi) + cross += 4/cpsi + 1 + cross *= _np.sin(psi) + cross = _scyint.cumtrapz(cross, x=psi, initial=0.0) + cross /= cross[-1] + return psi, cross + + +def cross_section_draw_samples(psim, num_part): + psi, cross = get_cross_section_distribution(psim) + crs = _np.random.rand(num_part) + return _np.interp(crs, cross, psi) + + +def scatter_particles(part1, part2, de_min): + gamma = 3e9 / 0.510e6 + beta = _np.sqrt(1 - 1/gamma/gamma) + num_part = part1.shape[1] + + xl1, yl1, de1 = part1[1], part1[3], part1[4] + xl2, yl2, de2 = part2[1], part2[3], part2[4] + + # calculating the changing base matrix for every particle + pz1 = _np.sqrt((1+de1)**2 - xl1*xl1 - yl1*yl1) + pz2 = _np.sqrt((1+de2)**2 - xl2*xl2 - yl2*yl2) + + # desired vectors to construct the transformation matrix + p_1 = _np.vstack([xl1, yl1, pz1]) + p_2 = _np.vstack([xl2, yl2, pz2]) + + # new coordinate system + p_j = p_1 + p_2 + p_j /= _np.linalg.norm(p_j, axis=0) # sum + p_k = _np.cross(p_1.T, p_2.T).T + p_k /= _np.linalg.norm(p_k, axis=0) # cross product + p_l = _np.cross(p_j.T, p_k.T).T + + jkl2xyz = _np.zeros([num_part, 3, 3]) + jkl2xyz[:, :, 0] = p_j.T + jkl2xyz[:, :, 1] = p_k.T + jkl2xyz[:, :, 2] = p_l.T + + # calculating theta and zeta + theta = xl1 - xl2 + zeta = yl1 - yl2 + # defining the value of the scattering angle chi + chi = _np.sqrt(zeta**2 + theta**2)/2 + + # draw the scattering angles from uniform distribution: + phi = _np.random.rand(num_part)* 2*_np.pi + psi = _np.random.rand(num_part)* _np.pi/2 + + # draw the psi angle from the cross section probability density: + # we need to define a maximum angle to normalize the cross section + # distribution because it diverges when the full interval [0, pi/2] + # is considered. + # To estimate this angle we define a threshold for the minimum energy + # deviation we care about (de_min) and consider the worst case scenario + # in terms of chi that could create such scattering. + # The worst case happens when chi is maximum, because in this way a small + # scattering angle would create a larger energy deviation. + # We considered here a chi twice as large as the maximum chi draw from + # the particles distribution. + # This method of doing things should be tested and thought about very + # carefully, though. + psim = _np.arccos(de_min/gamma/(chi.max()*2)) + fact=psim*2/_np.pi + print(psim*2/_np.pi) + psi = cross_section_draw_samples(psim, num_part) + + # new momentum in j,k,l (eq. 16 of Piwinski paper) + gammat = gamma/_np.sqrt(1 + beta*beta*gamma*gamma*chi*chi) + dp_ = _np.sin(chi[None, :]) * _np.vstack([ + gammat*_np.cos(psi), + _np.sin(psi)*_np.cos(phi), + _np.sin(psi)*_np.sin(phi)]) + p_prime1 = _np.zeros((3, chi.size)) + p_prime1[0] = _np.cos(chi) + p_prime2 = p_prime1.copy() + p_prime1 += dp_ + p_prime2 -= dp_ + + # returning to momentum x,y,z + pnew_1 = (jkl2xyz @ p_prime1.T[:, :, None]).squeeze().T + pnew_2 = (jkl2xyz @ p_prime2.T[:, :, None]).squeeze().T + + delta1 = _np.linalg.norm(pnew_1, axis=0) - 1 + delta2 = _np.linalg.norm(pnew_2, axis=0) - 1 + + part1_new = part1.copy() + part1_new[1] = pnew_1[0] + part1_new[3] = pnew_1[1] + part1_new[4] = delta1 + + part2_new = part2.copy() + part2_new[1] = pnew_2[0] + part2_new[3] = pnew_2[1] + part2_new[4] = delta2 + + return part1_new, part2_new, fact + +def histgms(acc,l_spos,num_part, accep, de_min): + + envelopes = _pyaccel.optics.calc_beamenvelope(acc) + spos=_pyaccel.lattice.find_spos(acc, indices='closed') + _npoint = int((spos[-1]-spos[0])/0.1) + scalc = _np.linspace(spos[0], spos[-1], _npoint) + histsp1=[] + histsp2=[] + indices=[] + for iten in l_spos: + + idx_model = _np.argmin(_np.abs(spos - iten)) + idx = _np.argmin(_np.abs(scalc - iten)) + + env = envelopes[idx_model] + part1, part2= create_particles(env, num_part) + part1_new, part2_new, fact = scatter_particles(part1, part2, de_min) + +# acpp, acpn = accep[1][idx], accep[0][idx] + +# check1 = acpp - part1_new[4] +# check2 = -(acpn - part2_new[4]) +# cond2 = check2<0 +# cond1 = check1<0 + +# ind1 = _np.where(cond1)[0] # apenas os desvios de energia maiores que a a aceitancia da máquina +# ind2 = _np.where(cond2)[0] + + ind1 = _np.where(part1_new[4]>=0.001) # teste sugerido pelo ximenes + ind2 = _np.where(part2_new[4]<=-0.001) + + histsp1.append((part1_new[4][ind1])) + histsp2.append((part2_new[4][ind2])) + indices.append(idx) + + hist1=_np.array(histsp1, dtype='object') + hist2=_np.array(histsp2, dtype='object') + indices=_np.array(indices) + + return histsp1, histsp2, indices \ No newline at end of file From ae08aff6e90ee20886ff716b371e1ab50b3317a2 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 21 Aug 2023 15:05:55 -0300 Subject: [PATCH 002/108] =?UTF-8?q?mudan=C3=A7a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 55 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/functions.py b/functions.py index 69fbb2d4..7dab0bc4 100644 --- a/functions.py +++ b/functions.py @@ -204,20 +204,39 @@ def select_idx(list_, param1, param2): return n_arr -def f_function_arg_mod(kappa, kappam, b1_, b2_): - tau = (_np.tan(kappa)**2)[:, None] - taum = (_np.tan(kappam)**2) - beta = _beam_rigidity(energy=3)[2] - ratio = tau/taum/(1+tau) - arg = (2*tau+1)**2 * (ratio - 1)/tau - arg += tau - _np.sqrt(tau*taum*(1+tau)) - arg -= (2+1/(2*tau))*_np.log(ratio) - arg *= _np.sqrt(1+tau) -# arg *= beta* _np.cos(kappa)[:, None]**2 - arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) - arg *= 2* beta* _np.sqrt(tau) - - bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) +def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): + + if norm: + tau = (_np.tan(kappa)**2)[:, None] + taum = (_np.tan(kappam)**2) + beta = _beam_rigidity(energy=3)[2] + ratio = tau/taum/(1+tau) + arg = (2*tau+1)**2 * (ratio - 1)/tau + arg += tau - _np.sqrt(tau*taum*(1+tau)) + arg -= (2+1/(2*tau))*_np.log(ratio) + arg *= _np.sqrt(1+tau) + # arg *= beta* _np.cos(kappa)[:, None]**2 + arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) + arg *= 2* beta* _np.sqrt(tau) + + bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + + else: + tau = (_np.tan(kappa)**2)[:, None] + taum = (_np.tan(kappam)**2) + beta = _beam_rigidity(energy=3)[2] + ratio = tau/taum/(1+tau) + arg = (2*tau+1)**2 * (ratio - 1)/tau + arg += tau - _np.sqrt(tau*taum*(1+tau)) + arg -= (2+1/(2*tau))*_np.log(ratio) + arg *= _np.sqrt(1+tau) + # arg *= beta* _np.cos(kappa)[:, None]**2 + arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) + arg *= 2* beta* _np.sqrt(tau) + arg *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum + + bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + return arg * bessel def f_integral_simps_l_mod(taum, b1_, b2_): @@ -286,8 +305,8 @@ def get_dis(lsps, _npt, accep, norm): kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) deltan = 1/beta * _np.tan(kappan) - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx]) - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx]) + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm) + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm) y_p = y_p.squeeze() y_n = y_n.squeeze() @@ -311,8 +330,8 @@ def get_dis(lsps, _npt, accep, norm): kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) deltan = 1/beta * _np.tan(kappan) - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx]) - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx]) + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm) + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm) y_p = y_p.squeeze() y_n = y_n.squeeze() From 7746efaa0dfdaacbc951b4304fc28708e647719e Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 22 Aug 2023 09:48:14 -0300 Subject: [PATCH 003/108] =?UTF-8?q?mudan=C3=A7a=20na=20fun=C3=A7=C3=A3o=20?= =?UTF-8?q?para=20obter=20distribui=C3=A7=C3=A3o=20normalizada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 141 +++++++++++++++++++-------------------------------- new.ipynb | 0 2 files changed, 51 insertions(+), 90 deletions(-) create mode 100644 new.ipynb diff --git a/functions.py b/functions.py index 7dab0bc4..d99da4c2 100644 --- a/functions.py +++ b/functions.py @@ -206,38 +206,29 @@ def select_idx(list_, param1, param2): def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): - if norm: - tau = (_np.tan(kappa)**2)[:, None] - taum = (_np.tan(kappam)**2) - beta = _beam_rigidity(energy=3)[2] - ratio = tau/taum/(1+tau) - arg = (2*tau+1)**2 * (ratio - 1)/tau - arg += tau - _np.sqrt(tau*taum*(1+tau)) - arg -= (2+1/(2*tau))*_np.log(ratio) - arg *= _np.sqrt(1+tau) - # arg *= beta* _np.cos(kappa)[:, None]**2 - arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) - arg *= 2* beta* _np.sqrt(tau) + tau = (_np.tan(kappa)**2)[:, None] + taum = (_np.tan(kappam)**2) + beta = _beam_rigidity(energy=3)[2] + ratio = tau/taum/(1+tau) + arg = (2*tau+1)**2 * (ratio - 1)/tau + arg += tau - _np.sqrt(tau*taum*(1+tau)) + arg -= (2+1/(2*tau))*_np.log(ratio) + arg *= _np.sqrt(1+tau) +# arg *= beta* _np.cos(kappa)[:, None]**2 + arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) + arg *= 2* beta* _np.sqrt(tau) - bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + + if norm: + pass else: - tau = (_np.tan(kappa)**2)[:, None] - taum = (_np.tan(kappam)**2) - beta = _beam_rigidity(energy=3)[2] - ratio = tau/taum/(1+tau) - arg = (2*tau+1)**2 * (ratio - 1)/tau - arg += tau - _np.sqrt(tau*taum*(1+tau)) - arg -= (2+1/(2*tau))*_np.log(ratio) - arg *= _np.sqrt(1+tau) - # arg *= beta* _np.cos(kappa)[:, None]**2 - arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) - arg *= 2* beta* _np.sqrt(tau) arg *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum - bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) - + return arg * bessel + def f_integral_simps_l_mod(taum, b1_, b2_): kappam = _np.arctan(_np.sqrt(taum)) @@ -258,39 +249,33 @@ def f_integral_simps_l_mod(taum, b1_, b2_): f_int *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum return f_int -def get_dis(lsps, _npt, accep, norm): - model = _pymodels.si.create_accelerator() - model = _pymodels.si.fitted_models.vertical_dispersion_and_coupling(model) - - spos = _pyaccel.lattice.find_spos(model, indices='closed') +def norm_d(acc, lsps, _npt, accep, norm=True): + + spos = _pyaccel.lattice.find_spos(acc, indices='closed') _npoints = int((spos[-1]-spos[0])/0.1) scalc= _np.linspace(spos[0],spos[-1], _npoints) - - daccp = _np.interp(scalc, spos, accep[1]) - daccn = _np.interp(scalc, spos, accep[0]) - beta = _beam_rigidity(energy=3)[2] - taum_p = (beta*daccp)**2 - taum_n = (beta*daccn)**2 - kappam_p = _np.arctan(_np.sqrt(taum_p)) - kappam_n = _np.arctan(_np.sqrt(taum_n)) + # daccp = _np.interp(scalc, spos, accep[1]) + # daccn = _np.interp(scalc, spos, accep[0]) + # taum_p = (beta*daccp)**2 + # taum_n = (beta*daccn)**2 + # kappam_p = _np.arctan(_np.sqrt(taum_p)) + # kappam_n = _np.arctan(_np.sqrt(taum_n)) - ltime = _pyaccel.lifetime.Lifetime(model) + ltime = _pyaccel.lifetime.Lifetime(acc) b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] calc_dp, calc_dn = [], [] deltasp, deltasn = [], [] indices, indices_model= [], [] - for indx, s in enumerate(lsps): + for _, s in enumerate(lsps): - dif = _np.abs(scalc - s) - idx = _np.argmin(dif) + idx = _np.argmin(_np.abs(scalc - s)) indices.append(idx) - - dif1 = _np.abs(spos - s) - idx_model = _np.argmin(dif1) + idx_model = _np.argmin(_np.abs(spos - s)) + indices_model.append(idx_model) # kappam_p0 = kappam_p[idx] # kappam_n0 = kappam_n[idx] @@ -298,49 +283,26 @@ def get_dis(lsps, _npt, accep, norm): kappam_p0 = 0.00001 # teste sugerido pelo ximenes kappam_n0 = 0.00001 - - if norm: - kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) - deltap = 1/beta * _np.tan(kappap) - kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) - deltan = 1/beta * _np.tan(kappan) - - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm) - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm) - y_p = y_p.squeeze() - y_n = y_n.squeeze() - - norm_facp = _scyint.trapz(y_p, deltap) - norm_facn = _scyint.trapz(y_n, deltan) - - # Normalizing the probability density function - - y_p /= (norm_facp) - y_n /= (norm_facn) - - calc_dp.append(y_p) - calc_dn.append(y_n) - deltasp.append(deltap) - deltasn.append(deltan) - indices_model.append(idx_model) - - else: - kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) - deltap = 1/beta * _np.tan(kappap) - kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) - deltan = 1/beta * _np.tan(kappan) - - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm) - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm) - y_p = y_p.squeeze() - y_n = y_n.squeeze() - - calc_dp.append(y_p) - calc_dn.append(y_n) - deltasp.append(deltap) - deltasn.append(deltan) - indices_model.append(idx_model) - + kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) + deltap = 1/beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) + deltan = 1/beta * _np.tan(kappan) + + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + + norm_facp = _scyint.trapz(y_p, deltap) + norm_facn = _scyint.trapz(y_n, deltan) + +# Normalizing to obtain the probability density function + + y_p /= (norm_facp) + y_n /= (norm_facn) + + calc_dp.append(y_p) + calc_dn.append(y_n) + deltasp.append(deltap) + deltasn.append(deltan) calc_dp = _np.array(calc_dp) calc_dn = _np.array(calc_dn) @@ -349,7 +311,6 @@ def get_dis(lsps, _npt, accep, norm): indices = _np.array(indices) indices_model = _np.array(indices_model) - return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model diff --git a/new.ipynb b/new.ipynb new file mode 100644 index 00000000..e69de29b From 748296dbd6834bf3d18b983947ffe7dfa8b7de87 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 22 Aug 2023 14:54:04 -0300 Subject: [PATCH 004/108] =?UTF-8?q?criando=20fun=C3=A7=C3=A3o=20para=20pes?= =?UTF-8?q?agem=20dos=20desvios=20de=20energia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/functions.py b/functions.py index d99da4c2..fe70c907 100644 --- a/functions.py +++ b/functions.py @@ -313,6 +313,64 @@ def norm_d(acc, lsps, _npt, accep, norm=True): return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model +def n_norm_d(acc, lsps, _npt, accep, norm=False): + + spos = _pyaccel.lattice.find_spos(acc, indices='closed') + _npoints = int((spos[-1]-spos[0])/0.1) + scalc= _np.linspace(spos[0],spos[-1], _npoints) + beta = _beam_rigidity(energy=3)[2] + + daccp = _np.interp(scalc, spos, accep[1]) + daccn = _np.interp(scalc, spos, accep[0]) + taum_p = (beta*daccp)**2 + taum_n = (beta*daccn)**2 + kappam_p = _np.arctan(_np.sqrt(taum_p)) + kappam_n = _np.arctan(_np.sqrt(taum_n)) + + ltime = _pyaccel.lifetime.Lifetime(acc) + b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + + calc_dp, calc_dn = [], [] + deltasp, deltasn = [], [] + indices, indices_model= [], [] + + for _, s in enumerate(lsps): + + idx = _np.argmin(_np.abs(scalc - s)) + indices.append(idx) + idx_model = _np.argmin(_np.abs(spos - s)) + indices_model.append(idx_model) + + kappam_p0 = kappam_p[idx] + kappam_n0 = kappam_n[idx] + + kappam_p0x = 0.00001 # teste sugerido pelo ximenes + kappam_n0x = 0.00001 + + kappap = _np.linspace(kappam_p0x, _np.pi/2, _npt) + deltap = 1/beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0x, _np.pi/2, _npt) + deltan = 1/beta * _np.tan(kappan) + + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + + calc_dp.append(y_p) + calc_dn.append(y_n) + deltasp.append(deltap) + deltasn.append(deltan) + + if s == lsps[-1]: + + calc_dp = _np.array(calc_dp) + calc_dn = _np.array(calc_dn) + deltasp = _np.array(deltasp) + deltasn = _np.array(deltasn) + indices = _np.array(indices) + indices_model = _np.array(indices_model) + + return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model + def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): From 8accf29536a62c069d965a6303f7b33b799cb866 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 22 Aug 2023 14:58:42 -0300 Subject: [PATCH 005/108] del_new --- new.ipynb | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 new.ipynb diff --git a/new.ipynb b/new.ipynb deleted file mode 100644 index e69de29b..00000000 From 616555170338a8f18b6153ee6704ae3e4e41b4f0 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 12:20:14 -0300 Subject: [PATCH 006/108] =?UTF-8?q?adicionando=20funcionalidades=20a=20fun?= =?UTF-8?q?=C3=A7=C3=A3o=20que=20realizar=C3=A1=20a=20pesagem=20dos=20desv?= =?UTF-8?q?ios=20de=20energia=20e=20alterando=20alguns=20par=C3=A2metros?= =?UTF-8?q?=20do=20m=C3=A9todo=20que=20calcula=20a=20fun=C3=A7=C3=A3o=20de?= =?UTF-8?q?nsidade=20de=20probabilidade=20j=C3=A1=20normalizada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/functions.py b/functions.py index fe70c907..7017c7b7 100644 --- a/functions.py +++ b/functions.py @@ -225,7 +225,6 @@ def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): else: arg *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum - bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) return arg * bessel @@ -249,20 +248,10 @@ def f_integral_simps_l_mod(taum, b1_, b2_): f_int *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum return f_int -def norm_d(acc, lsps, _npt, accep, norm=True): +def norm_d(acc, lsps, scalc,_npt, norm=True): spos = _pyaccel.lattice.find_spos(acc, indices='closed') - _npoints = int((spos[-1]-spos[0])/0.1) - scalc= _np.linspace(spos[0],spos[-1], _npoints) beta = _beam_rigidity(energy=3)[2] - - # daccp = _np.interp(scalc, spos, accep[1]) - # daccn = _np.interp(scalc, spos, accep[0]) - # taum_p = (beta*daccp)**2 - # taum_n = (beta*daccn)**2 - # kappam_p = _np.arctan(_np.sqrt(taum_p)) - # kappam_n = _np.arctan(_np.sqrt(taum_n)) - ltime = _pyaccel.lifetime.Lifetime(acc) b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -276,9 +265,6 @@ def norm_d(acc, lsps, _npt, accep, norm=True): indices.append(idx) idx_model = _np.argmin(_np.abs(spos - s)) indices_model.append(idx_model) - -# kappam_p0 = kappam_p[idx] -# kappam_n0 = kappam_n[idx] kappam_p0 = 0.00001 # teste sugerido pelo ximenes kappam_n0 = 0.00001 @@ -290,7 +276,6 @@ def norm_d(acc, lsps, _npt, accep, norm=True): y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - norm_facp = _scyint.trapz(y_p, deltap) norm_facn = _scyint.trapz(y_n, deltan) @@ -332,14 +317,11 @@ def n_norm_d(acc, lsps, _npt, accep, norm=False): calc_dp, calc_dn = [], [] deltasp, deltasn = [], [] - indices, indices_model= [], [] for _, s in enumerate(lsps): idx = _np.argmin(_np.abs(scalc - s)) indices.append(idx) - idx_model = _np.argmin(_np.abs(spos - s)) - indices_model.append(idx_model) kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] @@ -354,22 +336,21 @@ def n_norm_d(acc, lsps, _npt, accep, norm=False): y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + indp = _np.argmin(_np.abs(deltap- 1/beta * _np.tan(kappam_p0))) + indn = _np.argmin(_np.abs(deltan- 1/beta * _np.tan(kappam_n0))) - calc_dp.append(y_p) - calc_dn.append(y_n) - deltasp.append(deltap) - deltasn.append(deltan) - - if s == lsps[-1]: + calc_dp.append(y_p[indp:]) + calc_dn.append(y_n[indn:]) + deltasp.append(deltap[indp:]) + deltasn.append(deltan[indn:]) - calc_dp = _np.array(calc_dp) - calc_dn = _np.array(calc_dn) - deltasp = _np.array(deltasp) - deltasn = _np.array(deltasn) - indices = _np.array(indices) - indices_model = _np.array(indices_model) + calc_dp = _np.array(calc_dp, dtype=object) + calc_dn = _np.array(calc_dn, dtype=object) + deltasp = _np.array(deltasp, dtype=object) + deltasn = _np.array(deltasn, dtype=object) + indices = _np.array(indices, dtype=object) - return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model + return calc_dp, calc_dn, deltasp, deltasn, indices def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): From 6910314394b621efafcb45848bf5645bb53c4ae6 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 13:05:56 -0300 Subject: [PATCH 007/108] =?UTF-8?q?adcionando=20otimiza=C3=A7=C3=B5es=20no?= =?UTF-8?q?=20m=C3=A9todo=20que=20realizar=C3=A1=20a=20pesagem=20dos=20des?= =?UTF-8?q?vios=20de=20energia=20e=20adicionando=20save=20and=20load=5Fpic?= =?UTF-8?q?kle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/functions.py b/functions.py index 7017c7b7..457c3e23 100644 --- a/functions.py +++ b/functions.py @@ -5,6 +5,7 @@ import scipy.integrate as _scyint import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity +from mathphys.functions import save_pickle, load_pickle def calc_amp(acc,energy_offsets, hmax, hmin): @@ -298,17 +299,23 @@ def norm_d(acc, lsps, scalc,_npt, norm=True): return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model -def n_norm_d(acc, lsps, _npt, accep, norm=False): - +def get_scaccep(acc, accep): spos = _pyaccel.lattice.find_spos(acc, indices='closed') - _npoints = int((spos[-1]-spos[0])/0.1) - scalc= _np.linspace(spos[0],spos[-1], _npoints) + + npt = int((spos[-1]-spos[0])/0.1) + scalc = _np.linspace(spos[0],spos[-1], npt) + daccpp = _np.interp(scalc, spos, accep[1]) + daccpn = _np.interp(scalc, spos, accep[0]) + + return scalc, daccpp, daccpn + +def n_norm_d(acc, lsps, _npt, accep, getsacp, norm=False): + + scalc, daccpp, daccpn = getsacp beta = _beam_rigidity(energy=3)[2] - daccp = _np.interp(scalc, spos, accep[1]) - daccn = _np.interp(scalc, spos, accep[0]) - taum_p = (beta*daccp)**2 - taum_n = (beta*daccn)**2 + taum_p = (beta*daccpp)**2 + taum_n = (beta*daccpn)**2 kappam_p = _np.arctan(_np.sqrt(taum_p)) kappam_n = _np.arctan(_np.sqrt(taum_n)) From 7cbe1c8858363001c297093450a97c9344684c0a Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 13:06:54 -0300 Subject: [PATCH 008/108] =?UTF-8?q?retirando=20par=C3=A2metro=20n=C3=A3o?= =?UTF-8?q?=20utilizado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions.py b/functions.py index 457c3e23..493fdc29 100644 --- a/functions.py +++ b/functions.py @@ -309,7 +309,7 @@ def get_scaccep(acc, accep): return scalc, daccpp, daccpn -def n_norm_d(acc, lsps, _npt, accep, getsacp, norm=False): +def n_norm_d(acc, lsps, _npt, getsacp, norm=False): scalc, daccpp, daccpn = getsacp beta = _beam_rigidity(energy=3)[2] From 679b709d099042cb47d20fa082be0e55cc402f94 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 13:15:09 -0300 Subject: [PATCH 009/108] =?UTF-8?q?retifica=C3=A7=C3=B5es=20de=20vari?= =?UTF-8?q?=C3=A1vel=20que=20n=C3=A3o=20havia=20sido=20declarada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/functions.py b/functions.py index 493fdc29..de409118 100644 --- a/functions.py +++ b/functions.py @@ -328,7 +328,6 @@ def n_norm_d(acc, lsps, _npt, getsacp, norm=False): for _, s in enumerate(lsps): idx = _np.argmin(_np.abs(scalc - s)) - indices.append(idx) kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] From 85fab3a4df20af77536764998dfb909d7ed6b482 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 13:25:41 -0300 Subject: [PATCH 010/108] =?UTF-8?q?mais=20corre=C3=A7=C3=B5es=20a=20respei?= =?UTF-8?q?to=20da=20vari=C3=A1vel=20n=C3=A3o=20declarada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/functions.py b/functions.py index de409118..60cd89f9 100644 --- a/functions.py +++ b/functions.py @@ -354,7 +354,6 @@ def n_norm_d(acc, lsps, _npt, getsacp, norm=False): calc_dn = _np.array(calc_dn, dtype=object) deltasp = _np.array(deltasp, dtype=object) deltasn = _np.array(deltasn, dtype=object) - indices = _np.array(indices, dtype=object) return calc_dp, calc_dn, deltasp, deltasn, indices From 479d35c0c9e89214c2b3785e6bba7f5d518e85e2 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 13:26:30 -0300 Subject: [PATCH 011/108] =?UTF-8?q?mais=20corre=C3=A7=C3=B5es...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions.py b/functions.py index 60cd89f9..950a5357 100644 --- a/functions.py +++ b/functions.py @@ -355,7 +355,7 @@ def n_norm_d(acc, lsps, _npt, getsacp, norm=False): deltasp = _np.array(deltasp, dtype=object) deltasn = _np.array(deltasn, dtype=object) - return calc_dp, calc_dn, deltasp, deltasn, indices + return calc_dp, calc_dn, deltasp, deltasn def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): From 4b55c5c2b6203aca1936748fc5d208d5c1165ce0 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 16:04:48 -0300 Subject: [PATCH 012/108] =?UTF-8?q?adicionando=20mudan=C3=A7as=20referente?= =?UTF-8?q?s=20ao=20nome=20do=20par=C3=A2metro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 0 functions.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 Classes.py diff --git a/Classes.py b/Classes.py new file mode 100644 index 00000000..e69de29b diff --git a/functions.py b/functions.py index 950a5357..7114667c 100644 --- a/functions.py +++ b/functions.py @@ -309,7 +309,7 @@ def get_scaccep(acc, accep): return scalc, daccpp, daccpn -def n_norm_d(acc, lsps, _npt, getsacp, norm=False): +def n_norm_d(acc, lsps, _npt, getsacp, cutoff, norm=False): scalc, daccpp, daccpn = getsacp beta = _beam_rigidity(energy=3)[2] @@ -332,8 +332,8 @@ def n_norm_d(acc, lsps, _npt, getsacp, norm=False): kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] - kappam_p0x = 0.00001 # teste sugerido pelo ximenes - kappam_n0x = 0.00001 + kappam_p0x = cutoff # teste sugerido pelo Ximenes + kappam_n0x = cutoff kappap = _np.linspace(kappam_p0x, _np.pi/2, _npt) deltap = 1/beta * _np.tan(kappap) From cd6d0dd95a8d0030ff5c1f1d9ea9c62a9eb871c0 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 23 Aug 2023 16:59:21 -0300 Subject: [PATCH 013/108] class for touschek analysis --- Classes.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Classes.py b/Classes.py index e69de29b..11f46b1c 100644 --- a/Classes.py +++ b/Classes.py @@ -0,0 +1,39 @@ +from pyaccel.lifetime import Lifetime + + +class tous_analysis(): + + # Defining this class I can call any accelerator I want to realize touschek scattering analysis + # Keep in mind another terms that could be add in the init of the class + + # the acceptance is calculated utilizing the de accelerator's model so it'isnt necessary a priori + # pass the energy acceptance to the class + + # Define the interval to choose the energy deviation to realize the tracking simulation + # Pass a parameter to define when I desire to use some function + # if tracking calculates the simulation utilizing the tracking function that was created + # if linear calculates the physical limitants that use a type of model for the calculation + + def __init__(self,accelerator): + self.acc = accelerator + self.accep = None + self.ltime = None + self.nturns = None + self.deltas = None + self.param = None + + + @property + def setting_tousdata(self): + if self.ltime is None: + self.ltime = Lifetime(self.acc) + return self.ltime + + # @property + # def define_nturns(self): + # if + + + + + From 7573eb075f66481865fd759604ea92609ee2dc19 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 24 Aug 2023 13:20:02 -0300 Subject: [PATCH 014/108] =?UTF-8?q?mudan=C3=A7as=20do=20dia=2024.08.2023?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++---- functions.py | 55 ++++++++++++++++++++- 2 files changed, 179 insertions(+), 11 deletions(-) diff --git a/Classes.py b/Classes.py index 11f46b1c..0482ad94 100644 --- a/Classes.py +++ b/Classes.py @@ -1,4 +1,10 @@ from pyaccel.lifetime import Lifetime +from pyaccel.lattice import get_attribute +import touschek_pack.functions as tousfunc +import pymodels +import pyaccel.optics as py_op +import numpy as _np +import matplotlib.pyplot as _plt class tous_analysis(): @@ -14,21 +20,130 @@ class tous_analysis(): # if tracking calculates the simulation utilizing the tracking function that was created # if linear calculates the physical limitants that use a type of model for the calculation + # I can take the indices a long the ring as parameters to use in the model. + + # eu tenho que pensar, porque se eu ficar fazendo dessa maneira todos os meus atributos serão none + # e depois eu vou precisar alterar este atributo manualmente será que é realmente isso que eu desejo ? + + # em primeiro lugar apenas para esclarecimento, eu posso definir um atributo da maneira que eu quiser e depois posso alterá-lo + # da forma que eu achar necessário + + # o que é mais vantajoso definir os atributos como None e depois alterar seus valores manualmente ou possuir uma configuração padrão em que + # esses atributos já são definidos automaticamente? + + # Parece interessante a ideia de que os atributos sejam definidos em uma configuração padrão e sejam alterados conforme eu vá passando + # informações para o objeto da classe criada + + # em classes eu posso passar alguns parâmetros para que a classe saiba identificar qual é o modelo necessário que deve ser utilizado + # ou então como definir os atributos com base nas palavras chave passada nos argumentos + + # vou começar a justificar alguns passos na criação desta classes para posteriormente eu me orientar + # e não criar uma classe sem saber interpretar os motivos de estar definindo de uma forma e não de outra + + '''Justificativa do por quê definir alguns atributos com valor padrão None''' + + # em primeiro lugar, a partir do que conversei com o fernando no dia 23.08.2023 é uma boa prática de progrmação criar classes que + # não gastem muito tempo ao serem iniciadas, ou seja, não é desejado que ao criar um objeto muito tempo seja empregado + # na construção do __init__. + # Pensando nisso, existem atributos que são fundamentais para a classe que está sendo criada e, portanto, já devem ser + # definidos no __init__, mas como não desejamos que muito tempo seja empregado na operação de instaciação de um objeto, + # definimos alguns objetos com valor padrão None, para posteriormente redefinir essas grandezas provavelmente com a definição de outras + # funções que já estão inicialmente implementadas + + # Agora vejamos, eu preciso definir diversos atributos que não necessitam de um tempo de execução muito longo + # qual a melhor forma de se fazer isso ? + + # eu poderia definir uma função que define mais atributos ao mesmo tempo? + # isso pode ser util quando feito de maneira clara + + # é interessante que esta classe seja flexível a ponto de permitir que as simulações de tracking sejam realizadas + # por quem a esta utilizando + + # todas as funções que foram definidas até o momento são utilizadas por meio de um loop que é executado em todos os elementos de + # uma lista de posições ao longo do feixe, essa lista pode até mesmo ser a lista completa de todas as posições do anel + # essa lista pode ser de elementos específicos em que se deseje estudar a taxa de espalhamento touschek + def __init__(self,accelerator): self.acc = accelerator - self.accep = None - self.ltime = None - self.nturns = None - self.deltas = None - self.param = None + self.h_pos = get_attribute(self.acc, 'hmax', indices='closed') # getting the vchamber's height + self.h_neg = get_attribute(self.acc, 'hmin', indices='closed') + self.ltime = Lifetime(self.acc) + fam = pymodels.si.get_family_data(self.acc) # Geting the name of the element we desire to study + self.lname = list(fam.keys()) # geting + self.index = tousfunc.el_idx_collector() # this calculation is relativily fast to execute, + off_array = _np.linspace(0,0.46, 460) + self.ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model + + self.sc_accps = None # check + self._accep = None # check + self.nturns = None # check + self.deltas = None # check + + self.linear_model_ampp = None + self.idx_lim_pos = None + self.linear_model_ampn = None + self.idx_lim_neg = None + + # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @property - def setting_tousdata(self): - if self.ltime is None: - self.ltime = Lifetime(self.acc) - return self.ltime - + def accep(self): + if self._accep is None: + self._accep = py_op.calc_touschek_energy_acceptance(self.acc) + return self._accep + + # Defining the s position, positive and negative accptances along the ring at each 10 meters. + # the description above is actually the returns of the function + @property + def convert_scalc(self): + if self.sc_accps is None: + self.sc_accps = tousfunc.get_scaccep(self.acc, self.accep) + return self.sc_accps + + # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model + @property + def lin_offs_set(self): + return self.ener_off + + @lin_offs_set.setter + def lin_offs_set(self, new): + self.ener_off = new + return self.ener_off + + # Defining the electron number of turns to + @property + def nturns_set(self): + return self.nturns + + @nturns_set.setter + def nturns_set(self, new_turns): + self.nturns = new_turns + return self.nturns + + @property + def deltas_set(self): + return self.nturns + + @deltas_set.setter + def deltas_set(self, new_deltas): + self.nturns = new_deltas + return self.nturns + + + + + + # tudo bem que desenvolver um código que obtenha diversos trackings para todos os pontos do anel é de fato uma coisa legal + # mas para fazer isso é necessário empregar muito tempo de simulação + # dessa forma, é possível definir funções que serão implementadas para realizar simulações rápidas + # e é possível definir funções que vão realizar simulações mais demoradas (provavelmente neste caso será realizada uma sondagem ao longo + # de todo anel de armazenamento) + + # tenho de pensar em como realizar essas simulações rápidas, uma vez que eu já possuo + + + # @property # def define_nturns(self): # if diff --git a/functions.py b/functions.py index 7114667c..70a5c3db 100644 --- a/functions.py +++ b/functions.py @@ -76,7 +76,7 @@ def trackm_elec(acc,deltas, n_turn, lspos): for k, iten in enumerate(lspos): - el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to calculate the lost positions + el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to shift the tracking simulation turnl = track_eletrons(deltas, n_turn, el_idx, acc, pos_x=1e-5, pos_y=3e-6) results.append(turnl) # ind.append(el_idx) @@ -357,6 +357,59 @@ def n_norm_d(acc, lsps, _npt, getsacp, cutoff, norm=False): return calc_dp, calc_dn, deltasp, deltasn +# Como discutido no dia 23.08.2023 a primeira abordagem para a realizaçao da pesagem vai +# vai ser feita definindo o corte como sendo a aceitancia de energia, isso foi deinido com base +# no cálculo já implementados para o tempo de vida touschek que é coerente com o tempo do SIRIUS +# futuramente isso pode ser alterado e redefinido + +def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): + + scalc, daccpp, daccpn = getsacp + beta = _beam_rigidity(energy=3)[2] + + taum_p = (beta*daccpp)**2 + taum_n = (beta*daccpn)**2 + kappam_p = _np.arctan(_np.sqrt(taum_p)) + kappam_n = _np.arctan(_np.sqrt(taum_n)) + + ltime = _pyaccel.lifetime.Lifetime(acc) + b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + + calc_dp, calc_dn = [], [] + deltasp, deltasn = [], [] + + for _, s in enumerate(lsps): + + idx = _np.argmin(_np.abs(scalc - s)) + kappam_p0 = kappam_p[idx] + kappam_n0 = kappam_n[idx] + + kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) + deltap = 1/beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) + deltan = 1/beta * _np.tan(kappan) + + y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + + # eliminating the negative values from array + indp = _np.where(y_p<0) + indn = _np.where(y_n<0) + y_p[indp] == 0 + y_n[indn] == 0 + + calc_dp.append(y_p) + calc_dn.append(y_n) + deltasp.append(deltap) + deltasn.append(deltan) + + calc_dp = _np.array(calc_dp, dtype=object) + calc_dn = _np.array(calc_dn, dtype=object) + deltasp = _np.array(deltasp, dtype=object) + deltasn = _np.array(deltasn, dtype=object) + + return calc_dp, calc_dn, deltasp, deltasn + def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): From dafcf116173e036f01d4bc03f9ce283cc8c86f1b Mon Sep 17 00:00:00 2001 From: Thales_note Date: Mon, 28 Aug 2023 09:40:07 -0300 Subject: [PATCH 015/108] =?UTF-8?q?mudan=C3=A7a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 154 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 55 deletions(-) diff --git a/Classes.py b/Classes.py index 0482ad94..5353119a 100644 --- a/Classes.py +++ b/Classes.py @@ -1,13 +1,13 @@ from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute -import touschek_pack.functions as tousfunc +import functions as tousfunc import pymodels import pyaccel.optics as py_op import numpy as _np import matplotlib.pyplot as _plt -class tous_analysis(): +class Tous_analysis(): # Defining this class I can call any accelerator I want to realize touschek scattering analysis # Keep in mind another terms that could be add in the init of the class @@ -64,74 +64,127 @@ class tous_analysis(): # essa lista pode ser de elementos específicos em que se deseje estudar a taxa de espalhamento touschek def __init__(self,accelerator): - self.acc = accelerator - self.h_pos = get_attribute(self.acc, 'hmax', indices='closed') # getting the vchamber's height - self.h_neg = get_attribute(self.acc, 'hmin', indices='closed') - self.ltime = Lifetime(self.acc) - fam = pymodels.si.get_family_data(self.acc) # Geting the name of the element we desire to study + self._acc = accelerator + self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height + self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') + self.ltime = Lifetime(self._acc) + fam = pymodels.si.get_family_data(self._acc) # Geting the name of the element we desire to study self.lname = list(fam.keys()) # geting - self.index = tousfunc.el_idx_collector() # this calculation is relativily fast to execute, - off_array = _np.linspace(0,0.46, 460) - self.ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model - - self.sc_accps = None # check - self._accep = None # check - self.nturns = None # check - self.deltas = None # check - - self.linear_model_ampp = None - self.idx_lim_pos = None - self.linear_model_ampn = None - self.idx_lim_neg = None + self.index = tousfunc.el_idx_collector(self._acc, self.lname) # this calculation is relativily fast to execute, + self._sc_accps = None # check + self._accep = None # check + off_array = _np.linspace(0,0.46, 460) + self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model + self._nturns = None # check + self._deltas = None # check + + self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @property def accep(self): if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance(self.acc) + self._accep = py_op.calc_touschek_energy_acceptance(self._acc) return self._accep # Defining the s position, positive and negative accptances along the ring at each 10 meters. # the description above is actually the returns of the function @property - def convert_scalc(self): - if self.sc_accps is None: - self.sc_accps = tousfunc.get_scaccep(self.acc, self.accep) - return self.sc_accps + def scalc(self): + if self._sc_accps is None: + self._sc_accps = tousfunc.get_scaccep(self._acc, self._accep) + return self._sc_accps # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model @property - def lin_offs_set(self): - return self.ener_off + def ener_off(self): + return self._ener_off - @lin_offs_set.setter - def lin_offs_set(self, new): - self.ener_off = new - return self.ener_off + @ener_off.setter + def ener_off(self, new): + self._ener_off = new + return self._ener_off - # Defining the electron number of turns to + # Defining the number of turns to realize the tracking simulation @property - def nturns_set(self): - return self.nturns + def nturns(self): + return self._nturns - @nturns_set.setter - def nturns_set(self, new_turns): - self.nturns = new_turns - return self.nturns + @nturns.setter + def nturns(self, new_turns): + self._nturns = new_turns + return self._nturns @property - def deltas_set(self): - return self.nturns + def deltas(self): + return self._deltas - @deltas_set.setter - def deltas_set(self, new_deltas): - self.nturns = new_deltas - return self.nturns + @deltas.setter + def deltas(self, new_deltas): + self._deltas = new_deltas + return self._deltas + # Function below calculates the linear model amplitudes for graphic analysis + + # this function defines too the physical limitants calculate by our linear model + # I have to verify if this function is a good programing practice, I dont know if this is the best aproach + + + # This property is defined in this way to calculate the linear model maximum amplitudes + # and to obtain the indices of the physical limitants + + @property + def lamppn_idx(self): + if self._lamppn_idx is None: + model = pymodels.si.create_accelerator() + model.cavity_on = False + model.radiation_on = False + self.lmd_amp_pos, self.idx_lim_pos = Tous_analysis.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) + self.lmd_amp_neg, self.idx_lim_neg = Tous_analysis.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) + + return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg + + + + # agora é hora de definir outras propriedades que serão utilizadas nesta classe para realizar a contabilização + # dos devios de energia mais relevantes para o projeto + # this function will calculate the weight factor to get the most important + # energy deviation in a touschek scattering process + + # this function must take two functions of my previous code + # all I need to do is take f_arg_mod and track_electrons + # Is important to note that track_electrons is based on the nominal model + # in this way I must convert the index of the elements from spos calculated by pyaccel + # and get the index that aproximates scalc to the spos positions + + #o que eu vou precisar para fazer esta função + #com certeza eu vou precisar tomar a aceitancia da maquina para o modelo passado no + #inicio da classe e então selecionar o valor para realizar o corte de desvio de energia + # + + def return_tracked(self,s_position, par): + if 'pos' in par: + res, ind = tousfunc.trackm_elec(self._acc,self._deltas,self._nturns,s_position) + elif 'neg' in par: + res, ind = tousfunc.trackm_elec(self._acc,-self._deltas,self._nturns,s_position) + + return res, ind + + #this function must pass the s_position for the calculation and the weighting the energy deviations + # and this function will use the functions that I'm defining in this class to get + # the tracked energy deviations already weighted by the touschek scattering piwinski + # distribution + + #for example: + # fast_aquisition(s_position, par) will use return_tracked + + def fast_aquisition(self): + pass + # tudo bem que desenvolver um código que obtenha diversos trackings para todos os pontos do anel é de fato uma coisa legal @@ -140,15 +193,6 @@ def deltas_set(self, new_deltas): # e é possível definir funções que vão realizar simulações mais demoradas (provavelmente neste caso será realizada uma sondagem ao longo # de todo anel de armazenamento) - # tenho de pensar em como realizar essas simulações rápidas, uma vez que eu já possuo - - - - # @property - # def define_nturns(self): - # if - - - - + # tenho de pensar em como realizar essas simulações rápidas, uma vez que eu já possuo as funções e como + # e como podemos saber em quais pontos específicos é bom realizar esta análise From f246df7e86fd57d330fa552b8153d083a30138df Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 28 Aug 2023 13:02:11 -0300 Subject: [PATCH 016/108] adcionando as funcionalidades a minha classe --- Classes.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Classes.py b/Classes.py index 5353119a..f7fe3cb2 100644 --- a/Classes.py +++ b/Classes.py @@ -1,6 +1,6 @@ from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute -import functions as tousfunc +import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op import numpy as _np @@ -74,7 +74,7 @@ def __init__(self,accelerator): self._sc_accps = None # check self._accep = None # check - off_array = _np.linspace(0,0.46, 460) + off_array = _np.linspace(0,0.046, 460) self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model self._nturns = None # check self._deltas = None # check @@ -174,6 +174,19 @@ def return_tracked(self,s_position, par): return res, ind + def get_weighting_tous(self, s_position): + + lspos = [s_position] + getacp = tousfunc.get_scaccep + + get_dis = tousfunc.nnorm_cutacp(self.acc, lspos, 5000, getacp) + + # this function will return the weighting factors in the scalc position convertion + return get_dis + + + + #this function must pass the s_position for the calculation and the weighting the energy deviations # and this function will use the functions that I'm defining in this class to get # the tracked energy deviations already weighted by the touschek scattering piwinski @@ -182,8 +195,20 @@ def return_tracked(self,s_position, par): #for example: # fast_aquisition(s_position, par) will use return_tracked - def fast_aquisition(self): - pass + def fast_aquisition(self, s_position, par): + + res, ind = Tous_analysis.return_tracked(s_position, par) + turn_lost, element_idx, deltas = res + + fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) + + Ddeltas = _np.diff(self.deltas) + + + + return res + + From 39bb212401cac31683151d7280bdeb590f07883b Mon Sep 17 00:00:00 2001 From: Thales_note Date: Tue, 29 Aug 2023 09:22:25 -0300 Subject: [PATCH 017/108] =?UTF-8?q?adcionando=20os=20calculos=20referentes?= =?UTF-8?q?=20a=20aquis=C3=A3o=20da=20distribui=C3=A7=C3=A3o=20de=20espalh?= =?UTF-8?q?amento=20touschek=20r=C3=A1pida?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 40 +++++++++++++++++++++++++++------------- functions.py | 2 +- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Classes.py b/Classes.py index f7fe3cb2..d99176ad 100644 --- a/Classes.py +++ b/Classes.py @@ -5,6 +5,7 @@ import pyaccel.optics as py_op import numpy as _np import matplotlib.pyplot as _plt +from mathphys.beam_optics import beam_rigidity class Tous_analysis(): @@ -65,9 +66,10 @@ class Tous_analysis(): def __init__(self,accelerator): self._acc = accelerator + self._beta = beam_rigidity(energy=3)[2] # defining beta to tranformate the energy deviation self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') - self.ltime = Lifetime(self._acc) + self._ltime = Lifetime(self._acc) fam = pymodels.si.get_family_data(self._acc) # Geting the name of the element we desire to study self.lname = list(fam.keys()) # geting self.index = tousfunc.el_idx_collector(self._acc, self.lname) # this calculation is relativily fast to execute, @@ -77,7 +79,7 @@ def __init__(self,accelerator): off_array = _np.linspace(0,0.046, 460) self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model self._nturns = None # check - self._deltas = None # check + self._deltas = None # check self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model @@ -167,25 +169,37 @@ def lamppn_idx(self): # def return_tracked(self,s_position, par): + lspos = _np.array(s_position, dtype=object) if 'pos' in par: - res, ind = tousfunc.trackm_elec(self._acc,self._deltas,self._nturns,s_position) + res, ind = tousfunc.trackm_elec(self._acc,self._deltas,self._nturns,lspos) elif 'neg' in par: - res, ind = tousfunc.trackm_elec(self._acc,-self._deltas,self._nturns,s_position) + res, ind = tousfunc.trackm_elec(self._acc,-self._deltas,self._nturns,lspos) return res, ind - def get_weighting_tous(self, s_position): + def get_weighting_tous(self, s_position, npt=5000): - lspos = [s_position] - getacp = tousfunc.get_scaccep - - get_dis = tousfunc.nnorm_cutacp(self.acc, lspos, 5000, getacp) + scalc, daccp, daccn = tousfunc.get_scaccep(self._acc, self._accep) + bf = self._beta + ltime = self._ltime + b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + taup, taun = (bf* daccp)**2, (bf*daccn)**2 + idx = _np.argmin(_np.abs(scalc-s_position)) + taup_0, taun_0 = taup[idx], taun[idx] + kappap_0 = _np.arctan(_np.sqrt(taup_0)) + kappan_0 = _np.arctan(_np.sqrt(taun_0)) + + kappa_pos = _np.linspace(kappap_0, _np.pi/2, npt) + kappa_neg = _np.linspace(kappan_0, _np.pi/2, npt) + + deltp = _np.tan(kappa_pos)/bf + deltn = _np.tan(kappa_neg)/bf + getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) + getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # this function will return the weighting factors in the scalc position convertion - return get_dis - - - + + return getdp, getdn, deltp, deltn #this function must pass the s_position for the calculation and the weighting the energy deviations # and this function will use the functions that I'm defining in this class to get diff --git a/functions.py b/functions.py index 70a5c3db..495d537b 100644 --- a/functions.py +++ b/functions.py @@ -72,7 +72,7 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): def trackm_elec(acc,deltas, n_turn, lspos): results = [] ind = [] - spos = _pyaccel.lattice.find_spos(acc) + spos = _pyaccel.lattice.find_spos(acc, indices='closed') for k, iten in enumerate(lspos): From 8cb48696e156538b7a535aa5039c641d25d5e3e8 Mon Sep 17 00:00:00 2001 From: Thales_note Date: Tue, 29 Aug 2023 10:56:52 -0300 Subject: [PATCH 018/108] tentativas de multiplicar os fatores de peso pelos delta de desvio de energia --- Classes.py | 114 ++++++++------------------------------------------- functions.py | 2 +- 2 files changed, 19 insertions(+), 97 deletions(-) diff --git a/Classes.py b/Classes.py index d99176ad..c1e70e4a 100644 --- a/Classes.py +++ b/Classes.py @@ -10,60 +10,6 @@ class Tous_analysis(): - # Defining this class I can call any accelerator I want to realize touschek scattering analysis - # Keep in mind another terms that could be add in the init of the class - - # the acceptance is calculated utilizing the de accelerator's model so it'isnt necessary a priori - # pass the energy acceptance to the class - - # Define the interval to choose the energy deviation to realize the tracking simulation - # Pass a parameter to define when I desire to use some function - # if tracking calculates the simulation utilizing the tracking function that was created - # if linear calculates the physical limitants that use a type of model for the calculation - - # I can take the indices a long the ring as parameters to use in the model. - - # eu tenho que pensar, porque se eu ficar fazendo dessa maneira todos os meus atributos serão none - # e depois eu vou precisar alterar este atributo manualmente será que é realmente isso que eu desejo ? - - # em primeiro lugar apenas para esclarecimento, eu posso definir um atributo da maneira que eu quiser e depois posso alterá-lo - # da forma que eu achar necessário - - # o que é mais vantajoso definir os atributos como None e depois alterar seus valores manualmente ou possuir uma configuração padrão em que - # esses atributos já são definidos automaticamente? - - # Parece interessante a ideia de que os atributos sejam definidos em uma configuração padrão e sejam alterados conforme eu vá passando - # informações para o objeto da classe criada - - # em classes eu posso passar alguns parâmetros para que a classe saiba identificar qual é o modelo necessário que deve ser utilizado - # ou então como definir os atributos com base nas palavras chave passada nos argumentos - - # vou começar a justificar alguns passos na criação desta classes para posteriormente eu me orientar - # e não criar uma classe sem saber interpretar os motivos de estar definindo de uma forma e não de outra - - '''Justificativa do por quê definir alguns atributos com valor padrão None''' - - # em primeiro lugar, a partir do que conversei com o fernando no dia 23.08.2023 é uma boa prática de progrmação criar classes que - # não gastem muito tempo ao serem iniciadas, ou seja, não é desejado que ao criar um objeto muito tempo seja empregado - # na construção do __init__. - # Pensando nisso, existem atributos que são fundamentais para a classe que está sendo criada e, portanto, já devem ser - # definidos no __init__, mas como não desejamos que muito tempo seja empregado na operação de instaciação de um objeto, - # definimos alguns objetos com valor padrão None, para posteriormente redefinir essas grandezas provavelmente com a definição de outras - # funções que já estão inicialmente implementadas - - # Agora vejamos, eu preciso definir diversos atributos que não necessitam de um tempo de execução muito longo - # qual a melhor forma de se fazer isso ? - - # eu poderia definir uma função que define mais atributos ao mesmo tempo? - # isso pode ser util quando feito de maneira clara - - # é interessante que esta classe seja flexível a ponto de permitir que as simulações de tracking sejam realizadas - # por quem a esta utilizando - - # todas as funções que foram definidas até o momento são utilizadas por meio de um loop que é executado em todos os elementos de - # uma lista de posições ao longo do feixe, essa lista pode até mesmo ser a lista completa de todas as posições do anel - # essa lista pode ser de elementos específicos em que se deseje estudar a taxa de espalhamento touschek - def __init__(self,accelerator): self._acc = accelerator self._beta = beam_rigidity(energy=3)[2] # defining beta to tranformate the energy deviation @@ -127,15 +73,6 @@ def deltas(self): def deltas(self, new_deltas): self._deltas = new_deltas return self._deltas - - # Function below calculates the linear model amplitudes for graphic analysis - - # this function defines too the physical limitants calculate by our linear model - # I have to verify if this function is a good programing practice, I dont know if this is the best aproach - - - # This property is defined in this way to calculate the linear model maximum amplitudes - # and to obtain the indices of the physical limitants @property def lamppn_idx(self): @@ -147,26 +84,6 @@ def lamppn_idx(self): self.lmd_amp_neg, self.idx_lim_neg = Tous_analysis.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg - - - - # agora é hora de definir outras propriedades que serão utilizadas nesta classe para realizar a contabilização - # dos devios de energia mais relevantes para o projeto - - - # this function will calculate the weight factor to get the most important - # energy deviation in a touschek scattering process - - # this function must take two functions of my previous code - # all I need to do is take f_arg_mod and track_electrons - # Is important to note that track_electrons is based on the nominal model - # in this way I must convert the index of the elements from spos calculated by pyaccel - # and get the index that aproximates scalc to the spos positions - - #o que eu vou precisar para fazer esta função - #com certeza eu vou precisar tomar a aceitancia da maquina para o modelo passado no - #inicio da classe e então selecionar o valor para realizar o corte de desvio de energia - # def return_tracked(self,s_position, par): lspos = _np.array(s_position, dtype=object) @@ -197,33 +114,38 @@ def get_weighting_tous(self, s_position, npt=5000): deltn = _np.tan(kappa_neg)/bf getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) + + # eliminating negative values + indp = _np.where(getdp<0) + indn = _np.where(getdn<0) + getdp[indp] == 0 + getdn[indn] == 0 + # this function will return the weighting factors in the scalc position convertion return getdp, getdn, deltp, deltn - #this function must pass the s_position for the calculation and the weighting the energy deviations - # and this function will use the functions that I'm defining in this class to get - # the tracked energy deviations already weighted by the touschek scattering piwinski - # distribution - - #for example: - # fast_aquisition(s_position, par) will use return_tracked - def fast_aquisition(self, s_position, par): res, ind = Tous_analysis.return_tracked(s_position, par) - turn_lost, element_idx, deltas = res - - fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) + + turn_lost = _np.zeros(len(res)) + delta = _np.zeros(len(res)) + for idx, iten in enumerate(res): - Ddeltas = _np.diff(self.deltas) + turn_lost[idx] = iten[0] + delta[idx] = iten[2] + fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) - return res + Ddeltas = _np.diff(delta) + size = Ddeltas.size + # for i, iten in enumerate(deltp): + return res # tudo bem que desenvolver um código que obtenha diversos trackings para todos os pontos do anel é de fato uma coisa legal diff --git a/functions.py b/functions.py index 495d537b..ce8cb4df 100644 --- a/functions.py +++ b/functions.py @@ -302,7 +302,7 @@ def norm_d(acc, lsps, scalc,_npt, norm=True): def get_scaccep(acc, accep): spos = _pyaccel.lattice.find_spos(acc, indices='closed') - npt = int((spos[-1]-spos[0])/0.1) + npt = int((spos[-1]-spos[0])/0.01) scalc = _np.linspace(spos[0],spos[-1], npt) daccpp = _np.interp(scalc, spos, accep[1]) daccpn = _np.interp(scalc, spos, accep[0]) From 60a3d7a3fd65c3d3999d7651c14529afb48410fc Mon Sep 17 00:00:00 2001 From: Thales_note Date: Tue, 29 Aug 2023 13:03:06 -0300 Subject: [PATCH 019/108] =?UTF-8?q?mais=20implementa=C3=A7=C3=B5es=20refer?= =?UTF-8?q?entes=20a=20pesagem=20dos=20desvios=20de=20enrgia=20mais=20rele?= =?UTF-8?q?vantes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Classes.py b/Classes.py index c1e70e4a..374e179d 100644 --- a/Classes.py +++ b/Classes.py @@ -129,21 +129,22 @@ def fast_aquisition(self, s_position, par): res, ind = Tous_analysis.return_tracked(s_position, par) - turn_lost = _np.zeros(len(res)) - delta = _np.zeros(len(res)) + turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) for idx, iten in enumerate(res): - turn_lost[idx] = iten[0] + elem_lost[idx] = iten[1] delta[idx] = iten[2] - fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) - Ddeltas = _np.diff(delta) - size = Ddeltas.size - # for i, iten in enumerate(deltp): + for i, iten in enumerate(delta): + indp = _np.where(delta[i] < deltp < delta[i+1]) + fdensp[indp] = fdensp * Ddeltas[i] + + indn = _np.where(delta[i] < deltn < delta[i+1]) + fdensn[indn] = fdensn * Ddeltas[i] return res From a1d7639cafa0dfbc4769c6879243b9144cac2fa6 Mon Sep 17 00:00:00 2001 From: Thales_note Date: Tue, 29 Aug 2023 19:12:17 -0300 Subject: [PATCH 020/108] =?UTF-8?q?=20adcionando=20estrutura=20de=20decis?= =?UTF-8?q?=C3=A3o=20que=20bloqueia=20futuros=20erros=20no=20codigo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Classes.py b/Classes.py index 374e179d..e6405021 100644 --- a/Classes.py +++ b/Classes.py @@ -137,16 +137,21 @@ def fast_aquisition(self, s_position, par): fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) Ddeltas = _np.diff(delta) - + + # here the multiplication by the variation of the energy deviation for i, iten in enumerate(delta): + # this condition is necessary for eliminate boundary errors + if i == delta.size: + break + # this version is an attempt to turn this code completly generic + # and appliable to another codes indp = _np.where(delta[i] < deltp < delta[i+1]) - fdensp[indp] = fdensp * Ddeltas[i] - + fdensp[indp] = fdensp[indp] * Ddeltas[i] indn = _np.where(delta[i] < deltn < delta[i+1]) - fdensn[indn] = fdensn * Ddeltas[i] + fdensn[indn] = fdensn[indn] * Ddeltas[i] - return res + return fdensp, fdensn, deltp, deltn # tudo bem que desenvolver um código que obtenha diversos trackings para todos os pontos do anel é de fato uma coisa legal From 6ef9970f8b7c5cba29b5b5382b554a8b6e38976e Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 30 Aug 2023 13:24:49 -0300 Subject: [PATCH 021/108] =?UTF-8?q?as=20altera=C3=A7=C3=B5es=20provavelmen?= =?UTF-8?q?te=20n=C3=A3o=20ser=C3=A3o=20permanentes=20at=C3=A9=20eu=20obte?= =?UTF-8?q?r=20uma=20forma=20de=20definir=20a=20fun=C3=A7=C3=A3o=20de=20um?= =?UTF-8?q?a=20forma=20mais=20consistente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 73 +++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/Classes.py b/Classes.py index e6405021..eb1c64cf 100644 --- a/Classes.py +++ b/Classes.py @@ -5,14 +5,14 @@ import pyaccel.optics as py_op import numpy as _np import matplotlib.pyplot as _plt -from mathphys.beam_optics import beam_rigidity +from mathphys.beam_optics import beam_rigidity as _beam_rigidity class Tous_analysis(): def __init__(self,accelerator): self._acc = accelerator - self._beta = beam_rigidity(energy=3)[2] # defining beta to tranformate the energy deviation + self._beta = _beam_rigidity(energy=3)[2] # defining beta to tranformate the energy deviation self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') self._ltime = Lifetime(self._acc) @@ -80,19 +80,22 @@ def lamppn_idx(self): model = pymodels.si.create_accelerator() model.cavity_on = False model.radiation_on = False - self.lmd_amp_pos, self.idx_lim_pos = Tous_analysis.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) - self.lmd_amp_neg, self.idx_lim_neg = Tous_analysis.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) + self.lmd_amp_pos, self.idx_lim_pos = tousfunc.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) + self.lmd_amp_neg, self.idx_lim_neg = tousfunc.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg def return_tracked(self,s_position, par): - lspos = _np.array(s_position, dtype=object) + model = pymodels.si.create_accelerator() + model.cavity_on = True + model.radiation_on = True + lspos = [s_position] if 'pos' in par: - res, ind = tousfunc.trackm_elec(self._acc,self._deltas,self._nturns,lspos) + res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,lspos) elif 'neg' in par: - res, ind = tousfunc.trackm_elec(self._acc,-self._deltas,self._nturns,lspos) + res, ind = tousfunc.trackm_elec(model,-self._deltas,self._nturns,lspos) - return res, ind + return res[0] def get_weighting_tous(self, s_position, npt=5000): @@ -112,54 +115,46 @@ def get_weighting_tous(self, s_position, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf - getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) - getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) + getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False).squeeze() + getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False).squeeze() # eliminating negative values indp = _np.where(getdp<0) indn = _np.where(getdn<0) + indp = indp[0] + indn = indn[0] getdp[indp] == 0 getdn[indn] == 0 - # this function will return the weighting factors in the scalc position convertion + # this function will return the weighting factors in the scalc position convertion return getdp, getdn, deltp, deltn + + # In general, this function is usefull when we desire to calculate the touschek scattering weighting function for one specific point along the ring def fast_aquisition(self, s_position, par): - res, ind = Tous_analysis.return_tracked(s_position, par) - + res = self.return_tracked(s_position, par) turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) + for idx, iten in enumerate(res): - turn_lost[idx] = iten[0] - elem_lost[idx] = iten[1] - delta[idx] = iten[2] + tlost, elmnlost, delt = iten + turn_lost[idx] = tlost + elem_lost[idx] = elmnlost + delta[idx] = delt - fdensp, fdensn, deltp, deltn = Tous_analysis.get_weighting_tous(s_position) - Ddeltas = _np.diff(delta) + Ddeltas = _np.diff(delta)[0] + fdensp, fdensn, deltp, deltn = self.get_weighting_tous(s_position) - # here the multiplication by the variation of the energy deviation - for i, iten in enumerate(delta): - # this condition is necessary for eliminate boundary errors - if i == delta.size: - break - # this version is an attempt to turn this code completly generic - # and appliable to another codes - indp = _np.where(delta[i] < deltp < delta[i+1]) - fdensp[indp] = fdensp[indp] * Ddeltas[i] + fp = fdensp.squeeze() + fn = fdensn.squeeze() - indn = _np.where(delta[i] < deltn < delta[i+1]) - fdensn[indn] = fdensn[indn] * Ddeltas[i] - - return fdensp, fdensn, deltp, deltn + fp *= Ddeltas + fn *= Ddeltas + deltp *= 1e2 + deltn *= 1e2 + + return fp, fn, deltp, deltn - # tudo bem que desenvolver um código que obtenha diversos trackings para todos os pontos do anel é de fato uma coisa legal - # mas para fazer isso é necessário empregar muito tempo de simulação - # dessa forma, é possível definir funções que serão implementadas para realizar simulações rápidas - # e é possível definir funções que vão realizar simulações mais demoradas (provavelmente neste caso será realizada uma sondagem ao longo - # de todo anel de armazenamento) - - # tenho de pensar em como realizar essas simulações rápidas, uma vez que eu já possuo as funções e como - # e como podemos saber em quais pontos específicos é bom realizar esta análise From 17f064d8f9265172dfd385eaf1abf77698992656 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 30 Aug 2023 14:11:57 -0300 Subject: [PATCH 022/108] =?UTF-8?q?adicionando=20os=20coment=C3=A1rios=20p?= =?UTF-8?q?ara=20nortear=20os=20pr=C3=B3ximos=20passos=20que=20devo=20real?= =?UTF-8?q?izar=20na=20constru=C3=A7=C3=A3o=20da=20minha=20classe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Classes.py b/Classes.py index eb1c64cf..53ec7fa9 100644 --- a/Classes.py +++ b/Classes.py @@ -156,5 +156,12 @@ def fast_aquisition(self, s_position, par): return fp, fn, deltp, deltn + # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades + + # Uma nova funcionalidade que eu preciso inserir é o plot dos gráficos referentes ao mapa de onde as particulas se perdem + # para determinados desvios de energia + + # Eu posso retornar o gráfico para as distribuições de espalhamento touschek sozinhas + # Eu posso também plotar os gráficos juntos From 9b4ebef241f7406248e5c21da12aee3be13fc74e Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 30 Aug 2023 14:13:23 -0300 Subject: [PATCH 023/108] comentando a respeito dos proximos passos ainda --- Classes.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Classes.py b/Classes.py index 53ec7fa9..a455387d 100644 --- a/Classes.py +++ b/Classes.py @@ -157,11 +157,29 @@ def fast_aquisition(self, s_position, par): return fp, fn, deltp, deltn # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades - - # Uma nova funcionalidade que eu preciso inserir é o plot dos gráficos referentes ao mapa de onde as particulas se perdem - # para determinados desvios de energia - # Eu posso retornar o gráfico para as distribuições de espalhamento touschek sozinhas - # Eu posso também plotar os gráficos juntos + # Eu posso retornar o gráfico para as distribuições de espalhamento touschek sozinhas (apenas as distribuições de espalhamento touschek) + # Eu quero que esta classe também seja capaz de plotar o gráfico de tracking juntamente com + # as voltas em que esses elétrons foram perdidos e juntamente com as distribuições de espalhamento touschek + + # (isso é bastante util para analisar o tracking e e verificar os fatores de peso para cada desvio de energia) + + + # eu estou pensando conforme eu havia proposto, que esta classe também forneça as pesagens para elementos + # específicos do anel, para isso alguma função da classe ou até mesmo a classe poderia receber os nomes dos elementos em + # que se deseja realizar a análise do espalhamento + # + # mas se a classe receber diretamente o nome do elemento que eu desejo realizar a análise eu preciso me perguntar + # se isso pode prejudicar a função que calcula a aquisição rápida das distribuições de espalhamento eu preciso repensar essa abordagem + # porém se eu definir funções independetes acredito que isso não afetará + + # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo + # + # + # + # + # + # + # From c31a7c6cf65130c26db623eb471b9db3068fbb70 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 30 Aug 2023 14:59:28 -0300 Subject: [PATCH 024/108] =?UTF-8?q?coment=C3=A1rios=20adicionais=20feitos?= =?UTF-8?q?=20para=20seguir=20com=20os=20pr=C3=B3ximos=20passos=20que=20eu?= =?UTF-8?q?=20devo=20seguir,=20o=20dia=20de=20hoje=20foi=20complicado,=20e?= =?UTF-8?q?u=20percebi=20que=20eu=20criei=20uma=20fun=C3=A7=C3=A3o=20que?= =?UTF-8?q?=20n=C3=A3o=20=C3=A9=20t=C3=A3o=20=C3=BAtil=20quanto=20eu=20pen?= =?UTF-8?q?sava=20porque=20j=C3=A1=20existe=20a=20pyaccel.lattice.find=5Fi?= =?UTF-8?q?ndices=20a=20qual=20busca=20todos=20os=20indices=20quando=20vc?= =?UTF-8?q?=20passa=20o=20fam=5Fname=20e=20o=20nome=20real=20do=20elemento?= =?UTF-8?q?=20em=20que=20se=20deseja=20realizar=20as=20an=C3=A1lises.=20Eu?= =?UTF-8?q?=20estava=20bastante=20cansado=20e=20a=20=C3=BAnica=20coisa=20q?= =?UTF-8?q?ue=20eu=20conseguir=20fazer=20foi=20corrigir=20alguns=20problem?= =?UTF-8?q?as=20que=20estava=20verificando=20em=20minha=20classe=20anterio?= =?UTF-8?q?rmente,=20descobri=20que=20para=20chamar=20uma=20fun=C3=A7?= =?UTF-8?q?=C3=A3o=20dentro=20de=20uma=20classe=20basta=20escrever=20self.?= =?UTF-8?q?fun=C3=A7=C3=A3o=5Fdefinida.=20Foi=20um=20dia=20de=20pequenos?= =?UTF-8?q?=20progressos=20porque=20eu=20estava=20muito=20cansado,=20mas?= =?UTF-8?q?=20acredito=20que=20n=C3=A3o=20tenha=20sido=20t=C3=A3o=20ruim.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 16 ++++++++++++++-- functions.py | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Classes.py b/Classes.py index a455387d..ecd8cad2 100644 --- a/Classes.py +++ b/Classes.py @@ -165,14 +165,26 @@ def fast_aquisition(self, s_position, par): # (isso é bastante util para analisar o tracking e e verificar os fatores de peso para cada desvio de energia) - # eu estou pensando conforme eu havia proposto, que esta classe também forneça as pesagens para elementos + # eu estou pensando, conforme eu havia proposto, em fazer esta classe também fornecer as pesagens para elementos # específicos do anel, para isso alguma função da classe ou até mesmo a classe poderia receber os nomes dos elementos em - # que se deseja realizar a análise do espalhamento + # que se deseja realizar a análise do espalhamento como por exemplo ('BC', 'B1',...) # # mas se a classe receber diretamente o nome do elemento que eu desejo realizar a análise eu preciso me perguntar # se isso pode prejudicar a função que calcula a aquisição rápida das distribuições de espalhamento eu preciso repensar essa abordagem # porém se eu definir funções independetes acredito que isso não afetará + # para não prejudicar nenhuma funcionalidade da classe o que eu posso fazer é criar uma espécie de verificador onde eu defino um determinado atributo que receba um + # numero indeterminado de nomes dos elementos para que a ánálise seja realizada e por meio deste atributo em específico + # vai ter uma função especifica + + # o problema dessa análise é que a função que eu implementei não é genérica e além disso possuo o problema de essa mesma função não conseguir + # selecionar elementos que estejam em markers de trechos retos ou em trechos de baixo beta + + # Agora eu to pensando aqui comigo que como sempre eu sou inutil mesmo e que ja existe uma função implementada no pyaccel que seleciona os indices + # a função find_indices e get_atributte encontram qualquer coisa que vc precisa então tenho pensado que eu raelmente deva + # considerar como irrelevantes as funções que eu mesmo implementei porque estas funções com certeza já estão devidamente otimizadas + + # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo # # diff --git a/functions.py b/functions.py index ce8cb4df..01e5465d 100644 --- a/functions.py +++ b/functions.py @@ -83,6 +83,24 @@ def trackm_elec(acc,deltas, n_turn, lspos): return results, ind +# this function will sellect the index by the array containing the names of the elements along the ring that people desire to study +# please let's try to run away from the repetitive structures that + +# certo eu vou ter todos os indices referentes ao elementos que eu preciso e quero analisar, mas qual eu devo escolher, +# devo tentar selecionar o trecho em que o beta é mínimo para obter + +# sabendo que a função beta é a envoltória do feixe e, portanto, os pontos onde o feixe se encontra em posições de menor beta são as posições onde podem +# ocorrer com maior probabilidade os espalhamentos touschek, lembrando que a envoltória é quem rege o quanto de espaço estes elétrons possuem para oscilar +# Dessa forma, menor a envoltória menor também será o espaço que os elétrons podem realizar suas oscilações betatron aumentando a densidade do feixe em regiões +# de baixo beta + +# so the lname passed to the function must be an array + +def index_getter(acc, par, lname): + + lname + + # function returns the desired element index of dipoles, quadrupoles, sextupoles and any other # element that is desired, the only thing that is needed is to pass a string From cd158172bee74832e6d859c24697f0a2bf5cdf34 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 30 Aug 2023 15:01:01 -0300 Subject: [PATCH 025/108] =?UTF-8?q?ficou=20faltando=20esta=20modifica?= =?UTF-8?q?=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Classes.py b/Classes.py index ecd8cad2..ac4b2bb7 100644 --- a/Classes.py +++ b/Classes.py @@ -183,7 +183,9 @@ def fast_aquisition(self, s_position, par): # Agora eu to pensando aqui comigo que como sempre eu sou inutil mesmo e que ja existe uma função implementada no pyaccel que seleciona os indices # a função find_indices e get_atributte encontram qualquer coisa que vc precisa então tenho pensado que eu raelmente deva # considerar como irrelevantes as funções que eu mesmo implementei porque estas funções com certeza já estão devidamente otimizadas - + + # tornando as coisas mais claras: a find_indices necessita find_indices(acc, 'fam_name', 'nome_do_elemento') + # o segundo elemento passado para a função é literalmente # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo # From 22a006ceab487c5de8d2993a6aa734f641458c59 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 31 Aug 2023 11:30:34 -0300 Subject: [PATCH 026/108] add changes --- Classes.py | 25 +++++++++++++++++++------ functions.py | 19 ++++++++++++++----- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Classes.py b/Classes.py index ac4b2bb7..7cea1bfe 100644 --- a/Classes.py +++ b/Classes.py @@ -1,5 +1,5 @@ from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute +from pyaccel.lattice import get_attribute, find_indices import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op @@ -16,9 +16,7 @@ def __init__(self,accelerator): self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') self._ltime = Lifetime(self._acc) - fam = pymodels.si.get_family_data(self._acc) # Geting the name of the element we desire to study - self.lname = list(fam.keys()) # geting - self.index = tousfunc.el_idx_collector(self._acc, self.lname) # this calculation is relativily fast to execute, + self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires self._sc_accps = None # check self._accep = None # check @@ -28,6 +26,12 @@ def __init__(self,accelerator): self._deltas = None # check self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model + + + # eu tenho que pensar em como eu vou passar esses indices para realizar as analises + + + self.index = find_indices(self._acc, 'fam_name', ) # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @@ -73,6 +77,15 @@ def deltas(self): def deltas(self, new_deltas): self._deltas = new_deltas return self._deltas + + @property + def lname(self): + return self._lname + + @lname.setter + def lname(self, call_lname): + self._lname = call_lname + return self._lname @property def lamppn_idx(self): @@ -184,8 +197,8 @@ def fast_aquisition(self, s_position, par): # a função find_indices e get_atributte encontram qualquer coisa que vc precisa então tenho pensado que eu raelmente deva # considerar como irrelevantes as funções que eu mesmo implementei porque estas funções com certeza já estão devidamente otimizadas - # tornando as coisas mais claras: a find_indices necessita find_indices(acc, 'fam_name', 'nome_do_elemento') - # o segundo elemento passado para a função é literalmente + # Tornando as coisas mais claras: a find_indices necessita find_indices(acc, 'fam_name', 'nome_do_elemento') + # O segundo elemento passado para a função é literalmente # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo # diff --git a/functions.py b/functions.py index 01e5465d..b101566d 100644 --- a/functions.py +++ b/functions.py @@ -96,20 +96,29 @@ def trackm_elec(acc,deltas, n_turn, lspos): # so the lname passed to the function must be an array -def index_getter(acc, par, lname): - - lname +# lname deve ser a lista de elementos que será passada para a função ['BC','B1','B2'] por exemplo - # function returns the desired element index of dipoles, quadrupoles, sextupoles and any other # element that is desired, the only thing that is needed is to pass a string +# eu preciso pensar se vale a pena colocar todos os indices que eu estou pensando em colocar ou se o pymodels da conta do recado +# eu tenho que me perguntar se é interessante obter os indices de elementos como lkkp por exemplo + def el_idx_collector(acc, lname): + all_index = [] + + if 'mia' in lname: + all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mia')) + elif'mib' in lname: + all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mib')) + elif 'mip' in lname: + all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mip')) + fam_data = _pymodels.si.get_family_data(acc) - for string in lname: + for string in list(lname): element_index = [] array_idx = _np.array(fam_data[string]['index'], dtype=object) From 4750e2c589543a135a4ec123ec63dd4655fd05a7 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 31 Aug 2023 11:32:33 -0300 Subject: [PATCH 027/108] add changes --- Classes.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Classes.py b/Classes.py index 7cea1bfe..daef8231 100644 --- a/Classes.py +++ b/Classes.py @@ -18,20 +18,14 @@ def __init__(self,accelerator): self._ltime = Lifetime(self._acc) self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires - self._sc_accps = None # check - self._accep = None # check + self._sc_accps = None + self._accep = None off_array = _np.linspace(0,0.046, 460) self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model - self._nturns = None # check - self._deltas = None # check - - self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model - - - # eu tenho que pensar em como eu vou passar esses indices para realizar as analises + self._nturns = None + self._deltas = None - - self.index = find_indices(self._acc, 'fam_name', ) + self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @@ -83,7 +77,7 @@ def lname(self): return self._lname @lname.setter - def lname(self, call_lname): + def lname(self, call_lname): # call_name is the list of element names (passed by the user) that someone desires to know the distribution self._lname = call_lname return self._lname @@ -168,6 +162,11 @@ def fast_aquisition(self, s_position, par): deltn *= 1e2 return fp, fn, deltp, deltn + + # e se eu fizesse a função dessa classe já pensando na possibilidade do calculo ser realizado para apenas um ponto do anel ou para varios ? + # caso eu seja questionado sobre isso, posso justificar que para apenas um ponto do anel os cálculos são executados mais rapidamente. + + # caso seja necessário pegar algum indice que esteja fora do get_family_data eu preciso usar o find_indices do pyaccel # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades From f70914a571857afa231463c4ea535b54355b31b9 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 31 Aug 2023 11:33:27 -0300 Subject: [PATCH 028/108] add changes --- functions.py | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/functions.py b/functions.py index b101566d..9b35fe99 100644 --- a/functions.py +++ b/functions.py @@ -106,7 +106,6 @@ def trackm_elec(acc,deltas, n_turn, lspos): # eu tenho que me perguntar se é interessante obter os indices de elementos como lkkp por exemplo def el_idx_collector(acc, lname): - all_index = [] if 'mia' in lname: @@ -143,13 +142,9 @@ def el_idx_collector(acc, lname): return all_index -def plot_track(lista_resul, lista_idx, lista_off, param, element_idx, accep): +def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep): # ---------------- - acc= _pymodels.si.create_accelerator() - acc.cavity_on = False - acc.radiation_on= False - acc.vchamber_on = False twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax betax = betax*(1/5) @@ -181,12 +176,7 @@ def plot_track(lista_resul, lista_idx, lista_off, param, element_idx, accep): a2.set_title(r'tracking ', fontsize=16) - # Tracking graphics - # ---------------- - -# defining the acceptance given a point s of the ring - - acp_s = accep[element_idx] + acp_s = accep[element_idx] # defining the acceptance given the begining tracking point ind = _np.argmin(_np.abs(lista_off-acp_s)) a2.plot(spos[lista_idx][:ind], lista_off[:ind]*1e2,'b.', label=r'accep. limit', alpha=0.25) @@ -199,27 +189,15 @@ def plot_track(lista_resul, lista_idx, lista_off, param, element_idx, accep): a2.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') for item in lista_resul: a2.plot(spos[int(item[1])], -item[2]*1e2, 'r.') - -# plotting acceptances with _plt.hlines - _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) - - # linear model graphic - # ---------------- - - # plotting beta function - a2.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') - - # plotting magnetic lattice - _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) - - # initial position that tracking begins + _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff + a2.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function + _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) #magnetic lattice a2.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( - acc[element_idx].fam_name, "%.2f" % spos[element_idx])) + acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position that tracking begins - # setting configurations of the graphic - a2.set_xlabel(r'$s$ [m]', fontsize=14) + a2.set_xlabel(r'$s$ [m]', fontsize=14) # setting configurations of the graphic a2.legend(loc='best', ncol=2) fig.tight_layout() From 9c90fec1b6d2eb9e4cd8d77903431e21fbf33f9d Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 31 Aug 2023 13:11:51 -0300 Subject: [PATCH 029/108] =?UTF-8?q?adicionando=20mais=20mudan=C3=A7as=20e?= =?UTF-8?q?=20ideias=20na=20classe=20que=20estou=20desenvolvendo=20e=20me?= =?UTF-8?q?=20lascando=20bastante=20pra=20fazer=20isso=20:)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 22 ++++++++++++++++++---- functions.py | 4 ++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Classes.py b/Classes.py index daef8231..59adf65a 100644 --- a/Classes.py +++ b/Classes.py @@ -96,13 +96,15 @@ def return_tracked(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True model.radiation_on = True - lspos = [s_position] + model.vchamber = True + lspos = list(s_position) + if 'pos' in par: res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,lspos) elif 'neg' in par: res, ind = tousfunc.trackm_elec(model,-self._deltas,self._nturns,lspos) - return res[0] + return res, ind def get_weighting_tous(self, s_position, npt=5000): @@ -140,10 +142,14 @@ def get_weighting_tous(self, s_position, npt=5000): # In general, this function is usefull when we desire to calculate the touschek scattering weighting function for one specific point along the ring def fast_aquisition(self, s_position, par): + # this raise blocks to runing the program if the list of s position has more than 1 element + if len(list(s_position)) != 1: + raise Exception('This function suports only one s position') - res = self.return_tracked(s_position, par) + res, ind = self.return_tracked(s_position, par) + res = res[0] turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) - + for idx, iten in enumerate(res): tlost, elmnlost, delt = iten turn_lost[idx] = tlost @@ -163,6 +169,14 @@ def fast_aquisition(self, s_position, par): return fp, fn, deltp, deltn + def comp_aq(self, lspos, par): + + # remember that ind is the index that represents the initial position where tracking begins + res, ind = self.return_tracked(lspos, par) + + + + # e se eu fizesse a função dessa classe já pensando na possibilidade do calculo ser realizado para apenas um ponto do anel ou para varios ? # caso eu seja questionado sobre isso, posso justificar que para apenas um ponto do anel os cálculos são executados mais rapidamente. diff --git a/functions.py b/functions.py index 9b35fe99..3275ba0d 100644 --- a/functions.py +++ b/functions.py @@ -398,8 +398,8 @@ def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() # eliminating the negative values from array - indp = _np.where(y_p<0) - indn = _np.where(y_n<0) + indp = _np.where(y_p<0)[0] + indn = _np.where(y_n<0)[0] y_p[indp] == 0 y_n[indn] == 0 From 1e9f0f5ac9bc8c1daa80ad339329c90007215bbb Mon Sep 17 00:00:00 2001 From: Thales_note Date: Thu, 31 Aug 2023 19:07:32 -0300 Subject: [PATCH 030/108] corrigindo problemas que ocorreram quando eu fiz alguns testes com a minha classe --- Classes.py | 5 ++--- functions.py | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Classes.py b/Classes.py index 59adf65a..a33e03e0 100644 --- a/Classes.py +++ b/Classes.py @@ -96,8 +96,7 @@ def return_tracked(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True model.radiation_on = True - model.vchamber = True - lspos = list(s_position) + lspos = tousfunc.t_list(s_position) if 'pos' in par: res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,lspos) @@ -143,7 +142,7 @@ def get_weighting_tous(self, s_position, npt=5000): def fast_aquisition(self, s_position, par): # this raise blocks to runing the program if the list of s position has more than 1 element - if len(list(s_position)) != 1: + if len(tousfunc.t_list(s_position)) != 1: raise Exception('This function suports only one s position') res, ind = self.return_tracked(s_position, par) diff --git a/functions.py b/functions.py index 3275ba0d..7b933d2d 100644 --- a/functions.py +++ b/functions.py @@ -210,6 +210,13 @@ def select_idx(list_, param1, param2): return n_arr +def t_list(elmnt): + if type(elmnt) == float or type(elmnt) == int: + return [elmnt] + else: + return list(elmnt) + + def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): tau = (_np.tan(kappa)**2)[:, None] From 6866b754cf3372d441a92b1a169bf264f108c90f Mon Sep 17 00:00:00 2001 From: Thales_note Date: Thu, 31 Aug 2023 19:08:56 -0300 Subject: [PATCH 031/108] =?UTF-8?q?n=C3=A3o=20tinha=20alterado=20tudo=20qu?= =?UTF-8?q?e=20era=20pra=20alterar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Classes.py b/Classes.py index a33e03e0..62cc8342 100644 --- a/Classes.py +++ b/Classes.py @@ -168,6 +168,8 @@ def fast_aquisition(self, s_position, par): return fp, fn, deltp, deltn + # vale mencionar que a fast aquisition da forma como esta definida já está funcional + def comp_aq(self, lspos, par): # remember that ind is the index that represents the initial position where tracking begins From b0e8407658954270b359f013f106f5ded31e1154 Mon Sep 17 00:00:00 2001 From: Thales_note Date: Fri, 1 Sep 2023 11:04:23 -0300 Subject: [PATCH 032/108] =?UTF-8?q?adcionando=20mudan=C3=A7as=20e=20novas?= =?UTF-8?q?=20funcionalidades=20a=20classe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 99 ++++++++++++++++++++++++++++------------------------ functions.py | 9 +++++ 2 files changed, 63 insertions(+), 45 deletions(-) diff --git a/Classes.py b/Classes.py index 62cc8342..eb47df72 100644 --- a/Classes.py +++ b/Classes.py @@ -1,5 +1,5 @@ from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute, find_indices +from pyaccel.lattice import get_attribute, find_indices, find_spos import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op @@ -92,16 +92,17 @@ def lamppn_idx(self): return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg - def return_tracked(self,s_position, par): + def return_single_tracked(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True model.radiation_on = True - lspos = tousfunc.t_list(s_position) + # alterar depois a função que é utilizada nesta função para realizar o tracking. + if 'pos' in par: - res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,lspos) + res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,s_position) elif 'neg' in par: - res, ind = tousfunc.trackm_elec(model,-self._deltas,self._nturns,lspos) + res, ind = tousfunc.trackm_elec(model,-self._deltas,self._nturns,s_position) return res, ind @@ -123,8 +124,8 @@ def get_weighting_tous(self, s_position, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf - getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False).squeeze() - getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False).squeeze() + getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) + getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # eliminating negative values indp = _np.where(getdp<0) @@ -144,8 +145,9 @@ def fast_aquisition(self, s_position, par): # this raise blocks to runing the program if the list of s position has more than 1 element if len(tousfunc.t_list(s_position)) != 1: raise Exception('This function suports only one s position') - - res, ind = self.return_tracked(s_position, par) + + lspos = tousfunc.t_list(s_position) + res, ind = self.return_tracked(lspos, par) res = res[0] turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) @@ -170,57 +172,64 @@ def fast_aquisition(self, s_position, par): # vale mencionar que a fast aquisition da forma como esta definida já está funcional - def comp_aq(self, lspos, par): - # remember that ind is the index that represents the initial position where tracking begins - res, ind = self.return_tracked(lspos, par) +# a função complete aquisition poderia receber uma lista com os nomes dos elementos que se +# deseja estudar, mas poderia também passar uma lista de elementos quaisquer +# como fazer para a função calcular uma hora um uma hora outro ? +# uma coisa é certa é melhor definir estas condições antes do programa realizar os calculos +# eu poderia fazer um função para vincular o nome do elemento as posições s ao longo do anel +# isso parece ser bem util caso alguem deseje estudar um elemento em um ponto ja especificado - - # e se eu fizesse a função dessa classe já pensando na possibilidade do calculo ser realizado para apenas um ponto do anel ou para varios ? - # caso eu seja questionado sobre isso, posso justificar que para apenas um ponto do anel os cálculos são executados mais rapidamente. + def comp_aq(self, lname_or_spos, par): + + param = tousfunc.char_check(lname_or_spos) - # caso seja necessário pegar algum indice que esteja fora do get_family_data eu preciso usar o find_indices do pyaccel + if param is str: + + indices = tousfunc.el_idx_collector(self._acc, lname_or_spos) + spos = find_spos(self._acc, indices='closed') + res, ind = self.return_tracked(lspos, par) - # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades + calc_dp, calc_dn, delta_p, delta_n = tousfunc.nnorm_cutacp(self._acc, lspos, + npt=5000, getsacp=getsacp) - # Eu posso retornar o gráfico para as distribuições de espalhamento touschek sozinhas (apenas as distribuições de espalhamento touschek) - # Eu quero que esta classe também seja capaz de plotar o gráfico de tracking juntamente com - # as voltas em que esses elétrons foram perdidos e juntamente com as distribuições de espalhamento touschek + # chama a função tousfunc.el_idx_collector para selecionar os indices dos elementos em que se + # deseja realizar as análises + # indices esses que serão os pontos iniciais para a realização do tracking + pass + elif param is float: + pass + # se o usuário desejar obter o estudo ao longo de todo o anel ele simplesmente + # pode colocar como input todas as posições s que vem do modelo nominal - # (isso é bastante util para analisar o tracking e e verificar os fatores de peso para cada desvio de energia) + # remember that ind is the index that represents the initial position where tracking begins + getsacp = tousfunc.get_scaccep(self._acc, self._accep) + + + + - # eu estou pensando, conforme eu havia proposto, em fazer esta classe também fornecer as pesagens para elementos - # específicos do anel, para isso alguma função da classe ou até mesmo a classe poderia receber os nomes dos elementos em - # que se deseja realizar a análise do espalhamento como por exemplo ('BC', 'B1',...) - # - # mas se a classe receber diretamente o nome do elemento que eu desejo realizar a análise eu preciso me perguntar - # se isso pode prejudicar a função que calcula a aquisição rápida das distribuições de espalhamento eu preciso repensar essa abordagem - # porém se eu definir funções independetes acredito que isso não afetará - # para não prejudicar nenhuma funcionalidade da classe o que eu posso fazer é criar uma espécie de verificador onde eu defino um determinado atributo que receba um - # numero indeterminado de nomes dos elementos para que a ánálise seja realizada e por meio deste atributo em específico - # vai ter uma função especifica - # o problema dessa análise é que a função que eu implementei não é genérica e além disso possuo o problema de essa mesma função não conseguir - # selecionar elementos que estejam em markers de trechos retos ou em trechos de baixo beta + #o resultado para este res será uma lista com diversas tuplas então agora eu tenho que me perguntar como + #eu vou organizar isso + + + # e se eu fizesse a função dessa classe já pensando na possibilidade do calculo ser realizado para apenas um ponto do anel ou para varios ? + # caso eu seja questionado sobre isso, posso justificar que para apenas um ponto do anel os cálculos são executados mais rapidamente. - # Agora eu to pensando aqui comigo que como sempre eu sou inutil mesmo e que ja existe uma função implementada no pyaccel que seleciona os indices - # a função find_indices e get_atributte encontram qualquer coisa que vc precisa então tenho pensado que eu raelmente deva - # considerar como irrelevantes as funções que eu mesmo implementei porque estas funções com certeza já estão devidamente otimizadas - # Tornando as coisas mais claras: a find_indices necessita find_indices(acc, 'fam_name', 'nome_do_elemento') - # O segundo elemento passado para a função é literalmente + # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades + # Proximos passos + # preciso implementar o gráfico da distribuição junto com o gráfico do tracking + # esses gráficos podem ser mostrados juntamente com o tracking o separados + # preciso implementar o complete aquisition + # e ainda preciso pensar em como será o input dessa função + # se ela vai usar o get_family_data ou find_indices (saber quando cada um será usado) # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo - # - # - # - # - # - # - # diff --git a/functions.py b/functions.py index 7b933d2d..eaa92c0f 100644 --- a/functions.py +++ b/functions.py @@ -141,6 +141,15 @@ def el_idx_collector(acc, lname): return all_index +# this function recieves a list and search all elements checking if there are strings into the list + +def char_check(elmnt): + for char in elmnt: + returnval = type(char) + if returnval is str: + return str + elif returnval is float or returnval is int: + return float def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep): # ---------------- From 8bc3e0ed3cba376c247b924995854921100bf9e1 Mon Sep 17 00:00:00 2001 From: Thales_note Date: Fri, 1 Sep 2023 14:01:08 -0300 Subject: [PATCH 033/108] adicionando funcionalidades e modificando algumas coisas --- Classes.py | 69 +++++++++++++++++++++++++++++++++++++--------------- functions.py | 9 ++++--- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/Classes.py b/Classes.py index eb47df72..4e9d6b51 100644 --- a/Classes.py +++ b/Classes.py @@ -24,6 +24,7 @@ def __init__(self,accelerator): self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model self._nturns = None self._deltas = None + self._spos = find_spos(self._acc, indices='open') self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model @@ -80,6 +81,14 @@ def lname(self): def lname(self, call_lname): # call_name is the list of element names (passed by the user) that someone desires to know the distribution self._lname = call_lname return self._lname + + @property + def spos(self): + return self._spos + + @spos.setter + def spos(self, s): + return @property def lamppn_idx(self): @@ -92,19 +101,39 @@ def lamppn_idx(self): return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg - def return_single_tracked(self,s_position, par): + def return_sinpos_track(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True model.radiation_on = True - + spos = self._spos + # alterar depois a função que é utilizada nesta função para realizar o tracking. + + index = _np.argmin(_np.abs(spos-s_position)) + if 'pos' in par: + res = tousfunc.track_eletrons(self.deltas,self._nturns, + index, self._acc, pos_x=1e-5, pos_y=3e-6) + elif 'neg' in par: + res = tousfunc.track_eletrons(-self.deltas,self._nturns, + index, self._acc, pos_x=1e-5, pos_y=3e-6) + + return res + + def return_compos_track(self, lspos, par): + model = pymodels.si.create_accelerator() + model.cavity_on = True + model.radiation_on = True + if 'pos' in par: - res, ind = tousfunc.trackm_elec(model,self._deltas,self._nturns,s_position) + res = tousfunc.trackm_elec(self._acc, self._deltas, + self._nturns, lspos) elif 'neg' in par: - res, ind = tousfunc.trackm_elec(model,-self._deltas,self._nturns,s_position) + res = tousfunc.trackm_elec(self._acc, -self._deltas, + self._nturns, lspos) + return res - return res, ind + def get_weighting_tous(self, s_position, npt=5000): @@ -147,7 +176,7 @@ def fast_aquisition(self, s_position, par): raise Exception('This function suports only one s position') lspos = tousfunc.t_list(s_position) - res, ind = self.return_tracked(lspos, par) + res = self.return_sinpos_track(lspos, par) res = res[0] turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) @@ -163,12 +192,12 @@ def fast_aquisition(self, s_position, par): fp = fdensp.squeeze() fn = fdensn.squeeze() - fp *= Ddeltas - fn *= Ddeltas - deltp *= 1e2 - deltn *= 1e2 - - return fp, fn, deltp, deltn + if 'pos' in par: + return fp*Ddeltas, deltp *1e2 + elif 'neg' in par: + return fn*Ddeltas, deltn*1e2 + else: + return fp*Ddeltas, fn*Ddeltas, deltp*1e2, deltn*1e2 # vale mencionar que a fast aquisition da forma como esta definida já está funcional @@ -183,22 +212,22 @@ def fast_aquisition(self, s_position, par): # isso parece ser bem util caso alguem deseje estudar um elemento em um ponto ja especificado def comp_aq(self, lname_or_spos, par): - param = tousfunc.char_check(lname_or_spos) if param is str: - indices = tousfunc.el_idx_collector(self._acc, lname_or_spos) - spos = find_spos(self._acc, indices='closed') - res, ind = self.return_tracked(lspos, par) - - calc_dp, calc_dn, delta_p, delta_n = tousfunc.nnorm_cutacp(self._acc, lspos, - npt=5000, getsacp=getsacp) + spos = find_spos(self._acc, indices='open') + all_indices = tousfunc.el_idx_collector(self._acc, lname_or_spos) + all_indices = _np.array(all_indices, dtype=object) + for idx, indices in enumerate(all_indices): + + res, ind = self.return_tracked(indices, par) + calc_dp, calc_dn, delta_p, delta_n = tousfunc.nnorm_cutacp(self._acc, indices, + npt=5000, getsacp=getsacp) # chama a função tousfunc.el_idx_collector para selecionar os indices dos elementos em que se # deseja realizar as análises # indices esses que serão os pontos iniciais para a realização do tracking - pass elif param is float: pass # se o usuário desejar obter o estudo ao longo de todo o anel ele simplesmente diff --git a/functions.py b/functions.py index eaa92c0f..7b1fe94c 100644 --- a/functions.py +++ b/functions.py @@ -71,17 +71,15 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): def trackm_elec(acc,deltas, n_turn, lspos): results = [] - ind = [] - spos = _pyaccel.lattice.find_spos(acc, indices='closed') + spos = _pyaccel.lattice.find_spos(acc, indices='open') for k, iten in enumerate(lspos): el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to shift the tracking simulation turnl = track_eletrons(deltas, n_turn, el_idx, acc, pos_x=1e-5, pos_y=3e-6) results.append(turnl) # - ind.append(el_idx) - return results, ind + return results # this function will sellect the index by the array containing the names of the elements along the ring that people desire to study # please let's try to run away from the repetitive structures that @@ -220,6 +218,9 @@ def select_idx(list_, param1, param2): return n_arr def t_list(elmnt): + #this condition significates that if the input is only a number, then + #the fucntion transforms it into a list to avoid errors. Actually, I will delete this function, + # so just forget this bulshit if type(elmnt) == float or type(elmnt) == int: return [elmnt] else: From ce5d4d99cc2e0ffb3bdb8bcc253e896f2e558d36 Mon Sep 17 00:00:00 2001 From: Thales_note Date: Fri, 1 Sep 2023 16:03:02 -0300 Subject: [PATCH 034/108] =?UTF-8?q?uma=20nova=20fun=C3=A7=C3=A3o=20foi=20c?= =?UTF-8?q?riada=20para=20a=20classe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 63 ++++++++++++++++++++++++++++++---------------------- functions.py | 2 +- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/Classes.py b/Classes.py index 4e9d6b51..8232a55f 100644 --- a/Classes.py +++ b/Classes.py @@ -22,7 +22,7 @@ def __init__(self,accelerator): self._accep = None off_array = _np.linspace(0,0.046, 460) self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model - self._nturns = None + self._nturns = 7 # defined like this by the standard self._deltas = None self._spos = find_spos(self._acc, indices='open') @@ -53,15 +53,14 @@ def ener_off(self): def ener_off(self, new): self._ener_off = new return self._ener_off - - # Defining the number of turns to realize the tracking simulation + @property def nturns(self): return self._nturns @nturns.setter def nturns(self, new_turns): - self._nturns = new_turns + self._nturns = new_turns # changes in the nturns to simulate with tracking return self._nturns @property @@ -70,7 +69,7 @@ def deltas(self): @deltas.setter def deltas(self, new_deltas): - self._deltas = new_deltas + self._deltas = new_deltas # if the user desires to make a change in the quantity of energ. dev. return self._deltas @property @@ -87,8 +86,9 @@ def spos(self): return self._spos @spos.setter - def spos(self, s): - return + def spos(self, s): # if the user desires to make a change in the indices in the s position array + self._spos = s + return self._spos @property def lamppn_idx(self): @@ -101,6 +101,7 @@ def lamppn_idx(self): return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg + def return_sinpos_track(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True @@ -119,21 +120,20 @@ def return_sinpos_track(self,s_position, par): return res + def return_compos_track(self, lspos, par): model = pymodels.si.create_accelerator() model.cavity_on = True model.radiation_on = True - if 'pos' in par: - res = tousfunc.trackm_elec(self._acc, self._deltas, + res = tousfunc.trackm_elec(model, self._deltas, self._nturns, lspos) elif 'neg' in par: - res = tousfunc.trackm_elec(self._acc, -self._deltas, + res = tousfunc.trackm_elec(model, -self._deltas, self._nturns, lspos) return res - def get_weighting_tous(self, s_position, npt=5000): @@ -211,30 +211,39 @@ def fast_aquisition(self, s_position, par): # eu poderia fazer um função para vincular o nome do elemento as posições s ao longo do anel # isso parece ser bem util caso alguem deseje estudar um elemento em um ponto ja especificado - def comp_aq(self, lname_or_spos, par): + def complete_aquisition(self, lname_or_spos, par): param = tousfunc.char_check(lname_or_spos) + getsacp = tousfunc.get_scaccep(self._acc, self._accep) + spos = self._spos - if param is str: + if issubclass(param, str): # if user pass a list of element names - spos = find_spos(self._acc, indices='open') all_indices = tousfunc.el_idx_collector(self._acc, lname_or_spos) all_indices = _np.array(all_indices, dtype=object) - for idx, indices in enumerate(all_indices): + ress = [] + scatsdis = [] + + for indices in all_indices: - res, ind = self.return_tracked(indices, par) - calc_dp, calc_dn, delta_p, delta_n = tousfunc.nnorm_cutacp(self._acc, indices, - npt=5000, getsacp=getsacp) - - # chama a função tousfunc.el_idx_collector para selecionar os indices dos elementos em que se - # deseja realizar as análises - # indices esses que serão os pontos iniciais para a realização do tracking - elif param is float: - pass - # se o usuário desejar obter o estudo ao longo de todo o anel ele simplesmente - # pode colocar como input todas as posições s que vem do modelo nominal + res = self.return_compos_track(spos[indices], par) + scat_dis = tousfunc.nnorm_cutacp(self._acc, spos[indices], + npt=5000, getsacp=getsacp) + ress.append(res) + scatsdis.append(scat_dis) + + # if user pass a list of positions (it can be all s posistions if the user desires) + elif issubclass(param, float): + ress = self.return_compos_track(lname_or_spos, par) + scat_dis = tousfunc.nnorm_cutacp(self._acc, spos[indices], + npt=5000, getsacp=getsacp) + + return ress, scat_dis + + #if the user desires to know all the scattering events along the ring, + #only its necessary to do is to pass the # remember that ind is the index that represents the initial position where tracking begins - getsacp = tousfunc.get_scaccep(self._acc, self._accep) + diff --git a/functions.py b/functions.py index 7b1fe94c..41facbe1 100644 --- a/functions.py +++ b/functions.py @@ -76,7 +76,7 @@ def trackm_elec(acc,deltas, n_turn, lspos): for k, iten in enumerate(lspos): el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to shift the tracking simulation - turnl = track_eletrons(deltas, n_turn, el_idx, acc, pos_x=1e-5, pos_y=3e-6) + turnl = track_eletrons(deltas, n_turn, el_idx, acc) results.append(turnl) # return results From 721169629644e5188eccaaaf3b8e48b7e3dda4e6 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 4 Sep 2023 13:42:02 -0300 Subject: [PATCH 035/108] =?UTF-8?q?adicionando=20algumas=20ideias=20que=20?= =?UTF-8?q?o=20ximenes=20me=20passou=20sobre=20a=20defini=C3=A7=C3=A3o=20d?= =?UTF-8?q?e=20alguns=20inputs=20para=20a=20classe=20que=20esta=20sendo=20?= =?UTF-8?q?definada,=20acrescentando=20mais=20parametros,=20fun=C3=A7?= =?UTF-8?q?=C3=B5es=20dentro=20da=20classe=20e=20definindo=20as=20proximas?= =?UTF-8?q?=20etapas=20para=20a=20fun=C3=A7=C3=A3o=20que=20realizar=C3=A1?= =?UTF-8?q?=20o=20plot=20principal=20para=20as=20analises=20da=20distribui?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20espalhamento=20ao=20longo=20do=20anel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 142 ++++++++++++++++++++++++++++++++++++--------------- functions.py | 14 +++-- 2 files changed, 107 insertions(+), 49 deletions(-) diff --git a/Classes.py b/Classes.py index 8232a55f..c6525720 100644 --- a/Classes.py +++ b/Classes.py @@ -10,24 +10,33 @@ class Tous_analysis(): - def __init__(self,accelerator): + def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): + if energies_off is None: + energy_off = _np.linspace(0,0.046, 460) + deltas = _np.linspace(0,0.1,400) + + if beam_energy is None: # beam_energy is associated to the beta factor of the electrons of the storage ring + beta = _beam_rigidity(energy=3)[2] # defining by default the energy of the beam + self._acc = accelerator - self._beta = _beam_rigidity(energy=3)[2] # defining beta to tranformate the energy deviation + self._sc_accps = None + self._accep = None + self._inds_pos = None + self._inds_neg = None + self._amps_pos = None + self._amps_neg = None + + self._beta = beta # beta is a constant necessary to the calculations self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') self._ltime = Lifetime(self._acc) - self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires + # self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires - self._sc_accps = None - self._accep = None - off_array = _np.linspace(0,0.046, 460) - self._ener_off = off_array # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model - self._nturns = 7 # defined like this by the standard - self._deltas = None + self._off_energy = energy_off # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model + self._nturns = n_turns # defined like this by the standard + self._deltas = deltas # defined by the standard self._spos = find_spos(self._acc, indices='open') - self._lamppn_idx = None # this parameter defines 4 analysis' elements calculated by the linear model - # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @property @@ -43,16 +52,49 @@ def scalc(self): if self._sc_accps is None: self._sc_accps = tousfunc.get_scaccep(self._acc, self._accep) return self._sc_accps + + # This property calculates the physical limitants by the prediction of the linear model + # Eu poderia colocar algum parâmetro ele retornasse também as amplitudes caso alguém deseje ver como elas se comportam de acordo com o desvio de energia + # mas como passar esse parâmetro da melhor forma possivel + @property + def amp_and_limidx(self): + if self._amp_and_limidx is None: + model = pymodels.si.create_accelerator() + model.cavity_on = False + model.radiation_on = False + self._amps_pos, self._inds_pos = tousfunc.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) + self._amps_neg, self._inds_neg = tousfunc.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) + self._amp_and_limidx = True + + return self._amp_and_limidx # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model + @property - def ener_off(self): - return self._ener_off + def accelerator(self): + return self._acc + + @accelerator.setter + def accelerator(self, new_model): #This line defines a new accelerator if the user desires + self._acc = new_model - @ener_off.setter - def ener_off(self, new): - self._ener_off = new - return self._ener_off + @property + def beam_energy(self): + return self._beta + + @beam_energy.setter + def beam_energy(self, new_beam_energy): + energy = new_beam_energy + self._beta = _beam_rigidity(energy=new_beam_energy)[2] + + @property + def off_energy(self): + return self._off_energy + + @off_energy.setter + def off_energy(self, new): + self._off_energy = new + return self._off_energy @property def nturns(self): @@ -69,7 +111,7 @@ def deltas(self): @deltas.setter def deltas(self, new_deltas): - self._deltas = new_deltas # if the user desires to make a change in the quantity of energ. dev. + self._deltas = new_deltas # if the user desires to make a change in the quantity of energ. dev. in tracking simulation return self._deltas @property @@ -89,19 +131,22 @@ def spos(self): def spos(self, s): # if the user desires to make a change in the indices in the s position array self._spos = s return self._spos - - @property - def lamppn_idx(self): - if self._lamppn_idx is None: - model = pymodels.si.create_accelerator() - model.cavity_on = False - model.radiation_on = False - self.lmd_amp_pos, self.idx_lim_pos = tousfunc.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) - self.lmd_amp_neg, self.idx_lim_neg = tousfunc.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) - - return self.lmd_amp_pos, self.idx_lim_pos, self.lmd_amp_neg, self.idx_lim_neg - + # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula + # as amplitudes e os indices limitantes + + # vai ser melhor retornar todos os parametros que eu preciso de uma vez, + # esses parametros são utilizados em momentos diferentes mas todos eles são necessários para a realização das análises tanto rapida quanto a completa + # mas inicialmente não tem como o usuário saber que ele precisa definir estes parâmetros para visualização e análise dos gráficos entao + # eu ainda preciso pensar em como tornar esta biblioteca mais simples de ser utilizada por alguem que nao conhece a fundo o código + # isso significa que ao longo do codigo eu vou chamar as funções como se esses parametros ja tivessem sido definidos, mas na verdade eles so são + # definidos pelo usuário quando a classe é instanciada e a função abaixo é chamada definido estes 3 parametros ao mesmo tempo + def get_accep(self): + return self.accep() + + def get_amps_idxs(self): + return self.accep #, self.scalc + def return_sinpos_track(self,s_position, par): model = pymodels.si.create_accelerator() model.cavity_on = True @@ -175,8 +220,7 @@ def fast_aquisition(self, s_position, par): if len(tousfunc.t_list(s_position)) != 1: raise Exception('This function suports only one s position') - lspos = tousfunc.t_list(s_position) - res = self.return_sinpos_track(lspos, par) + res = self.return_sinpos_track(s_position, par) res = res[0] turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) @@ -193,11 +237,11 @@ def fast_aquisition(self, s_position, par): fn = fdensn.squeeze() if 'pos' in par: - return fp*Ddeltas, deltp *1e2 + return res, fp*Ddeltas, deltp *1e2 elif 'neg' in par: - return fn*Ddeltas, deltn*1e2 + return res, fn*Ddeltas, deltn*1e2 else: - return fp*Ddeltas, fn*Ddeltas, deltp*1e2, deltn*1e2 + return res, fp*Ddeltas, fn*Ddeltas, deltp*1e2, deltn*1e2 # vale mencionar que a fast aquisition da forma como esta definida já está funcional @@ -239,19 +283,32 @@ def complete_aquisition(self, lname_or_spos, par): return ress, scat_dis - #if the user desires to know all the scattering events along the ring, - #only its necessary to do is to pass the + # this function plot the graphic of tracking and the touschek scattering distribution for one single position + def plot_analysi_at_position(self, spos, par, amp_on): + # defining some params top plot the tracking and the scattering distribution + # In a first approach I dont have to be concerned in this decision structure because all variables necessary for the calculation will be defined + # I will may let this part of the code if I know a best method or decide to make a change here - # remember that ind is the index that represents the initial position where tracking begins - + # if self._amp_and_limidx is None: + # amps_and_idxs = self.amp_and_limidx + # else: + # amps_and_idxs = self._amp_and_limidx - - + res, fp, dp = self.fast_aquisition(spos, par) + tousfunc.plot_track(self._acc,res, ) + + #if the user desires to know all the scattering events along the ring, + #only its necessary to do is to pass the + + # remember that ind is the index that represents the initial position where tracking begins + + + #o resultado para este res será uma lista com diversas tuplas então agora eu tenho que me perguntar como #eu vou organizar isso @@ -269,5 +326,8 @@ def complete_aquisition(self, lname_or_spos, par): # e ainda preciso pensar em como será o input dessa função # se ela vai usar o get_family_data ou find_indices (saber quando cada um será usado) # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo + + # eu vou definir alguns parametros de uma forma que talvez não seja ideal + # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função diff --git a/functions.py b/functions.py index 41facbe1..c6587b66 100644 --- a/functions.py +++ b/functions.py @@ -168,14 +168,12 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.xaxis.grid(False) a1.set_title(r'$\delta \times$ lost turn', fontsize=16) - if 'pos' in param: - for item in lista_resul: - a1.plot(item[0], item[2]*1e2, 'k.', label = '') + + for iten in lista_resul: + a1.plot(iten[0], iten[2]*1e2, 'k.', label = '') + if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=14) - - elif 'neg' in param: - for item in lista_resul: - a1.plot(item[0], -item[2]*1e2, 'k.', label = '') + elif 'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=14) a1.set_xlabel(r'n de voltas', fontsize=14) @@ -202,7 +200,7 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) #magnetic lattice a2.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( - acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position that tracking begins + acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position where tracking begins a2.set_xlabel(r'$s$ [m]', fontsize=14) # setting configurations of the graphic a2.legend(loc='best', ncol=2) From c19da9e17d5f83fb4b4931e6a5516df5c880e19d Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 4 Sep 2023 14:37:41 -0300 Subject: [PATCH 036/108] =?UTF-8?q?adicionando=20um=20model=20nominal=20n?= =?UTF-8?q?=C3=A3o=20corrigido=20seguindo=20a=20sugest=C3=A3o=20do=20muril?= =?UTF-8?q?o,=20alterando=20os=20setters=20que=20haviam=20sido=20definidos?= =?UTF-8?q?=20com=20returns=20adicionais.=20Alterei=20tamb=C3=A9m=20o=20no?= =?UTF-8?q?me=20do=20atributo=20acc=20(accelerator)=20para=20model=5Ffit?= =?UTF-8?q?=20e=20model=20tamb=C3=A9m=20seguindo=20a=20minha=20ideia=20de?= =?UTF-8?q?=20sugest=C3=A3o=20do=20murilo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 113 ++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/Classes.py b/Classes.py index c6525720..2d36debb 100644 --- a/Classes.py +++ b/Classes.py @@ -12,13 +12,15 @@ class Tous_analysis(): def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): if energies_off is None: - energy_off = _np.linspace(0,0.046, 460) - deltas = _np.linspace(0,0.1,400) + energy_off = _np.linspace(0,0.046, 460) # used when calculating physical limitants by the linear model + deltas = _np.linspace(0,0.1,400) # used in tracking simulation if beam_energy is None: # beam_energy is associated to the beta factor of the electrons of the storage ring beta = _beam_rigidity(energy=3)[2] # defining by default the energy of the beam - self._acc = accelerator + self._model_fit = accelerator + self._model = pymodels.si.create_accelerator() # No necessity to change this model, because it's an internal tool for calculations. + self._amp_and_limidx = None self._sc_accps = None self._accep = None self._inds_pos = None @@ -27,22 +29,22 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._amps_neg = None self._beta = beta # beta is a constant necessary to the calculations - self.h_pos = get_attribute(self._acc, 'hmax', indices='closed') # getting the vchamber's height - self.h_neg = get_attribute(self._acc, 'hmin', indices='closed') - self._ltime = Lifetime(self._acc) + self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') # getting the vchamber's height + self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') + self._ltime = Lifetime(self._model_fit) # self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires self._off_energy = energy_off # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model self._nturns = n_turns # defined like this by the standard self._deltas = deltas # defined by the standard - self._spos = find_spos(self._acc, indices='open') + self._spos = find_spos(self._model_fit, indices='open') # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @property def accep(self): if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance(self._acc) + self._accep = py_op.calc_touschek_energy_acceptance(self._model_fit) return self._accep # Defining the s position, positive and negative accptances along the ring at each 10 meters. @@ -50,20 +52,17 @@ def accep(self): @property def scalc(self): if self._sc_accps is None: - self._sc_accps = tousfunc.get_scaccep(self._acc, self._accep) + self._sc_accps = tousfunc.get_scaccep(self._model_fit, self._accep) return self._sc_accps # This property calculates the physical limitants by the prediction of the linear model - # Eu poderia colocar algum parâmetro ele retornasse também as amplitudes caso alguém deseje ver como elas se comportam de acordo com o desvio de energia - # mas como passar esse parâmetro da melhor forma possivel @property def amp_and_limidx(self): if self._amp_and_limidx is None: - model = pymodels.si.create_accelerator() - model.cavity_on = False - model.radiation_on = False - self._amps_pos, self._inds_pos = tousfunc.calc_amp(model, self.ener_off, self.h_pos, self.h_neg) - self._amps_neg, self._inds_neg = tousfunc.calc_amp(model, -self.ener_off, self.h_pos, self.h_neg) + self._model.cavity_on = False # this step is necessary to define if the + self._model.radiation_on = False + self._amps_pos, self._inds_pos = tousfunc.calc_amp(self._model, self.ener_off, self.h_pos, self.h_neg) + self._amps_neg, self._inds_neg = tousfunc.calc_amp(self._model, -self.ener_off, self.h_pos, self.h_neg) self._amp_and_limidx = True return self._amp_and_limidx @@ -72,21 +71,36 @@ def amp_and_limidx(self): @property def accelerator(self): - return self._acc + return self._model_fit @accelerator.setter def accelerator(self, new_model): #This line defines a new accelerator if the user desires - self._acc = new_model + self._model_fit = new_model @property def beam_energy(self): return self._beta @beam_energy.setter - def beam_energy(self, new_beam_energy): - energy = new_beam_energy + def beam_energy(self, new_beam_energy): # the user could change the energy of the beam if it is necessary self._beta = _beam_rigidity(energy=new_beam_energy)[2] + + @property + def pos_vchamber(self): + return self.h_pos + + @pos_vchamber.setter + def pos_vchamber(self, indices): # here indices must be a string, closed or open, the user could define if it is necessary + self.h_pos = find_spos(self._model_fit, indices=indices) + + @property + def neg_vchamber(self): + return self.h_neg + @neg_vchamber.setter + def neg_vchamber(self, indices): + self.h_neg = find_spos(self._model_fit, indices=indices) + @property def off_energy(self): return self._off_energy @@ -94,7 +108,6 @@ def off_energy(self): @off_energy.setter def off_energy(self, new): self._off_energy = new - return self._off_energy @property def nturns(self): @@ -103,7 +116,6 @@ def nturns(self): @nturns.setter def nturns(self, new_turns): self._nturns = new_turns # changes in the nturns to simulate with tracking - return self._nturns @property def deltas(self): @@ -112,7 +124,6 @@ def deltas(self): @deltas.setter def deltas(self, new_deltas): self._deltas = new_deltas # if the user desires to make a change in the quantity of energ. dev. in tracking simulation - return self._deltas @property def lname(self): @@ -121,16 +132,14 @@ def lname(self): @lname.setter def lname(self, call_lname): # call_name is the list of element names (passed by the user) that someone desires to know the distribution self._lname = call_lname - return self._lname @property def spos(self): return self._spos @spos.setter - def spos(self, s): # if the user desires to make a change in the indices in the s position array - self._spos = s - return self._spos + def spos(self, indices): # if the user desires to make a change in the indices in the s position array + self._spos = find_spos(self._model_fit, indices=indices) # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula # as amplitudes e os indices limitantes @@ -144,51 +153,49 @@ def spos(self, s): # if the user desires to make a change in the indices in the def get_accep(self): return self.accep() - def get_amps_idxs(self): - return self.accep #, self.scalc + def get_amps_idxs(self): # this step calls 3 disctinct getters + return self.amp_and_limidx, self.accep, self.scalc - def return_sinpos_track(self,s_position, par): - model = pymodels.si.create_accelerator() - model.cavity_on = True - model.radiation_on = True + def return_sinpos_track(self,single_spos, par): + self._model.cavity_on = True + self._model.radiation_on = True spos = self._spos # alterar depois a função que é utilizada nesta função para realizar o tracking. - index = _np.argmin(_np.abs(spos-s_position)) + index = _np.argmin(_np.abs(spos-single_spos)) if 'pos' in par: res = tousfunc.track_eletrons(self.deltas,self._nturns, - index, self._acc, pos_x=1e-5, pos_y=3e-6) + index, self._model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: res = tousfunc.track_eletrons(-self.deltas,self._nturns, - index, self._acc, pos_x=1e-5, pos_y=3e-6) + index, self._model, pos_x=1e-5, pos_y=3e-6) return res def return_compos_track(self, lspos, par): - model = pymodels.si.create_accelerator() - model.cavity_on = True - model.radiation_on = True + self._model.cavity_on = True + self._model.radiation_on = True if 'pos' in par: - res = tousfunc.trackm_elec(model, self._deltas, + res = tousfunc.trackm_elec(self._model, self._deltas, self._nturns, lspos) elif 'neg' in par: - res = tousfunc.trackm_elec(model, -self._deltas, + res = tousfunc.trackm_elec(self._model, -self._deltas, self._nturns, lspos) return res - def get_weighting_tous(self, s_position, npt=5000): + def get_weighting_tous(self, single_spos, npt=5000): - scalc, daccp, daccn = tousfunc.get_scaccep(self._acc, self._accep) + scalc, daccp, daccn = tousfunc.get_scaccep(self._model_fit, self._accep) bf = self._beta ltime = self._ltime b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] taup, taun = (bf* daccp)**2, (bf*daccn)**2 - idx = _np.argmin(_np.abs(scalc-s_position)) + idx = _np.argmin(_np.abs(scalc-single_spos)) taup_0, taun_0 = taup[idx], taun[idx] kappap_0 = _np.arctan(_np.sqrt(taup_0)) kappan_0 = _np.arctan(_np.sqrt(taun_0)) @@ -215,12 +222,12 @@ def get_weighting_tous(self, s_position, npt=5000): # In general, this function is usefull when we desire to calculate the touschek scattering weighting function for one specific point along the ring - def fast_aquisition(self, s_position, par): + def fast_aquisition(self, single_spos, par): # this raise blocks to runing the program if the list of s position has more than 1 element - if len(tousfunc.t_list(s_position)) != 1: + if len(tousfunc.t_list(single_spos)) != 1: raise Exception('This function suports only one s position') - res = self.return_sinpos_track(s_position, par) + res = self.return_sinpos_track(single_spos, par) res = res[0] turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) @@ -231,7 +238,7 @@ def fast_aquisition(self, s_position, par): delta[idx] = delt Ddeltas = _np.diff(delta)[0] - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(s_position) + fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) fp = fdensp.squeeze() fn = fdensn.squeeze() @@ -257,12 +264,12 @@ def fast_aquisition(self, s_position, par): def complete_aquisition(self, lname_or_spos, par): param = tousfunc.char_check(lname_or_spos) - getsacp = tousfunc.get_scaccep(self._acc, self._accep) + getsacp = tousfunc.get_scaccep(self._model_fit, self._accep) spos = self._spos if issubclass(param, str): # if user pass a list of element names - all_indices = tousfunc.el_idx_collector(self._acc, lname_or_spos) + all_indices = tousfunc.el_idx_collector(self._model_fit, lname_or_spos) all_indices = _np.array(all_indices, dtype=object) ress = [] scatsdis = [] @@ -270,7 +277,7 @@ def complete_aquisition(self, lname_or_spos, par): for indices in all_indices: res = self.return_compos_track(spos[indices], par) - scat_dis = tousfunc.nnorm_cutacp(self._acc, spos[indices], + scat_dis = tousfunc.nnorm_cutacp(self._model_fit, spos[indices], npt=5000, getsacp=getsacp) ress.append(res) scatsdis.append(scat_dis) @@ -278,7 +285,7 @@ def complete_aquisition(self, lname_or_spos, par): # if user pass a list of positions (it can be all s posistions if the user desires) elif issubclass(param, float): ress = self.return_compos_track(lname_or_spos, par) - scat_dis = tousfunc.nnorm_cutacp(self._acc, spos[indices], + scat_dis = tousfunc.nnorm_cutacp(self._model_fit, spos[indices], npt=5000, getsacp=getsacp) return ress, scat_dis @@ -296,7 +303,7 @@ def plot_analysi_at_position(self, spos, par, amp_on): res, fp, dp = self.fast_aquisition(spos, par) - tousfunc.plot_track(self._acc,res, ) + tousfunc.plot_track(self._model_fit,res, ) From 83c2ec67a9d73cb467e938e07287ae2cf5f557a7 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 4 Sep 2023 14:56:20 -0300 Subject: [PATCH 037/108] =?UTF-8?q?Estava=20em=20d=C3=BAvida=20sobre=20com?= =?UTF-8?q?o=20deveria=20chamar=20uma=20fun=C3=A7=C3=A3o=20dentro=20da=20m?= =?UTF-8?q?inha=20classe=20ent=C3=A3o=20eu=20adicionei=20textos=20comentad?= =?UTF-8?q?os=20para=20me=20lembrar=20de=20como=20eu=20devo=20fazer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Classes.py b/Classes.py index 2d36debb..cdda3020 100644 --- a/Classes.py +++ b/Classes.py @@ -50,7 +50,7 @@ def accep(self): # Defining the s position, positive and negative accptances along the ring at each 10 meters. # the description above is actually the returns of the function @property - def scalc(self): + def s_calc(self): if self._sc_accps is None: self._sc_accps = tousfunc.get_scaccep(self._model_fit, self._accep) return self._sc_accps @@ -150,10 +150,14 @@ def spos(self, indices): # if the user desires to make a change in the indices i # eu ainda preciso pensar em como tornar esta biblioteca mais simples de ser utilizada por alguem que nao conhece a fundo o código # isso significa que ao longo do codigo eu vou chamar as funções como se esses parametros ja tivessem sido definidos, mas na verdade eles so são # definidos pelo usuário quando a classe é instanciada e a função abaixo é chamada definido estes 3 parametros ao mesmo tempo - def get_accep(self): - return self.accep() + + # def get_scaccep(self): + # return self.accep + + # def get_scalc(self): + # return self.s_calc let this code here to remind me how I may call a function in a class - def get_amps_idxs(self): # this step calls 3 disctinct getters + def get_amps_idxs(self): # this step calls and defines 3 disctinct getters return self.amp_and_limidx, self.accep, self.scalc def return_sinpos_track(self,single_spos, par): From 194de3641c9d7bebd6ffe95d93bc77d954053481 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 5 Sep 2023 14:55:25 -0300 Subject: [PATCH 038/108] =?UTF-8?q?corringindo=20um=20problema=20que=20est?= =?UTF-8?q?ava=20com=20o=20plot=20do=20gr=C3=A1fico=20e=20ainda=20fazendo?= =?UTF-8?q?=20algumas=20altera=C3=A7=C3=B5es=20nas=20fun=C3=A7=C3=B5es=20q?= =?UTF-8?q?ue=20ser=C3=A3o=20utilizadas=20para=20plotar=20os=20gr=C3=A1fic?= =?UTF-8?q?os=20mais=20relavantes=20para=20as=20an=C3=A1lises=20das=20taxa?= =?UTF-8?q?s=20de=20espalhamento=20touschek=20aop=20longo=20do=20anel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 21 ++++++++--------- functions.py | 65 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/Classes.py b/Classes.py index cdda3020..4cecbc87 100644 --- a/Classes.py +++ b/Classes.py @@ -61,8 +61,8 @@ def amp_and_limidx(self): if self._amp_and_limidx is None: self._model.cavity_on = False # this step is necessary to define if the self._model.radiation_on = False - self._amps_pos, self._inds_pos = tousfunc.calc_amp(self._model, self.ener_off, self.h_pos, self.h_neg) - self._amps_neg, self._inds_neg = tousfunc.calc_amp(self._model, -self.ener_off, self.h_pos, self.h_neg) + self._amps_pos, self._inds_pos = tousfunc.calc_amp(self._model, self._off_energy, self.h_pos, self.h_neg) + self._amps_neg, self._inds_neg = tousfunc.calc_amp(self._model, -self._off_energy, self.h_pos, self.h_neg) self._amp_and_limidx = True return self._amp_and_limidx @@ -158,7 +158,7 @@ def spos(self, indices): # if the user desires to make a change in the indices i # return self.s_calc let this code here to remind me how I may call a function in a class def get_amps_idxs(self): # this step calls and defines 3 disctinct getters - return self.amp_and_limidx, self.accep, self.scalc + return self.amp_and_limidx, self.accep, self.s_calc def return_sinpos_track(self,single_spos, par): self._model.cavity_on = True @@ -232,14 +232,13 @@ def fast_aquisition(self, single_spos, par): raise Exception('This function suports only one s position') res = self.return_sinpos_track(single_spos, par) - res = res[0] - turn_lost, elem_lost, delta = _np.zeros(len(res)), _np.zeros(len(res)), _np.zeros(len(res)) - - for idx, iten in enumerate(res): - tlost, elmnlost, delt = iten - turn_lost[idx] = tlost - elem_lost[idx] = elmnlost - delta[idx] = delt + turn_lost, elmnt_lost, delta = _np.zeros(len(res)),_np.zeros(len(res)),_np.zeros(len(res)) + + for index, iten in enumerate(res): + tlost, ellost, delt = iten + turn_lost[index] = tlost + elmnt_lost[index] = ellost + delta[index] = delt Ddeltas = _np.diff(delta)[0] fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) diff --git a/functions.py b/functions.py index c6587b66..dc6cf6b5 100644 --- a/functions.py +++ b/functions.py @@ -149,7 +149,10 @@ def char_check(elmnt): elif returnval is float or returnval is int: return float -def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep): +# this function will plot the tracking simultation with the linear model calculated plus the touschek scattering distribution +# in the first graphic the plot will be the touschek scattering distribution + +def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens): # ---------------- twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') @@ -158,52 +161,68 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep spos = _pyaccel.lattice.find_spos(acc) - fig, (a1, a2) = _plt.subplots(1, 2, figsize=(10, 5), sharey=True, gridspec_kw={'width_ratios': [1, 3]}) + fig, (a1, a2, a3) = _plt.subplots(1, 3, figsize=(10, 5), sharey=True, gridspec_kw={'width_ratios': [1, 3, 3]}) + # defining the form that graphic will be plotted, trying to amplify the best I can the letters to see it in a easier way a1.grid(True, alpha=0.5, ls='--', color='k') a1.tick_params(axis='both', labelsize=12) a2.grid(True, alpha=0.5, ls='--', color='k') a2.tick_params(axis='both', labelsize=12) - a2.xaxis.grid(False) + a3.grid(True, alpha=0.5, ls='--', color='k') + a3.tick_params(axis='both', labelsize=12) a1.xaxis.grid(False) + a2.xaxis.grid(False) + a3.xaxis.grid(False) - a1.set_title(r'$\delta \times$ lost turn', fontsize=16) + + a1.set_title(r'taxa de espalhamento touschek') # setting the title of the first graphic + + if 'pos' in param: # defining the y and x label of the first graphic + a1.set_ylabel(r'positive energy deviation') + elif'neg' in param: + a1.set_ylabel(r'negative positive energy deviation') + a1.set_xlabel(r'Scattering touschek rate') - for iten in lista_resul: - a1.plot(iten[0], iten[2]*1e2, 'k.', label = '') - if 'pos' in param: - a1.set_ylabel(r'positive $\delta$ [%]', fontsize=14) - elif 'neg' in param: - a1.set_ylabel(r'negative $\delta$ [%]', fontsize=14) - - a1.set_xlabel(r'n de voltas', fontsize=14) + a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - a2.set_title(r'tracking ', fontsize=16) + a2.set_title(r'$\delta \times$ lost turn', fontsize=16) # setting the tilte of the second graphic + + if 'pos' in param: # defining the y and x label of the second graphic + a2.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + elif 'neg' in param: + a2.set_ylabel(r'negative $\delta$ [%]', fontsize=14) + + a2.set_xlabel(r'n de voltas', fontsize=14) + for iten in lista_resul: + a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') + + + a3.set_title(r'tracking ', fontsize=16) # setting the title of the third graphic - acp_s = accep[element_idx] # defining the acceptance given the begining tracking point + acp_s = accep[element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted ind = _np.argmin(_np.abs(lista_off-acp_s)) - a2.plot(spos[lista_idx][:ind], lista_off[:ind]*1e2,'b.', label=r'accep. limit', alpha=0.25) + a3.plot(spos[lista_idx][:ind], lista_off[:ind]*1e2,'b.', label=r'accep. limit', alpha=0.25) if 'pos' in param: - a2.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') for item in lista_resul: - a2.plot(spos[int(item[1])], item[2]*1e2, 'r.') + a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif 'neg' in param: - a2.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') for item in lista_resul: - a2.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff - a2.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function + a3.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) #magnetic lattice - a2.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( + a3.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position where tracking begins - a2.set_xlabel(r'$s$ [m]', fontsize=14) # setting configurations of the graphic - a2.legend(loc='best', ncol=2) + a3.set_xlabel(r'$s$ [m]', fontsize=14) # setting configurations of the graphic + a3.legend(loc='best', ncol=2) fig.tight_layout() fig.show() From c54bf12040797e6a82eea86944ae2577355160fd Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 5 Sep 2023 14:59:39 -0300 Subject: [PATCH 039/108] =?UTF-8?q?adicionando=20legenda=20para=20que=20eu?= =?UTF-8?q?=20me=20lembre=20de=20fazer=20essa=20altera=C3=A7=C3=A3o=20mais?= =?UTF-8?q?=20tarde?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/functions.py b/functions.py index dc6cf6b5..c84fe84d 100644 --- a/functions.py +++ b/functions.py @@ -184,6 +184,10 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.set_xlabel(r'Scattering touschek rate') a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') + + # LEMBRAR DE DEFINIR CORRETAMENTE OS INTERVALOS PARA PLOTAR OS DESVIOS DE ENERGIA. PERCEBA QUE OS DESVIOS DE ENERGIA PROVENIENTES DESTA FUNÇÃO + # VÃO ATÉ INFINITO BASICAMENTE. EU POSSO SIMPLESMENTE FAZER UM SLICE E DEFINIR ATÉ ONDE EU QUERO QUE O ARRAY SEJA PLOTADO PRA NÃO TER QUE + # ME PREOCUPAR COM CONSERTAR LIMITES DE PLOT DE GRÁFICOS a2.set_title(r'$\delta \times$ lost turn', fontsize=16) # setting the tilte of the second graphic From 4d197a8263b4ff4ca962e52f133e571e2d2dd43c Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 6 Sep 2023 14:31:49 -0300 Subject: [PATCH 040/108] =?UTF-8?q?hoje=20eu=20adicionei=20a=20funcionalid?= =?UTF-8?q?ade=20de=20plotar=20juntamente=20com=20os=20gr=C3=A1ficos=20de?= =?UTF-8?q?=20tracking=20e=20onde=20os=20el=C3=A9trons=20s=C3=A3o=20perdid?= =?UTF-8?q?os=20a=20taxa=20de=20espalhamento=20touschek=20para=20pontos=20?= =?UTF-8?q?escolhidos=20como=20input=20da=20fun=C3=A7=C3=A3o=20suportada?= =?UTF-8?q?=20na=20classe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 5 +++-- functions.py | 52 +++++++++++++++++++++++----------------------------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/Classes.py b/Classes.py index 4cecbc87..e6c3572d 100644 --- a/Classes.py +++ b/Classes.py @@ -161,6 +161,7 @@ def get_amps_idxs(self): # this step calls and defines 3 disctinct getters return self.amp_and_limidx, self.accep, self.s_calc def return_sinpos_track(self,single_spos, par): + self._model.cavity_on = True self._model.radiation_on = True spos = self._spos @@ -217,8 +218,8 @@ def get_weighting_tous(self, single_spos, npt=5000): indn = _np.where(getdn<0) indp = indp[0] indn = indn[0] - getdp[indp] == 0 - getdn[indn] == 0 + getdp[indp] = 0 + getdn[indn] = 0 # this function will return the weighting factors in the scalc position convertion diff --git a/functions.py b/functions.py index c84fe84d..63ed5c74 100644 --- a/functions.py +++ b/functions.py @@ -173,17 +173,30 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.xaxis.grid(False) a2.xaxis.grid(False) a3.xaxis.grid(False) - - - a1.set_title(r'taxa de espalhamento touschek') # setting the title of the first graphic + ind = _np.int0(_np.where(f_dens>1e-17)[0]) + if 'pos' in param: # defining the y and x label of the first graphic - a1.set_ylabel(r'positive energy deviation') + a1.set_ylabel(r'positive energy deviation', fontsize=14) + a2.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + acp_s = accep[1][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted + indx = _np.argmin(_np.abs(lista_off-acp_s)) + for item in lista_resul: + a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: - a1.set_ylabel(r'negative positive energy deviation') - a1.set_xlabel(r'Scattering touschek rate') + a1.set_ylabel(r'negative positive energy deviation', fontsize=14) + a2.set_ylabel(r'negative $\delta$ [%]', fontsize=14) + a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + acp_s = accep[0][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted + indx = _np.argmin(_np.abs(lista_off-acp_s)) + for item in lista_resul: + a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + + a1.set_title(r'taxa de espalhamento touschek', fontsize=14) # setting the title of the first graphic + a1.set_xlabel(r'Scattering touschek rate', fontsize=14) - a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') + a1.plot(f_dens[ind], delt[ind], label='Scattering touschek rate', color='black') # LEMBRAR DE DEFINIR CORRETAMENTE OS INTERVALOS PARA PLOTAR OS DESVIOS DE ENERGIA. PERCEBA QUE OS DESVIOS DE ENERGIA PROVENIENTES DESTA FUNÇÃO # VÃO ATÉ INFINITO BASICAMENTE. EU POSSO SIMPLESMENTE FAZER UM SLICE E DEFINIR ATÉ ONDE EU QUERO QUE O ARRAY SEJA PLOTADO PRA NÃO TER QUE @@ -191,32 +204,13 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a2.set_title(r'$\delta \times$ lost turn', fontsize=16) # setting the tilte of the second graphic - - if 'pos' in param: # defining the y and x label of the second graphic - a2.set_ylabel(r'positive $\delta$ [%]', fontsize=14) - elif 'neg' in param: - a2.set_ylabel(r'negative $\delta$ [%]', fontsize=14) - a2.set_xlabel(r'n de voltas', fontsize=14) for iten in lista_resul: a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') a3.set_title(r'tracking ', fontsize=16) # setting the title of the third graphic - - acp_s = accep[element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted - ind = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[lista_idx][:ind], lista_off[:ind]*1e2,'b.', label=r'accep. limit', alpha=0.25) - - if 'pos' in param: - a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - for item in lista_resul: - a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') - - elif 'neg' in param: - a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - for item in lista_resul: - a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', label=r'accep. limit', alpha=0.25) _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff a3.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function @@ -438,8 +432,8 @@ def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): # eliminating the negative values from array indp = _np.where(y_p<0)[0] indn = _np.where(y_n<0)[0] - y_p[indp] == 0 - y_n[indn] == 0 + y_p[indp] = 0 + y_n[indn] = 0 calc_dp.append(y_p) calc_dn.append(y_n) From 7e7d64eed4898267677085f9df08a23ecd226ddc Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 6 Sep 2023 14:33:09 -0300 Subject: [PATCH 041/108] =?UTF-8?q?corrigi=20uma=20nota=C3=A7=C3=A3o=20que?= =?UTF-8?q?=20era=20desnecess=C3=A1ria?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Classes.py b/Classes.py index e6c3572d..bb640d0a 100644 --- a/Classes.py +++ b/Classes.py @@ -214,10 +214,8 @@ def get_weighting_tous(self, single_spos, npt=5000): getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # eliminating negative values - indp = _np.where(getdp<0) - indn = _np.where(getdn<0) - indp = indp[0] - indn = indn[0] + indp = _np.where(getdp<0)[0] + indn = _np.where(getdn<0)[0] getdp[indp] = 0 getdn[indn] = 0 From 53fea00e563687e13cb2cdc49c9852472c97de51 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 6 Sep 2023 14:53:54 -0300 Subject: [PATCH 042/108] =?UTF-8?q?alterando=20a=20segmenta=C3=A7=C3=A3o?= =?UTF-8?q?=20do=20modelo,=20pelo=20visto=20existem=20muitas=20coisas=20er?= =?UTF-8?q?radas=20que=20eu=20vou=20precisar=20consertar=20ainda?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions.py b/functions.py index 63ed5c74..325cf8f7 100644 --- a/functions.py +++ b/functions.py @@ -339,7 +339,7 @@ def norm_d(acc, lsps, scalc,_npt, norm=True): def get_scaccep(acc, accep): spos = _pyaccel.lattice.find_spos(acc, indices='closed') - npt = int((spos[-1]-spos[0])/0.01) + npt = int((spos[-1]-spos[0])/0.1) scalc = _np.linspace(spos[0],spos[-1], npt) daccpp = _np.interp(scalc, spos, accep[1]) daccpn = _np.interp(scalc, spos, accep[0]) From 79671e9c27812b3727a643087587b13930c699da Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 11 Sep 2023 11:08:08 -0300 Subject: [PATCH 043/108] =?UTF-8?q?Tentativa=20de=20sincronizar=20o=20limi?= =?UTF-8?q?te=20para=20os=20desvios=20de=20energia=20que=20ser=C3=A3o=20jo?= =?UTF-8?q?gados=20no=20tracking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 70 ++++++++++++++++++++++++++++++++++++---------------- functions.py | 3 +-- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/Classes.py b/Classes.py index bb640d0a..d028720b 100644 --- a/Classes.py +++ b/Classes.py @@ -106,8 +106,8 @@ def off_energy(self): return self._off_energy @off_energy.setter - def off_energy(self, new): - self._off_energy = new + def off_energy(self, accep_limit, steps=460): + self._off_energy = _np.linspace(0, accep_limit, steps) @property def nturns(self): @@ -122,8 +122,9 @@ def deltas(self): return self._deltas @deltas.setter - def deltas(self, new_deltas): - self._deltas = new_deltas # if the user desires to make a change in the quantity of energ. dev. in tracking simulation + def deltas(self, dev_percent,steps=400): + dev = dev_percent/100 + self._deltas = _np.linspace(0,dev, steps) # if the user desires to make a change in the quantity of energ. dev. in tracking simulation @property def lname(self): @@ -138,8 +139,17 @@ def spos(self): return self._spos @spos.setter - def spos(self, indices): # if the user desires to make a change in the indices in the s position array + def spos(self, indices): # if the user desires to make a change in the indices in the s position array / the variable indices must be a string 'closed' or 'open' self._spos = find_spos(self._model_fit, indices=indices) + + # this indices are obtained from the linear approach for the physical limitants + @property + def inds_pos(self): + return self._inds_pos + + @property + def inds_neg(self): + return self._inds_neg # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula # as amplitudes e os indices limitantes @@ -162,19 +172,21 @@ def get_amps_idxs(self): # this step calls and defines 3 disctinct getters def return_sinpos_track(self,single_spos, par): - self._model.cavity_on = True - self._model.radiation_on = True - spos = self._spos + model = pymodels.si.create_accelerator() + model.cavity_on = True + model.radiation_on = True + model.vchamber_on = False + spos = self.spos # alterar depois a função que é utilizada nesta função para realizar o tracking. index = _np.argmin(_np.abs(spos-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons(self.deltas,self._nturns, - index, self._model, pos_x=1e-5, pos_y=3e-6) + res = tousfunc.track_eletrons(self.deltas,self.nturns, + index, model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: res = tousfunc.track_eletrons(-self.deltas,self._nturns, - index, self._model, pos_x=1e-5, pos_y=3e-6) + index, model, pos_x=1e-5, pos_y=3e-6) return res @@ -219,6 +231,17 @@ def get_weighting_tous(self, single_spos, npt=5000): getdp[indp] = 0 getdn[indn] = 0 + ind = _np.int0(_np.where(getdp>1e-2)[0]) + getdp = getdp[ind] + deltp = deltp[ind] + ind = _np.int0(_np.where(getdn>1e-2)[0]) + getdn = getdn[ind] + deltn = deltn[ind] + + # defining the energy deviation limit until tracking will be performed + + self.deltas = deltp[-1]*1e2 + # this function will return the weighting factors in the scalc position convertion return getdp, getdn, deltp, deltn @@ -229,22 +252,24 @@ def fast_aquisition(self, single_spos, par): # this raise blocks to runing the program if the list of s position has more than 1 element if len(tousfunc.t_list(single_spos)) != 1: raise Exception('This function suports only one s position') + + + fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) + + fp = fdensp.squeeze() + fn = fdensn.squeeze() res = self.return_sinpos_track(single_spos, par) turn_lost, elmnt_lost, delta = _np.zeros(len(res)),_np.zeros(len(res)),_np.zeros(len(res)) + Ddeltas = _np.diff(delta)[0] + for index, iten in enumerate(res): tlost, ellost, delt = iten turn_lost[index] = tlost elmnt_lost[index] = ellost delta[index] = delt - Ddeltas = _np.diff(delta)[0] - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) - - fp = fdensp.squeeze() - fn = fdensn.squeeze() - if 'pos' in par: return res, fp*Ddeltas, deltp *1e2 elif 'neg' in par: @@ -293,7 +318,7 @@ def complete_aquisition(self, lname_or_spos, par): return ress, scat_dis # this function plot the graphic of tracking and the touschek scattering distribution for one single position - def plot_analysi_at_position(self, spos, par, amp_on): + def plot_analysis_at_position(self, single_spos, par): # defining some params top plot the tracking and the scattering distribution # In a first approach I dont have to be concerned in this decision structure because all variables necessary for the calculation will be defined # I will may let this part of the code if I know a best method or decide to make a change here @@ -303,9 +328,12 @@ def plot_analysi_at_position(self, spos, par, amp_on): # else: # amps_and_idxs = self._amp_and_limidx - res, fp, dp = self.fast_aquisition(spos, par) - - tousfunc.plot_track(self._model_fit,res, ) + res, fp, dp = self.fast_aquisition(single_spos, par) + spos = self.spos + index = _np.argmin(_np.abs(spos-single_spos)) + accep = self.accep + inds_lim = _np.int0(self.inds_pos) + tousfunc.plot_track(self.accelerator, res, inds_lim, self.off_energy, par, index, accep, dp, fp) diff --git a/functions.py b/functions.py index 325cf8f7..0ca2f607 100644 --- a/functions.py +++ b/functions.py @@ -174,7 +174,6 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a2.xaxis.grid(False) a3.xaxis.grid(False) - ind = _np.int0(_np.where(f_dens>1e-17)[0]) if 'pos' in param: # defining the y and x label of the first graphic a1.set_ylabel(r'positive energy deviation', fontsize=14) @@ -196,7 +195,7 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.set_title(r'taxa de espalhamento touschek', fontsize=14) # setting the title of the first graphic a1.set_xlabel(r'Scattering touschek rate', fontsize=14) - a1.plot(f_dens[ind], delt[ind], label='Scattering touschek rate', color='black') + a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') # LEMBRAR DE DEFINIR CORRETAMENTE OS INTERVALOS PARA PLOTAR OS DESVIOS DE ENERGIA. PERCEBA QUE OS DESVIOS DE ENERGIA PROVENIENTES DESTA FUNÇÃO # VÃO ATÉ INFINITO BASICAMENTE. EU POSSO SIMPLESMENTE FAZER UM SLICE E DEFINIR ATÉ ONDE EU QUERO QUE O ARRAY SEJA PLOTADO PRA NÃO TER QUE From 26b0765872be5a55950d63cff4ba373eb504ca85 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Sep 2023 10:14:01 -0300 Subject: [PATCH 044/108] mudancas nos deltas. --- Classes.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Classes.py b/Classes.py index d028720b..db084cd2 100644 --- a/Classes.py +++ b/Classes.py @@ -206,8 +206,8 @@ def return_compos_track(self, lspos, par): def get_weighting_tous(self, single_spos, npt=5000): - scalc, daccp, daccn = tousfunc.get_scaccep(self._model_fit, self._accep) - bf = self._beta + scalc, daccp, daccn = tousfunc.get_scaccep(self.accelerator, self.accep) + bf = self.beam_energy ltime = self._ltime b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -231,16 +231,16 @@ def get_weighting_tous(self, single_spos, npt=5000): getdp[indp] = 0 getdn[indn] = 0 - ind = _np.int0(_np.where(getdp>1e-2)[0]) - getdp = getdp[ind] - deltp = deltp[ind] - ind = _np.int0(_np.where(getdn>1e-2)[0]) - getdn = getdn[ind] - deltn = deltn[ind] + # ind = _np.int0(_np.where(getdp>1e-2)[0]) + # getdp = getdp[ind] + # deltp = deltp[ind] + # ind = _np.int0(_np.where(getdn>1e-2)[0]) + # getdn = getdn[ind] + # deltn = deltn[ind] # defining the energy deviation limit until tracking will be performed - self.deltas = deltp[-1]*1e2 + # self.deltas = deltp[-1]*1e2 # this function will return the weighting factors in the scalc position convertion @@ -262,7 +262,7 @@ def fast_aquisition(self, single_spos, par): res = self.return_sinpos_track(single_spos, par) turn_lost, elmnt_lost, delta = _np.zeros(len(res)),_np.zeros(len(res)),_np.zeros(len(res)) - Ddeltas = _np.diff(delta)[0] + for index, iten in enumerate(res): tlost, ellost, delt = iten @@ -270,6 +270,8 @@ def fast_aquisition(self, single_spos, par): elmnt_lost[index] = ellost delta[index] = delt + Ddeltas = _np.diff(delta)[0] + if 'pos' in par: return res, fp*Ddeltas, deltp *1e2 elif 'neg' in par: From 0bf5dd1c1e226829d2809b36419417c882820908 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Wed, 13 Sep 2023 10:17:32 -0300 Subject: [PATCH 045/108] =?UTF-8?q?adicionando=20a=20funcionalidade=20do?= =?UTF-8?q?=20gr=C3=A1fico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 149 +++++++++++++++++++++++++++++++-------------------- functions.py | 4 -- 2 files changed, 90 insertions(+), 63 deletions(-) diff --git a/Classes.py b/Classes.py index db084cd2..1a4b56f4 100644 --- a/Classes.py +++ b/Classes.py @@ -1,6 +1,6 @@ from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute, find_indices, find_spos -import touschek_pack.functions as tousfunc +import nova_pasta.functions as tousfunc import pymodels import pyaccel.optics as py_op import numpy as _np @@ -29,8 +29,8 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._amps_neg = None self._beta = beta # beta is a constant necessary to the calculations - self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') # getting the vchamber's height - self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') + self._h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') # getting the vchamber's height + self._h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') self._ltime = Lifetime(self._model_fit) # self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires @@ -41,10 +41,40 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model + @property + def accelerator(self): + return self._model_fit + + @accelerator.setter + def accelerator(self, new_model): #This line defines a new accelerator if the user desires + self._model_fit = new_model + + # defining the nominal accelerator + @property + def nom_model(self): + return self._model + + # defining the heights of the vchamber, this properties vary the lenght of the array hpos and hneg + @property + def hpos(self): + return self._h_pos + + @hpos.setter + def hpos(self, indices): + self._h_pos = get_attribute(self.accelerator, 'hmax', indices=indices) + + @property + def hneg(self): + return self._h_neg + + @hneg.setter + def hneg(self, indices): + self._h_neg = get_attribute(self.accelerator, 'hmin', indices=indices) + @property def accep(self): if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance(self._model_fit) + self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) return self._accep # Defining the s position, positive and negative accptances along the ring at each 10 meters. @@ -52,30 +82,28 @@ def accep(self): @property def s_calc(self): if self._sc_accps is None: - self._sc_accps = tousfunc.get_scaccep(self._model_fit, self._accep) + self._sc_accps = tousfunc.get_scaccep(self.accelerator, self.accep) return self._sc_accps # This property calculates the physical limitants by the prediction of the linear model @property def amp_and_limidx(self): if self._amp_and_limidx is None: - self._model.cavity_on = False # this step is necessary to define if the - self._model.radiation_on = False - self._amps_pos, self._inds_pos = tousfunc.calc_amp(self._model, self._off_energy, self.h_pos, self.h_neg) - self._amps_neg, self._inds_neg = tousfunc.calc_amp(self._model, -self._off_energy, self.h_pos, self.h_neg) + self.nom_model.cavity_on = False # this step is necessary to define if the + self.nom_model.radiation_on = False + self._amps_pos, self._inds_pos = tousfunc.calc_amp(self.nom_model, + self.off_energy, self.hpos, self.hneg) + self._amps_neg, self._inds_neg = tousfunc.calc_amp(self.nom_model, + -self.off_energy, self.hpos, self.hneg) self._amp_and_limidx = True return self._amp_and_limidx - - # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model + # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model + @property - def accelerator(self): - return self._model_fit - - @accelerator.setter - def accelerator(self, new_model): #This line defines a new accelerator if the user desires - self._model_fit = new_model + def ltime(self): + return self._ltime @property def beam_energy(self): @@ -105,9 +133,13 @@ def neg_vchamber(self, indices): def off_energy(self): return self._off_energy + # the cutoff for energy deviation is the energy acceptance limit @off_energy.setter - def off_energy(self, accep_limit, steps=460): - self._off_energy = _np.linspace(0, accep_limit, steps) + def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if the user desire + accep_pos, accep_neg = accep + accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) + steps = int(accep_lim*10000) # choosed to be the number of steps + self._off_energy = _np.linspace(0, accep_lim, steps) @property def nturns(self): @@ -123,8 +155,8 @@ def deltas(self): @deltas.setter def deltas(self, dev_percent,steps=400): - dev = dev_percent/100 - self._deltas = _np.linspace(0,dev, steps) # if the user desires to make a change in the quantity of energ. dev. in tracking simulation + dev_percent /= 100 + self._deltas = _np.linspace(0,dev_percent, steps) # if the user desires to make a change in the quantity of energ. dev. in tracking simulation @property def lname(self): @@ -142,6 +174,7 @@ def spos(self): def spos(self, indices): # if the user desires to make a change in the indices in the s position array / the variable indices must be a string 'closed' or 'open' self._spos = find_spos(self._model_fit, indices=indices) + # the four properties defining below are to be fixed # this indices are obtained from the linear approach for the physical limitants @property def inds_pos(self): @@ -151,6 +184,16 @@ def inds_pos(self): def inds_neg(self): return self._inds_neg + # This two propertier will help if the user wants to plot the amplitudes calculated by the linear model + @property + def amp_pos(self): + return self._amps_pos + + @property + def amp_neg(self): + return self._amps_neg + + # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula # as amplitudes e os indices limitantes @@ -171,36 +214,34 @@ def get_amps_idxs(self): # this step calls and defines 3 disctinct getters return self.amp_and_limidx, self.accep, self.s_calc def return_sinpos_track(self,single_spos, par): - - model = pymodels.si.create_accelerator() - model.cavity_on = True - model.radiation_on = True - model.vchamber_on = False + + self.nom_model.cavity_on = True + self.nom_model.radiation_on = True + self.nom_model.vchamber_on = True spos = self.spos - - # alterar depois a função que é utilizada nesta função para realizar o tracking. index = _np.argmin(_np.abs(spos-single_spos)) if 'pos' in par: res = tousfunc.track_eletrons(self.deltas,self.nturns, - index, model, pos_x=1e-5, pos_y=3e-6) + index, self.nom_model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: res = tousfunc.track_eletrons(-self.deltas,self._nturns, - index, model, pos_x=1e-5, pos_y=3e-6) + index, self.nom_model, pos_x=1e-5, pos_y=3e-6) return res def return_compos_track(self, lspos, par): - self._model.cavity_on = True - self._model.radiation_on = True + self.nom_model.cavity_on = True + self.nom_model.radiation_on = True + self.nom_model.vchamber_on = True if 'pos' in par: - res = tousfunc.trackm_elec(self._model, self._deltas, - self._nturns, lspos) + res = tousfunc.trackm_elec(self.nom_model, self.deltas, + self.nturns, lspos) elif 'neg' in par: - res = tousfunc.trackm_elec(self._model, -self._deltas, - self._nturns, lspos) + res = tousfunc.trackm_elec(self.nom_model, -self.deltas, + self.nturns, lspos) return res @@ -231,16 +272,16 @@ def get_weighting_tous(self, single_spos, npt=5000): getdp[indp] = 0 getdn[indn] = 0 - # ind = _np.int0(_np.where(getdp>1e-2)[0]) - # getdp = getdp[ind] - # deltp = deltp[ind] - # ind = _np.int0(_np.where(getdn>1e-2)[0]) - # getdn = getdn[ind] - # deltn = deltn[ind] + ind = _np.intp(_np.where(getdp>1e-2)[0]) + getdp = getdp[ind] + deltp = deltp[ind] + ind = _np.intp(_np.where(getdn>1e-2)[0]) + getdn = getdn[ind] + deltn = deltn[ind] # defining the energy deviation limit until tracking will be performed - # self.deltas = deltp[-1]*1e2 + self.deltas = deltp[-1]*1e2 # this function will return the weighting factors in the scalc position convertion @@ -253,25 +294,20 @@ def fast_aquisition(self, single_spos, par): if len(tousfunc.t_list(single_spos)) != 1: raise Exception('This function suports only one s position') - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) fp = fdensp.squeeze() fn = fdensn.squeeze() res = self.return_sinpos_track(single_spos, par) - turn_lost, elmnt_lost, delta = _np.zeros(len(res)),_np.zeros(len(res)),_np.zeros(len(res)) - - + delta = _np.zeros(len(res)) for index, iten in enumerate(res): tlost, ellost, delt = iten - turn_lost[index] = tlost - elmnt_lost[index] = ellost delta[index] = delt Ddeltas = _np.diff(delta)[0] - + if 'pos' in par: return res, fp*Ddeltas, deltp *1e2 elif 'neg' in par: @@ -320,7 +356,7 @@ def complete_aquisition(self, lname_or_spos, par): return ress, scat_dis # this function plot the graphic of tracking and the touschek scattering distribution for one single position - def plot_analysis_at_position(self, single_spos, par): + def plot_analysis_at_position(self, single_spos, par, accep): # defining some params top plot the tracking and the scattering distribution # In a first approach I dont have to be concerned in this decision structure because all variables necessary for the calculation will be defined # I will may let this part of the code if I know a best method or decide to make a change here @@ -333,14 +369,10 @@ def plot_analysis_at_position(self, single_spos, par): res, fp, dp = self.fast_aquisition(single_spos, par) spos = self.spos index = _np.argmin(_np.abs(spos-single_spos)) - accep = self.accep - inds_lim = _np.int0(self.inds_pos) - tousfunc.plot_track(self.accelerator, res, inds_lim, self.off_energy, par, index, accep, dp, fp) + tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), + self.off_energy, par, index, accep, dp, fp) - - - #if the user desires to know all the scattering events along the ring, #only its necessary to do is to pass the @@ -368,5 +400,4 @@ def plot_analysis_at_position(self, single_spos, par): # eu vou definir alguns parametros de uma forma que talvez não seja ideal # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função - - + \ No newline at end of file diff --git a/functions.py b/functions.py index 0ca2f607..50bbdb88 100644 --- a/functions.py +++ b/functions.py @@ -196,10 +196,6 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.set_xlabel(r'Scattering touschek rate', fontsize=14) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - - # LEMBRAR DE DEFINIR CORRETAMENTE OS INTERVALOS PARA PLOTAR OS DESVIOS DE ENERGIA. PERCEBA QUE OS DESVIOS DE ENERGIA PROVENIENTES DESTA FUNÇÃO - # VÃO ATÉ INFINITO BASICAMENTE. EU POSSO SIMPLESMENTE FAZER UM SLICE E DEFINIR ATÉ ONDE EU QUERO QUE O ARRAY SEJA PLOTADO PRA NÃO TER QUE - # ME PREOCUPAR COM CONSERTAR LIMITES DE PLOT DE GRÁFICOS a2.set_title(r'$\delta \times$ lost turn', fontsize=16) # setting the tilte of the second graphic From 4cbf6ecadf04134f72201ed10da0196aa18b7832 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Sep 2023 14:40:47 -0300 Subject: [PATCH 046/108] =?UTF-8?q?pequenas=20altera=C3=A7=C3=B5es,=20hoje?= =?UTF-8?q?=20a=20fun=C3=A7=C3=A3o=20para=20a=20an=C3=A1lise=20de=20todos?= =?UTF-8?q?=20os=20c=C3=A1lculos=20realizados=20at=C3=A9=20o=20momento=20f?= =?UTF-8?q?icou=20pronta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 2 +- functions.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Classes.py b/Classes.py index 1a4b56f4..e259661b 100644 --- a/Classes.py +++ b/Classes.py @@ -1,6 +1,6 @@ from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute, find_indices, find_spos -import nova_pasta.functions as tousfunc +import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op import numpy as _np diff --git a/functions.py b/functions.py index 50bbdb88..8a972cd8 100644 --- a/functions.py +++ b/functions.py @@ -6,6 +6,7 @@ import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity from mathphys.functions import save_pickle, load_pickle +import pandas as pd def calc_amp(acc,energy_offsets, hmax, hmin): @@ -176,16 +177,15 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep if 'pos' in param: # defining the y and x label of the first graphic - a1.set_ylabel(r'positive energy deviation', fontsize=14) - a2.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + a1.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: - a1.set_ylabel(r'negative positive energy deviation', fontsize=14) - a2.set_ylabel(r'negative $\delta$ [%]', fontsize=14) + a1.set_ylabel(r'negative $\delta$ [%]', fontsize=14) a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted indx = _np.argmin(_np.abs(lista_off-acp_s)) @@ -662,4 +662,8 @@ def histgms(acc,l_spos,num_part, accep, de_min): hist2=_np.array(histsp2, dtype='object') indices=_np.array(indices) - return histsp1, histsp2, indices \ No newline at end of file + return histsp1, histsp2, indices + +def defining_tables(): + + return None \ No newline at end of file From 47ca6d67a73e365c29fec45a4621e0b5ce2d2592 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 20 Sep 2023 14:36:12 -0300 Subject: [PATCH 047/108] =?UTF-8?q?lembrete=20de=20adicionar=20neste=20arq?= =?UTF-8?q?uivo=20python=20a=20fun=C3=A7=C3=A3o=20que=20ser=C3=A1=20utiliz?= =?UTF-8?q?ada=20no=20estudo=20de=20m=C3=A1quina?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/functions.py b/functions.py index 8a972cd8..0322265e 100644 --- a/functions.py +++ b/functions.py @@ -66,6 +66,9 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): return turnl_element +def f_mchn_stdy(): + pass + # This function will calculate where the electrons are lost using tracking # The function recives an array containing all the s positions along the ring From 510f35e7b3ede038df521336f1497bec6435a507 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 11 Oct 2023 13:41:58 -0300 Subject: [PATCH 048/108] =?UTF-8?q?adicionando=20um=20prototipo=20da=20fun?= =?UTF-8?q?=C3=A7ao=20que=20far=C3=A1=20o=20calculo=20mais=20importante=20?= =?UTF-8?q?do=20projeto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/Classes.py b/Classes.py index e259661b..3da18fdc 100644 --- a/Classes.py +++ b/Classes.py @@ -6,6 +6,7 @@ import numpy as _np import matplotlib.pyplot as _plt from mathphys.beam_optics import beam_rigidity as _beam_rigidity +import pandas as _pd class Tous_analysis(): @@ -20,6 +21,7 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._model_fit = accelerator self._model = pymodels.si.create_accelerator() # No necessity to change this model, because it's an internal tool for calculations. + self._amp_and_limidx = None self._sc_accps = None self._accep = None @@ -37,7 +39,7 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._off_energy = energy_off # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model self._nturns = n_turns # defined like this by the standard self._deltas = deltas # defined by the standard - self._spos = find_spos(self._model_fit, indices='open') + self._spos = find_spos(self._model_fit, indices='closed') # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @@ -400,4 +402,94 @@ def plot_analysis_at_position(self, single_spos, par, accep): # eu vou definir alguns parametros de uma forma que talvez não seja ideal # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função - \ No newline at end of file + + +def get_table(self,l_scattered_pos): + + fact = 0.03 + spos = self._spos + + ltime = Lifetime(self._model_fit) + tous_rate = ltime.touschek_data['rate'] + + self._model.radiation_on = True + self._model.cavity_on = True + self.vchamber_on = True + + for j, scattered_pos in enumerate(l_scattered_pos): + + index = _np.argmin(_np.abs(scattered_pos-spos)) + res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) + + lostinds, deltas = _np.zeros(len(res)), _np.zeros(len(res)) + for idx,iten in enumerate(res): + _, ellost, delta = iten + lostinds[idx] = ellost + deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos + + lostinds = _np.intp(lostinds) + lost_positions = spos[lostinds] + lost_positions = _np.round(lost_positions, 2) + + step = int((deltas[0]+deltas[-1])/fact) + itv_track = _np.linspace(deltas[0], deltas[-1], step) # method learned by fac repositories + + data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) # create the dataframe that is obtained by tracking + lost_pos_column = (data.groupby('lost_pos_by_tracking').groups).keys() + data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) # this step agroups the lost_positions + + # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain the scattered positions and the lost positions after scattering + + itv_delta = [] + for current, next_iten in zip(itv_track, itv_track[1:]): + data['{:.2f} % < delta < {:.2f} %'.format(current*1e2, next_iten*1e2)] = _np.zeros(len(list(lost_pos_column))) # this step creates new columns in the dataframe and fill with zeros + itv_delta.append((current, next_iten)) + # Next step must calculate each matrix element from the dataframe + + var = list(data.index) + # quando as duas variáveis são iguais isso acab resultando em um erro então estou colocando essa condição. + if var == lost_pos_column: + pass + else: + data = data.set_index('lost_pos_by_tracking') + + + for idx, lost_pos in enumerate(lost_positions): # essas duas estruturas de repetição são responsáveis por calcular + # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico + delta = deltas[idx] + lps = [] + for j, interval in enumerate(itv_delta): + if j == 0: + if interval[0]<= delta <= interval[1]: + data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + else: + if interval[0]< delta <= interval[1]: + data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + + data = data / len(deltas) + + npt = int((spos[-1]-spos[0])/0.1) + + + scalc = _np.linspace(spos[0], spos[-1], npt) + rate_nom_lattice = _np.interp(spos, scalc, tous_rate) + + dic_res = {} + lost_pos_df = [] + part_prob = [] + for index, iten in data.iterrows(): + t_prob = 0 + for idx, m in enumerate(iten): + t_prob += m + if idx == iten.count()-1: + part_prob.append(t_prob) + lost_pos_df.append(index) + + lost_pos_df = _np.array(lost_pos_df) + part_prob = _np.array(part_prob) + + + dic_res['lost_position'] = lost_pos_df + dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] + + _pd.DataFrame(dic_res).set_index('lost_position').transpose() \ No newline at end of file From 7eac5f68e809cf10a41a9f81fa98cb442c3c2b51 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 16 Oct 2023 11:07:05 -0300 Subject: [PATCH 049/108] =?UTF-8?q?avan=C3=A7os=20da=20segunda?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Classes.py b/Classes.py index 3da18fdc..2ff7b920 100644 --- a/Classes.py +++ b/Classes.py @@ -428,8 +428,7 @@ def get_table(self,l_scattered_pos): deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos lostinds = _np.intp(lostinds) - lost_positions = spos[lostinds] - lost_positions = _np.round(lost_positions, 2) + lost_positions = _np.round(spos[lostinds], 2) step = int((deltas[0]+deltas[-1])/fact) itv_track = _np.linspace(deltas[0], deltas[-1], step) # method learned by fac repositories @@ -458,8 +457,8 @@ def get_table(self,l_scattered_pos): # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico delta = deltas[idx] lps = [] - for j, interval in enumerate(itv_delta): - if j == 0: + for i, interval in enumerate(itv_delta): + if i == 0: if interval[0]<= delta <= interval[1]: data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 else: @@ -477,19 +476,28 @@ def get_table(self,l_scattered_pos): dic_res = {} lost_pos_df = [] part_prob = [] - for index, iten in data.iterrows(): + for indx, iten in data.iterrows(): t_prob = 0 for idx, m in enumerate(iten): t_prob += m if idx == iten.count()-1: part_prob.append(t_prob) - lost_pos_df.append(index) + lost_pos_df.append(indx) lost_pos_df = _np.array(lost_pos_df) part_prob = _np.array(part_prob) - dic_res['lost_position'] = lost_pos_df dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] - _pd.DataFrame(dic_res).set_index('lost_position').transpose() \ No newline at end of file + dataframe = _pd.DataFrame(dic_res) + + if j: + for k, iten in enumerate(lost_pos_df): + if not _np.isin(iten, _np.array(dataframe.index.tolist())): + new_line = _pd.Series({'lost_position': iten}) + idx_new_line = len(dataframe) + dataframe.loc[idx_new_line] = new_line + + return dataframe + From 5f319bde7e4d001443e5d33dedf55029740dd658 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 16 Oct 2023 14:55:48 -0300 Subject: [PATCH 050/108] =?UTF-8?q?come=C3=A7ando=20a=20fazer=20a=20varred?= =?UTF-8?q?ura=20dos=20pontos=20de=20espalhamento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 198 +++++++++++++++++++++++++++-------------------------- 1 file changed, 100 insertions(+), 98 deletions(-) diff --git a/Classes.py b/Classes.py index 2ff7b920..027e3371 100644 --- a/Classes.py +++ b/Classes.py @@ -217,10 +217,10 @@ def get_amps_idxs(self): # this step calls and defines 3 disctinct getters def return_sinpos_track(self,single_spos, par): - self.nom_model.cavity_on = True - self.nom_model.radiation_on = True - self.nom_model.vchamber_on = True - spos = self.spos + self._model.cavity_on = True + self._model.radiation_on = True + self._model.vchamber_on = True + spos = self._spos index = _np.argmin(_np.abs(spos-single_spos)) if 'pos' in par: @@ -404,100 +404,102 @@ def plot_analysis_at_position(self, single_spos, par, accep): # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função -def get_table(self,l_scattered_pos): - - fact = 0.03 - spos = self._spos - - ltime = Lifetime(self._model_fit) - tous_rate = ltime.touschek_data['rate'] - - self._model.radiation_on = True - self._model.cavity_on = True - self.vchamber_on = True - - for j, scattered_pos in enumerate(l_scattered_pos): - - index = _np.argmin(_np.abs(scattered_pos-spos)) - res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) - - lostinds, deltas = _np.zeros(len(res)), _np.zeros(len(res)) - for idx,iten in enumerate(res): - _, ellost, delta = iten - lostinds[idx] = ellost - deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos - - lostinds = _np.intp(lostinds) - lost_positions = _np.round(spos[lostinds], 2) - - step = int((deltas[0]+deltas[-1])/fact) - itv_track = _np.linspace(deltas[0], deltas[-1], step) # method learned by fac repositories - - data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) # create the dataframe that is obtained by tracking - lost_pos_column = (data.groupby('lost_pos_by_tracking').groups).keys() - data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) # this step agroups the lost_positions - - # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain the scattered positions and the lost positions after scattering - - itv_delta = [] - for current, next_iten in zip(itv_track, itv_track[1:]): - data['{:.2f} % < delta < {:.2f} %'.format(current*1e2, next_iten*1e2)] = _np.zeros(len(list(lost_pos_column))) # this step creates new columns in the dataframe and fill with zeros - itv_delta.append((current, next_iten)) - # Next step must calculate each matrix element from the dataframe - - var = list(data.index) - # quando as duas variáveis são iguais isso acab resultando em um erro então estou colocando essa condição. - if var == lost_pos_column: - pass - else: - data = data.set_index('lost_pos_by_tracking') - - - for idx, lost_pos in enumerate(lost_positions): # essas duas estruturas de repetição são responsáveis por calcular - # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico - delta = deltas[idx] - lps = [] - for i, interval in enumerate(itv_delta): - if i == 0: - if interval[0]<= delta <= interval[1]: - data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 - else: - if interval[0]< delta <= interval[1]: - data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 - - data = data / len(deltas) - - npt = int((spos[-1]-spos[0])/0.1) - - - scalc = _np.linspace(spos[0], spos[-1], npt) - rate_nom_lattice = _np.interp(spos, scalc, tous_rate) - - dic_res = {} - lost_pos_df = [] - part_prob = [] - for indx, iten in data.iterrows(): - t_prob = 0 - for idx, m in enumerate(iten): - t_prob += m - if idx == iten.count()-1: - part_prob.append(t_prob) - lost_pos_df.append(indx) - - lost_pos_df = _np.array(lost_pos_df) - part_prob = _np.array(part_prob) - - dic_res['lost_position'] = lost_pos_df - dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] + def get_table(self,l_scattered_pos): + + fact = 0.03 + spos = self._spos - dataframe = _pd.DataFrame(dic_res) + ltime = Lifetime(self._model_fit) + tous_rate = ltime.touschek_data['rate'] - if j: - for k, iten in enumerate(lost_pos_df): - if not _np.isin(iten, _np.array(dataframe.index.tolist())): - new_line = _pd.Series({'lost_position': iten}) - idx_new_line = len(dataframe) - dataframe.loc[idx_new_line] = new_line - - return dataframe + self._model.radiation_on = True + self._model.cavity_on = True + self._model.vchamber_on = True + + for j, scattered_pos in enumerate(l_scattered_pos): + + index = _np.argmin(_np.abs(scattered_pos-spos)) + res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) + + lostinds, deltas = _np.zeros(len(res)), _np.zeros(len(res)) + for idx,iten in enumerate(res): + _, ellost, delta = iten + lostinds[idx] = ellost + deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos + + lostinds = _np.intp(lostinds) + lost_positions = _np.round(spos[lostinds], 2) + + step = int((deltas[0]+deltas[-1])/fact) + itv_track = _np.linspace(deltas[0], deltas[-1], step) # method learned by fac repositories + + data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) # create the dataframe that is obtained by tracking + lost_pos_column = (data.groupby('lost_pos_by_tracking').groups).keys() + data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) # this step agroups the lost_positions + + # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain the scattered positions and the lost positions after scattering + + itv_delta = [] + for current, next_iten in zip(itv_track, itv_track[1:]): + data['{:.2f} % < delta < {:.2f} %'.format(current*1e2, next_iten*1e2)] = _np.zeros(len(list(lost_pos_column))) # this step creates new columns in the dataframe and fill with zeros + itv_delta.append((current, next_iten)) + # Next step must calculate each matrix element from the dataframe + + var = list(data.index) + # quando as duas variáveis são iguais isso acab resultando em um erro então estou colocando essa condição. + if var == lost_pos_column: + pass + else: + data = data.set_index('lost_pos_by_tracking') + + + for idx, lost_pos in enumerate(lost_positions): # essas duas estruturas de repetição são responsáveis por calcular + # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico + delta = deltas[idx] + lps = [] + for i, interval in enumerate(itv_delta): + if i == 0: + if interval[0]<= delta <= interval[1]: + data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + else: + if interval[0]< delta <= interval[1]: + data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + + data = data / len(deltas) + + npt = int((spos[-1]-spos[0])/0.1) + + + scalc = _np.linspace(spos[0], spos[-1], npt) + rate_nom_lattice = _np.interp(spos, scalc, tous_rate) + + dic_res = {} + lost_pos_df = [] + part_prob = [] + for indx, iten in data.iterrows(): + t_prob = 0 + for idx, m in enumerate(iten): + t_prob += m + if idx == iten.count()-1: + part_prob.append(t_prob) + lost_pos_df.append(indx) + + lost_pos_df = _np.array(lost_pos_df) + part_prob = _np.array(part_prob) + + dic_res['lost_position'] = lost_pos_df + dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] + + dataframe = _pd.DataFrame(dic_res) + print(j) + + if not j: + for k, iten in enumerate(lost_pos_df): + if not _np.isin(iten, _np.array(dataframe.index.tolist())): + new_line = _pd.Series({'lost_position': iten}) + idx_new_line = len(dataframe) + dataframe.loc[idx_new_line] = new_line + print(j) + + return dataframe From 92003514a825c3474eb3b823747b9ba8d1f0df33 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Tue, 17 Oct 2023 18:48:41 -0300 Subject: [PATCH 051/108] ta ficando apertado --- Classes.py | 91 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 24 deletions(-) diff --git a/Classes.py b/Classes.py index 027e3371..db91d2fe 100644 --- a/Classes.py +++ b/Classes.py @@ -404,25 +404,46 @@ def plot_analysis_at_position(self, single_spos, par, accep): # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função - def get_table(self,l_scattered_pos): + def get_track(self,l_scattered_pos): - fact = 0.03 + all_track = [] + indices = [] spos = self._spos - - ltime = Lifetime(self._model_fit) - tous_rate = ltime.touschek_data['rate'] self._model.radiation_on = True self._model.cavity_on = True self._model.vchamber_on = True - for j, scattered_pos in enumerate(l_scattered_pos): + for _, scattered_pos in enumerate(l_scattered_pos): index = _np.argmin(_np.abs(scattered_pos-spos)) + indices.append(index) res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) + all_track.append(res) + + return all_track, indices + + def get_table(self, l_scattered_pos): + dic_res = {} - lostinds, deltas = _np.zeros(len(res)), _np.zeros(len(res)) - for idx,iten in enumerate(res): + all_track, indices = self.get_track(l_scattered_pos) + spos = self._spos + + fact = 0.03 + ltime = Lifetime(self._model_fit) + tous_rate = ltime.touschek_data['rate'] + + prob = [] + lostp = [] + all_lostp = [] + + for j, iten in enumerate(all_track): + + index = indices[j] + scattered_pos = l_scattered_pos[j] + + lostinds, deltas = _np.zeros(len(iten)), _np.zeros(len(iten)) + for idx,iten in enumerate(iten): _, ellost, delta = iten lostinds[idx] = ellost deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos @@ -452,7 +473,6 @@ def get_table(self,l_scattered_pos): else: data = data.set_index('lost_pos_by_tracking') - for idx, lost_pos in enumerate(lost_positions): # essas duas estruturas de repetição são responsáveis por calcular # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico delta = deltas[idx] @@ -469,11 +489,9 @@ def get_table(self,l_scattered_pos): npt = int((spos[-1]-spos[0])/0.1) - scalc = _np.linspace(spos[0], spos[-1], npt) rate_nom_lattice = _np.interp(spos, scalc, tous_rate) - dic_res = {} lost_pos_df = [] part_prob = [] for indx, iten in data.iterrows(): @@ -487,19 +505,44 @@ def get_table(self,l_scattered_pos): lost_pos_df = _np.array(lost_pos_df) part_prob = _np.array(part_prob) - dic_res['lost_position'] = lost_pos_df - dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] + # dic_res['lost_position_{}'.format(j+1)] = lost_pos_df + + prob.append(part_prob * rate_nom_lattice[index]) + lostp.append(lost_pos_df) - dataframe = _pd.DataFrame(dic_res) - print(j) - if not j: - for k, iten in enumerate(lost_pos_df): - if not _np.isin(iten, _np.array(dataframe.index.tolist())): - new_line = _pd.Series({'lost_position': iten}) - idx_new_line = len(dataframe) - dataframe.loc[idx_new_line] = new_line - print(j) - - return dataframe + all_lostp = lost_pos_df + else: + boolean_array = _np.isin(lost_pos_df, all_lostp) + for ind, boolean_indc in enumerate(boolean_array): + if not boolean_indc: + all_lostp = _np.append(all_lostp, lost_pos_df[ind]) + + return all_lostp + # dataframe = _pd.DataFrame(dic_res) + + + # if j>0: + # bool_array = _np.isin(lost_pos_df, _np.array(dataframe.index.tolist())) + # for iten in bool_array: + # if not iten: + # new_line = _pd.Series({'lost_position': iten}) + # idx_new_line = len(dataframe) + # dataframe.loc[idx_new_line] = new_line + + # dic_res['lost_position'] = lost_pos_df + # dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] + + # df = _pd.DataFrame(dic_res) + # print(j) + # bool_array = _np.isin(lost_pos_df, ) + # b = lost_pos_df + + # for k, iten in enumerate(lost_pos_df): + # if not : + # new_line = _pd.Series({'lost_position': iten}) + # idx_new_line = len(dataframe) + # dataframe.loc[idx_new_line] = new_line + + return From 23ff1df6a4119543a7cf314c2cb0e77e7eee4f01 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Tue, 17 Oct 2023 19:37:41 -0300 Subject: [PATCH 052/108] ta ficando mais apertado ainda --- Classes.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Classes.py b/Classes.py index db91d2fe..f77906ef 100644 --- a/Classes.py +++ b/Classes.py @@ -436,6 +436,7 @@ def get_table(self, l_scattered_pos): prob = [] lostp = [] all_lostp = [] + bool_list = [] for j, iten in enumerate(all_track): @@ -505,10 +506,9 @@ def get_table(self, l_scattered_pos): lost_pos_df = _np.array(lost_pos_df) part_prob = _np.array(part_prob) - # dic_res['lost_position_{}'.format(j+1)] = lost_pos_df + dic_res[tuple(lost_pos_df)] = part_prob * rate_nom_lattice[index] - prob.append(part_prob * rate_nom_lattice[index]) - lostp.append(lost_pos_df) + # para acessar as chaves deste dicionario list(df.keys())[0] if not j: all_lostp = lost_pos_df @@ -518,7 +518,14 @@ def get_table(self, l_scattered_pos): if not boolean_indc: all_lostp = _np.append(all_lostp, lost_pos_df[ind]) - return all_lostp + if j == len(l_scattered_pos)-1: + for l_pos in lostp: + bool_array = _np.isin(all_lostp, l_pos) + bool_list.append(bool_array) + + + + return dic_res # dataframe = _pd.DataFrame(dic_res) From 3e67db800be5445e2771cc91db673c1a1d9b60bc Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Wed, 18 Oct 2023 08:29:40 -0300 Subject: [PATCH 053/108] =?UTF-8?q?mais=20fun=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/Classes.py b/Classes.py index f77906ef..638dc713 100644 --- a/Classes.py +++ b/Classes.py @@ -506,10 +506,10 @@ def get_table(self, l_scattered_pos): lost_pos_df = _np.array(lost_pos_df) part_prob = _np.array(part_prob) - dic_res[tuple(lost_pos_df)] = part_prob * rate_nom_lattice[index] + prob.append(part_prob * rate_nom_lattice[index]) + lostp.append(lost_pos_df) # para acessar as chaves deste dicionario list(df.keys())[0] - if not j: all_lostp = lost_pos_df else: @@ -523,33 +523,21 @@ def get_table(self, l_scattered_pos): bool_array = _np.isin(all_lostp, l_pos) bool_list.append(bool_array) - - - return dic_res + return all_lostp, bool_list, prob, lostp # dataframe = _pd.DataFrame(dic_res) + + def get_finally(self,l_scattered_pos): + + all_lostp, bool_list, prob, lostp = self.get_table(l_scattered_pos) + + for i,l_bool in enumerate(bool_list): + for j, boo in enumerate(l_bool): + if boo: + var = all_lostp[i][j] + print(_np.where(lostp[i]==var)) + + return None + + - - # if j>0: - # bool_array = _np.isin(lost_pos_df, _np.array(dataframe.index.tolist())) - # for iten in bool_array: - # if not iten: - # new_line = _pd.Series({'lost_position': iten}) - # idx_new_line = len(dataframe) - # dataframe.loc[idx_new_line] = new_line - - # dic_res['lost_position'] = lost_pos_df - # dic_res['{}'.format(scattered_pos)] = part_prob * rate_nom_lattice[index] - - # df = _pd.DataFrame(dic_res) - # print(j) - # bool_array = _np.isin(lost_pos_df, ) - # b = lost_pos_df - - # for k, iten in enumerate(lost_pos_df): - # if not : - # new_line = _pd.Series({'lost_position': iten}) - # idx_new_line = len(dataframe) - # dataframe.loc[idx_new_line] = new_line - - return From 9d129f0c635f314e8230f9a4c8cb1de62f6f66c1 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 18 Oct 2023 11:04:05 -0300 Subject: [PATCH 054/108] =?UTF-8?q?quase=20l=C3=A1..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Classes.py b/Classes.py index 638dc713..7fedee27 100644 --- a/Classes.py +++ b/Classes.py @@ -509,7 +509,6 @@ def get_table(self, l_scattered_pos): prob.append(part_prob * rate_nom_lattice[index]) lostp.append(lost_pos_df) - # para acessar as chaves deste dicionario list(df.keys())[0] if not j: all_lostp = lost_pos_df else: @@ -523,21 +522,32 @@ def get_table(self, l_scattered_pos): bool_array = _np.isin(all_lostp, l_pos) bool_list.append(bool_array) - return all_lostp, bool_list, prob, lostp + return all_lostp, prob, lostp # dataframe = _pd.DataFrame(dic_res) def get_finally(self,l_scattered_pos): - all_lostp, bool_list, prob, lostp = self.get_table(l_scattered_pos) + all_lostp, prob, lostp = self.get_table(l_scattered_pos) - for i,l_bool in enumerate(bool_list): - for j, boo in enumerate(l_bool): - if boo: - var = all_lostp[i][j] - print(_np.where(lostp[i]==var)) - - return None + shaper = [] + + for idx, scattered_pos in enumerate(l_scattered_pos): + # for j, lpos in enumerate(all_lostp): + + future_df = [] + bool_array = _np.isin(all_lostp, lostp[idx]) + + for j, boolean in enumerate(bool_array): + if boolean: + index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) + # print(index) + future_df.append(prob[idx][index]) + else: + future_df.append(0) + + shaper.append(future_df) + return shaper From 75c159ddd26e7b05f9b7956ed4ac5a4aa0da35c8 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 18 Oct 2023 11:41:26 -0300 Subject: [PATCH 055/108] agora realmente ta quase pronto --- Classes.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Classes.py b/Classes.py index 7fedee27..108d42f7 100644 --- a/Classes.py +++ b/Classes.py @@ -423,8 +423,7 @@ def get_track(self,l_scattered_pos): return all_track, indices - def get_table(self, l_scattered_pos): - dic_res = {} + def find_data(self, l_scattered_pos): all_track, indices = self.get_track(l_scattered_pos) spos = self._spos @@ -436,7 +435,6 @@ def get_table(self, l_scattered_pos): prob = [] lostp = [] all_lostp = [] - bool_list = [] for j, iten in enumerate(all_track): @@ -517,37 +515,40 @@ def get_table(self, l_scattered_pos): if not boolean_indc: all_lostp = _np.append(all_lostp, lost_pos_df[ind]) - if j == len(l_scattered_pos)-1: - for l_pos in lostp: - bool_array = _np.isin(all_lostp, l_pos) - bool_list.append(bool_array) - return all_lostp, prob, lostp # dataframe = _pd.DataFrame(dic_res) - def get_finally(self,l_scattered_pos): - - all_lostp, prob, lostp = self.get_table(l_scattered_pos) + def get_table(self,l_scattered_pos): + + dic_res = {} + all_lostp, prob, lostp = self.find_data(l_scattered_pos) - shaper = [] + all_scat = [] for idx, scattered_pos in enumerate(l_scattered_pos): # for j, lpos in enumerate(all_lostp): - future_df = [] + scat_data = [] bool_array = _np.isin(all_lostp, lostp[idx]) for j, boolean in enumerate(bool_array): if boolean: index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) # print(index) - future_df.append(prob[idx][index]) + scat_data.append(prob[idx][index]) else: - future_df.append(0) - - shaper.append(future_df) + scat_data.append(0) + # all_scat.append(scat_data) + + if not idx: + dic_res['lost_positions'] = all_lostp + dic_res['{}'.format(scattered_pos)] = scat_data + else: + dic_res['{}'.format(scattered_pos)] = scat_data + + # df = _pd.DataFrame(dic_res) - return shaper + return dic_res From 9106f84238021d7e31dd5d6e2c1058029a4c8ad8 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 18 Oct 2023 14:53:12 -0300 Subject: [PATCH 056/108] =?UTF-8?q?pequenas=20mudan=C3=A7as?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/Classes.py b/Classes.py index 108d42f7..cc72de66 100644 --- a/Classes.py +++ b/Classes.py @@ -250,7 +250,7 @@ def return_compos_track(self, lspos, par): def get_weighting_tous(self, single_spos, npt=5000): scalc, daccp, daccn = tousfunc.get_scaccep(self.accelerator, self.accep) - bf = self.beam_energy + bf = self.beam_energy # bf is the beta factor ltime = self._ltime b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -381,29 +381,6 @@ def plot_analysis_at_position(self, single_spos, par, accep): # remember that ind is the index that represents the initial position where tracking begins - - #o resultado para este res será uma lista com diversas tuplas então agora eu tenho que me perguntar como - #eu vou organizar isso - - - # e se eu fizesse a função dessa classe já pensando na possibilidade do calculo ser realizado para apenas um ponto do anel ou para varios ? - # caso eu seja questionado sobre isso, posso justificar que para apenas um ponto do anel os cálculos são executados mais rapidamente. - - - # As mensagens deixadas aqui são referentes a modificações que eu preciso realizar nesta classe com novas funcionalidades - - # Proximos passos - # preciso implementar o gráfico da distribuição junto com o gráfico do tracking - # esses gráficos podem ser mostrados juntamente com o tracking o separados - # preciso implementar o complete aquisition - # e ainda preciso pensar em como será o input dessa função - # se ela vai usar o get_family_data ou find_indices (saber quando cada um será usado) - # eu também deveria fazer a pesagem também por meio da simulação monte carlo que foi implementada há algum tempo - - # eu vou definir alguns parametros de uma forma que talvez não seja ideal - # o que eu vou fazer vai ser definir todos os parametros que eu preciso de uma vez que eu preciso por meio de uma função - - def get_track(self,l_scattered_pos): all_track = [] @@ -523,10 +500,7 @@ def get_table(self,l_scattered_pos): dic_res = {} all_lostp, prob, lostp = self.find_data(l_scattered_pos) - all_scat = [] - for idx, scattered_pos in enumerate(l_scattered_pos): - # for j, lpos in enumerate(all_lostp): scat_data = [] bool_array = _np.isin(all_lostp, lostp[idx]) @@ -534,11 +508,9 @@ def get_table(self,l_scattered_pos): for j, boolean in enumerate(bool_array): if boolean: index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) - # print(index) scat_data.append(prob[idx][index]) else: scat_data.append(0) - # all_scat.append(scat_data) if not idx: dic_res['lost_positions'] = all_lostp From 5b221e272bb129b818b6c1a05fc46ba73f0cbb83 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 19 Oct 2023 10:49:27 -0300 Subject: [PATCH 057/108] =?UTF-8?q?adicionando=20fun=C3=A7=C3=A3o=20para?= =?UTF-8?q?=20analisar=20melhor=20o=20mapa=20de=20calor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Classes.py b/Classes.py index cc72de66..c955eff7 100644 --- a/Classes.py +++ b/Classes.py @@ -499,9 +499,10 @@ def get_table(self,l_scattered_pos): dic_res = {} all_lostp, prob, lostp = self.find_data(l_scattered_pos) + n_scat = _np.round(l_scattered_pos, 2) + + for idx, scattered_pos in enumerate(n_scat): - for idx, scattered_pos in enumerate(l_scattered_pos): - scat_data = [] bool_array = _np.isin(all_lostp, lostp[idx]) @@ -521,6 +522,18 @@ def get_table(self,l_scattered_pos): # df = _pd.DataFrame(dic_res) return dic_res + + def reorder_dict(self, l_scattered_pos, reording_key): # chatgpt code to reorder the dictionary + + dic = self.get_table(l_scattered_pos) + + zip_tuples = zip(*[dic[chave] for chave in dic]) + new_tuples = sorted(zip_tuples, key=lambda x: x[list(dic.keys()).index(reording_key)]) + zip_ordered = zip(*new_tuples) + + new_dict = {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} + + return new_dict From 97b4c8b14ce505399eaadf4318fe031decda6722 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 19 Oct 2023 10:50:56 -0300 Subject: [PATCH 058/108] =?UTF-8?q?alterando=20o=20nome=20do=20metodo=20qu?= =?UTF-8?q?e=20reordena=20o=20dicionario=20para=20facilitar=20as=20an?= =?UTF-8?q?=C3=A1lises?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes.py b/Classes.py index c955eff7..87004c53 100644 --- a/Classes.py +++ b/Classes.py @@ -523,7 +523,7 @@ def get_table(self,l_scattered_pos): return dic_res - def reorder_dict(self, l_scattered_pos, reording_key): # chatgpt code to reorder the dictionary + def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to reorder the dictionary dic = self.get_table(l_scattered_pos) From 0029b2e42c2c435817317a7dd32e113bb2ff74c1 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 19 Oct 2023 13:06:10 -0300 Subject: [PATCH 059/108] =?UTF-8?q?implementando=20o=20c=C3=B3digo=20que?= =?UTF-8?q?=20vai=20plotar=20o=20mapa=20de=20calor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Classes.py b/Classes.py index 87004c53..7348f5db 100644 --- a/Classes.py +++ b/Classes.py @@ -534,6 +534,60 @@ def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to r new_dict = {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} return new_dict + + def plot_scat_table(self, l_scattered_pos, n_r,n_c=1): + + new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') + + df = _pd.DataFrame(new_dic) + df = df.set_index('lost_positions') + + fig, ax = _plt.subplots(n_c, n_r, figsize=(10, 6)) + ax.set_title('Loss profile') + + ax.set_xlabel('scattered positions [m]', fontsize=16) + ax.set_ylabel('lost positions [m]', fontsize=16) + + heatmap = ax.pcolor(df, cmap='jet') + _plt.colorbar(heatmap) + + step1 = int(len(new_dic.keys())/5) + arr1 = df.columns.values[::step1] + + _plt.xticks(_np.arange(df.shape[1])[::step1] + 0.5, arr1, fontsize=12) + + step2 = int(len(new_dic['lost_positions'])/5) + arr2 = df.index.values[::step2] + + _plt.yticks(_np.arange(df.shape[0])[::step2] + 0.5, arr2, fontsize=12) + + fig.tight_layout() + + _plt.show() + + +# # This function will probably will be in my repositories +# # I dont know if I will use it again, but it seems to me that it could be uselfull in some point + +# def extract_delt(groups, deltas): +# c = 0 +# big_list = [] +# for lists in groups: +# lil_list = [] +# for _ in lists: +# lil_list.append(c) +# c+=1 + +# big_list.append(lil_list) + +# sep_deltas = [] +# comp_l = [] + +# for iten in big_list: +# sep_deltas.append(deltas[iten]) +# comp_l.append(len(iten)) + +# return sep_deltas, comp_l From a272845d2c69249daea7ae8a2a3d9f15dc3c758c Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Fri, 20 Oct 2023 09:38:12 -0300 Subject: [PATCH 060/108] =?UTF-8?q?adicionando=20a=20possibilidade=20de=20?= =?UTF-8?q?ver=20qual=20=C3=A9=20o=20elemento=20analisado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Classes.py b/Classes.py index 7348f5db..2266ca8c 100644 --- a/Classes.py +++ b/Classes.py @@ -1,5 +1,5 @@ from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute, find_indices, find_spos +from pyaccel.lattice import get_attribute, find_indices, find_spos, find_dict import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op @@ -536,14 +536,40 @@ def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to r return new_dict def plot_scat_table(self, l_scattered_pos, n_r,n_c=1): - + spos = self._spos new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') + if len(l_scattered_pos)%2 == 0: + array = _np.arange(l_scattered_pos.size) + j = _np.intp(_np.where(array == int((len(l_scattered_pos)/2 + 1)))[0]) + array_j = l_scattered_pos[j] + index = _np.argmin(_np.abs(spos-array_j)) + + lists = list(find_dict(self._model_fit, 'fam_name').values()) + + else: + array = _np.arange(l_scattered_pos.size) + j = _np.where(array == int((len(l_scattered_pos)+1)/2))[0] + array_j = l_scattered_pos[j] + index = _np.argmin(_np.abs(spos-array_j)) + + lists = list(find_dict(self._model_fit, 'fam_name').values()) + + for i, l in enumerate(lists): + if _np.isin(index, l).item(): + fam_name = list(find_dict(self._model_fit, 'fam_name').keys())[i] + df = _pd.DataFrame(new_dic) df = df.set_index('lost_positions') fig, ax = _plt.subplots(n_c, n_r, figsize=(10, 6)) ax.set_title('Loss profile') + + legend = ax.text(0.5, -0.1, '{}'.format(fam_name), size=12, color='black', + ha='center', va='center', transform=_plt.gca().transAxes) + + # Ajustando a legenda (posicionamento) + legend.set_bbox({'facecolor': 'white', 'alpha': 0.5, 'edgecolor': 'black'}) ax.set_xlabel('scattered positions [m]', fontsize=16) ax.set_ylabel('lost positions [m]', fontsize=16) From ee4c27bf664164795fe4de91bfa1694639f2ecea Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 24 Oct 2023 11:17:13 -0300 Subject: [PATCH 061/108] =?UTF-8?q?adicionando=20fun=C3=A7=C3=A3o=20para?= =?UTF-8?q?=20o=20plot=20da=20densidade=20de=20probabilidade=20e=20modific?= =?UTF-8?q?ando=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 73 ++++++++++++++++++++++++++++++++++++++++++---------- functions.py | 31 +++++++++++++++------- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/Classes.py b/Classes.py index 2266ca8c..bdfa36d7 100644 --- a/Classes.py +++ b/Classes.py @@ -317,17 +317,6 @@ def fast_aquisition(self, single_spos, par): else: return res, fp*Ddeltas, fn*Ddeltas, deltp*1e2, deltn*1e2 - # vale mencionar que a fast aquisition da forma como esta definida já está funcional - - -# a função complete aquisition poderia receber uma lista com os nomes dos elementos que se -# deseja estudar, mas poderia também passar uma lista de elementos quaisquer -# como fazer para a função calcular uma hora um uma hora outro ? - -# uma coisa é certa é melhor definir estas condições antes do programa realizar os calculos - -# eu poderia fazer um função para vincular o nome do elemento as posições s ao longo do anel -# isso parece ser bem util caso alguem deseje estudar um elemento em um ponto ja especificado def complete_aquisition(self, lname_or_spos, par): param = tousfunc.char_check(lname_or_spos) @@ -373,13 +362,69 @@ def plot_analysis_at_position(self, single_spos, par, accep): index = _np.argmin(_np.abs(spos-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), self.off_energy, par, index, accep, dp, fp) + + # remember that ind is the index that represents the initial position where tracking begins + + def plot_normtousd(self, spos): + + spos_ring = self._spos + model = self._model_fit + accep = self._accep + dic = tousfunc.norm_cutacp(self._model_fit, + spos, 5000, accep, norm=True) + fdensp = dic['fdensp'] + fdensn = dic['fdensp'] + deltasp = dic['deltasp'] + deltasn = dic['deltasn'] + + fig, ax = _plt.subplots(figsize=(10,5)) + ax.set_title('Densidade de probabilidade para cada elemento da rede magnética') + ax.grid(True, alpha=0.5, ls='--', color='k') + ax.xaxis.grid(False) + ax.set_xlabel('s position [m]', fontsize=14) + ax.set_ylabel('Normalized density probability', fontsize=14) + ax.tick_params(axis='both', labelsize=12) + + apind = [] + + for idx, s in enumerate(spos): + + array_fdens = fdensp[idx] + index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) - #if the user desires to know all the scattering events along the ring, - #only its necessary to do is to pass the + # apind.append(index) - # remember that ind is the index that represents the initial position where tracking begins + # isso dai vai funcionar mas eu preciso dar um jeito de selecionar após um determinado indice + + if not idx: + best_index = index + else: + if best_index < index: + best_index = index + else: + pass + + for idx, s in enumerate(spos): + + mod_ind = _np.argmin(_np.abs(spos_ring-s)) + + fdenspi = fdensp[idx][:best_index] + fdensni = fdensn[idx][:best_index] + deltaspi = deltasp[idx][:best_index] + deltasni = -deltasn[idx][:best_index] + + color = _plt.cm.gist_rainbow(idx/len(spos)) + + ax.plot(deltaspi, fdenspi, label='{}'.format(model[mod_ind].fam_name), color=color) + ax.plot(deltasni, fdensni, color=color ) + + apind.append(mod_ind) + + ax.legend(loc='best', fontsize=13) + return apind + def get_track(self,l_scattered_pos): diff --git a/functions.py b/functions.py index 0322265e..01e2fcc7 100644 --- a/functions.py +++ b/functions.py @@ -344,9 +344,9 @@ def get_scaccep(acc, accep): return scalc, daccpp, daccpn -def n_norm_d(acc, lsps, _npt, getsacp, cutoff, norm=False): +def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): - scalc, daccpp, daccpn = getsacp + scalc, daccpp, daccpn = get_scaccep(acc, accep) beta = _beam_rigidity(energy=3)[2] taum_p = (beta*daccpp)**2 @@ -397,9 +397,10 @@ def n_norm_d(acc, lsps, _npt, getsacp, cutoff, norm=False): # no cálculo já implementados para o tempo de vida touschek que é coerente com o tempo do SIRIUS # futuramente isso pode ser alterado e redefinido -def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): +def norm_cutacp(acc, lsps, _npt, accep, norm=False): + dic = {} - scalc, daccpp, daccpn = getsacp + scalc, daccpp, daccpn = get_scaccep(acc, accep) beta = _beam_rigidity(energy=3)[2] taum_p = (beta*daccpp)**2 @@ -410,7 +411,7 @@ def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): ltime = _pyaccel.lifetime.Lifetime(acc) b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] - calc_dp, calc_dn = [], [] + fdens_p, fdens_n = [], [] deltasp, deltasn = [], [] for _, s in enumerate(lsps): @@ -426,6 +427,11 @@ def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + norm_facp = _scyint.trapz(y_p, deltap) + norm_facn = _scyint.trapz(y_n, deltan) + + y_p /= norm_facp + y_n /= norm_facn # eliminating the negative values from array indp = _np.where(y_p<0)[0] @@ -433,17 +439,22 @@ def nnorm_cutacp(acc, lsps, _npt, getsacp, norm=False): y_p[indp] = 0 y_n[indn] = 0 - calc_dp.append(y_p) - calc_dn.append(y_n) + fdens_p.append(y_p) + fdens_n.append(y_n) deltasp.append(deltap) deltasn.append(deltan) - calc_dp = _np.array(calc_dp, dtype=object) - calc_dn = _np.array(calc_dn, dtype=object) + fdens_p = _np.array(fdens_p, dtype=object) + fdens_n = _np.array(fdens_n, dtype=object) deltasp = _np.array(deltasp, dtype=object) deltasn = _np.array(deltasn, dtype=object) - return calc_dp, calc_dn, deltasp, deltasn + dic['fdensp'] = fdens_p + dic['fdensn'] = fdens_n + dic['deltasp'] = deltasp + dic['deltasn'] = deltasn + + return dic def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): From 0ec0c73485085c625ebe07ed35930a33344ac8d1 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 24 Oct 2023 11:19:10 -0300 Subject: [PATCH 062/108] esqueci de ajustar algumas coisas --- Classes.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Classes.py b/Classes.py index bdfa36d7..7c3c8579 100644 --- a/Classes.py +++ b/Classes.py @@ -385,8 +385,7 @@ def plot_normtousd(self, spos): ax.set_xlabel('s position [m]', fontsize=14) ax.set_ylabel('Normalized density probability', fontsize=14) ax.tick_params(axis='both', labelsize=12) - - apind = [] + # ap_ind = [] for idx, s in enumerate(spos): @@ -394,9 +393,7 @@ def plot_normtousd(self, spos): index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) # apind.append(index) - - # isso dai vai funcionar mas eu preciso dar um jeito de selecionar após um determinado indice - + # this block selects the best index for plot the density distribution if not idx: best_index = index else: @@ -418,12 +415,9 @@ def plot_normtousd(self, spos): ax.plot(deltaspi, fdenspi, label='{}'.format(model[mod_ind].fam_name), color=color) ax.plot(deltasni, fdensni, color=color ) - - apind.append(mod_ind) + # ap_ind.append(mod_ind) ax.legend(loc='best', fontsize=13) - - return apind def get_track(self,l_scattered_pos): From 40e3e265173b1406801b4bd2a997471aae0115e4 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 24 Oct 2023 14:04:14 -0300 Subject: [PATCH 063/108] consertando as labels --- Classes.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Classes.py b/Classes.py index 7c3c8579..97e4591d 100644 --- a/Classes.py +++ b/Classes.py @@ -379,11 +379,11 @@ def plot_normtousd(self, spos): deltasn = dic['deltasn'] fig, ax = _plt.subplots(figsize=(10,5)) - ax.set_title('Densidade de probabilidade para cada elemento da rede magnética') + ax.set_title('Densidade de probabilidade para posições distintas da rede magnética') ax.grid(True, alpha=0.5, ls='--', color='k') ax.xaxis.grid(False) - ax.set_xlabel('s position [m]', fontsize=14) - ax.set_ylabel('Normalized density probability', fontsize=14) + ax.set_xlabel(r'$\delta$ [%]', fontsize=14) + ax.set_ylabel('PDF', fontsize=14) ax.tick_params(axis='both', labelsize=12) # ap_ind = [] @@ -403,21 +403,27 @@ def plot_normtousd(self, spos): pass for idx, s in enumerate(spos): - + mod_ind = _np.argmin(_np.abs(spos_ring-s)) fdenspi = fdensp[idx][:best_index] fdensni = fdensn[idx][:best_index] - deltaspi = deltasp[idx][:best_index] - deltasni = -deltasn[idx][:best_index] + deltaspi = deltasp[idx][:best_index]*1e2 + deltasni = -deltasn[idx][:best_index]*1e2 color = _plt.cm.gist_rainbow(idx/len(spos)) + not_desired = ['calc_mom_accep', + 'mia', 'mib', 'mip', + 'mb1', 'mb2', 'mc'] + + while model[mod_ind].fam_name in not_desired: + mod_ind += 1 - ax.plot(deltaspi, fdenspi, label='{}'.format(model[mod_ind].fam_name), color=color) + ax.plot(deltaspi, fdenspi,label='{} em {} m'.format(model[mod_ind].fam_name, _np.round(spos_ring[mod_ind], 2)),color=color) ax.plot(deltasni, fdensni, color=color ) # ap_ind.append(mod_ind) - ax.legend(loc='best', fontsize=13) + ax.legend(loc='best', fontsize=12) def get_track(self,l_scattered_pos): From 52f083429ab27f2d3018c78eea2e29ddd68bf9f8 Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 24 Oct 2023 14:44:24 -0300 Subject: [PATCH 064/108] =?UTF-8?q?ajustando=20a=20fun=C3=A7=C3=A3o=20que?= =?UTF-8?q?=20vai=20fornecer=20os=20dados=20referentes=20a=20simula=C3=A7?= =?UTF-8?q?=C3=A3o=20de=20monte-carlo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 7 +++++++ functions.py | 49 ++++++++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Classes.py b/Classes.py index 97e4591d..4b0a5a6c 100644 --- a/Classes.py +++ b/Classes.py @@ -365,6 +365,7 @@ def plot_analysis_at_position(self, single_spos, par, accep): # remember that ind is the index that represents the initial position where tracking begins + # this function is used to compare the PDF of distinct s positions along the storage ring def plot_normtousd(self, spos): spos_ring = self._spos @@ -425,6 +426,12 @@ def plot_normtousd(self, spos): ax.legend(loc='best', fontsize=12) + # this function plots the histograms returned by the monte carlo simulation + def plot_histograms(self): + + + return + def get_track(self,l_scattered_pos): diff --git a/functions.py b/functions.py index 01e2fcc7..14381b58 100644 --- a/functions.py +++ b/functions.py @@ -637,43 +637,46 @@ def scatter_particles(part1, part2, de_min): return part1_new, part2_new, fact -def histgms(acc,l_spos,num_part, accep, de_min): +def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): envelopes = _pyaccel.optics.calc_beamenvelope(acc) spos=_pyaccel.lattice.find_spos(acc, indices='closed') - _npoint = int((spos[-1]-spos[0])/0.1) - scalc = _np.linspace(spos[0], spos[-1], _npoint) - histsp1=[] - histsp2=[] - indices=[] + npt = int((spos[-1]-spos[0])/0.1) + scalc = _np.linspace(spos[0], spos[-1], npt) + + histsp1, histsp2, indices=[],[],[] + for iten in l_spos: idx_model = _np.argmin(_np.abs(spos - iten)) - idx = _np.argmin(_np.abs(scalc - iten)) - + + # this index is necessary to the s position indices from analitically calculated PDF + # match with monte carlo simulation s position indices + idx = _np.argmin(_np.abs(scalc-iten)) env = envelopes[idx_model] + + # this two lines of code are the monte-carlo simulation part1, part2= create_particles(env, num_part) - part1_new, part2_new, fact = scatter_particles(part1, part2, de_min) + part1_new, part2_new, _ = scatter_particles(part1, part2, de_min) -# acpp, acpn = accep[1][idx], accep[0][idx] - -# check1 = acpp - part1_new[4] -# check2 = -(acpn - part2_new[4]) -# cond2 = check2<0 -# cond1 = check1<0 - -# ind1 = _np.where(cond1)[0] # apenas os desvios de energia maiores que a a aceitancia da máquina -# ind2 = _np.where(cond2)[0] + if cutaccep: # if True selects the energy acceptance as the cutoof of the graphic + + acpp, acpn = accep[1][idx], accep[0][idx] + check1 = acpp - part1_new[4] + check2 = -(acpn - part2_new[4]) + + ind1 = _np.intp(_np.where(check1<0)[0]) + ind2 = _np.intp(_np.where(check2<0)[0]) - ind1 = _np.where(part1_new[4]>=0.001) # teste sugerido pelo ximenes - ind2 = _np.where(part2_new[4]<=-0.001) + else: + ind1 = _np.intp(_np.where(part1_new[4]>=0.001)) # teste sugerido pelo ximenes + ind2 = _np.intp(_np.where(part2_new[4]<=-0.001)) histsp1.append((part1_new[4][ind1])) histsp2.append((part2_new[4][ind2])) - indices.append(idx) - hist1=_np.array(histsp1, dtype='object') - hist2=_np.array(histsp2, dtype='object') + # hist1=_np.array(histsp1, dtype='object') + # hist2=_np.array(histsp2, dtype='object') indices=_np.array(indices) return histsp1, histsp2, indices From 59ff17d7ee8fb25c881f02eea20e9272ad75a1ac Mon Sep 17 00:00:00 2001 From: Thales Date: Tue, 24 Oct 2023 14:48:20 -0300 Subject: [PATCH 065/108] ajustando um pequeno erro que eu nao tinha percebido --- functions.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/functions.py b/functions.py index 14381b58..47444cc9 100644 --- a/functions.py +++ b/functions.py @@ -665,15 +665,18 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): check1 = acpp - part1_new[4] check2 = -(acpn - part2_new[4]) - ind1 = _np.intp(_np.where(check1<0)[0]) - ind2 = _np.intp(_np.where(check2<0)[0]) - + ind1 = _np.intp(_np.where(check1<0)[0][0]) + ind2 = _np.intp(_np.where(check2<0)[0][0]) + + histsp1.append((part1_new[4][ind1:])) + histsp2.append((part2_new[4][ind2:])) + else: ind1 = _np.intp(_np.where(part1_new[4]>=0.001)) # teste sugerido pelo ximenes ind2 = _np.intp(_np.where(part2_new[4]<=-0.001)) - - histsp1.append((part1_new[4][ind1])) - histsp2.append((part2_new[4][ind2])) + + histsp1.append((part1_new[4][ind1])) + histsp2.append((part2_new[4][ind2])) # hist1=_np.array(histsp1, dtype='object') # hist2=_np.array(histsp2, dtype='object') From afac9446044c75e5859d23e6ce14fba0a1e87e09 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 25 Oct 2023 15:02:21 -0300 Subject: [PATCH 066/108] ajustando os codigos --- Classes.py | 43 +++++++++++++++++++++++++++++++++++++++++-- functions.py | 31 ++++++++++++++----------------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/Classes.py b/Classes.py index 4b0a5a6c..0283844c 100644 --- a/Classes.py +++ b/Classes.py @@ -29,6 +29,8 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._inds_neg = None self._amps_pos = None self._amps_neg = None + self._num_part = 5000 + self._energy_dev_min = 1e-4 self._beta = beta # beta is a constant necessary to the calculations self._h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') # getting the vchamber's height @@ -194,6 +196,23 @@ def amp_pos(self): @property def amp_neg(self): return self._amps_neg + + @property + def num_part(self): + return self._num_part + + @num_part.setter + def num_part(self, new_num_part): + self._num_part = new_num_part + + @property + def energy_dev_mcs(self): + return self._energy_dev_min + + @energy_dev_mcs.setter + def energy_dev_mcs(self, new_energy_dev): + self._energy_dev_min = new_energy_dev + # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula @@ -427,10 +446,30 @@ def plot_normtousd(self, spos): ax.legend(loc='best', fontsize=12) # this function plots the histograms returned by the monte carlo simulation - def plot_histograms(self): + def plot_histograms(self, l_spos): + # spos = self._spos + accep = self.accep + model = self._model_fit + + tup = tousfunc.histgms(self._model_fit, l_spos, self._num_part, accep, + self._energy_dev_min,cutaccep=False) + hp, hn, idx_model = tup + + fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(10,5)) + # fig.set_title('Densidade de probabilidade a partir da simulação Monte-Carlo') + # ax.grid(True, alpha=0.5, ls='--', color='k') + # ax.xaxis.grid(False) + # ax.set_xlabel(r'$\delta$ [%]', fontsize=14) + # ax.set_ylabel('PDF', fontsize=14) + # ax.tick_params(axis='both', labelsize=12) + - return + for index, iten in enumerate(idx_model): + ay = ax[index] + ay.hist(hp[index], density=True, bins=200, color='lightgrey', label='{}'.format(model[iten].fam_name)) + ay.hist(hn[index], density=True, bins=200, color='lightgrey') + ay.legend() def get_track(self,l_scattered_pos): diff --git a/functions.py b/functions.py index 47444cc9..78b0b1ee 100644 --- a/functions.py +++ b/functions.py @@ -641,39 +641,40 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): envelopes = _pyaccel.optics.calc_beamenvelope(acc) spos=_pyaccel.lattice.find_spos(acc, indices='closed') - npt = int((spos[-1]-spos[0])/0.1) - scalc = _np.linspace(spos[0], spos[-1], npt) + + scalc, daccpp, daccpn = get_scaccep(acc, accep) histsp1, histsp2, indices=[],[],[] for iten in l_spos: idx_model = _np.argmin(_np.abs(spos - iten)) - + idx = _np.argmin(_np.abs(scalc - iten)) + indices.append(idx_model) + # this index is necessary to the s position indices from analitically calculated PDF # match with monte carlo simulation s position indices - idx = _np.argmin(_np.abs(scalc-iten)) env = envelopes[idx_model] # this two lines of code are the monte-carlo simulation - part1, part2= create_particles(env, num_part) + part1, part2 = create_particles(env, num_part) part1_new, part2_new, _ = scatter_particles(part1, part2, de_min) if cutaccep: # if True selects the energy acceptance as the cutoof of the graphic - acpp, acpn = accep[1][idx], accep[0][idx] + acpp, acpn = daccpp[idx], daccpn[idx] check1 = acpp - part1_new[4] check2 = -(acpn - part2_new[4]) - ind1 = _np.intp(_np.where(check1<0)[0][0]) - ind2 = _np.intp(_np.where(check2<0)[0][0]) - - histsp1.append((part1_new[4][ind1:])) - histsp2.append((part2_new[4][ind2:])) + ind1 = _np.intp(_np.where(check1<0)[0]) + ind2 = _np.intp(_np.where(check2<0)[0]) + + histsp1.append((part1_new[4][ind1])) + histsp2.append((part2_new[4][ind2])) else: - ind1 = _np.intp(_np.where(part1_new[4]>=0.001)) # teste sugerido pelo ximenes - ind2 = _np.intp(_np.where(part2_new[4]<=-0.001)) + ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) # teste sugerido pelo ximenes + ind2 = _np.intp(_np.where(part2_new[4]<=-0.01)[0]) histsp1.append((part1_new[4][ind1])) histsp2.append((part2_new[4][ind2])) @@ -683,7 +684,3 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): indices=_np.array(indices) return histsp1, histsp2, indices - -def defining_tables(): - - return None \ No newline at end of file From 4364f1ea9240e7051607096bbed186f479e00509 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 26 Oct 2023 09:10:13 -0300 Subject: [PATCH 067/108] =?UTF-8?q?mudan=C3=A7as=20semi-definitivas=20nas?= =?UTF-8?q?=20fun=C3=A7=C3=B5es=20respons=C3=A1veis=20pelo=20plot=20da=20d?= =?UTF-8?q?ensidade=20de=20probabilidade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 27 ++++++++++++++++----------- functions.py | 8 ++++---- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Classes.py b/Classes.py index 0283844c..26bec393 100644 --- a/Classes.py +++ b/Classes.py @@ -29,7 +29,7 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._inds_neg = None self._amps_pos = None self._amps_neg = None - self._num_part = 5000 + self._num_part = 50000 self._energy_dev_min = 1e-4 self._beta = beta # beta is a constant necessary to the calculations @@ -447,7 +447,7 @@ def plot_normtousd(self, spos): # this function plots the histograms returned by the monte carlo simulation def plot_histograms(self, l_spos): - # spos = self._spos + spos = self._spos accep = self.accep model = self._model_fit @@ -456,19 +456,24 @@ def plot_histograms(self, l_spos): hp, hn, idx_model = tup - fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(10,5)) - # fig.set_title('Densidade de probabilidade a partir da simulação Monte-Carlo') - # ax.grid(True, alpha=0.5, ls='--', color='k') - # ax.xaxis.grid(False) - # ax.set_xlabel(r'$\delta$ [%]', fontsize=14) - # ax.set_ylabel('PDF', fontsize=14) - # ax.tick_params(axis='both', labelsize=12) + fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(10,5), sharey=True) + fig.suptitle('Densidade de probabilidade a partir da simulação Monte-Carlo') + for index, iten in enumerate(idx_model): + color = _plt.cm.jet(index/len(idx_model)) ay = ax[index] - ay.hist(hp[index], density=True, bins=200, color='lightgrey', label='{}'.format(model[iten].fam_name)) - ay.hist(hn[index], density=True, bins=200, color='lightgrey') + if not index: + ay.set_ylabel('PDF', fontsize=14) + + ay.grid(True, alpha=0.5, ls='--', color='k') + ay.xaxis.grid(False) + ay.set_xlabel(r'$\delta$ [%]', fontsize=14) + ay.tick_params(axis='both', labelsize=12) + ay.hist(hp[index], density=True, bins=200, color=color, + label='element:{}, pos:{:.2f} [m]'.format(model[iten].fam_name, spos[iten])) + ay.hist(hn[index], density=True, bins=200, color=color) ay.legend() diff --git a/functions.py b/functions.py index 78b0b1ee..f00f738d 100644 --- a/functions.py +++ b/functions.py @@ -669,15 +669,15 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): ind1 = _np.intp(_np.where(check1<0)[0]) ind2 = _np.intp(_np.where(check2<0)[0]) - histsp1.append((part1_new[4][ind1])) - histsp2.append((part2_new[4][ind2])) + histsp1.append(part1_new[4][ind1]*1e2) + histsp2.append(part2_new[4][ind2]*1e2) else: ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) # teste sugerido pelo ximenes ind2 = _np.intp(_np.where(part2_new[4]<=-0.01)[0]) - histsp1.append((part1_new[4][ind1])) - histsp2.append((part2_new[4][ind2])) + histsp1.append(part1_new[4][ind1]*1e2) + histsp2.append(part2_new[4][ind2]*1e2) # hist1=_np.array(histsp1, dtype='object') # hist2=_np.array(histsp2, dtype='object') From 0cb91b3772e627c2bba11ce4d4f7b389089a06dd Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 26 Oct 2023 11:32:26 -0300 Subject: [PATCH 068/108] =?UTF-8?q?adicionando=20m=C3=A9todo=20para=20plot?= =?UTF-8?q?ar=20gr=C3=A1fico=20sugerido=20pelo=20=20Fernando?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Classes.py b/Classes.py index 26bec393..d9523b9e 100644 --- a/Classes.py +++ b/Classes.py @@ -631,6 +631,28 @@ def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to r return new_dict + def get_lost_profile(self, l_scattered_pos, reording_key): + + dic = self.get_reordered_dict(l_scattered_pos, reording_key) + + df = _pd.DataFrame(dic) + a = df.set_index('lost_positions') + + summed = [] + for idx, iten in a.iterrows(): + sum_row = a.loc[idx][:].sum() + summed.append(sum_row) + + fig, ax = _plt.subplots(figsize=(10,5)) + + ax.set_xlabel('s position [m]', fontsize=16) + ax.set_ylabel('lost position [m]', fontsize=16) + + ax.scatter(list(a.index), summed, label='.', s=8) + ax.legend() + + return + def plot_scat_table(self, l_scattered_pos, n_r,n_c=1): spos = self._spos new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') From 720be0118f18cea0332fb1184b5bcf9754ad6645 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 26 Oct 2023 15:01:06 -0300 Subject: [PATCH 069/108] =?UTF-8?q?adicionando=20fun=C3=A7=C3=A3o=20para?= =?UTF-8?q?=20plotar=20o=20perfil=20de=20perda=20ao=20longo=20do=20anel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/Classes.py b/Classes.py index d9523b9e..1732f286 100644 --- a/Classes.py +++ b/Classes.py @@ -7,7 +7,9 @@ import matplotlib.pyplot as _plt from mathphys.beam_optics import beam_rigidity as _beam_rigidity import pandas as _pd - +import scipy.integrate as scyint +import pyaccel as _pyaccel +import matplotlib.gridspec as gs class Tous_analysis(): @@ -631,31 +633,40 @@ def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to r return new_dict - def get_lost_profile(self, l_scattered_pos, reording_key): + def get_lost_profile(self, dic): - dic = self.get_reordered_dict(l_scattered_pos, reording_key) + # dic = self.get_reordered_dict(l_scattered_pos, reording_key) + spos = self._spos df = _pd.DataFrame(dic) a = df.set_index('lost_positions') + scat_pos = _np.array(a.columns, dtype=float) + + indices = [] + for iten in scat_pos: + ind = _np.argmin(_np.abs(spos-iten)) + indices.append(ind) + summed = [] for idx, iten in a.iterrows(): - sum_row = a.loc[idx][:].sum() + sum_row = scyint.trapz(a.loc[idx], spos[indices]) summed.append(sum_row) - fig, ax = _plt.subplots(figsize=(10,5)) + fig, ax = _plt.subplots(figsize=(10,5),gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) + ax.set_title('loss rate integral along the ring', fontsize=16) - ax.set_xlabel('s position [m]', fontsize=16) - ax.set_ylabel('lost position [m]', fontsize=16) + ax.set_xlabel('lost position [m]', fontsize=16) + ax.set_ylabel('loss rate [1/s]', fontsize=16) - ax.scatter(list(a.index), summed, label='.', s=8) - ax.legend() + ax.plot(list(a.index), summed, color='orange') + _pyaccel.graphics.draw_lattice(self._model_fit, + offset=-1e-6, height=1e-6, gca=True) - return - def plot_scat_table(self, l_scattered_pos, n_r,n_c=1): + def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): spos = self._spos - new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') + # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') if len(l_scattered_pos)%2 == 0: array = _np.arange(l_scattered_pos.size) @@ -683,11 +694,11 @@ def plot_scat_table(self, l_scattered_pos, n_r,n_c=1): fig, ax = _plt.subplots(n_c, n_r, figsize=(10, 6)) ax.set_title('Loss profile') - legend = ax.text(0.5, -0.1, '{}'.format(fam_name), size=12, color='black', - ha='center', va='center', transform=_plt.gca().transAxes) + # legend = ax.text(0.5, -0.1, '{}'.format(fam_name), size=12, color='black', + # ha='center', va='center', transform=_plt.gca().transAxes) - # Ajustando a legenda (posicionamento) - legend.set_bbox({'facecolor': 'white', 'alpha': 0.5, 'edgecolor': 'black'}) + # # Ajustando a legenda (posicionamento) + # legend.set_bbox({'facecolor': 'white', 'alpha': 0.5, 'edgecolor': 'black'}) ax.set_xlabel('scattered positions [m]', fontsize=16) ax.set_ylabel('lost positions [m]', fontsize=16) From 25968abb319c8a1d492e5522d33735c141537aa4 Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 27 Oct 2023 10:41:11 -0300 Subject: [PATCH 070/108] adicionando escala log nos meus dados --- Classes.py | 68 +++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/Classes.py b/Classes.py index 1732f286..caa5b284 100644 --- a/Classes.py +++ b/Classes.py @@ -659,66 +659,62 @@ def get_lost_profile(self, dic): ax.set_xlabel('lost position [m]', fontsize=16) ax.set_ylabel('loss rate [1/s]', fontsize=16) - ax.plot(list(a.index), summed, color='orange') + ax.plot(list(a.index), summed, color='navy') _pyaccel.graphics.draw_lattice(self._model_fit, offset=-1e-6, height=1e-6, gca=True) def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): spos = self._spos + # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') - if len(l_scattered_pos)%2 == 0: - array = _np.arange(l_scattered_pos.size) - j = _np.intp(_np.where(array == int((len(l_scattered_pos)/2 + 1)))[0]) - array_j = l_scattered_pos[j] - index = _np.argmin(_np.abs(spos-array_j)) + # if len(l_scattered_pos)%2 == 0: + # array = _np.arange(l_scattered_pos.size) + # j = _np.intp(_np.where(array == int((len(l_scattered_pos)/2 + 1)))[0]) + # array_j = l_scattered_pos[j] + # index = _np.argmin(_np.abs(spos-array_j)) - lists = list(find_dict(self._model_fit, 'fam_name').values()) + # lists = list(find_dict(self._model_fit, 'fam_name').values()) - else: - array = _np.arange(l_scattered_pos.size) - j = _np.where(array == int((len(l_scattered_pos)+1)/2))[0] - array_j = l_scattered_pos[j] - index = _np.argmin(_np.abs(spos-array_j)) + # else: + # array = _np.arange(l_scattered_pos.size) + # j = _np.where(array == int((len(l_scattered_pos)+1)/2))[0] + # array_j = l_scattered_pos[j] + # index = _np.argmin(_np.abs(spos-array_j)) - lists = list(find_dict(self._model_fit, 'fam_name').values()) + # lists = list(find_dict(self._model_fit, 'fam_name').values()) - for i, l in enumerate(lists): - if _np.isin(index, l).item(): - fam_name = list(find_dict(self._model_fit, 'fam_name').keys())[i] + # for i, l in enumerate(lists): + # if _np.isin(index, l).item(): + # fam_name = list(find_dict(self._model_fit, 'fam_name').keys())[i] df = _pd.DataFrame(new_dic) df = df.set_index('lost_positions') - fig, ax = _plt.subplots(n_c, n_r, figsize=(10, 6)) - ax.set_title('Loss profile') - - # legend = ax.text(0.5, -0.1, '{}'.format(fam_name), size=12, color='black', - # ha='center', va='center', transform=_plt.gca().transAxes) - - # # Ajustando a legenda (posicionamento) - # legend.set_bbox({'facecolor': 'white', 'alpha': 0.5, 'edgecolor': 'black'}) + val = df.values.copy() + idx = val != 0.0 + val[idx] = _np.log(val[idx]) + val[~idx] = val[idx].min() - ax.set_xlabel('scattered positions [m]', fontsize=16) - ax.set_ylabel('lost positions [m]', fontsize=16) + fig, ax = _plt.subplots(figsize=(10,5)) - heatmap = ax.pcolor(df, cmap='jet') - _plt.colorbar(heatmap) + y = _np.linspace(0,spos[-1],df.shape[0]+1) + x = _np.linspace(0,spos[-1],df.shape[1]+1) + X,Y = _np.meshgrid(x,y) - step1 = int(len(new_dic.keys())/5) - arr1 = df.columns.values[::step1] + heatmp = ax.pcolor(X,Y,val, cmap='jet',shading='flat') - _plt.xticks(_np.arange(df.shape[1])[::step1] + 0.5, arr1, fontsize=12) + cbar = _plt.colorbar(heatmp) + cbar.set_label('scat. rate in logarithmic scale', rotation=90) - step2 = int(len(new_dic['lost_positions'])/5) - arr2 = df.index.values[::step2] + ax.set_title('Loss profile', fontsize=16) - _plt.yticks(_np.arange(df.shape[0])[::step2] + 0.5, arr2, fontsize=12) + ax.set_xlabel('scattered positions [m]', fontsize=16) + ax.set_ylabel('lost positions [m]', fontsize=16) fig.tight_layout() - - _plt.show() + _plt.show() # # This function will probably will be in my repositories From 2ecb1e6d29119e01c836b7e8744328d4f4b9ca44 Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 27 Oct 2023 12:55:59 -0300 Subject: [PATCH 071/108] =?UTF-8?q?adcionando=20na=20classe=20a=20funciona?= =?UTF-8?q?lidade=20da=20varia=C3=A7=C3=A3o=20da=20scraper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 67 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/Classes.py b/Classes.py index caa5b284..eb92ceaf 100644 --- a/Classes.py +++ b/Classes.py @@ -44,6 +44,8 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._nturns = n_turns # defined like this by the standard self._deltas = deltas # defined by the standard self._spos = find_spos(self._model_fit, indices='closed') + self._scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') + self._scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @@ -215,26 +217,20 @@ def energy_dev_mcs(self): def energy_dev_mcs(self, new_energy_dev): self._energy_dev_min = new_energy_dev - - - # define aceitancia de energia, define também o fator de conversão que é sempre necessário das posições s do modelo nominal para scalc, e além disso calcula - # as amplitudes e os indices limitantes - - # vai ser melhor retornar todos os parametros que eu preciso de uma vez, - # esses parametros são utilizados em momentos diferentes mas todos eles são necessários para a realização das análises tanto rapida quanto a completa - # mas inicialmente não tem como o usuário saber que ele precisa definir estes parâmetros para visualização e análise dos gráficos entao - # eu ainda preciso pensar em como tornar esta biblioteca mais simples de ser utilizada por alguem que nao conhece a fundo o código - # isso significa que ao longo do codigo eu vou chamar as funções como se esses parametros ja tivessem sido definidos, mas na verdade eles so são - # definidos pelo usuário quando a classe é instanciada e a função abaixo é chamada definido estes 3 parametros ao mesmo tempo - - # def get_scaccep(self): - # return self.accep - - # def get_scalc(self): - # return self.s_calc let this code here to remind me how I may call a function in a class - def get_amps_idxs(self): # this step calls and defines 3 disctinct getters return self.amp_and_limidx, self.accep, self.s_calc + + def set_vchamber_scraper(self, vchamber): + model = self._model + scph_inds = self._scraph_inds + scpv_inds = self._scrapv_inds + + for iten in scph_inds: + model[iten].hmin = vchamber[0] + model[iten].hmax = vchamber[1] + for iten in scpv_inds: + model[iten].vmin = vchamber[2] + model[iten].vmax = vchamber[3] def return_sinpos_track(self,single_spos, par): @@ -302,15 +298,9 @@ def get_weighting_tous(self, single_spos, npt=5000): getdn = getdn[ind] deltn = deltn[ind] - # defining the energy deviation limit until tracking will be performed - self.deltas = deltp[-1]*1e2 - - # this function will return the weighting factors in the scalc position convertion return getdp, getdn, deltp, deltn - - # In general, this function is usefull when we desire to calculate the touschek scattering weighting function for one specific point along the ring def fast_aquisition(self, single_spos, par): # this raise blocks to runing the program if the list of s position has more than 1 element @@ -479,8 +469,8 @@ def plot_histograms(self, l_spos): ay.legend() - def get_track(self,l_scattered_pos): - + def get_track(self,l_scattered_pos, scrap, vchamber): + all_track = [] indices = [] spos = self._spos @@ -489,6 +479,11 @@ def get_track(self,l_scattered_pos): self._model.cavity_on = True self._model.vchamber_on = True + if scrap: + self.set_vchamber_scraper(vchamber) + print(self._model[self._scraph_inds[0]].hmax) + print(self._model[self._scraph_inds[0]].hmin) + for _, scattered_pos in enumerate(l_scattered_pos): index = _np.argmin(_np.abs(scattered_pos-spos)) @@ -496,11 +491,19 @@ def get_track(self,l_scattered_pos): res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) all_track.append(res) + hx = self.model_fit[self._scraph_inds[0]].hmax + hn = self.model_fit[self._scraph_inds[0]].hmin + vx = self.model_fit[self._scraph_inds[0]].vmax + vn = self.model_fit[self._scraph_inds[0]].vmin + vchamber = [hx, hn, vx, vn] + + self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) + return all_track, indices - def find_data(self, l_scattered_pos): + def find_data(self, l_scattered_pos, scrap, vchamber): - all_track, indices = self.get_track(l_scattered_pos) + all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) spos = self._spos fact = 0.03 @@ -593,10 +596,10 @@ def find_data(self, l_scattered_pos): return all_lostp, prob, lostp # dataframe = _pd.DataFrame(dic_res) - def get_table(self,l_scattered_pos): + def get_table(self,l_scattered_pos, scrap, vchamber): dic_res = {} - all_lostp, prob, lostp = self.find_data(l_scattered_pos) + all_lostp, prob, lostp = self.find_data(l_scattered_pos, scrap, vchamber) n_scat = _np.round(l_scattered_pos, 2) for idx, scattered_pos in enumerate(n_scat): @@ -621,9 +624,9 @@ def get_table(self,l_scattered_pos): return dic_res - def get_reordered_dict(self, l_scattered_pos, reording_key): # chatgpt code to reorder the dictionary + def get_reordered_dict(self, l_scattered_pos, reording_key, scrap, vchamber): # chatgpt code to reorder the dictionary - dic = self.get_table(l_scattered_pos) + dic = self.get_table(l_scattered_pos, scrap, vchamber) zip_tuples = zip(*[dic[chave] for chave in dic]) new_tuples = sorted(zip_tuples, key=lambda x: x[list(dic.keys()).index(reording_key)]) From 60f2b9dc8c72739d021f0e456d9e69040a2164e8 Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 27 Oct 2023 14:22:27 -0300 Subject: [PATCH 072/108] =?UTF-8?q?adicionando=20as=20altera=C3=A7=C3=B5es?= =?UTF-8?q?=20propostas=20pelo=20ximenes=20e=20corrigindo=20erros?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Classes.py b/Classes.py index eb92ceaf..c2aaa042 100644 --- a/Classes.py +++ b/Classes.py @@ -491,10 +491,10 @@ def get_track(self,l_scattered_pos, scrap, vchamber): res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) all_track.append(res) - hx = self.model_fit[self._scraph_inds[0]].hmax - hn = self.model_fit[self._scraph_inds[0]].hmin - vx = self.model_fit[self._scraph_inds[0]].vmax - vn = self.model_fit[self._scraph_inds[0]].vmin + hx = self._model_fit[self._scraph_inds[0]].hmax + hn = self._model_fit[self._scraph_inds[0]].hmin + vx = self._model_fit[self._scraph_inds[0]].vmax + vn = self._model_fit[self._scraph_inds[0]].vmin vchamber = [hx, hn, vx, vn] self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) @@ -697,10 +697,10 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): val = df.values.copy() idx = val != 0.0 - val[idx] = _np.log(val[idx]) + val[idx] = _np.log10(val[idx]) val[~idx] = val[idx].min() - fig, ax = _plt.subplots(figsize=(10,5)) + fig, ax = _plt.subplots(figsize=(10,10)) y = _np.linspace(0,spos[-1],df.shape[0]+1) x = _np.linspace(0,spos[-1],df.shape[1]+1) @@ -709,7 +709,7 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): heatmp = ax.pcolor(X,Y,val, cmap='jet',shading='flat') cbar = _plt.colorbar(heatmp) - cbar.set_label('scat. rate in logarithmic scale', rotation=90) + cbar.set_label('scat. rate [1/s] in logarithmic scale', rotation=90) ax.set_title('Loss profile', fontsize=16) @@ -717,6 +717,7 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): ax.set_ylabel('lost positions [m]', fontsize=16) fig.tight_layout() + _plt.gca().set_aspect('equal') _plt.show() From 901595ebd0d6d47d59441a83370eeaecd7d6448e Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Mon, 27 Nov 2023 12:03:14 -0300 Subject: [PATCH 073/108] =?UTF-8?q?mudan=C3=A7as=20para=20relatorio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 22 ++++++++++++---------- functions.py | 36 +++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Classes.py b/Classes.py index c2aaa042..ad63a3fc 100644 --- a/Classes.py +++ b/Classes.py @@ -391,12 +391,12 @@ def plot_normtousd(self, spos): deltasn = dic['deltasn'] fig, ax = _plt.subplots(figsize=(10,5)) - ax.set_title('Densidade de probabilidade para posições distintas da rede magnética') + ax.set_title('Probability density analytically calculated', fontsize=20) ax.grid(True, alpha=0.5, ls='--', color='k') ax.xaxis.grid(False) - ax.set_xlabel(r'$\delta$ [%]', fontsize=14) - ax.set_ylabel('PDF', fontsize=14) - ax.tick_params(axis='both', labelsize=12) + ax.set_xlabel(r'$\delta$ [%]', fontsize=25) + ax.set_ylabel('PDF', fontsize=25) + ax.tick_params(axis='both', labelsize=28) # ap_ind = [] for idx, s in enumerate(spos): @@ -435,7 +435,7 @@ def plot_normtousd(self, spos): ax.plot(deltasni, fdensni, color=color ) # ap_ind.append(mod_ind) - ax.legend(loc='best', fontsize=12) + ax.legend(loc='best', fontsize=20) # this function plots the histograms returned by the monte carlo simulation def plot_histograms(self, l_spos): @@ -449,23 +449,24 @@ def plot_histograms(self, l_spos): hp, hn, idx_model = tup - fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(10,5), sharey=True) - fig.suptitle('Densidade de probabilidade a partir da simulação Monte-Carlo') + fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(30,10), sharey=True) + fig.suptitle('Probability density calculated by Monte-Carlo simulation', fontsize=20) for index, iten in enumerate(idx_model): color = _plt.cm.jet(index/len(idx_model)) ay = ax[index] if not index: - ay.set_ylabel('PDF', fontsize=14) + ay.set_ylabel('PDF', fontsize=25) ay.grid(True, alpha=0.5, ls='--', color='k') ay.xaxis.grid(False) - ay.set_xlabel(r'$\delta$ [%]', fontsize=14) - ay.tick_params(axis='both', labelsize=12) + ay.set_xlabel(r'$\delta$ [%]', fontsize=25) + ay.tick_params(axis='both', labelsize=18) ay.hist(hp[index], density=True, bins=200, color=color, label='element:{}, pos:{:.2f} [m]'.format(model[iten].fam_name, spos[iten])) ay.hist(hn[index], density=True, bins=200, color=color) + _plt.tight_layout() ay.legend() @@ -661,6 +662,7 @@ def get_lost_profile(self, dic): ax.set_xlabel('lost position [m]', fontsize=16) ax.set_ylabel('loss rate [1/s]', fontsize=16) + ax.tick_params(axis='both', labelsize=16) ax.plot(list(a.index), summed, color='navy') _pyaccel.graphics.draw_lattice(self._model_fit, diff --git a/functions.py b/functions.py index f00f738d..d1a41aa7 100644 --- a/functions.py +++ b/functions.py @@ -165,22 +165,28 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep spos = _pyaccel.lattice.find_spos(acc) - fig, (a1, a2, a3) = _plt.subplots(1, 3, figsize=(10, 5), sharey=True, gridspec_kw={'width_ratios': [1, 3, 3]}) + fig = _plt.figure(figsize=(17, 7)) + gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) + a1 = fig.add_subplot(gs[0, 0]) + a2 = fig.add_subplot(gs[0, 1], sharey=a1) + a3 = fig.add_subplot(gs[0, 2], sharey=a1) + a2.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) + a3.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) # defining the form that graphic will be plotted, trying to amplify the best I can the letters to see it in a easier way a1.grid(True, alpha=0.5, ls='--', color='k') - a1.tick_params(axis='both', labelsize=12) + a1.tick_params(axis='both', labelsize=18) a2.grid(True, alpha=0.5, ls='--', color='k') - a2.tick_params(axis='both', labelsize=12) + # a2.tick_params(axis='both', labelsize=18) a3.grid(True, alpha=0.5, ls='--', color='k') - a3.tick_params(axis='both', labelsize=12) + # a3.tick_params(axis='both', labelsize=18) a1.xaxis.grid(False) a2.xaxis.grid(False) a3.xaxis.grid(False) - + _plt.subplots_adjust(wspace=0.1) if 'pos' in param: # defining the y and x label of the first graphic - a1.set_ylabel(r'positive $\delta$ [%]', fontsize=14) + a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted @@ -188,26 +194,26 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: - a1.set_ylabel(r'negative $\delta$ [%]', fontsize=14) + a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') - a1.set_title(r'taxa de espalhamento touschek', fontsize=14) # setting the title of the first graphic - a1.set_xlabel(r'Scattering touschek rate', fontsize=14) + a1.set_title(r'$\delta \times scat. rate$', fontsize=20) # setting the title of the first graphic + a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - a2.set_title(r'$\delta \times$ lost turn', fontsize=16) # setting the tilte of the second graphic - a2.set_xlabel(r'n de voltas', fontsize=14) + a2.set_title(r'$\delta \times$ lost turn', fontsize=20) # setting the tilte of the second graphic + a2.set_xlabel(r'number of turns', fontsize=25) for iten in lista_resul: a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') - a3.set_title(r'tracking ', fontsize=16) # setting the title of the third graphic + a3.set_title(r'tracking ', fontsize=20) # setting the title of the third graphic a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', label=r'accep. limit', alpha=0.25) _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff @@ -217,10 +223,10 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a3.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position where tracking begins - a3.set_xlabel(r'$s$ [m]', fontsize=14) # setting configurations of the graphic - a3.legend(loc='best', ncol=2) + a3.set_xlabel(r'$s$ [m]', fontsize=25) # setting configurations of the graphic + a3.legend(loc='upper right', ncol=1, fontsize=15) - fig.tight_layout() + # fig.tight_layout() fig.show() def select_idx(list_, param1, param2): From 1e7aff8eec35451ad46a0434a5da5e44e18fbecd Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 27 Nov 2023 12:27:54 -0300 Subject: [PATCH 074/108] loss rate --- Classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes.py b/Classes.py index ad63a3fc..66be0873 100644 --- a/Classes.py +++ b/Classes.py @@ -711,7 +711,7 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): heatmp = ax.pcolor(X,Y,val, cmap='jet',shading='flat') cbar = _plt.colorbar(heatmp) - cbar.set_label('scat. rate [1/s] in logarithmic scale', rotation=90) + cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) ax.set_title('Loss profile', fontsize=16) From 54d9d8bd5d9ee3e0bc7ac22b526516bfe8ac45ab Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 30 Nov 2023 13:06:15 -0300 Subject: [PATCH 075/108] =?UTF-8?q?modifica=C3=A7=C3=B5es=20para=20salvar?= =?UTF-8?q?=20os=20arquivos=20gerados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 71 +++++++++++++++++++++++++++------------------------- functions.py | 11 +++++--- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/Classes.py b/Classes.py index 66be0873..195c3227 100644 --- a/Classes.py +++ b/Classes.py @@ -358,7 +358,7 @@ def complete_aquisition(self, lname_or_spos, par): return ress, scat_dis # this function plot the graphic of tracking and the touschek scattering distribution for one single position - def plot_analysis_at_position(self, single_spos, par, accep): + def plot_analysis_at_position(self, single_spos, par, accep,filename): # defining some params top plot the tracking and the scattering distribution # In a first approach I dont have to be concerned in this decision structure because all variables necessary for the calculation will be defined # I will may let this part of the code if I know a best method or decide to make a change here @@ -372,12 +372,12 @@ def plot_analysis_at_position(self, single_spos, par, accep): spos = self.spos index = _np.argmin(_np.abs(spos-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), - self.off_energy, par, index, accep, dp, fp) + self.off_energy, par, index, accep, dp, fp, filename) # remember that ind is the index that represents the initial position where tracking begins # this function is used to compare the PDF of distinct s positions along the storage ring - def plot_normtousd(self, spos): + def plot_normtousd(self, spos,filename): spos_ring = self._spos model = self._model_fit @@ -436,6 +436,7 @@ def plot_normtousd(self, spos): # ap_ind.append(mod_ind) ax.legend(loc='best', fontsize=20) + fig.savefig(filename, dpi=150) # this function plots the histograms returned by the monte carlo simulation def plot_histograms(self, l_spos): @@ -494,8 +495,8 @@ def get_track(self,l_scattered_pos, scrap, vchamber): hx = self._model_fit[self._scraph_inds[0]].hmax hn = self._model_fit[self._scraph_inds[0]].hmin - vx = self._model_fit[self._scraph_inds[0]].vmax - vn = self._model_fit[self._scraph_inds[0]].vmin + vx = self._model_fit[self._scrapv_inds[0]].vmax + vn = self._model_fit[self._scrapv_inds[0]].vmin vchamber = [hx, hn, vx, vn] self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) @@ -637,7 +638,7 @@ def get_reordered_dict(self, l_scattered_pos, reording_key, scrap, vchamber): # return new_dict - def get_lost_profile(self, dic): + def get_lost_profile(self, dic, filename): # dic = self.get_reordered_dict(l_scattered_pos, reording_key) spos = self._spos @@ -657,7 +658,7 @@ def get_lost_profile(self, dic): sum_row = scyint.trapz(a.loc[idx], spos[indices]) summed.append(sum_row) - fig, ax = _plt.subplots(figsize=(10,5),gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) + fig, ax = _plt.subplots(figsize=(13,7),gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) ax.set_title('loss rate integral along the ring', fontsize=16) ax.set_xlabel('lost position [m]', fontsize=16) @@ -667,9 +668,36 @@ def get_lost_profile(self, dic): ax.plot(list(a.index), summed, color='navy') _pyaccel.graphics.draw_lattice(self._model_fit, offset=-1e-6, height=1e-6, gca=True) + fig.savefig(filename,dpi=150) + + def get_lost_profilel(self, l_dic): + + # dic = self.get_reordered_dict(l_scattered_pos, reording_key) + l = [] + for dic in l_dic: + spos = self._spos + + df = _pd.DataFrame(dic) + a = df.set_index('lost_positions') + + scat_pos = _np.array(a.columns, dtype=float) + + indices = [] + for iten in scat_pos: + ind = _np.argmin(_np.abs(spos-iten)) + indices.append(ind) + + summed = [] + for idx, iten in a.iterrows(): + sum_row = scyint.trapz(a.loc[idx], spos[indices]) + summed.append(sum_row) + + l.append((a.index, summed)) + + return l - def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): + def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): spos = self._spos # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') @@ -720,31 +748,6 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,n_c=1): fig.tight_layout() _plt.gca().set_aspect('equal') + # fig.savefig(filename, dpi=150) _plt.show() - -# # This function will probably will be in my repositories -# # I dont know if I will use it again, but it seems to me that it could be uselfull in some point - -# def extract_delt(groups, deltas): -# c = 0 -# big_list = [] -# for lists in groups: -# lil_list = [] -# for _ in lists: -# lil_list.append(c) -# c+=1 - -# big_list.append(lil_list) - -# sep_deltas = [] -# comp_l = [] - -# for iten in big_list: -# sep_deltas.append(deltas[iten]) -# comp_l.append(len(iten)) - - -# return sep_deltas, comp_l - - diff --git a/functions.py b/functions.py index d1a41aa7..77dfadf6 100644 --- a/functions.py +++ b/functions.py @@ -156,16 +156,18 @@ def char_check(elmnt): # this function will plot the tracking simultation with the linear model calculated plus the touschek scattering distribution # in the first graphic the plot will be the touschek scattering distribution -def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens): +def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): # ---------------- + cm = 1/2.54 + twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax betax = betax*(1/5) spos = _pyaccel.lattice.find_spos(acc) - fig = _plt.figure(figsize=(17, 7)) + fig = _plt.figure(figsize=(38.5*cm,18*cm)) gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) a1 = fig.add_subplot(gs[0, 0]) a2 = fig.add_subplot(gs[0, 1], sharey=a1) @@ -177,9 +179,9 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a1.grid(True, alpha=0.5, ls='--', color='k') a1.tick_params(axis='both', labelsize=18) a2.grid(True, alpha=0.5, ls='--', color='k') - # a2.tick_params(axis='both', labelsize=18) + a2.tick_params(axis='both', labelsize=18) a3.grid(True, alpha=0.5, ls='--', color='k') - # a3.tick_params(axis='both', labelsize=18) + a3.tick_params(axis='both', labelsize=18) a1.xaxis.grid(False) a2.xaxis.grid(False) a3.xaxis.grid(False) @@ -227,6 +229,7 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a3.legend(loc='upper right', ncol=1, fontsize=15) # fig.tight_layout() + fig.savefig(filename, dpi=150) fig.show() def select_idx(list_, param1, param2): From dda77a3a04c5358579ae523b1ab38176076915c9 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Fri, 1 Dec 2023 15:35:39 -0300 Subject: [PATCH 076/108] organizando a classe --- Classes.py | 131 ++++++++------------------------------------------- functions.py | 65 +++++-------------------- 2 files changed, 31 insertions(+), 165 deletions(-) diff --git a/Classes.py b/Classes.py index 195c3227..b4b4c053 100644 --- a/Classes.py +++ b/Classes.py @@ -18,15 +18,15 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): energy_off = _np.linspace(0,0.046, 460) # used when calculating physical limitants by the linear model deltas = _np.linspace(0,0.1,400) # used in tracking simulation - if beam_energy is None: # beam_energy is associated to the beta factor of the electrons of the storage ring - beta = _beam_rigidity(energy=3)[2] # defining by default the energy of the beam + if beam_energy is None: # defining beta factor + beta = _beam_rigidity(energy=3)[2] self._model_fit = accelerator - self._model = pymodels.si.create_accelerator() # No necessity to change this model, because it's an internal tool for calculations. + self._model = pymodels.si.create_accelerator() self._amp_and_limidx = None self._sc_accps = None - self._accep = None + self._accep = None self._inds_pos = None self._inds_neg = None self._amps_pos = None @@ -62,23 +62,6 @@ def accelerator(self, new_model): #This line defines a new accelerator if the us def nom_model(self): return self._model - # defining the heights of the vchamber, this properties vary the lenght of the array hpos and hneg - @property - def hpos(self): - return self._h_pos - - @hpos.setter - def hpos(self, indices): - self._h_pos = get_attribute(self.accelerator, 'hmax', indices=indices) - - @property - def hneg(self): - return self._h_neg - - @hneg.setter - def hneg(self, indices): - self._h_neg = get_attribute(self.accelerator, 'hmin', indices=indices) - @property def accep(self): if self._accep is None: @@ -100,42 +83,16 @@ def amp_and_limidx(self): self.nom_model.cavity_on = False # this step is necessary to define if the self.nom_model.radiation_on = False self._amps_pos, self._inds_pos = tousfunc.calc_amp(self.nom_model, - self.off_energy, self.hpos, self.hneg) + self.off_energy, self._h_pos, self._h_neg) self._amps_neg, self._inds_neg = tousfunc.calc_amp(self.nom_model, - -self.off_energy, self.hpos, self.hneg) + -self.off_energy, self._h_pos, self._h_neg) self._amp_and_limidx = True return self._amp_and_limidx - - # Defining the energy array to get the maximum amplitudes and the limitant indices by the linear model @property def ltime(self): return self._ltime - - @property - def beam_energy(self): - return self._beta - - @beam_energy.setter - def beam_energy(self, new_beam_energy): # the user could change the energy of the beam if it is necessary - self._beta = _beam_rigidity(energy=new_beam_energy)[2] - - @property - def pos_vchamber(self): - return self.h_pos - - @pos_vchamber.setter - def pos_vchamber(self, indices): # here indices must be a string, closed or open, the user could define if it is necessary - self.h_pos = find_spos(self._model_fit, indices=indices) - - @property - def neg_vchamber(self): - return self.h_neg - - @neg_vchamber.setter - def neg_vchamber(self, indices): - self.h_neg = find_spos(self._model_fit, indices=indices) @property def off_energy(self): @@ -149,14 +106,6 @@ def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if t steps = int(accep_lim*10000) # choosed to be the number of steps self._off_energy = _np.linspace(0, accep_lim, steps) - @property - def nturns(self): - return self._nturns - - @nturns.setter - def nturns(self, new_turns): - self._nturns = new_turns # changes in the nturns to simulate with tracking - @property def deltas(self): return self._deltas @@ -173,14 +122,6 @@ def lname(self): @lname.setter def lname(self, call_lname): # call_name is the list of element names (passed by the user) that someone desires to know the distribution self._lname = call_lname - - @property - def spos(self): - return self._spos - - @spos.setter - def spos(self, indices): # if the user desires to make a change in the indices in the s position array / the variable indices must be a string 'closed' or 'open' - self._spos = find_spos(self._model_fit, indices=indices) # the four properties defining below are to be fixed # this indices are obtained from the linear approach for the physical limitants @@ -200,22 +141,6 @@ def amp_pos(self): @property def amp_neg(self): return self._amps_neg - - @property - def num_part(self): - return self._num_part - - @num_part.setter - def num_part(self, new_num_part): - self._num_part = new_num_part - - @property - def energy_dev_mcs(self): - return self._energy_dev_min - - @energy_dev_mcs.setter - def energy_dev_mcs(self, new_energy_dev): - self._energy_dev_min = new_energy_dev def get_amps_idxs(self): # this step calls and defines 3 disctinct getters return self.amp_and_limidx, self.accep, self.s_calc @@ -241,7 +166,7 @@ def return_sinpos_track(self,single_spos, par): index = _np.argmin(_np.abs(spos-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons(self.deltas,self.nturns, + res = tousfunc.track_eletrons(self.deltas,self._nturns, index, self.nom_model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: res = tousfunc.track_eletrons(-self.deltas,self._nturns, @@ -257,17 +182,17 @@ def return_compos_track(self, lspos, par): if 'pos' in par: res = tousfunc.trackm_elec(self.nom_model, self.deltas, - self.nturns, lspos) + self._nturns, lspos) elif 'neg' in par: res = tousfunc.trackm_elec(self.nom_model, -self.deltas, - self.nturns, lspos) + self._nturns, lspos) return res def get_weighting_tous(self, single_spos, npt=5000): scalc, daccp, daccn = tousfunc.get_scaccep(self.accelerator, self.accep) - bf = self.beam_energy # bf is the beta factor + bf = self._beta # bf is the beta factor ltime = self._ltime b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -359,36 +284,21 @@ def complete_aquisition(self, lname_or_spos, par): # this function plot the graphic of tracking and the touschek scattering distribution for one single position def plot_analysis_at_position(self, single_spos, par, accep,filename): - # defining some params top plot the tracking and the scattering distribution - # In a first approach I dont have to be concerned in this decision structure because all variables necessary for the calculation will be defined - # I will may let this part of the code if I know a best method or decide to make a change here - - # if self._amp_and_limidx is None: - # amps_and_idxs = self.amp_and_limidx - # else: - # amps_and_idxs = self._amp_and_limidx res, fp, dp = self.fast_aquisition(single_spos, par) - spos = self.spos + spos = self._spos index = _np.argmin(_np.abs(spos-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), self.off_energy, par, index, accep, dp, fp, filename) - # remember that ind is the index that represents the initial position where tracking begins - - # this function is used to compare the PDF of distinct s positions along the storage ring - def plot_normtousd(self, spos,filename): + def plot_normtousd(self, spos,filename): # user must provide a list of s positions spos_ring = self._spos - model = self._model_fit - accep = self._accep dic = tousfunc.norm_cutacp(self._model_fit, - spos, 5000, accep, norm=True) + spos, 5000, self._accep, norm=True) - fdensp = dic['fdensp'] - fdensn = dic['fdensp'] - deltasp = dic['deltasp'] - deltasn = dic['deltasn'] + fdensp, fdensn = dic['fdensp'], dic['fdensn'] + deltasp, deltasn = dic['deltasp'], dic['deltasn'] fig, ax = _plt.subplots(figsize=(10,5)) ax.set_title('Probability density analytically calculated', fontsize=20) @@ -397,7 +307,6 @@ def plot_normtousd(self, spos,filename): ax.set_xlabel(r'$\delta$ [%]', fontsize=25) ax.set_ylabel('PDF', fontsize=25) ax.tick_params(axis='both', labelsize=28) - # ap_ind = [] for idx, s in enumerate(spos): @@ -428,10 +337,11 @@ def plot_normtousd(self, spos,filename): 'mia', 'mib', 'mip', 'mb1', 'mb2', 'mc'] - while model[mod_ind].fam_name in not_desired: + while self._model_fit[mod_ind].fam_name in not_desired: mod_ind += 1 - ax.plot(deltaspi, fdenspi,label='{} em {} m'.format(model[mod_ind].fam_name, _np.round(spos_ring[mod_ind], 2)),color=color) + ax.plot(deltaspi, fdenspi, + label='{} em {} m'.format(self._model_fit[mod_ind].fam_name, _np.round(spos_ring[mod_ind], 2)),color=color) ax.plot(deltasni, fdensni, color=color ) # ap_ind.append(mod_ind) @@ -439,7 +349,8 @@ def plot_normtousd(self, spos,filename): fig.savefig(filename, dpi=150) # this function plots the histograms returned by the monte carlo simulation - def plot_histograms(self, l_spos): + + def plot_histograms(self, l_spos): # user must provide a list of s positions spos = self._spos accep = self.accep model = self._model_fit @@ -449,11 +360,9 @@ def plot_histograms(self, l_spos): hp, hn, idx_model = tup - fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(30,10), sharey=True) fig.suptitle('Probability density calculated by Monte-Carlo simulation', fontsize=20) - for index, iten in enumerate(idx_model): color = _plt.cm.jet(index/len(idx_model)) ay = ax[index] diff --git a/functions.py b/functions.py index 77dfadf6..8dd3debc 100644 --- a/functions.py +++ b/functions.py @@ -5,9 +5,6 @@ import scipy.integrate as _scyint import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity -from mathphys.functions import save_pickle, load_pickle -import pandas as pd - def calc_amp(acc,energy_offsets, hmax, hmin): a_def = _np.zeros(energy_offsets.size) @@ -33,14 +30,8 @@ def calc_amp(acc,energy_offsets, hmax, hmin): pass return _np.sqrt(a_def), indices -# Função criada em outro programa utilizando tracking - -# --------------------- def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): - # pos_x and pos_y have default values but it can be varied - # here we define the initial conditions for the simulation - orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] @@ -59,20 +50,13 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): turnl_element = [] for i,item in enumerate(turn_lost): - if item == n_turn and element_lost[i] == element_idx: # ignora elétrons que não foram perdidos + if item == n_turn and element_lost[i] == element_idx: pass else: turnl_element.append((item, element_lost[i], deltas[i])) return turnl_element -def f_mchn_stdy(): - pass - -# This function will calculate where the electrons are lost using tracking - -# The function recives an array containing all the s positions along the ring - def trackm_elec(acc,deltas, n_turn, lspos): results = [] spos = _pyaccel.lattice.find_spos(acc, indices='open') @@ -85,28 +69,6 @@ def trackm_elec(acc,deltas, n_turn, lspos): return results -# this function will sellect the index by the array containing the names of the elements along the ring that people desire to study -# please let's try to run away from the repetitive structures that - -# certo eu vou ter todos os indices referentes ao elementos que eu preciso e quero analisar, mas qual eu devo escolher, -# devo tentar selecionar o trecho em que o beta é mínimo para obter - -# sabendo que a função beta é a envoltória do feixe e, portanto, os pontos onde o feixe se encontra em posições de menor beta são as posições onde podem -# ocorrer com maior probabilidade os espalhamentos touschek, lembrando que a envoltória é quem rege o quanto de espaço estes elétrons possuem para oscilar -# Dessa forma, menor a envoltória menor também será o espaço que os elétrons podem realizar suas oscilações betatron aumentando a densidade do feixe em regiões -# de baixo beta - -# so the lname passed to the function must be an array - -# lname deve ser a lista de elementos que será passada para a função ['BC','B1','B2'] por exemplo - - -# function returns the desired element index of dipoles, quadrupoles, sextupoles and any other -# element that is desired, the only thing that is needed is to pass a string - -# eu preciso pensar se vale a pena colocar todos os indices que eu estou pensando em colocar ou se o pymodels da conta do recado -# eu tenho que me perguntar se é interessante obter os indices de elementos como lkkp por exemplo - def el_idx_collector(acc, lname): all_index = [] @@ -143,8 +105,6 @@ def el_idx_collector(acc, lname): return all_index -# this function recieves a list and search all elements checking if there are strings into the list - def char_check(elmnt): for char in elmnt: returnval = type(char) @@ -153,13 +113,10 @@ def char_check(elmnt): elif returnval is float or returnval is int: return float -# this function will plot the tracking simultation with the linear model calculated plus the touschek scattering distribution -# in the first graphic the plot will be the touschek scattering distribution - def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): # ---------------- - cm = 1/2.54 + cm = 1/2.54 # 'poster' twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax @@ -187,18 +144,18 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a3.xaxis.grid(False) _plt.subplots_adjust(wspace=0.1) - if 'pos' in param: # defining the y and x label of the first graphic + if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[1][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted + acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[0][element_idx] # defining the acceptance given the begining tracking point, this will be necessary to define until where the graphic will be plotted + acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') @@ -453,10 +410,10 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): deltasp.append(deltap) deltasn.append(deltan) - fdens_p = _np.array(fdens_p, dtype=object) - fdens_n = _np.array(fdens_n, dtype=object) - deltasp = _np.array(deltasp, dtype=object) - deltasn = _np.array(deltasn, dtype=object) + fdens_p = _np.array(fdens_p) + fdens_n = _np.array(fdens_n) + deltasp = _np.array(deltasp) + deltasn = _np.array(deltasn) dic['fdensp'] = fdens_p dic['fdensn'] = fdens_n @@ -541,10 +498,10 @@ def get_cross_section_distribution(psim, _npts=3000): beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) psi = _np.pi/2 - psi - psi = psi[::-1] # this step is necessary to reverse the order of psi + psi = psi[::-1] cpsi = _np.cos(psi) cross = _np.zeros(cpsi.size) - if beta_bar > 1e-19: # I think it maybe will be related to the relativistic regime + if beta_bar > 1e-19: cross += (1 + 1/beta_bar**2)**2 * (2*(1 + cpsi**2)/cpsi**3 - 3/cpsi) cross += 4/cpsi + 1 cross *= _np.sin(psi) From 29087799aebbbc87ad80e16fa83a378916d43d5d Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Fri, 1 Dec 2023 19:41:09 -0300 Subject: [PATCH 077/108] organizando a classe --- Classes.py | 120 +++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/Classes.py b/Classes.py index b4b4c053..8e88a5e6 100644 --- a/Classes.py +++ b/Classes.py @@ -22,7 +22,7 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): beta = _beam_rigidity(energy=3)[2] self._model_fit = accelerator - self._model = pymodels.si.create_accelerator() + self._model = pymodels.si.create_accelerator() self._amp_and_limidx = None self._sc_accps = None @@ -31,21 +31,20 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self._inds_neg = None self._amps_pos = None self._amps_neg = None - self._num_part = 50000 - self._energy_dev_min = 1e-4 - - self._beta = beta # beta is a constant necessary to the calculations - self._h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') # getting the vchamber's height - self._h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') - self._ltime = Lifetime(self._model_fit) - # self._lname = ['BC', 'Q1', 'SDA0'] # names defined by default. it can be modified as the users desires - - self._off_energy = energy_off # interval of energy deviation for calculating the amplitudes and idx_limitants from linear model - self._nturns = n_turns # defined like this by the standard - self._deltas = deltas # defined by the standard - self._spos = find_spos(self._model_fit, indices='closed') - self._scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') - self._scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') + self.num_part = 50000 + self.energy_dev_min = 1e-4 + + self.beta = beta # beta is a constant necessary to the calculations + self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') + self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') + self.ltime = Lifetime(self._model_fit) + # self._lname = ['BC', 'Q1', 'SDA0'] # it can be modified as the users desires + self._off_energy = energy_off # en_dev to calculate amplitudes and idx_limitants from linear model + self.nturns = n_turns + self._deltas = deltas + self.spos = find_spos(self._model_fit, indices='closed') + self.scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') + self.scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @@ -83,17 +82,13 @@ def amp_and_limidx(self): self.nom_model.cavity_on = False # this step is necessary to define if the self.nom_model.radiation_on = False self._amps_pos, self._inds_pos = tousfunc.calc_amp(self.nom_model, - self.off_energy, self._h_pos, self._h_neg) + self.off_energy, self.h_pos, self.h_neg) self._amps_neg, self._inds_neg = tousfunc.calc_amp(self.nom_model, - -self.off_energy, self._h_pos, self._h_neg) + -self.off_energy, self.h_pos, self.h_neg) self._amp_and_limidx = True return self._amp_and_limidx - @property - def ltime(self): - return self._ltime - @property def off_energy(self): return self._off_energy @@ -103,7 +98,7 @@ def off_energy(self): def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if the user desire accep_pos, accep_neg = accep accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) - steps = int(accep_lim*10000) # choosed to be the number of steps + steps = int(accep_lim*10000) # choosen to be the number of steps self._off_energy = _np.linspace(0, accep_lim, steps) @property @@ -147,8 +142,8 @@ def get_amps_idxs(self): # this step calls and defines 3 disctinct getters def set_vchamber_scraper(self, vchamber): model = self._model - scph_inds = self._scraph_inds - scpv_inds = self._scrapv_inds + scph_inds = self.scraph_inds + scpv_inds = self.scrapv_inds for iten in scph_inds: model[iten].hmin = vchamber[0] @@ -162,14 +157,14 @@ def return_sinpos_track(self,single_spos, par): self._model.cavity_on = True self._model.radiation_on = True self._model.vchamber_on = True - spos = self._spos + s = self.spos - index = _np.argmin(_np.abs(spos-single_spos)) + index = _np.argmin(_np.abs(s-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons(self.deltas,self._nturns, + res = tousfunc.track_eletrons(self.deltas,self.nturns, index, self.nom_model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: - res = tousfunc.track_eletrons(-self.deltas,self._nturns, + res = tousfunc.track_eletrons(-self.deltas,self.nturns, index, self.nom_model, pos_x=1e-5, pos_y=3e-6) return res @@ -182,19 +177,19 @@ def return_compos_track(self, lspos, par): if 'pos' in par: res = tousfunc.trackm_elec(self.nom_model, self.deltas, - self._nturns, lspos) + self.nturns, lspos) elif 'neg' in par: res = tousfunc.trackm_elec(self.nom_model, -self.deltas, - self._nturns, lspos) + self.nturns, lspos) return res def get_weighting_tous(self, single_spos, npt=5000): scalc, daccp, daccn = tousfunc.get_scaccep(self.accelerator, self.accep) - bf = self._beta # bf is the beta factor - ltime = self._ltime - b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + bf = self.beta # bf is the beta factor + lt = self.ltime + b1, b2 = lt.touschek_data['touschek_coeffs']['b1'],lt.touschek_data['touschek_coeffs']['b2'] taup, taun = (bf* daccp)**2, (bf*daccn)**2 idx = _np.argmin(_np.abs(scalc-single_spos)) @@ -257,7 +252,7 @@ def fast_aquisition(self, single_spos, par): def complete_aquisition(self, lname_or_spos, par): param = tousfunc.char_check(lname_or_spos) getsacp = tousfunc.get_scaccep(self._model_fit, self._accep) - spos = self._spos + s = self.spos if issubclass(param, str): # if user pass a list of element names @@ -268,8 +263,8 @@ def complete_aquisition(self, lname_or_spos, par): for indices in all_indices: - res = self.return_compos_track(spos[indices], par) - scat_dis = tousfunc.nnorm_cutacp(self._model_fit, spos[indices], + res = self.return_compos_track(s[indices], par) + scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], npt=5000, getsacp=getsacp) ress.append(res) scatsdis.append(scat_dis) @@ -277,7 +272,7 @@ def complete_aquisition(self, lname_or_spos, par): # if user pass a list of positions (it can be all s posistions if the user desires) elif issubclass(param, float): ress = self.return_compos_track(lname_or_spos, par) - scat_dis = tousfunc.nnorm_cutacp(self._model_fit, spos[indices], + scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], npt=5000, getsacp=getsacp) return ress, scat_dis @@ -286,14 +281,14 @@ def complete_aquisition(self, lname_or_spos, par): def plot_analysis_at_position(self, single_spos, par, accep,filename): res, fp, dp = self.fast_aquisition(single_spos, par) - spos = self._spos - index = _np.argmin(_np.abs(spos-single_spos)) + s = self.spos + index = _np.argmin(_np.abs(s-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), self.off_energy, par, index, accep, dp, fp, filename) def plot_normtousd(self, spos,filename): # user must provide a list of s positions - spos_ring = self._spos + spos_ring = self.spos dic = tousfunc.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) @@ -351,12 +346,12 @@ def plot_normtousd(self, spos,filename): # user must provide a list of s positio # this function plots the histograms returned by the monte carlo simulation def plot_histograms(self, l_spos): # user must provide a list of s positions - spos = self._spos + s = self.spos accep = self.accep model = self._model_fit - tup = tousfunc.histgms(self._model_fit, l_spos, self._num_part, accep, - self._energy_dev_min,cutaccep=False) + tup = tousfunc.histgms(self._model_fit, l_spos, self.num_part, accep, + self.energy_dev_min,cutaccep=False) hp, hn, idx_model = tup @@ -374,7 +369,7 @@ def plot_histograms(self, l_spos): # user must provide a list of s positions ay.set_xlabel(r'$\delta$ [%]', fontsize=25) ay.tick_params(axis='both', labelsize=18) ay.hist(hp[index], density=True, bins=200, color=color, - label='element:{}, pos:{:.2f} [m]'.format(model[iten].fam_name, spos[iten])) + label='element:{}, pos:{:.2f} [m]'.format(model[iten].fam_name, s[iten])) ay.hist(hn[index], density=True, bins=200, color=color) _plt.tight_layout() ay.legend() @@ -384,7 +379,7 @@ def get_track(self,l_scattered_pos, scrap, vchamber): all_track = [] indices = [] - spos = self._spos + spos = self.spos self._model.radiation_on = True self._model.cavity_on = True @@ -392,20 +387,18 @@ def get_track(self,l_scattered_pos, scrap, vchamber): if scrap: self.set_vchamber_scraper(vchamber) - print(self._model[self._scraph_inds[0]].hmax) - print(self._model[self._scraph_inds[0]].hmin) for _, scattered_pos in enumerate(l_scattered_pos): index = _np.argmin(_np.abs(scattered_pos-spos)) indices.append(index) - res = tousfunc.track_eletrons(self._deltas, self._nturns, index, self._model) + res = tousfunc.track_eletrons(self._deltas, self.nturns, index, self._model) all_track.append(res) - hx = self._model_fit[self._scraph_inds[0]].hmax - hn = self._model_fit[self._scraph_inds[0]].hmin - vx = self._model_fit[self._scrapv_inds[0]].vmax - vn = self._model_fit[self._scrapv_inds[0]].vmin + hx = self._model_fit[self.scraph_inds[0]].hmax + hn = self._model_fit[self.scraph_inds[0]].hmin + vx = self._model_fit[self.scrapv_inds[0]].vmax + vn = self._model_fit[self.scrapv_inds[0]].vmin vchamber = [hx, hn, vx, vn] self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) @@ -415,11 +408,10 @@ def get_track(self,l_scattered_pos, scrap, vchamber): def find_data(self, l_scattered_pos, scrap, vchamber): all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) - spos = self._spos + spos = self.spos - fact = 0.03 - ltime = Lifetime(self._model_fit) - tous_rate = ltime.touschek_data['rate'] + fact = 0.03 + tous_rate = self.ltime.touschek_data['rate'] prob = [] lostp = [] @@ -550,7 +542,7 @@ def get_reordered_dict(self, l_scattered_pos, reording_key, scrap, vchamber): # def get_lost_profile(self, dic, filename): # dic = self.get_reordered_dict(l_scattered_pos, reording_key) - spos = self._spos + spos = self.spos df = _pd.DataFrame(dic) a = df.set_index('lost_positions') @@ -584,7 +576,7 @@ def get_lost_profilel(self, l_dic): # dic = self.get_reordered_dict(l_scattered_pos, reording_key) l = [] for dic in l_dic: - spos = self._spos + s = self.spos df = _pd.DataFrame(dic) a = df.set_index('lost_positions') @@ -593,12 +585,12 @@ def get_lost_profilel(self, l_dic): indices = [] for iten in scat_pos: - ind = _np.argmin(_np.abs(spos-iten)) + ind = _np.argmin(_np.abs(s-iten)) indices.append(ind) summed = [] for idx, iten in a.iterrows(): - sum_row = scyint.trapz(a.loc[idx], spos[indices]) + sum_row = scyint.trapz(a.loc[idx], s[indices]) summed.append(sum_row) l.append((a.index, summed)) @@ -607,7 +599,7 @@ def get_lost_profilel(self, l_dic): def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): - spos = self._spos + s = self.spos # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') @@ -641,8 +633,8 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): fig, ax = _plt.subplots(figsize=(10,10)) - y = _np.linspace(0,spos[-1],df.shape[0]+1) - x = _np.linspace(0,spos[-1],df.shape[1]+1) + y = _np.linspace(0,s[-1],df.shape[0]+1) + x = _np.linspace(0,s[-1],df.shape[1]+1) X,Y = _np.meshgrid(x,y) heatmp = ax.pcolor(X,Y,val, cmap='jet',shading='flat') From a69881eb9fa1c0c7adbf1e80010a619b32f02797 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 4 Dec 2023 16:41:49 -0300 Subject: [PATCH 078/108] organizando a classe --- Classes.py | 408 ++++++++++++++++++++++++++++++--------------------- functions.py | 149 ++++++++++--------- 2 files changed, 318 insertions(+), 239 deletions(-) diff --git a/Classes.py b/Classes.py index 8e88a5e6..91ff6570 100644 --- a/Classes.py +++ b/Classes.py @@ -1,25 +1,28 @@ from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute, find_indices, find_spos, find_dict +from pyaccel.lattice import get_attribute, find_indices, find_spos import touschek_pack.functions as tousfunc import pymodels import pyaccel.optics as py_op import numpy as _np import matplotlib.pyplot as _plt +import matplotlib.cm as _cm from mathphys.beam_optics import beam_rigidity as _beam_rigidity import pandas as _pd import scipy.integrate as scyint import pyaccel as _pyaccel -import matplotlib.gridspec as gs class Tous_analysis(): + """Class for related with Touschek loss rate along the ring.""" - def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): + def __init__(self, accelerator, + energies_off=None, beam_energy=None, n_turns=7): + """.""" if energies_off is None: - energy_off = _np.linspace(0,0.046, 460) # used when calculating physical limitants by the linear model - deltas = _np.linspace(0,0.1,400) # used in tracking simulation + energy_off = _np.linspace(0,0.046, 460) # physical limitants + deltas = _np.linspace(0,0.1,400) # energy off for tracking if beam_energy is None: # defining beta factor - beta = _beam_rigidity(energy=3)[2] + beta = _beam_rigidity(energy=3)[2] self._model_fit = accelerator self._model = pymodels.si.create_accelerator() @@ -34,35 +37,37 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self.num_part = 50000 self.energy_dev_min = 1e-4 - self.beta = beta # beta is a constant necessary to the calculations - self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') + self.beta = beta # beta factor + self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') self.ltime = Lifetime(self._model_fit) - # self._lname = ['BC', 'Q1', 'SDA0'] # it can be modified as the users desires - self._off_energy = energy_off # en_dev to calculate amplitudes and idx_limitants from linear model - self.nturns = n_turns - self._deltas = deltas + # self._lname = ['BC', 'Q1', 'SDA0'] # it can be modified as the users + #desires + self._off_energy = energy_off # (linear model) en_dev to + # amplitudes + self.nturns = n_turns + self._deltas = deltas self.spos = find_spos(self._model_fit, indices='closed') self.scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') self.scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') - - # Defining the energy acceptance. This method also needs a setter to change the value of the acceptance by a different inserted model @property def accelerator(self): + """.""" return self._model_fit - + @accelerator.setter - def accelerator(self, new_model): #This line defines a new accelerator if the user desires + def accelerator(self, new_model): self._model_fit = new_model - # defining the nominal accelerator @property def nom_model(self): + """.""" return self._model @property def accep(self): + """.""" if self._accep is None: self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) return self._accep @@ -71,31 +76,37 @@ def accep(self): # the description above is actually the returns of the function @property def s_calc(self): + """.""" if self._sc_accps is None: self._sc_accps = tousfunc.get_scaccep(self.accelerator, self.accep) return self._sc_accps - + # This property calculates the physical limitants by the prediction of the linear model @property def amp_and_limidx(self): + """.""" if self._amp_and_limidx is None: - self.nom_model.cavity_on = False # this step is necessary to define if the + self.nom_model.cavity_on = False # this step is necessary to define if the self.nom_model.radiation_on = False - self._amps_pos, self._inds_pos = tousfunc.calc_amp(self.nom_model, - self.off_energy, self.h_pos, self.h_neg) - self._amps_neg, self._inds_neg = tousfunc.calc_amp(self.nom_model, - -self.off_energy, self.h_pos, self.h_neg) + self._amps_pos, self._inds_pos = tousfunc.calc_amp( + self.nom_model,self.off_energy, self.h_pos, self.h_neg) + + self._amps_neg, self._inds_neg = tousfunc.calc_amp( + self.nom_model,-self.off_energy, self.h_pos, self.h_neg) + self._amp_and_limidx = True return self._amp_and_limidx @property def off_energy(self): + """.""" return self._off_energy - + # the cutoff for energy deviation is the energy acceptance limit @off_energy.setter def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if the user desire + """.""" accep_pos, accep_neg = accep accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) steps = int(accep_lim*10000) # choosen to be the number of steps @@ -103,44 +114,54 @@ def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if t @property def deltas(self): + """.""" return self._deltas - + @deltas.setter - def deltas(self, dev_percent,steps=400): + def deltas(self, dev_percent,steps=400): # dev_percent input-> [%] dev_percent /= 100 - self._deltas = _np.linspace(0,dev_percent, steps) # if the user desires to make a change in the quantity of energ. dev. in tracking simulation - + self._deltas = _np.linspace(0,dev_percent, steps) # if the user + # desires to make a change in the quantity of energ. dev. in tracking + # simulation + @property def lname(self): + """.""" return self._lname - + @lname.setter - def lname(self, call_lname): # call_name is the list of element names (passed by the user) that someone desires to know the distribution + def lname(self, call_lname): # input: list of element names + # used in tracking to define the elements' list + """.""" self._lname = call_lname - # the four properties defining below are to be fixed - # this indices are obtained from the linear approach for the physical limitants + # the four properties defining below are to be static @property def inds_pos(self): + """.""" return self._inds_pos - + @property def inds_neg(self): + """.""" return self._inds_neg - - # This two propertier will help if the user wants to plot the amplitudes calculated by the linear model + @property def amp_pos(self): + '''positive amplitudes from linear model''' return self._amps_pos - - @property + + @property # negative amplitudes from linear model def amp_neg(self): + """negative amplitudes from linear model""" return self._amps_neg - def get_amps_idxs(self): # this step calls and defines 3 disctinct getters + def get_amps_idxs(self): # Defines various parameters + """.""" return self.amp_and_limidx, self.accep, self.s_calc - + def set_vchamber_scraper(self, vchamber): + """.""" model = self._model scph_inds = self.scraph_inds scpv_inds = self.scrapv_inds @@ -153,44 +174,51 @@ def set_vchamber_scraper(self, vchamber): model[iten].vmax = vchamber[3] def return_sinpos_track(self,single_spos, par): - + """.""" + self._model.cavity_on = True self._model.radiation_on = True self._model.vchamber_on = True s = self.spos - + index = _np.argmin(_np.abs(s-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons(self.deltas,self.nturns, - index, self.nom_model, pos_x=1e-5, pos_y=3e-6) + res = tousfunc.track_eletrons( + self.deltas,self.nturns,index, + self.nom_model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: - res = tousfunc.track_eletrons(-self.deltas,self.nturns, - index, self.nom_model, pos_x=1e-5, pos_y=3e-6) - + res = tousfunc.track_eletrons( + -self.deltas,self.nturns,index, + self.nom_model, pos_x=1e-5, pos_y=3e-6) + return res - + def return_compos_track(self, lspos, par): + """.""" self.nom_model.cavity_on = True self.nom_model.radiation_on = True self.nom_model.vchamber_on = True if 'pos' in par: - res = tousfunc.trackm_elec(self.nom_model, self.deltas, - self.nturns, lspos) + res = tousfunc.trackm_elec( + self.nom_model, self.deltas,self.nturns, lspos) elif 'neg' in par: - res = tousfunc.trackm_elec(self.nom_model, -self.deltas, - self.nturns, lspos) + res = tousfunc.trackm_elec( + self.nom_model, -self.deltas,self.nturns, lspos) return res - - + + def get_weighting_tous(self, single_spos, npt=5000): - - scalc, daccp, daccn = tousfunc.get_scaccep(self.accelerator, self.accep) - bf = self.beta # bf is the beta factor + """.""" + + scalc, daccp, daccn = tousfunc.get_scaccep( + self.accelerator, self.accep) + bf = self.beta # bf:beta factor lt = self.ltime - b1, b2 = lt.touschek_data['touschek_coeffs']['b1'],lt.touschek_data['touschek_coeffs']['b2'] - + b1 = lt.touschek_data['touschek_coeffs']['b1'] + b2 = lt.touschek_data['touschek_coeffs']['b2'] + taup, taun = (bf* daccp)**2, (bf*daccn)**2 idx = _np.argmin(_np.abs(scalc-single_spos)) taup_0, taun_0 = taup[idx], taun[idx] @@ -202,8 +230,11 @@ def get_weighting_tous(self, single_spos, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf - getdp = tousfunc.f_function_arg_mod(kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) - getdn = tousfunc.f_function_arg_mod(kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) + getdp = tousfunc.f_function_arg_mod( + kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) + + getdn = tousfunc.f_function_arg_mod( + kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # eliminating negative values indp = _np.where(getdp<0)[0] @@ -219,80 +250,83 @@ def get_weighting_tous(self, single_spos, npt=5000): deltn = deltn[ind] self.deltas = deltp[-1]*1e2 - + return getdp, getdn, deltp, deltn def fast_aquisition(self, single_spos, par): # this raise blocks to runing the program if the list of s position has more than 1 element + """.""" if len(tousfunc.t_list(single_spos)) != 1: - raise Exception('This function suports only one s position') + raise ValueError('This function suports only one s position') fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) - + fp = fdensp.squeeze() fn = fdensn.squeeze() - + res = self.return_sinpos_track(single_spos, par) delta = _np.zeros(len(res)) for index, iten in enumerate(res): - tlost, ellost, delt = iten + _, _, delt = iten delta[index] = delt - Ddeltas = _np.diff(delta)[0] + delta_ = _np.diff(delta)[0] if 'pos' in par: - return res, fp*Ddeltas, deltp *1e2 + return res, fp*delta_, deltp *1e2 elif 'neg' in par: - return res, fn*Ddeltas, deltn*1e2 + return res, fn*delta_, deltn*1e2 else: - return res, fp*Ddeltas, fn*Ddeltas, deltp*1e2, deltn*1e2 - + return res, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 - def complete_aquisition(self, lname_or_spos, par): - param = tousfunc.char_check(lname_or_spos) - getsacp = tousfunc.get_scaccep(self._model_fit, self._accep) - s = self.spos - if issubclass(param, str): # if user pass a list of element names - - all_indices = tousfunc.el_idx_collector(self._model_fit, lname_or_spos) - all_indices = _np.array(all_indices, dtype=object) - ress = [] - scatsdis = [] - - for indices in all_indices: - - res = self.return_compos_track(s[indices], par) - scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], - npt=5000, getsacp=getsacp) - ress.append(res) - scatsdis.append(scat_dis) - - # if user pass a list of positions (it can be all s posistions if the user desires) - elif issubclass(param, float): - ress = self.return_compos_track(lname_or_spos, par) - scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], - npt=5000, getsacp=getsacp) - - return ress, scat_dis - - # this function plot the graphic of tracking and the touschek scattering distribution for one single position - def plot_analysis_at_position(self, single_spos, par, accep,filename): + # def complete_aquisition(self, lname_or_spos, par): + # """.""" + # param = tousfunc.char_check(lname_or_spos) + # getsacp = tousfunc.get_scaccep(self._model_fit, self._accep) + # s = self.spos + + # if issubclass(param, str): # if user pass a list of element names + + # all_indices = tousfunc.el_idx_collector(self._model_fit, lname_or_spos) + # all_indices = _np.array(all_indices, dtype=object) + # ress = [] + # scatsdis = [] + + # for indices in all_indices: + + # res = self.return_compos_track(s[indices], par) + # scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], + # npt=5000, getsacp=getsacp) + # ress.append(res) + # scatsdis.append(scat_dis) + # # if user pass a list of positions (it can be all s posistions if the user desires) + # elif issubclass(param, float): + # ress = self.return_compos_track(lname_or_spos, par) + # scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], + # npt=5000, getsacp=getsacp) + + # return ress, scat_dis + + # this function plot the graphic of tracking and the touschek scattering + # distribution for one single position + def plot_analysis_at_position(self, single_spos, par, accep,filename): + """.""" res, fp, dp = self.fast_aquisition(single_spos, par) s = self.spos index = _np.argmin(_np.abs(s-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), self.off_energy, par, index, accep, dp, fp, filename) - def plot_normtousd(self, spos,filename): # user must provide a list of s positions - + def plot_normtousd(self, spos, filename): # user must provide a list of s positions + """touschek scattering density""" spos_ring = self.spos - dic = tousfunc.norm_cutacp(self._model_fit, + dic = tousfunc.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) - - fdensp, fdensn = dic['fdensp'], dic['fdensn'] + + fdensp, fdensn = dic['fdensp'], dic['fdensn'] deltasp, deltasn = dic['deltasp'], dic['deltasn'] fig, ax = _plt.subplots(figsize=(10,5)) @@ -304,7 +338,7 @@ def plot_normtousd(self, spos,filename): # user must provide a list of s positio ax.tick_params(axis='both', labelsize=28) for idx, s in enumerate(spos): - + array_fdens = fdensp[idx] index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) @@ -327,39 +361,46 @@ def plot_normtousd(self, spos,filename): # user must provide a list of s positio deltaspi = deltasp[idx][:best_index]*1e2 deltasni = -deltasn[idx][:best_index]*1e2 - color = _plt.cm.gist_rainbow(idx/len(spos)) + color = _cm.gist_rainbow(idx/len(spos)) not_desired = ['calc_mom_accep', 'mia', 'mib', 'mip', 'mb1', 'mb2', 'mc'] - + while self._model_fit[mod_ind].fam_name in not_desired: mod_ind += 1 - ax.plot(deltaspi, fdenspi, - label='{} em {} m'.format(self._model_fit[mod_ind].fam_name, _np.round(spos_ring[mod_ind], 2)),color=color) + fam_name = self._model_fit[mod_ind].fam_name + s_stri = _np.round(spos_ring[mod_ind], 2) + stri = f'{fam_name} em {s_stri} m' + + ax.plot(deltaspi, fdenspi, label= stri, color=color) ax.plot(deltasni, fdensni, color=color ) - # ap_ind.append(mod_ind) ax.legend(loc='best', fontsize=20) fig.savefig(filename, dpi=150) # this function plots the histograms returned by the monte carlo simulation - - def plot_histograms(self, l_spos): # user must provide a list of s positions + + def plot_histograms(self, l_spos): + """Touschek scattering density from Monte-Carlo simulation; + input: list of desired positions""" s = self.spos accep = self.accep model = self._model_fit tup = tousfunc.histgms(self._model_fit, l_spos, self.num_part, accep, self.energy_dev_min,cutaccep=False) - + hp, hn, idx_model = tup - - fig, ax = _plt.subplots(ncols=len(l_spos), nrows=1,figsize=(30,10), sharey=True) - fig.suptitle('Probability density calculated by Monte-Carlo simulation', fontsize=20) - + + fig, ax = _plt.subplots( + ncols=len(l_spos), nrows=1,figsize=(30,10), sharey=True) + fig.suptitle( + 'Probability density calculated by Monte-Carlo simulation', + fontsize=20) + for index, iten in enumerate(idx_model): - color = _plt.cm.jet(index/len(idx_model)) + color = _cm.jet(index/len(idx_model)) ay = ax[index] if not index: ay.set_ylabel('PDF', fontsize=25) @@ -368,19 +409,25 @@ def plot_histograms(self, l_spos): # user must provide a list of s positions ay.xaxis.grid(False) ay.set_xlabel(r'$\delta$ [%]', fontsize=25) ay.tick_params(axis='both', labelsize=18) - ay.hist(hp[index], density=True, bins=200, color=color, - label='element:{}, pos:{:.2f} [m]'.format(model[iten].fam_name, s[iten])) + + stri = f'{model[iten].fam_name:s}, {s[iten]:.2f}' + ay.hist(hp[index], density=True, bins=200, color=color, label=stri) ay.hist(hn[index], density=True, bins=200, color=color) _plt.tight_layout() ay.legend() def get_track(self,l_scattered_pos, scrap, vchamber): + """Tracking to get the loss profile along the ring. + + l_scattered_pos: scattered positions, + scrap: if True, the vchamber's height must be changed, + vchmaber: defines the vchamber's height""" all_track = [] indices = [] spos = self.spos - + self._model.radiation_on = True self._model.cavity_on = True self._model.vchamber_on = True @@ -404,15 +451,16 @@ def get_track(self,l_scattered_pos, scrap, vchamber): self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) return all_track, indices - + def find_data(self, l_scattered_pos, scrap, vchamber): + """obtaining the graphic""" all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) spos = self.spos - - fact = 0.03 + + fact = 0.03 tous_rate = self.ltime.touschek_data['rate'] - + prob = [] lostp = [] all_lostp = [] @@ -420,50 +468,68 @@ def find_data(self, l_scattered_pos, scrap, vchamber): for j, iten in enumerate(all_track): index = indices[j] - scattered_pos = l_scattered_pos[j] - + # scattered_pos = l_scattered_pos[j] + lostinds, deltas = _np.zeros(len(iten)), _np.zeros(len(iten)) for idx,iten in enumerate(iten): _, ellost, delta = iten lostinds[idx] = ellost - deltas[idx] = delta # alguns elétrons possuem desvio de energia abaixo da aceitancia e acabam não sendo perdidos + deltas[idx] = delta # alguns elétrons possuem desvio de + # energia abaixo da aceitancia e acabam não sendo perdidos lostinds = _np.intp(lostinds) lost_positions = _np.round(spos[lostinds], 2) step = int((deltas[0]+deltas[-1])/fact) - itv_track = _np.linspace(deltas[0], deltas[-1], step) # method learned by fac repositories + itv_track = _np.linspace(deltas[0], deltas[-1], step) - data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) # create the dataframe that is obtained by tracking - lost_pos_column = (data.groupby('lost_pos_by_tracking').groups).keys() - data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) # this step agroups the lost_positions + data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) + # dataframe that storages the tracking data + lost_pos_column = \ + (data.groupby('lost_pos_by_tracking').groups).keys() + data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) + # this step agroups the lost_positions - # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain the scattered positions and the lost positions after scattering + # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain + # the scattered positions and the lost positions after scattering itv_delta = [] for current, next_iten in zip(itv_track, itv_track[1:]): - data['{:.2f} % < delta < {:.2f} %'.format(current*1e2, next_iten*1e2)] = _np.zeros(len(list(lost_pos_column))) # this step creates new columns in the dataframe and fill with zeros + stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' + data[stri] = _np.zeros(len(list(lost_pos_column))) # this step + #creates new columns in the dataframe and fill with zeros + itv_delta.append((current, next_iten)) - # Next step must calculate each matrix element from the dataframe + # Next step must calculate each matrix element from the + # dataframe - var = list(data.index) - # quando as duas variáveis são iguais isso acab resultando em um erro então estou colocando essa condição. + var = list(data.index) + # quando as duas variáveis são iguais isso acab resultando em um + # erro então estou colocando essa condição. if var == lost_pos_column: pass else: data = data.set_index('lost_pos_by_tracking') - for idx, lost_pos in enumerate(lost_positions): # essas duas estruturas de repetição são responsáveis por calcular - # o percentual dos eletrons que possuem um determinado desvio de energia e se perdem em um intervalo de desvio de energia específico + for idx, lost_pos in enumerate(lost_positions): # essas duas + # estruturas de repetição são responsáveis por calcular + # o percentual dos eletrons que possuem um determinado desvio + # de energia e se perdem em um intervalo de desvio de energia + # específico delta = deltas[idx] - lps = [] + # lps = [] for i, interval in enumerate(itv_delta): if i == 0: if interval[0]<= delta <= interval[1]: - data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + stri = \ + f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + data.loc[lost_pos, stri] += 1 + else: if interval[0]< delta <= interval[1]: - data.loc[lost_pos, '{:.2f} % < delta < {:.2f} %'.format(interval[0]*1e2, interval[1]*1e2)] += 1 + stri = \ + f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + data.loc[lost_pos, stri] += 1 data = data / len(deltas) @@ -498,9 +564,10 @@ def find_data(self, l_scattered_pos, scrap, vchamber): return all_lostp, prob, lostp # dataframe = _pd.DataFrame(dic_res) - + def get_table(self,l_scattered_pos, scrap, vchamber): - + """This is the heatmap """ + dic_res = {} all_lostp, prob, lostp = self.find_data(l_scattered_pos, scrap, vchamber) n_scat = _np.round(l_scattered_pos, 2) @@ -509,37 +576,47 @@ def get_table(self,l_scattered_pos, scrap, vchamber): scat_data = [] bool_array = _np.isin(all_lostp, lostp[idx]) - + for j, boolean in enumerate(bool_array): if boolean: - index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) + index = \ + _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) scat_data.append(prob[idx][index]) else: scat_data.append(0) if not idx: dic_res['lost_positions'] = all_lostp - dic_res['{}'.format(scattered_pos)] = scat_data + stri = f'{scattered_pos:s}' + dic_res[stri] = scat_data else: - dic_res['{}'.format(scattered_pos)] = scat_data + stri = f'{scattered_pos}' + dic_res[stri] = scat_data # df = _pd.DataFrame(dic_res) return dic_res - - def get_reordered_dict(self, l_scattered_pos, reording_key, scrap, vchamber): # chatgpt code to reorder the dictionary + + def get_reordered_dict(self, l_scattered_pos, + reording_key, scrap, vchamber): + # chatgpt code to reorder the dictionary + """Get the reordered dictionary""" dic = self.get_table(l_scattered_pos, scrap, vchamber) zip_tuples = zip(*[dic[chave] for chave in dic]) - new_tuples = sorted(zip_tuples, key=lambda x: x[list(dic.keys()).index(reording_key)]) + new_tuples = sorted(zip_tuples, + key=lambda x: x[list(dic.keys()).index(reording_key)]) zip_ordered = zip(*new_tuples) - new_dict = {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} + new_dict = \ + {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} return new_dict - - def get_lost_profile(self, dic, filename): + + def get_loss_profile(self, dic, filename): + """Integrates the lost positions for all s positions, + generating the loss profile along the ring.""" # dic = self.get_reordered_dict(l_scattered_pos, reording_key) spos = self.spos @@ -548,7 +625,7 @@ def get_lost_profile(self, dic, filename): a = df.set_index('lost_positions') scat_pos = _np.array(a.columns, dtype=float) - + indices = [] for iten in scat_pos: ind = _np.argmin(_np.abs(spos-iten)) @@ -571,18 +648,22 @@ def get_lost_profile(self, dic, filename): offset=-1e-6, height=1e-6, gca=True) fig.savefig(filename,dpi=150) - def get_lost_profilel(self, l_dic): + def get_loss_profilel(self, l_dic): + """Comparing distinct loss profiles, could be used to compare with + the insertion of scrapers or not. + + l_dic: list of dictionaries of loss profiles""" # dic = self.get_reordered_dict(l_scattered_pos, reording_key) l = [] - for dic in l_dic: + for dic in l_dic: s = self.spos df = _pd.DataFrame(dic) a = df.set_index('lost_positions') scat_pos = _np.array(a.columns, dtype=float) - + indices = [] for iten in scat_pos: ind = _np.argmin(_np.abs(s-iten)) @@ -594,10 +675,10 @@ def get_lost_profilel(self, l_dic): summed.append(sum_row) l.append((a.index, summed)) - + return l - + def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): s = self.spos @@ -635,9 +716,9 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): y = _np.linspace(0,s[-1],df.shape[0]+1) x = _np.linspace(0,s[-1],df.shape[1]+1) - X,Y = _np.meshgrid(x,y) + x_mesh,y_mesh = _np.meshgrid(x,y) - heatmp = ax.pcolor(X,Y,val, cmap='jet',shading='flat') + heatmp = ax.pcolor(x_mesh,y_mesh,val, cmap='jet',shading='flat') cbar = _plt.colorbar(heatmp) cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) @@ -649,6 +730,5 @@ def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): fig.tight_layout() _plt.gca().set_aspect('equal') - # fig.savefig(filename, dpi=150) + # fig.savefig(filename, dpi=300) _plt.show() - diff --git a/functions.py b/functions.py index 8dd3debc..1fc6c5ee 100644 --- a/functions.py +++ b/functions.py @@ -34,39 +34,39 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] - + rin = _np.zeros((6, deltas.size)) rin += orb[:, None] rin[0] += pos_x rin[2] += pos_y rin[4] += deltas - + track = _pyaccel.tracking.ring_pass( model, rin, nr_turns=n_turn, turn_by_turn=True, element_offset=element_idx, parallel=True) - + par_out, flag, turn_lost, element_lost, plane_lost = track - + turnl_element = [] for i,item in enumerate(turn_lost): - if item == n_turn and element_lost[i] == element_idx: + if item == n_turn and element_lost[i] == element_idx: pass else: turnl_element.append((item, element_lost[i], deltas[i])) - + return turnl_element def trackm_elec(acc,deltas, n_turn, lspos): results = [] spos = _pyaccel.lattice.find_spos(acc, indices='open') - + for k, iten in enumerate(lspos): - + el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to shift the tracking simulation turnl = track_eletrons(deltas, n_turn, el_idx, acc) - results.append(turnl) # - + results.append(turnl) # + return results def el_idx_collector(acc, lname): @@ -96,13 +96,13 @@ def el_idx_collector(acc, lname): try: ind = int(length/2 + 1) element_index.append(lista[ind]) - + except IndexError: ind = int(length/2 - 1) element_index.append(lista[ind]) - + all_index.append(element_index) - + return all_index def char_check(elmnt): @@ -115,13 +115,13 @@ def char_check(elmnt): def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): # ---------------- - + cm = 1/2.54 # 'poster' twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax betax = betax*(1/5) - + spos = _pyaccel.lattice.find_spos(acc) fig = _plt.figure(figsize=(38.5*cm,18*cm)) @@ -131,7 +131,7 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a3 = fig.add_subplot(gs[0, 2], sharey=a1) a2.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) a3.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) - + # defining the form that graphic will be plotted, trying to amplify the best I can the letters to see it in a easier way a1.grid(True, alpha=0.5, ls='--', color='k') a1.tick_params(axis='both', labelsize=18) @@ -144,67 +144,66 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep a3.xaxis.grid(False) _plt.subplots_adjust(wspace=0.1) - if 'pos' in param: + if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - + a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[1][element_idx] + acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[0][element_idx] + acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') - + a1.set_title(r'$\delta \times scat. rate$', fontsize=20) # setting the title of the first graphic a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - + a2.set_title(r'$\delta \times$ lost turn', fontsize=20) # setting the tilte of the second graphic a2.set_xlabel(r'number of turns', fontsize=25) for iten in lista_resul: a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') - + a3.set_title(r'tracking ', fontsize=20) # setting the title of the third graphic a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', label=r'accep. limit', alpha=0.25) - + _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff a3.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) #magnetic lattice - + a3.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position where tracking begins - + a3.set_xlabel(r'$s$ [m]', fontsize=25) # setting configurations of the graphic a3.legend(loc='upper right', ncol=1, fontsize=15) # fig.tight_layout() fig.savefig(filename, dpi=150) fig.show() - + def select_idx(list_, param1, param2): arr = _np.array(list_) - + n_arr = arr[param1:param2+1] - + return n_arr def t_list(elmnt): - #this condition significates that if the input is only a number, then - #the fucntion transforms it into a list to avoid errors. Actually, I will delete this function, - # so just forget this bulshit + #this condition significates that if the input is only a number, then + #the fucntion transforms it into a list to avoid errors. Actually, I will delete this function if type(elmnt) == float or type(elmnt) == int: return [elmnt] else: return list(elmnt) - + def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): @@ -229,7 +228,7 @@ def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): arg *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum return arg * bessel - + def f_integral_simps_l_mod(taum, b1_, b2_): kappam = _np.arctan(_np.sqrt(taum)) @@ -262,12 +261,12 @@ def norm_d(acc, lsps, scalc,_npt, norm=True): indices, indices_model= [], [] for _, s in enumerate(lsps): - + idx = _np.argmin(_np.abs(scalc - s)) indices.append(idx) idx_model = _np.argmin(_np.abs(spos - s)) indices_model.append(idx_model) - + kappam_p0 = 0.00001 # teste sugerido pelo ximenes kappam_n0 = 0.00001 @@ -290,7 +289,7 @@ def norm_d(acc, lsps, scalc,_npt, norm=True): calc_dn.append(y_n) deltasp.append(deltap) deltasn.append(deltan) - + calc_dp = _np.array(calc_dp) calc_dn = _np.array(calc_dn) deltasp = _np.array(deltasp) @@ -309,7 +308,7 @@ def get_scaccep(acc, accep): daccpn = _np.interp(scalc, spos, accep[0]) return scalc, daccpp, daccpn - + def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): scalc, daccpp, daccpn = get_scaccep(acc, accep) @@ -319,7 +318,7 @@ def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): taum_n = (beta*daccpn)**2 kappam_p = _np.arctan(_np.sqrt(taum_p)) kappam_n = _np.arctan(_np.sqrt(taum_n)) - + ltime = _pyaccel.lifetime.Lifetime(acc) b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -327,12 +326,12 @@ def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): deltasp, deltasn = [], [] for _, s in enumerate(lsps): - + idx = _np.argmin(_np.abs(scalc - s)) kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] - + kappam_p0x = cutoff # teste sugerido pelo Ximenes kappam_n0x = cutoff @@ -358,7 +357,7 @@ def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): return calc_dp, calc_dn, deltasp, deltasn -# Como discutido no dia 23.08.2023 a primeira abordagem para a realizaçao da pesagem vai +# Como discutido no dia 23.08.2023 a primeira abordagem para a realizaçao da pesagem vai # vai ser feita definindo o corte como sendo a aceitancia de energia, isso foi deinido com base # no cálculo já implementados para o tempo de vida touschek que é coerente com o tempo do SIRIUS # futuramente isso pode ser alterado e redefinido @@ -373,7 +372,7 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): taum_n = (beta*daccpn)**2 kappam_p = _np.arctan(_np.sqrt(taum_p)) kappam_n = _np.arctan(_np.sqrt(taum_n)) - + ltime = _pyaccel.lifetime.Lifetime(acc) b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] @@ -381,7 +380,7 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): deltasp, deltasn = [], [] for _, s in enumerate(lsps): - + idx = _np.argmin(_np.abs(scalc - s)) kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] @@ -398,13 +397,13 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): y_p /= norm_facp y_n /= norm_facn - + # eliminating the negative values from array indp = _np.where(y_p<0)[0] indn = _np.where(y_n<0)[0] y_p[indp] = 0 y_n[indn] = 0 - + fdens_p.append(y_p) fdens_n.append(y_n) deltasp.append(deltap) @@ -424,7 +423,7 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): - + fig, axis = _plt.subplots(1,l_index.squeeze().size, figsize=(10,6)) _plt.suptitle('Comparação entre densidade de probabilidade analítica e de M.C.', fontsize=15) spos = _pyaccel.lattice.find_spos(acc, indices='closed') @@ -433,7 +432,7 @@ def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): for c,iten in enumerate(l_index): ax = axis[c] - + if c == 0: ax.set_ylabel(r'PDF normalizada', fontsize=15) @@ -441,7 +440,7 @@ def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): ax.set_title('{}'.format(acc[iten].fam_name)) ax.plot(deltp[idx], f_densp[idx], color='blue', label='Analytic ({:.2f} [m])'.format(scalc[idx])) - + ax.tick_params(axis='both', labelsize=14) ax.hist(hn[idx], density=True, bins=200, color='lightgrey', label='Monte-Carlo') @@ -458,27 +457,27 @@ def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): ax.grid(axis='y', ls='--', alpha=0.5) # fig.tight_layout() _plt.show - + return idx def create_particles(cov_matrix, num_part): - + # permute indices to change the order of the columns: # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T idcs = [1, 3, 4, 0, 2, 5] # [px, py, de, rx, ry, dl]^T -> [rx, px, ry, py, de, dl]^T idcs_r = [3, 0, 4, 1, 2, 5] - + cov_matrix = cov_matrix[:, idcs][idcs, :] - + sig_xx = cov_matrix[:3, :3] sig_xy = cov_matrix[:3, 3:] sig_yx = cov_matrix[3:, :3] sig_yy = cov_matrix[3:, 3:] inv_yy = _np.linalg.inv(sig_yy) - + part1 = _np.random.multivariate_normal(_np.zeros(6), cov_matrix, num_part).T - # changing the matrices' columns order + # changing the matrices' columns order part2 = part1.copy() vec_a = part2[3:] @@ -487,7 +486,7 @@ def create_particles(cov_matrix, num_part): part2[:3] = _np.random.multivariate_normal(_np.zeros(3), new_cov, num_part).T part2[:3] += new_mean - + part2 = part2[idcs_r, :] part1 = part1[idcs_r, :] @@ -498,10 +497,10 @@ def get_cross_section_distribution(psim, _npts=3000): beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) psi = _np.pi/2 - psi - psi = psi[::-1] + psi = psi[::-1] cpsi = _np.cos(psi) cross = _np.zeros(cpsi.size) - if beta_bar > 1e-19: + if beta_bar > 1e-19: cross += (1 + 1/beta_bar**2)**2 * (2*(1 + cpsi**2)/cpsi**3 - 3/cpsi) cross += 4/cpsi + 1 cross *= _np.sin(psi) @@ -527,11 +526,11 @@ def scatter_particles(part1, part2, de_min): # calculating the changing base matrix for every particle pz1 = _np.sqrt((1+de1)**2 - xl1*xl1 - yl1*yl1) pz2 = _np.sqrt((1+de2)**2 - xl2*xl2 - yl2*yl2) - + # desired vectors to construct the transformation matrix p_1 = _np.vstack([xl1, yl1, pz1]) p_2 = _np.vstack([xl2, yl2, pz2]) - + # new coordinate system p_j = p_1 + p_2 p_j /= _np.linalg.norm(p_j, axis=0) # sum @@ -543,9 +542,9 @@ def scatter_particles(part1, part2, de_min): jkl2xyz[:, :, 0] = p_j.T jkl2xyz[:, :, 1] = p_k.T jkl2xyz[:, :, 2] = p_l.T - + # calculating theta and zeta - theta = xl1 - xl2 + theta = xl1 - xl2 zeta = yl1 - yl2 # defining the value of the scattering angle chi chi = _np.sqrt(zeta**2 + theta**2)/2 @@ -553,14 +552,14 @@ def scatter_particles(part1, part2, de_min): # draw the scattering angles from uniform distribution: phi = _np.random.rand(num_part)* 2*_np.pi psi = _np.random.rand(num_part)* _np.pi/2 - + # draw the psi angle from the cross section probability density: # we need to define a maximum angle to normalize the cross section # distribution because it diverges when the full interval [0, pi/2] # is considered. # To estimate this angle we define a threshold for the minimum energy # deviation we care about (de_min) and consider the worst case scenario - # in terms of chi that could create such scattering. + # in terms of chi that could create such scattering. # The worst case happens when chi is maximum, because in this way a small # scattering angle would create a larger energy deviation. # We considered here a chi twice as large as the maximum chi draw from @@ -571,7 +570,7 @@ def scatter_particles(part1, part2, de_min): fact=psim*2/_np.pi print(psim*2/_np.pi) psi = cross_section_draw_samples(psim, num_part) - + # new momentum in j,k,l (eq. 16 of Piwinski paper) gammat = gamma/_np.sqrt(1 + beta*beta*gamma*gamma*chi*chi) dp_ = _np.sin(chi[None, :]) * _np.vstack([ @@ -590,12 +589,12 @@ def scatter_particles(part1, part2, de_min): delta1 = _np.linalg.norm(pnew_1, axis=0) - 1 delta2 = _np.linalg.norm(pnew_2, axis=0) - 1 - + part1_new = part1.copy() part1_new[1] = pnew_1[0] part1_new[3] = pnew_1[1] part1_new[4] = delta1 - + part2_new = part2.copy() part2_new[1] = pnew_2[0] part2_new[3] = pnew_2[1] @@ -607,18 +606,18 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): envelopes = _pyaccel.optics.calc_beamenvelope(acc) spos=_pyaccel.lattice.find_spos(acc, indices='closed') - + scalc, daccpp, daccpn = get_scaccep(acc, accep) histsp1, histsp2, indices=[],[],[] - + for iten in l_spos: - + idx_model = _np.argmin(_np.abs(spos - iten)) idx = _np.argmin(_np.abs(scalc - iten)) indices.append(idx_model) - # this index is necessary to the s position indices from analitically calculated PDF + # this index is necessary to the s position indices from analitically calculated PDF # match with monte carlo simulation s position indices env = envelopes[idx_model] @@ -634,19 +633,19 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): ind1 = _np.intp(_np.where(check1<0)[0]) ind2 = _np.intp(_np.where(check2<0)[0]) - + histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - else: + else: ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) # teste sugerido pelo ximenes ind2 = _np.intp(_np.where(part2_new[4]<=-0.01)[0]) histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - + # hist1=_np.array(histsp1, dtype='object') # hist2=_np.array(histsp2, dtype='object') indices=_np.array(indices) - + return histsp1, histsp2, indices From d2af3af6d76067e5b7fdec8b283eea1b1e8eaa86 Mon Sep 17 00:00:00 2001 From: Thales Date: Mon, 4 Dec 2023 16:55:18 -0300 Subject: [PATCH 079/108] =?UTF-8?q?pequenas=20altera=C3=A7=C3=B5es=20para?= =?UTF-8?q?=20fins=20de=20organiza=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Classes.py b/Classes.py index 91ff6570..422307fd 100644 --- a/Classes.py +++ b/Classes.py @@ -1,3 +1,4 @@ +"""tous_analysis.""" from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute, find_indices, find_spos import touschek_pack.functions as tousfunc @@ -679,7 +680,8 @@ def get_loss_profilel(self, l_dic): return l - def plot_scat_table(self, l_scattered_pos, new_dic, n_r,filename, n_c=1): + def plot_scat_table(self, new_dic): + """ Heatmap plot indicating the heat points of loss along the ring """ s = self.spos # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') From ebe7c1b3f2158531e02886e7efeea4ac1b683120 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Tue, 5 Dec 2023 10:35:02 -0300 Subject: [PATCH 080/108] =?UTF-8?q?organizando=20a=20classe=20e=20as=20fun?= =?UTF-8?q?=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 46 --------- functions.py | 272 +++++++++++++-------------------------------------- 2 files changed, 67 insertions(+), 251 deletions(-) diff --git a/Classes.py b/Classes.py index 422307fd..eceae205 100644 --- a/Classes.py +++ b/Classes.py @@ -194,22 +194,6 @@ def return_sinpos_track(self,single_spos, par): return res - - def return_compos_track(self, lspos, par): - """.""" - self.nom_model.cavity_on = True - self.nom_model.radiation_on = True - self.nom_model.vchamber_on = True - - if 'pos' in par: - res = tousfunc.trackm_elec( - self.nom_model, self.deltas,self.nturns, lspos) - elif 'neg' in par: - res = tousfunc.trackm_elec( - self.nom_model, -self.deltas,self.nturns, lspos) - return res - - def get_weighting_tous(self, single_spos, npt=5000): """.""" @@ -281,36 +265,6 @@ def fast_aquisition(self, single_spos, par): else: return res, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 - - # def complete_aquisition(self, lname_or_spos, par): - # """.""" - # param = tousfunc.char_check(lname_or_spos) - # getsacp = tousfunc.get_scaccep(self._model_fit, self._accep) - # s = self.spos - - # if issubclass(param, str): # if user pass a list of element names - - # all_indices = tousfunc.el_idx_collector(self._model_fit, lname_or_spos) - # all_indices = _np.array(all_indices, dtype=object) - # ress = [] - # scatsdis = [] - - # for indices in all_indices: - - # res = self.return_compos_track(s[indices], par) - # scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], - # npt=5000, getsacp=getsacp) - # ress.append(res) - # scatsdis.append(scat_dis) - - # # if user pass a list of positions (it can be all s posistions if the user desires) - # elif issubclass(param, float): - # ress = self.return_compos_track(lname_or_spos, par) - # scat_dis = tousfunc.nnorm_cutacp(self._model_fit, s[indices], - # npt=5000, getsacp=getsacp) - - # return ress, scat_dis - # this function plot the graphic of tracking and the touschek scattering # distribution for one single position def plot_analysis_at_position(self, single_spos, par, accep,filename): diff --git a/functions.py b/functions.py index 1fc6c5ee..47c8781f 100644 --- a/functions.py +++ b/functions.py @@ -7,13 +7,16 @@ from mathphys.beam_optics import beam_rigidity as _beam_rigidity def calc_amp(acc,energy_offsets, hmax, hmin): + + """Calculates the amplitudes and gets the physical + limitants""" + a_def = _np.zeros(energy_offsets.size) indices = _np.zeros(energy_offsets.size) try: for idx,delta in enumerate(energy_offsets): - twi,*_ = _pyaccel.optics.calc_twiss(accelerator=acc, - energy_offset=delta, - indices='closed') + twi,*_ = _pyaccel.optics.calc_twiss( + accelerator=acc, energy_offset=delta, indices='closed') if _np.any(_np.isnan(twi[0].betax)): raise _pyaccel.optics.OpticsException('error') rx = twi.rx @@ -31,6 +34,7 @@ def calc_amp(acc,energy_offsets, hmax, hmin): return _np.sqrt(a_def), indices def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): + """ This function finds the lost electrons by tracking """ orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] @@ -45,7 +49,10 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): model, rin, nr_turns=n_turn, turn_by_turn=True, element_offset=element_idx, parallel=True) - par_out, flag, turn_lost, element_lost, plane_lost = track + _, _, turn_lost, element_lost, _ = track + # oculted variables/ part_out: final coordinates of electrons + # flag: indicates if there is any loss + # plane_lost: plane that electron was lost(x or y) turnl_element = [] @@ -58,26 +65,28 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): return turnl_element def trackm_elec(acc,deltas, n_turn, lspos): + """Run the tracking simulation for a list of s positions """ results = [] spos = _pyaccel.lattice.find_spos(acc, indices='open') - for k, iten in enumerate(lspos): + for _, iten in enumerate(lspos): - el_idx = _np.argmin(_np.abs(spos-iten)) # selecting the index to shift the tracking simulation + el_idx = _np.argmin(_np.abs(spos-iten)) # initial condition element turnl = track_eletrons(deltas, n_turn, el_idx, acc) results.append(turnl) # return results def el_idx_collector(acc, lname): + """.""" all_index = [] if 'mia' in lname: - all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mia')) + all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) elif'mib' in lname: - all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mib')) + all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) elif 'mip' in lname: - all_index.append(_pyaccel.optics.find_indices(acc, 'fam_name', 'mip')) + all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) fam_data = _pymodels.si.get_family_data(acc) @@ -85,7 +94,7 @@ def el_idx_collector(acc, lname): element_index = [] array_idx = _np.array(fam_data[string]['index'], dtype=object) - for k, lista in enumerate(array_idx): + for _, lista in enumerate(array_idx): length = len(lista) if length % 2 != 0: @@ -105,15 +114,15 @@ def el_idx_collector(acc, lname): return all_index -def char_check(elmnt): - for char in elmnt: - returnval = type(char) - if returnval is str: - return str - elif returnval is float or returnval is int: - return float - -def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): +def plot_track(acc, lista_resul, lista_idx, + lista_off, param, element_idx, accep, delt, f_dens, filename): + """ This function shows the touschek scattering density for s, + the number of turns before electron loss and a graphic + containing the magnetic lattice with the lost positions + of the electrons obtained by tracking simulation, the limit + energy acceptance in a determined point s and the physical + limitants calculated by a linear approach of the dependencies + of beta and eta functions""" # ---------------- cm = 1/2.54 # 'poster' @@ -125,14 +134,16 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep spos = _pyaccel.lattice.find_spos(acc) fig = _plt.figure(figsize=(38.5*cm,18*cm)) - gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) + gs = _plt.GridSpec(1, 3, left=0.1, + right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) a1 = fig.add_subplot(gs[0, 0]) a2 = fig.add_subplot(gs[0, 1], sharey=a1) a3 = fig.add_subplot(gs[0, 2], sharey=a1) - a2.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) - a3.tick_params(axis='y', which='both', left=False, right=False, labelleft=False) + a2.tick_params(axis='y', which='both', + left=False, right=False, labelleft=False) + a3.tick_params(axis='y', which='both', + left=False, right=False, labelleft=False) - # defining the form that graphic will be plotted, trying to amplify the best I can the letters to see it in a easier way a1.grid(True, alpha=0.5, ls='--', color='k') a1.tick_params(axis='both', labelsize=18) a2.grid(True, alpha=0.5, ls='--', color='k') @@ -160,55 +171,53 @@ def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep for item in lista_resul: a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') - a1.set_title(r'$\delta \times scat. rate$', fontsize=20) # setting the title of the first graphic + a1.set_title(r'$\delta \times scat. rate$', fontsize=20) a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - a2.set_title(r'$\delta \times$ lost turn', fontsize=20) # setting the tilte of the second graphic + a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) for iten in lista_resul: a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') - a3.set_title(r'tracking ', fontsize=20) # setting the title of the third graphic + a3.set_title(r'tracking ', fontsize=20) a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', label=r'accep. limit', alpha=0.25) - _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) # acceptance cutoff - a3.plot(spos, _np.sqrt(betax),color='orange', label=r'$ \sqrt{\beta_x} $') # beta function - _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) #magnetic lattice + _plt.hlines(1e2*acp_s, spos[0], + spos[-1], color='black', linestyles='dashed', alpha=0.5) + #hlines -> shows accep. limit - a3.plot(spos[element_idx], 0, 'ko', label='{}, ({} m)'.format( - acc[element_idx].fam_name, "%.2f" % spos[element_idx])) # initial position where tracking begins + a3.plot(spos, _np.sqrt(betax), + color='orange', label=r'$ \sqrt{\beta_x} $') # beta function + _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) - a3.set_xlabel(r'$s$ [m]', fontsize=25) # setting configurations of the graphic + stri = f'{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)' + a3.plot(spos[element_idx], 0, 'ko', label=stri) + a3.set_xlabel(r'$s$ [m]', fontsize=25) a3.legend(loc='upper right', ncol=1, fontsize=15) # fig.tight_layout() fig.savefig(filename, dpi=150) fig.show() -def select_idx(list_, param1, param2): - arr = _np.array(list_) - - n_arr = arr[param1:param2+1] - - return n_arr - def t_list(elmnt): + """.""" #this condition significates that if the input is only a number, then - #the fucntion transforms it into a list to avoid errors. Actually, I will delete this function - if type(elmnt) == float or type(elmnt) == int: + #the fucntion transforms it into a list to avoid errors. + if isinstance(elmnt,(float,int)): return [elmnt] else: return list(elmnt) def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): + """.""" tau = (_np.tan(kappa)**2)[:, None] - taum = (_np.tan(kappam)**2) + taum = _np.tan(kappam)**2 beta = _beam_rigidity(energy=3)[2] ratio = tau/taum/(1+tau) arg = (2*tau+1)**2 * (ratio - 1)/tau @@ -230,76 +239,8 @@ def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): return arg * bessel -def f_integral_simps_l_mod(taum, b1_, b2_): - kappam = _np.arctan(_np.sqrt(taum)) - _npts = int(9*1000) - dkappa = (_np.pi/2-kappam)/_npts - kappa = _np.linspace(kappam, _np.pi/2, _npts+1) - func = f_function_arg_mod(kappa, kappam, b1_, b2_) - - # Simpson's 3/8 Rule - N must be mod(N, 3) = 0 - val1 = func[0:-1:3, :] + func[3::3, :] - val2 = func[1::3, :] + func[2::3, :] - f_int = 3*dkappa/8*_np.sum(val1 + 3*val2, axis=0) - - # # Simpson's 1/3 Rule - N must be mod(N, 2) = 0 - # val1 = func[0::2, :] + func[2::2, :] - # val2 = func[1::2, :] - # f_int = dkappa/3*_np.sum(val1+4*val2, axis=0) - f_int *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum - return f_int - -def norm_d(acc, lsps, scalc,_npt, norm=True): - - spos = _pyaccel.lattice.find_spos(acc, indices='closed') - beta = _beam_rigidity(energy=3)[2] - ltime = _pyaccel.lifetime.Lifetime(acc) - b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] - - calc_dp, calc_dn = [], [] - deltasp, deltasn = [], [] - indices, indices_model= [], [] - - for _, s in enumerate(lsps): - - idx = _np.argmin(_np.abs(scalc - s)) - indices.append(idx) - idx_model = _np.argmin(_np.abs(spos - s)) - indices_model.append(idx_model) - - kappam_p0 = 0.00001 # teste sugerido pelo ximenes - kappam_n0 = 0.00001 - - kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) - deltap = 1/beta * _np.tan(kappap) - kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) - deltan = 1/beta * _np.tan(kappan) - - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - norm_facp = _scyint.trapz(y_p, deltap) - norm_facn = _scyint.trapz(y_n, deltan) - -# Normalizing to obtain the probability density function - - y_p /= (norm_facp) - y_n /= (norm_facn) - - calc_dp.append(y_p) - calc_dn.append(y_n) - deltasp.append(deltap) - deltasn.append(deltan) - - calc_dp = _np.array(calc_dp) - calc_dn = _np.array(calc_dn) - deltasp = _np.array(deltasp) - deltasn = _np.array(deltasn) - indices = _np.array(indices) - indices_model = _np.array(indices_model) - - return calc_dp, calc_dn, deltasp, deltasn, indices, indices_model - def get_scaccep(acc, accep): + """.""" spos = _pyaccel.lattice.find_spos(acc, indices='closed') npt = int((spos[-1]-spos[0])/0.1) @@ -309,60 +250,12 @@ def get_scaccep(acc, accep): return scalc, daccpp, daccpn -def n_norm_d(acc, lsps, _npt, cutoff, accep, norm=False): - - scalc, daccpp, daccpn = get_scaccep(acc, accep) - beta = _beam_rigidity(energy=3)[2] - - taum_p = (beta*daccpp)**2 - taum_n = (beta*daccpn)**2 - kappam_p = _np.arctan(_np.sqrt(taum_p)) - kappam_n = _np.arctan(_np.sqrt(taum_n)) - - ltime = _pyaccel.lifetime.Lifetime(acc) - b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] - - calc_dp, calc_dn = [], [] - deltasp, deltasn = [], [] - - for _, s in enumerate(lsps): - - idx = _np.argmin(_np.abs(scalc - s)) - - kappam_p0 = kappam_p[idx] - kappam_n0 = kappam_n[idx] - - kappam_p0x = cutoff # teste sugerido pelo Ximenes - kappam_n0x = cutoff - - kappap = _np.linspace(kappam_p0x, _np.pi/2, _npt) - deltap = 1/beta * _np.tan(kappap) - kappan = _np.linspace(kappam_n0x, _np.pi/2, _npt) - deltan = 1/beta * _np.tan(kappan) - - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0x,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - indp = _np.argmin(_np.abs(deltap- 1/beta * _np.tan(kappam_p0))) - indn = _np.argmin(_np.abs(deltan- 1/beta * _np.tan(kappam_n0))) - - calc_dp.append(y_p[indp:]) - calc_dn.append(y_n[indn:]) - deltasp.append(deltap[indp:]) - deltasn.append(deltan[indn:]) - - calc_dp = _np.array(calc_dp, dtype=object) - calc_dn = _np.array(calc_dn, dtype=object) - deltasp = _np.array(deltasp, dtype=object) - deltasn = _np.array(deltasn, dtype=object) - - return calc_dp, calc_dn, deltasp, deltasn - -# Como discutido no dia 23.08.2023 a primeira abordagem para a realizaçao da pesagem vai -# vai ser feita definindo o corte como sendo a aceitancia de energia, isso foi deinido com base -# no cálculo já implementados para o tempo de vida touschek que é coerente com o tempo do SIRIUS -# futuramente isso pode ser alterado e redefinido +# Como discutido no dia 23.08.2023 corte para a definição da densidade +# de espalhamento Touschek ocorre na aceitância de energia para deter +# minado ponto. def norm_cutacp(acc, lsps, _npt, accep, norm=False): + """.""" dic = {} scalc, daccpp, daccpn = get_scaccep(acc, accep) @@ -374,7 +267,8 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): kappam_n = _np.arctan(_np.sqrt(taum_n)) ltime = _pyaccel.lifetime.Lifetime(acc) - b1, b2 = ltime.touschek_data['touschek_coeffs']['b1'],ltime.touschek_data['touschek_coeffs']['b2'] + b1 = ltime.touschek_data['touschek_coeffs']['b1'] + b2 = ltime.touschek_data['touschek_coeffs']['b2'] fdens_p, fdens_n = [], [] deltasp, deltasn = [], [] @@ -390,8 +284,10 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) deltan = 1/beta * _np.tan(kappan) - y_p = f_function_arg_mod(kappa=kappap,kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() - y_n = f_function_arg_mod(kappa=kappan,kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + y_p = f_function_arg_mod(kappa=kappap, + kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + y_n = f_function_arg_mod(kappa=kappan, + kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() norm_facp = _scyint.trapz(y_p, deltap) norm_facn = _scyint.trapz(y_n, deltan) @@ -421,46 +317,8 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): return dic - -def plot_hdis(acc, l_index, deltp, f_densp, deltn, f_densn, hp, hn): - - fig, axis = _plt.subplots(1,l_index.squeeze().size, figsize=(10,6)) - _plt.suptitle('Comparação entre densidade de probabilidade analítica e de M.C.', fontsize=15) - spos = _pyaccel.lattice.find_spos(acc, indices='closed') - nb = int((spos[-1] - spos[0])/0.1) - scalc = _np.linspace(spos[0],spos[-1], nb) - - for c,iten in enumerate(l_index): - ax = axis[c] - - if c == 0: - ax.set_ylabel(r'PDF normalizada', fontsize=15) - - idx = _np.argmin(_np.abs(spos[iten] - scalc)) - - ax.set_title('{}'.format(acc[iten].fam_name)) - ax.plot(deltp[idx], f_densp[idx], color='blue', label='Analytic ({:.2f} [m])'.format(scalc[idx])) - - ax.tick_params(axis='both', labelsize=14) - - ax.hist(hn[idx], density=True, bins=200, color='lightgrey', label='Monte-Carlo') - ax.plot(-deltn[idx], f_densn[idx], color='blue') - # ax.set_yscale('log') - - ax.hist(hp[idx],density=True, bins=200,color='lightgrey') - # ax.set_ylim(1e-1,1e3) - ax.set_xlim(-0.3,0.3) - - ax.set_xlabel(r'$\delta$ [%]', fontsize=15) - ax.legend() - - ax.grid(axis='y', ls='--', alpha=0.5) - # fig.tight_layout() - _plt.show - - return idx - def create_particles(cov_matrix, num_part): + """ Creates the beam to realize the Monte-Carlo simulation """ # permute indices to change the order of the columns: # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T @@ -494,6 +352,7 @@ def create_particles(cov_matrix, num_part): def get_cross_section_distribution(psim, _npts=3000): + """.""" beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) psi = _np.pi/2 - psi @@ -510,12 +369,14 @@ def get_cross_section_distribution(psim, _npts=3000): def cross_section_draw_samples(psim, num_part): + """.""" psi, cross = get_cross_section_distribution(psim) crs = _np.random.rand(num_part) return _np.interp(crs, cross, psi) def scatter_particles(part1, part2, de_min): + """.""" gamma = 3e9 / 0.510e6 beta = _np.sqrt(1 - 1/gamma/gamma) num_part = part1.shape[1] @@ -603,6 +464,7 @@ def scatter_particles(part1, part2, de_min): return part1_new, part2_new, fact def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): + """.""" envelopes = _pyaccel.optics.calc_beamenvelope(acc) spos=_pyaccel.lattice.find_spos(acc, indices='closed') From aedba5d6d8d4c0ec613ec3aaa157ca399d50ca87 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Tue, 5 Dec 2023 12:23:39 -0300 Subject: [PATCH 081/108] =?UTF-8?q?modificando=20a=20principal=20fun=C3=A7?= =?UTF-8?q?=C3=A3o=20para=20otimiza=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 2 +- functions.py | 46 ++++++++++++++++++++++++++-------------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/Classes.py b/Classes.py index eceae205..2e663a46 100644 --- a/Classes.py +++ b/Classes.py @@ -408,7 +408,7 @@ def get_track(self,l_scattered_pos, scrap, vchamber): return all_track, indices def find_data(self, l_scattered_pos, scrap, vchamber): - """obtaining the graphic""" + """Get the data for touschek losses along the ring""" all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) spos = self.spos diff --git a/functions.py b/functions.py index 47c8781f..f3e41238 100644 --- a/functions.py +++ b/functions.py @@ -33,10 +33,10 @@ def calc_amp(acc,energy_offsets, hmax, hmin): pass return _np.sqrt(a_def), indices -def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): +def track_eletrons(model, deltas, n_turn, initial_idx, pos_x=1e-5, pos_y=3e-6): """ This function finds the lost electrons by tracking """ - orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) + orb = _pyaccel.tracking.find_orbit6(model, indices=[0, initial_idx]) orb = orb[:, 1] rin = _np.zeros((6, deltas.size)) @@ -47,22 +47,29 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): track = _pyaccel.tracking.ring_pass( model, rin, nr_turns=n_turn, turn_by_turn=True, - element_offset=element_idx, parallel=True) + element_offset=initial_idx, parallel=True) _, _, turn_lost, element_lost, _ = track # oculted variables/ part_out: final coordinates of electrons # flag: indicates if there is any loss # plane_lost: plane that electron was lost(x or y) - turnl_element = [] + dic_track = {} + t_lost, e_lost, delta = [], [], [] - for i,item in enumerate(turn_lost): - if item == n_turn and element_lost[i] == element_idx: + for idx ,item in enumerate(turn_lost): + if item == n_turn and element_lost[idx] == initial_idx: pass else: - turnl_element.append((item, element_lost[i], deltas[i])) + t_lost.append(item) + e_lost.append(element_lost[idx]) + delta.append(deltas[idx]) - return turnl_element + dic_track['turn_lost'] = t_lost + dic_track['element_lost'] = e_lost + dic_track['en_dev'] = delta + + return dic_track def trackm_elec(acc,deltas, n_turn, lspos): """Run the tracking simulation for a list of s positions """ @@ -114,7 +121,7 @@ def el_idx_collector(acc, lname): return all_index -def plot_track(acc, lista_resul, lista_idx, +def plot_track(acc, tracked, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): """ This function shows the touschek scattering density for s, the number of turns before electron loss and a graphic @@ -126,6 +133,7 @@ def plot_track(acc, lista_resul, lista_idx, # ---------------- cm = 1/2.54 # 'poster' + turn_lost, element_lost, delta = twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax @@ -145,30 +153,28 @@ def plot_track(acc, lista_resul, lista_idx, left=False, right=False, labelleft=False) a1.grid(True, alpha=0.5, ls='--', color='k') - a1.tick_params(axis='both', labelsize=18) + a1.tick_params(axis='y', labelsize=18) a2.grid(True, alpha=0.5, ls='--', color='k') - a2.tick_params(axis='both', labelsize=18) + a2.tick_params(axis='y', labelsize=18) a3.grid(True, alpha=0.5, ls='--', color='k') - a3.tick_params(axis='both', labelsize=18) - a1.xaxis.grid(False) - a2.xaxis.grid(False) - a3.xaxis.grid(False) + a3.tick_params(axis='y', labelsize=18) + _plt.subplots_adjust(wspace=0.1) if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(tracked[1][-1])], tracked[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - for item in lista_resul: + for item in tracked: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(tracked[1][-1])], -tracked[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - for item in lista_resul: + for item in tracked: a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') a1.set_title(r'$\delta \times scat. rate$', fontsize=20) @@ -179,7 +185,7 @@ def plot_track(acc, lista_resul, lista_idx, a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) - for iten in lista_resul: + for iten in tracked: a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') From 70150fd31c520ecdd9b8e7108cebe1b4d9bd2bbb Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Tue, 5 Dec 2023 12:40:23 -0300 Subject: [PATCH 082/108] =?UTF-8?q?mais=20modifica=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/functions.py b/functions.py index f3e41238..b7795320 100644 --- a/functions.py +++ b/functions.py @@ -121,7 +121,7 @@ def el_idx_collector(acc, lname): return all_index -def plot_track(acc, tracked, lista_idx, +def plot_track(acc, dic_track, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): """ This function shows the touschek scattering density for s, the number of turns before electron loss and a graphic @@ -133,7 +133,10 @@ def plot_track(acc, tracked, lista_idx, # ---------------- cm = 1/2.54 # 'poster' - turn_lost, element_lost, delta = + + turn_lost = dic_track['turn_lost'] + element_lost = dic_track['element_lost'] + delta = dic_track['en_dev'] twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax @@ -164,9 +167,12 @@ def plot_track(acc, tracked, lista_idx, if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - a3.plot(spos[int(tracked[1][-1])], tracked[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(element_lost[-1])], + delta[-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) + a3.plot(spos[int(element_lost)], delta*1e2, 'r.') + for item in tracked: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: From 9bf0f42799ca71e284770f86b45af3fa172562cc Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 6 Dec 2023 13:12:20 -0300 Subject: [PATCH 083/108] =?UTF-8?q?adicionando=20mudan=C3=A7as?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/functions.py b/functions.py index b7795320..d29b36fe 100644 --- a/functions.py +++ b/functions.py @@ -124,19 +124,19 @@ def el_idx_collector(acc, lname): def plot_track(acc, dic_track, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): """ This function shows the touschek scattering density for s, - the number of turns before electron loss and a graphic + the number of turns before an electron loss and a graphic containing the magnetic lattice with the lost positions of the electrons obtained by tracking simulation, the limit energy acceptance in a determined point s and the physical limitants calculated by a linear approach of the dependencies - of beta and eta functions""" + of beta and eta functions with the energy deviation.""" # ---------------- - cm = 1/2.54 # 'poster' - + # cm = 1/2.54 # 'poster' + accep_neg, accep_pos = accep[0], accep[1] turn_lost = dic_track['turn_lost'] element_lost = dic_track['element_lost'] - delta = dic_track['en_dev'] + delta = dic_track['en_dev']*1e2 twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax @@ -144,7 +144,8 @@ def plot_track(acc, dic_track, lista_idx, spos = _pyaccel.lattice.find_spos(acc) - fig = _plt.figure(figsize=(38.5*cm,18*cm)) + # fig = _plt.figure(figsize=(38.5*cm,18*cm)) 'poster' + fig = _plt.figure(figsize=(13,7)) gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) a1 = fig.add_subplot(gs[0, 0]) @@ -168,20 +169,18 @@ def plot_track(acc, dic_track, lista_idx, a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) a3.plot(spos[int(element_lost[-1])], - delta[-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[1][element_idx] + delta[-1], 'r.', label='lost pos. (track)') + acp_s = accep_pos[element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) a3.plot(spos[int(element_lost)], delta*1e2, 'r.') - for item in tracked: - a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[int(tracked[1][-1])], -tracked[2][-1]*1e2, 'r.', label='lost pos. (track)') - acp_s = accep[0][element_idx] + a3.plot(spos[int(element_lost[-1])], + -delta[-1], 'r.', label='lost pos. (track)') + acp_s = accep_neg[element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - for item in tracked: - a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + a3.plot(spos[int(element_lost)], -delta*1e2, 'r.') a1.set_title(r'$\delta \times scat. rate$', fontsize=20) a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) @@ -191,8 +190,7 @@ def plot_track(acc, dic_track, lista_idx, a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) - for iten in tracked: - a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') + a2.plot(turn_lost, delta, 'k.') a3.set_title(r'tracking ', fontsize=20) From 8126d8c491385b533aa3b6ae85224179532c21f1 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 7 Dec 2023 13:22:43 -0300 Subject: [PATCH 084/108] =?UTF-8?q?alterando=20bug=20que=20surgiu=20devido?= =?UTF-8?q?=20=C3=A0s=20corre=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Classes.py b/Classes.py index 2e663a46..00d1cb51 100644 --- a/Classes.py +++ b/Classes.py @@ -249,31 +249,34 @@ def fast_aquisition(self, single_spos, par): fp = fdensp.squeeze() fn = fdensn.squeeze() - res = self.return_sinpos_track(single_spos, par) - delta = _np.zeros(len(res)) - - for index, iten in enumerate(res): - _, _, delt = iten - delta[index] = delt + dic_track = self.return_sinpos_track(single_spos, par) + delta = dic_track['en_dev'] delta_ = _np.diff(delta)[0] if 'pos' in par: - return res, fp*delta_, deltp *1e2 + return dic_track, fp*delta_, deltp *1e2 elif 'neg' in par: - return res, fn*delta_, deltn*1e2 + return dic_track, fn*delta_, deltn*1e2 else: - return res, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 + return dic_track, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 # this function plot the graphic of tracking and the touschek scattering # distribution for one single position def plot_analysis_at_position(self, single_spos, par, accep,filename): """.""" - res, fp, dp = self.fast_aquisition(single_spos, par) + dic_track, fp, dp = self.fast_aquisition(single_spos, par) s = self.spos index = _np.argmin(_np.abs(s-single_spos)) - tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), - self.off_energy, par, index, accep, dp, fp, filename) + en = self.off_energy + + if 'pos' in par: + inds = self.inds_pos + elif 'neg' in par: + inds = self.inds_neg + + tousfunc.plot_track(self.accelerator, dic_track, + _np.intp(inds), en , par, index, accep, dp, fp, filename) def plot_normtousd(self, spos, filename): # user must provide a list of s positions """touschek scattering density""" From 66badb804de905147b41bcfa7a95085891b17fd7 Mon Sep 17 00:00:00 2001 From: thaleseqb Date: Mon, 11 Dec 2023 08:40:11 -0300 Subject: [PATCH 085/108] restaurando mu --- Classes.py | 29 ++++++++++------------ functions.py | 68 ++++++++++++++++++++++------------------------------ 2 files changed, 42 insertions(+), 55 deletions(-) diff --git a/Classes.py b/Classes.py index 00d1cb51..eceae205 100644 --- a/Classes.py +++ b/Classes.py @@ -249,34 +249,31 @@ def fast_aquisition(self, single_spos, par): fp = fdensp.squeeze() fn = fdensn.squeeze() - dic_track = self.return_sinpos_track(single_spos, par) + res = self.return_sinpos_track(single_spos, par) + delta = _np.zeros(len(res)) + + for index, iten in enumerate(res): + _, _, delt = iten + delta[index] = delt - delta = dic_track['en_dev'] delta_ = _np.diff(delta)[0] if 'pos' in par: - return dic_track, fp*delta_, deltp *1e2 + return res, fp*delta_, deltp *1e2 elif 'neg' in par: - return dic_track, fn*delta_, deltn*1e2 + return res, fn*delta_, deltn*1e2 else: - return dic_track, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 + return res, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 # this function plot the graphic of tracking and the touschek scattering # distribution for one single position def plot_analysis_at_position(self, single_spos, par, accep,filename): """.""" - dic_track, fp, dp = self.fast_aquisition(single_spos, par) + res, fp, dp = self.fast_aquisition(single_spos, par) s = self.spos index = _np.argmin(_np.abs(s-single_spos)) - en = self.off_energy - - if 'pos' in par: - inds = self.inds_pos - elif 'neg' in par: - inds = self.inds_neg - - tousfunc.plot_track(self.accelerator, dic_track, - _np.intp(inds), en , par, index, accep, dp, fp, filename) + tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), + self.off_energy, par, index, accep, dp, fp, filename) def plot_normtousd(self, spos, filename): # user must provide a list of s positions """touschek scattering density""" @@ -411,7 +408,7 @@ def get_track(self,l_scattered_pos, scrap, vchamber): return all_track, indices def find_data(self, l_scattered_pos, scrap, vchamber): - """Get the data for touschek losses along the ring""" + """obtaining the graphic""" all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) spos = self.spos diff --git a/functions.py b/functions.py index d29b36fe..47c8781f 100644 --- a/functions.py +++ b/functions.py @@ -33,10 +33,10 @@ def calc_amp(acc,energy_offsets, hmax, hmin): pass return _np.sqrt(a_def), indices -def track_eletrons(model, deltas, n_turn, initial_idx, pos_x=1e-5, pos_y=3e-6): +def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): """ This function finds the lost electrons by tracking """ - orb = _pyaccel.tracking.find_orbit6(model, indices=[0, initial_idx]) + orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] rin = _np.zeros((6, deltas.size)) @@ -47,29 +47,22 @@ def track_eletrons(model, deltas, n_turn, initial_idx, pos_x=1e-5, pos_y=3e-6): track = _pyaccel.tracking.ring_pass( model, rin, nr_turns=n_turn, turn_by_turn=True, - element_offset=initial_idx, parallel=True) + element_offset=element_idx, parallel=True) _, _, turn_lost, element_lost, _ = track # oculted variables/ part_out: final coordinates of electrons # flag: indicates if there is any loss # plane_lost: plane that electron was lost(x or y) - dic_track = {} - t_lost, e_lost, delta = [], [], [] + turnl_element = [] - for idx ,item in enumerate(turn_lost): - if item == n_turn and element_lost[idx] == initial_idx: + for i,item in enumerate(turn_lost): + if item == n_turn and element_lost[i] == element_idx: pass else: - t_lost.append(item) - e_lost.append(element_lost[idx]) - delta.append(deltas[idx]) + turnl_element.append((item, element_lost[i], deltas[i])) - dic_track['turn_lost'] = t_lost - dic_track['element_lost'] = e_lost - dic_track['en_dev'] = delta - - return dic_track + return turnl_element def trackm_elec(acc,deltas, n_turn, lspos): """Run the tracking simulation for a list of s positions """ @@ -121,22 +114,18 @@ def el_idx_collector(acc, lname): return all_index -def plot_track(acc, dic_track, lista_idx, +def plot_track(acc, lista_resul, lista_idx, lista_off, param, element_idx, accep, delt, f_dens, filename): """ This function shows the touschek scattering density for s, - the number of turns before an electron loss and a graphic + the number of turns before electron loss and a graphic containing the magnetic lattice with the lost positions of the electrons obtained by tracking simulation, the limit energy acceptance in a determined point s and the physical limitants calculated by a linear approach of the dependencies - of beta and eta functions with the energy deviation.""" + of beta and eta functions""" # ---------------- - # cm = 1/2.54 # 'poster' - accep_neg, accep_pos = accep[0], accep[1] - turn_lost = dic_track['turn_lost'] - element_lost = dic_track['element_lost'] - delta = dic_track['en_dev']*1e2 + cm = 1/2.54 # 'poster' twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') betax = twi0.betax @@ -144,8 +133,7 @@ def plot_track(acc, dic_track, lista_idx, spos = _pyaccel.lattice.find_spos(acc) - # fig = _plt.figure(figsize=(38.5*cm,18*cm)) 'poster' - fig = _plt.figure(figsize=(13,7)) + fig = _plt.figure(figsize=(38.5*cm,18*cm)) gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) a1 = fig.add_subplot(gs[0, 0]) @@ -157,30 +145,31 @@ def plot_track(acc, dic_track, lista_idx, left=False, right=False, labelleft=False) a1.grid(True, alpha=0.5, ls='--', color='k') - a1.tick_params(axis='y', labelsize=18) + a1.tick_params(axis='both', labelsize=18) a2.grid(True, alpha=0.5, ls='--', color='k') - a2.tick_params(axis='y', labelsize=18) + a2.tick_params(axis='both', labelsize=18) a3.grid(True, alpha=0.5, ls='--', color='k') - a3.tick_params(axis='y', labelsize=18) - + a3.tick_params(axis='both', labelsize=18) + a1.xaxis.grid(False) + a2.xaxis.grid(False) + a3.xaxis.grid(False) _plt.subplots_adjust(wspace=0.1) if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - a3.plot(spos[int(element_lost[-1])], - delta[-1], 'r.', label='lost pos. (track)') - acp_s = accep_pos[element_idx] + a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[int(element_lost)], delta*1e2, 'r.') - + for item in lista_resul: + a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[int(element_lost[-1])], - -delta[-1], 'r.', label='lost pos. (track)') - acp_s = accep_neg[element_idx] + a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[int(element_lost)], -delta*1e2, 'r.') + for item in lista_resul: + a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') a1.set_title(r'$\delta \times scat. rate$', fontsize=20) a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) @@ -190,7 +179,8 @@ def plot_track(acc, dic_track, lista_idx, a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) - a2.plot(turn_lost, delta, 'k.') + for iten in lista_resul: + a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') a3.set_title(r'tracking ', fontsize=20) From 110a41bc4e24f9b8bbff653d872b27b076dd0da4 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Dec 2023 12:45:48 -0300 Subject: [PATCH 086/108] adicionando doc strings e simplificando o codigo --- Classes.py | 148 ++++++++++++++++++++++++--------------------------- functions.py | 33 ++++++------ 2 files changed, 88 insertions(+), 93 deletions(-) diff --git a/Classes.py b/Classes.py index eceae205..6dc6b31e 100644 --- a/Classes.py +++ b/Classes.py @@ -13,7 +13,7 @@ import pyaccel as _pyaccel class Tous_analysis(): - """Class for related with Touschek loss rate along the ring.""" + """Class for the analyses of electron losses along the ring""" def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): @@ -42,10 +42,7 @@ def __init__(self, accelerator, self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') self.ltime = Lifetime(self._model_fit) - # self._lname = ['BC', 'Q1', 'SDA0'] # it can be modified as the users - #desires - self._off_energy = energy_off # (linear model) en_dev to - # amplitudes + self._off_energy = energy_off # (linear model) en_dev to amplitudes self.nturns = n_turns self._deltas = deltas self.spos = find_spos(self._model_fit, indices='closed') @@ -54,46 +51,53 @@ def __init__(self, accelerator, @property def accelerator(self): - """.""" + """Recieves fitted accelerator model""" return self._model_fit @accelerator.setter def accelerator(self, new_model): + """If requeried to change the accelerator model""" self._model_fit = new_model @property def nom_model(self): - """.""" + """Some calculus involves nominal model without coupling + and vertical dispersion corretion""" return self._model @property def accep(self): - """.""" + """Defines Touschek energy acceptance""" if self._accep is None: self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) return self._accep - # Defining the s position, positive and negative accptances along the ring at each 10 meters. - # the description above is actually the returns of the function @property def s_calc(self): - """.""" + """Defines s position and get the + energy accpetance both at each 10 + meters""" if self._sc_accps is None: self._sc_accps = tousfunc.get_scaccep(self.accelerator, self.accep) return self._sc_accps - # This property calculates the physical limitants by the prediction of the linear model @property def amp_and_limidx(self): - """.""" + """Defines 4 properties: + Positive and negative amplitudes + Indices where positive and nega- + tive amp(energy deviation depen- + dence) are minimum + """ if self._amp_and_limidx is None: - self.nom_model.cavity_on = False # this step is necessary to define if the - self.nom_model.radiation_on = False + self._model.cavity_on = False + self._model.radiation_on = False + self._amps_pos, self._inds_pos = tousfunc.calc_amp( - self.nom_model,self.off_energy, self.h_pos, self.h_neg) + self._model,self.off_energy, self.h_pos, self.h_neg) self._amps_neg, self._inds_neg = tousfunc.calc_amp( - self.nom_model,-self.off_energy, self.h_pos, self.h_neg) + self._model,-self.off_energy, self.h_pos, self.h_neg) self._amp_and_limidx = True @@ -104,10 +108,10 @@ def off_energy(self): """.""" return self._off_energy - # the cutoff for energy deviation is the energy acceptance limit @off_energy.setter - def off_energy(self, accep): # pass a new energy acceptance tuple of arrays if the user desire - """.""" + def off_energy(self, accep): + """the cutoff for energy deviation is the energy acceptance limit/ + pass a new energy acceptance tuple of arrays""" accep_pos, accep_neg = accep accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) steps = int(accep_lim*10000) # choosen to be the number of steps @@ -119,22 +123,12 @@ def deltas(self): return self._deltas @deltas.setter - def deltas(self, dev_percent,steps=400): # dev_percent input-> [%] + def deltas(self, dev_percent,steps=400): + """dev_percent is energy deviation in percents [%] + If the user desires to change the sample of energy + deviation""" dev_percent /= 100 - self._deltas = _np.linspace(0,dev_percent, steps) # if the user - # desires to make a change in the quantity of energ. dev. in tracking - # simulation - - @property - def lname(self): - """.""" - return self._lname - - @lname.setter - def lname(self, call_lname): # input: list of element names - # used in tracking to define the elements' list - """.""" - self._lname = call_lname + self._deltas = _np.linspace(0,dev_percent, steps) # the four properties defining below are to be static @property @@ -149,20 +143,20 @@ def inds_neg(self): @property def amp_pos(self): - '''positive amplitudes from linear model''' + '''.''' return self._amps_pos @property # negative amplitudes from linear model def amp_neg(self): - """negative amplitudes from linear model""" + """.""" return self._amps_neg def get_amps_idxs(self): # Defines various parameters - """.""" + """Defines 3 self params at same time""" return self.amp_and_limidx, self.accep, self.s_calc def set_vchamber_scraper(self, vchamber): - """.""" + """Function for setting the vchamber apperture""" model = self._model scph_inds = self.scraph_inds scpv_inds = self.scrapv_inds @@ -175,7 +169,7 @@ def set_vchamber_scraper(self, vchamber): model[iten].vmax = vchamber[3] def return_sinpos_track(self,single_spos, par): - """.""" + """Single position tracking""" self._model.cavity_on = True self._model.radiation_on = True @@ -184,13 +178,11 @@ def return_sinpos_track(self,single_spos, par): index = _np.argmin(_np.abs(s-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons( - self.deltas,self.nturns,index, - self.nom_model, pos_x=1e-5, pos_y=3e-6) + res = tousfunc.track_eletrons(self.deltas,self.nturns,index, + self._model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: - res = tousfunc.track_eletrons( - -self.deltas,self.nturns,index, - self.nom_model, pos_x=1e-5, pos_y=3e-6) + res = tousfunc.track_eletrons(-self.deltas,self.nturns,index, + self._model, pos_x=1e-5, pos_y=3e-6) return res @@ -215,32 +207,31 @@ def get_weighting_tous(self, single_spos, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf - getdp = tousfunc.f_function_arg_mod( + fdensp = tousfunc.f_function_arg_mod( kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) - getdn = tousfunc.f_function_arg_mod( + fdensn = tousfunc.f_function_arg_mod( kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # eliminating negative values - indp = _np.where(getdp<0)[0] - indn = _np.where(getdn<0)[0] - getdp[indp] = 0 - getdn[indn] = 0 + indp = _np.where(fdensp<0)[0] + indn = _np.where(fdensn<0)[0] + fdensp[indp] = 0 + fdensn[indn] = 0 - ind = _np.intp(_np.where(getdp>1e-2)[0]) - getdp = getdp[ind] + ind = _np.intp(_np.where(fdensp>1e-2)[0]) + fdensp = fdensp[ind] deltp = deltp[ind] - ind = _np.intp(_np.where(getdn>1e-2)[0]) - getdn = getdn[ind] + ind = _np.intp(_np.where(fdensn>1e-2)[0]) + fdensn = fdensn[ind] deltn = deltn[ind] self.deltas = deltp[-1]*1e2 - return getdp, getdn, deltp, deltn + return fdensp, fdensn, deltp, deltn def fast_aquisition(self, single_spos, par): - # this raise blocks to runing the program if the list of s position has more than 1 element - """.""" + """""" if len(tousfunc.t_list(single_spos)) != 1: raise ValueError('This function suports only one s position') @@ -268,15 +259,18 @@ def fast_aquisition(self, single_spos, par): # this function plot the graphic of tracking and the touschek scattering # distribution for one single position def plot_analysis_at_position(self, single_spos, par, accep,filename): - """.""" + """Plot the graphic of the positions electrons are lost + the number of turns electrons realize before the loss, + and the touschek loss density.""" res, fp, dp = self.fast_aquisition(single_spos, par) s = self.spos index = _np.argmin(_np.abs(s-single_spos)) tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), self.off_energy, par, index, accep, dp, fp, filename) - def plot_normtousd(self, spos, filename): # user must provide a list of s positions - """touschek scattering density""" + def plot_normtousd(self, spos, filename): + """User must provide a list of s positions to + calculate the loss density for each point""" spos_ring = self.spos dic = tousfunc.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) @@ -414,23 +408,20 @@ def find_data(self, l_scattered_pos, scrap, vchamber): spos = self.spos fact = 0.03 + # toushcek scattering rate tous_rate = self.ltime.touschek_data['rate'] + prob, lostp, all_lostp = [], [], [] - prob = [] - lostp = [] - all_lostp = [] - - for j, iten in enumerate(all_track): + for j, single_track in enumerate(all_track): index = indices[j] # scattered_pos = l_scattered_pos[j] lostinds, deltas = _np.zeros(len(iten)), _np.zeros(len(iten)) - for idx,iten in enumerate(iten): + for idx,iten in enumerate(single_track): _, ellost, delta = iten lostinds[idx] = ellost - deltas[idx] = delta # alguns elétrons possuem desvio de - # energia abaixo da aceitancia e acabam não sendo perdidos + deltas[idx] = delta lostinds = _np.intp(lostinds) lost_positions = _np.round(spos[lostinds], 2) @@ -445,9 +436,6 @@ def find_data(self, l_scattered_pos, scrap, vchamber): data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) # this step agroups the lost_positions - # scat_lost_df = pd.DataFrame(f'{s}':) # dataframe will contain - # the scattered positions and the lost positions after scattering - itv_delta = [] for current, next_iten in zip(itv_track, itv_track[1:]): stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' @@ -459,8 +447,7 @@ def find_data(self, l_scattered_pos, scrap, vchamber): # dataframe var = list(data.index) - # quando as duas variáveis são iguais isso acab resultando em um - # erro então estou colocando essa condição. + # if var == lost_pos_column: pass else: @@ -474,7 +461,7 @@ def find_data(self, l_scattered_pos, scrap, vchamber): delta = deltas[idx] # lps = [] for i, interval in enumerate(itv_delta): - if i == 0: + if not i: # subtle difference: <= in first iteraction if interval[0]<= delta <= interval[1]: stri = \ f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' @@ -495,20 +482,27 @@ def find_data(self, l_scattered_pos, scrap, vchamber): lost_pos_df = [] part_prob = [] + # Calculates the loss probablity by tracking for indx, iten in data.iterrows(): t_prob = 0 for idx, m in enumerate(iten): t_prob += m if idx == iten.count()-1: + # appends the probability after sum part_prob.append(t_prob) lost_pos_df.append(indx) lost_pos_df = _np.array(lost_pos_df) part_prob = _np.array(part_prob) + # Calculates the absolute probability for electron loss + # by touschek scattering rate prob.append(part_prob * rate_nom_lattice[index]) lostp.append(lost_pos_df) + # Aqui eu pego as posições em que os elétrons foram perdidos + # e armazeno todas em uma grande lista sem repetição de qualquer + # posição perdida if not j: all_lostp = lost_pos_df else: @@ -521,7 +515,7 @@ def find_data(self, l_scattered_pos, scrap, vchamber): # dataframe = _pd.DataFrame(dic_res) def get_table(self,l_scattered_pos, scrap, vchamber): - """This is the heatmap """ + """Generates the heat map of loss positions""" dic_res = {} all_lostp, prob, lostp = self.find_data(l_scattered_pos, scrap, vchamber) diff --git a/functions.py b/functions.py index 47c8781f..5d8425c8 100644 --- a/functions.py +++ b/functions.py @@ -158,14 +158,16 @@ def plot_track(acc, lista_resul, lista_idx, if 'pos' in param: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(lista_resul[1][-1])], + lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') elif'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[int(lista_resul[1][-1])], -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[int(lista_resul[1][-1])], + -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) for item in lista_resul: @@ -318,7 +320,7 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): return dic def create_particles(cov_matrix, num_part): - """ Creates the beam to realize the Monte-Carlo simulation """ + """ Creates the beam to realize the Monte-Carlo simulation""" # permute indices to change the order of the columns: # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T @@ -334,8 +336,9 @@ def create_particles(cov_matrix, num_part): sig_yy = cov_matrix[3:, 3:] inv_yy = _np.linalg.inv(sig_yy) - part1 = _np.random.multivariate_normal(_np.zeros(6), cov_matrix, num_part).T - # changing the matrices' columns order + part1 = _np.random.multivariate_normal(_np.zeros(6), + cov_matrix, num_part).T + part2 = part1.copy() vec_a = part2[3:] @@ -350,9 +353,8 @@ def create_particles(cov_matrix, num_part): return part1, part2 - def get_cross_section_distribution(psim, _npts=3000): - """.""" + """Calculates the Moller's cross section""" beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) psi = _np.pi/2 - psi @@ -369,14 +371,15 @@ def get_cross_section_distribution(psim, _npts=3000): def cross_section_draw_samples(psim, num_part): - """.""" + """Introduces the effect of the moller's cross section + in the M.C. simulation""" psi, cross = get_cross_section_distribution(psim) crs = _np.random.rand(num_part) return _np.interp(crs, cross, psi) def scatter_particles(part1, part2, de_min): - """.""" + """M.C. simulation of a Touschek scattering process""" gamma = 3e9 / 0.510e6 beta = _np.sqrt(1 - 1/gamma/gamma) num_part = part1.shape[1] @@ -464,11 +467,11 @@ def scatter_particles(part1, part2, de_min): return part1_new, part2_new, fact def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): - """.""" + """Calculates the touschek scattering densities for an array + of s positions""" envelopes = _pyaccel.optics.calc_beamenvelope(acc) spos=_pyaccel.lattice.find_spos(acc, indices='closed') - scalc, daccpp, daccpn = get_scaccep(acc, accep) histsp1, histsp2, indices=[],[],[] @@ -487,7 +490,7 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): part1, part2 = create_particles(env, num_part) part1_new, part2_new, _ = scatter_particles(part1, part2, de_min) - if cutaccep: # if True selects the energy acceptance as the cutoof of the graphic + if cutaccep: # if true the cutoff is the accp at the s acpp, acpn = daccpp[idx], daccpn[idx] check1 = acpp - part1_new[4] @@ -499,15 +502,13 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - else: - ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) # teste sugerido pelo ximenes + else: # ximenes cutoff + ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) ind2 = _np.intp(_np.where(part2_new[4]<=-0.01)[0]) histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - # hist1=_np.array(histsp1, dtype='object') - # hist2=_np.array(histsp2, dtype='object') indices=_np.array(indices) return histsp1, histsp2, indices From 1348d7ffae4f9ce27e38a9f9854371f3eefdbae1 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Dec 2023 12:48:24 -0300 Subject: [PATCH 087/108] simplificando ainda mais --- Classes.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/Classes.py b/Classes.py index 6dc6b31e..7256542d 100644 --- a/Classes.py +++ b/Classes.py @@ -632,28 +632,6 @@ def plot_scat_table(self, new_dic): """ Heatmap plot indicating the heat points of loss along the ring """ s = self.spos - # new_dic = self.get_reordered_dict(l_scattered_pos, 'lost_positions') - - # if len(l_scattered_pos)%2 == 0: - # array = _np.arange(l_scattered_pos.size) - # j = _np.intp(_np.where(array == int((len(l_scattered_pos)/2 + 1)))[0]) - # array_j = l_scattered_pos[j] - # index = _np.argmin(_np.abs(spos-array_j)) - - # lists = list(find_dict(self._model_fit, 'fam_name').values()) - - # else: - # array = _np.arange(l_scattered_pos.size) - # j = _np.where(array == int((len(l_scattered_pos)+1)/2))[0] - # array_j = l_scattered_pos[j] - # index = _np.argmin(_np.abs(spos-array_j)) - - # lists = list(find_dict(self._model_fit, 'fam_name').values()) - - # for i, l in enumerate(lists): - # if _np.isin(index, l).item(): - # fam_name = list(find_dict(self._model_fit, 'fam_name').keys())[i] - df = _pd.DataFrame(new_dic) df = df.set_index('lost_positions') From f023a4062072a495b08514384c4783e56095f819 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Dec 2023 12:52:56 -0300 Subject: [PATCH 088/108] alterando doc string --- Classes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Classes.py b/Classes.py index 7256542d..a4faa6fa 100644 --- a/Classes.py +++ b/Classes.py @@ -231,7 +231,8 @@ def get_weighting_tous(self, single_spos, npt=5000): return fdensp, fdensn, deltp, deltn def fast_aquisition(self, single_spos, par): - """""" + """get the tracked loss positions, number of turns and + the touschek loss density""" if len(tousfunc.t_list(single_spos)) != 1: raise ValueError('This function suports only one s position') @@ -629,7 +630,7 @@ def get_loss_profilel(self, l_dic): def plot_scat_table(self, new_dic): - """ Heatmap plot indicating the heat points of loss along the ring """ + """ Heatmap plot indicating the warm points of loss along the ring """ s = self.spos df = _pd.DataFrame(new_dic) From c4e454d954890e636c2cf0399c4a1e4375e1247f Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 13 Dec 2023 14:26:42 -0300 Subject: [PATCH 089/108] =?UTF-8?q?consertando=20erros=20na=20fun=C3=A7?= =?UTF-8?q?=C3=A3o=20que=20junta=20os=20gr=C3=A1ficos=20de=20densidade=20e?= =?UTF-8?q?=20tracking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 53 ++++++++++++++++++++++++++++------------------------ functions.py | 15 ++++++++++----- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/Classes.py b/Classes.py index a4faa6fa..c189d0b9 100644 --- a/Classes.py +++ b/Classes.py @@ -1,7 +1,7 @@ """tous_analysis.""" from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute, find_indices, find_spos -import touschek_pack.functions as tousfunc +import touschek_pack.functions as to_fu import pymodels import pyaccel.optics as py_op import numpy as _np @@ -13,7 +13,7 @@ import pyaccel as _pyaccel class Tous_analysis(): - """Class for the analyses of electron losses along the ring""" + """Class for the analysis of electron losses along the ring""" def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): @@ -78,7 +78,7 @@ def s_calc(self): energy accpetance both at each 10 meters""" if self._sc_accps is None: - self._sc_accps = tousfunc.get_scaccep(self.accelerator, self.accep) + self._sc_accps = to_fu.get_scaccep(self.accelerator, self.accep) return self._sc_accps @property @@ -93,10 +93,10 @@ def amp_and_limidx(self): self._model.cavity_on = False self._model.radiation_on = False - self._amps_pos, self._inds_pos = tousfunc.calc_amp( + self._amps_pos, self._inds_pos = to_fu.calc_amp( self._model,self.off_energy, self.h_pos, self.h_neg) - self._amps_neg, self._inds_neg = tousfunc.calc_amp( + self._amps_neg, self._inds_neg = to_fu.calc_amp( self._model,-self.off_energy, self.h_pos, self.h_neg) self._amp_and_limidx = True @@ -168,7 +168,7 @@ def set_vchamber_scraper(self, vchamber): model[iten].vmin = vchamber[2] model[iten].vmax = vchamber[3] - def return_sinpos_track(self,single_spos, par): + def single_pos_track(self,single_spos, par): """Single position tracking""" self._model.cavity_on = True @@ -178,10 +178,10 @@ def return_sinpos_track(self,single_spos, par): index = _np.argmin(_np.abs(s-single_spos)) if 'pos' in par: - res = tousfunc.track_eletrons(self.deltas,self.nturns,index, + res = to_fu.track_eletrons(self.deltas,self.nturns,index, self._model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: - res = tousfunc.track_eletrons(-self.deltas,self.nturns,index, + res = to_fu.track_eletrons(-self.deltas,self.nturns,index, self._model, pos_x=1e-5, pos_y=3e-6) return res @@ -189,7 +189,7 @@ def return_sinpos_track(self,single_spos, par): def get_weighting_tous(self, single_spos, npt=5000): """.""" - scalc, daccp, daccn = tousfunc.get_scaccep( + scalc, daccp, daccn = to_fu.get_scaccep( self.accelerator, self.accep) bf = self.beta # bf:beta factor lt = self.ltime @@ -207,10 +207,10 @@ def get_weighting_tous(self, single_spos, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf - fdensp = tousfunc.f_function_arg_mod( + fdensp = to_fu.f_function_arg_mod( kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) - fdensn = tousfunc.f_function_arg_mod( + fdensn = to_fu.f_function_arg_mod( kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) # eliminating negative values @@ -230,10 +230,10 @@ def get_weighting_tous(self, single_spos, npt=5000): return fdensp, fdensn, deltp, deltn - def fast_aquisition(self, single_spos, par): + def get_trackndens(self, single_spos, par): """get the tracked loss positions, number of turns and the touschek loss density""" - if len(tousfunc.t_list(single_spos)) != 1: + if len(to_fu.t_list(single_spos)) != 1: raise ValueError('This function suports only one s position') fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) @@ -241,39 +241,44 @@ def fast_aquisition(self, single_spos, par): fp = fdensp.squeeze() fn = fdensn.squeeze() - res = self.return_sinpos_track(single_spos, par) + res = self.single_pos_track(single_spos, par) delta = _np.zeros(len(res)) for index, iten in enumerate(res): _, _, delt = iten delta[index] = delt - delta_ = _np.diff(delta)[0] + delta_ = _np.abs(_np.diff(delta)[0]) if 'pos' in par: return res, fp*delta_, deltp *1e2 elif 'neg' in par: - return res, fn*delta_, deltn*1e2 + return res, fn*delta_, -deltn*1e2 else: - return res, fp*delta_, fn*delta_, deltp*1e2, deltn*1e2 + return res, fp*delta_, fn*delta_, deltp*1e2, -deltn*1e2 # this function plot the graphic of tracking and the touschek scattering # distribution for one single position - def plot_analysis_at_position(self, single_spos, par, accep,filename): + def plot_track_tousdens(self, single_spos, par, accep,filename): """Plot the graphic of the positions electrons are lost the number of turns electrons realize before the loss, and the touschek loss density.""" - res, fp, dp = self.fast_aquisition(single_spos, par) + res, fp, dp = self.get_trackndens(single_spos, par) s = self.spos + + if 'pos' in par: + inds = _np.intp(self.inds_pos) + elif 'neg' in par: + inds = _np.intp(self.inds_neg) index = _np.argmin(_np.abs(s-single_spos)) - tousfunc.plot_track(self.accelerator, res, _np.intp(self.inds_pos), - self.off_energy, par, index, accep, dp, fp, filename) + to_fu.plot_track(self.accelerator, res, inds, + self.off_energy, par, index, accep, dp, fp,filename) def plot_normtousd(self, spos, filename): """User must provide a list of s positions to calculate the loss density for each point""" spos_ring = self.spos - dic = tousfunc.norm_cutacp(self._model_fit, + dic = to_fu.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) fdensp, fdensn = dic['fdensp'], dic['fdensn'] @@ -338,7 +343,7 @@ def plot_histograms(self, l_spos): accep = self.accep model = self._model_fit - tup = tousfunc.histgms(self._model_fit, l_spos, self.num_part, accep, + tup = to_fu.histgms(self._model_fit, l_spos, self.num_part, accep, self.energy_dev_min,cutaccep=False) hp, hn, idx_model = tup @@ -389,7 +394,7 @@ def get_track(self,l_scattered_pos, scrap, vchamber): index = _np.argmin(_np.abs(scattered_pos-spos)) indices.append(index) - res = tousfunc.track_eletrons(self._deltas, self.nturns, index, self._model) + res = to_fu.track_eletrons(self._deltas, self.nturns, index, self._model) all_track.append(res) hx = self._model_fit[self.scraph_inds[0]].hmax diff --git a/functions.py b/functions.py index 5d8425c8..9d10c6be 100644 --- a/functions.py +++ b/functions.py @@ -162,23 +162,26 @@ def plot_track(acc, lista_resul, lista_idx, lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) + a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', + label=r'accep. limit', alpha=0.25) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') - elif'neg' in param: + elif 'neg' in param: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], - -lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) + a3.plot(spos[lista_idx][indx:], -lista_off[indx:]*1e2,'b.', + label=r'accep. limit', alpha=0.25) for item in lista_resul: - a3.plot(spos[int(item[1])], -item[2]*1e2, 'r.') + a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') a1.set_title(r'$\delta \times scat. rate$', fontsize=20) a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) for iten in lista_resul: @@ -186,7 +189,9 @@ def plot_track(acc, lista_resul, lista_idx, a3.set_title(r'tracking ', fontsize=20) - a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', label=r'accep. limit', alpha=0.25) + # plot the physical limitant untill the acceptance limit + # a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', + # label=r'accep. limit', alpha=0.25) _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) From 7de5f829751aa20917d0575ddaab54710f25acea Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 14 Dec 2023 09:14:39 -0300 Subject: [PATCH 090/108] =?UTF-8?q?altera=C3=A7=C3=B5es=20segundo=20ruff?= =?UTF-8?q?=20e=20corre=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Classes.py | 164 +++++++++++++++++++++++++-------------------------- functions.py | 35 ++++++----- 2 files changed, 96 insertions(+), 103 deletions(-) diff --git a/Classes.py b/Classes.py index c189d0b9..1470257b 100644 --- a/Classes.py +++ b/Classes.py @@ -19,10 +19,10 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): """.""" if energies_off is None: - energy_off = _np.linspace(0,0.046, 460) # physical limitants - deltas = _np.linspace(0,0.1,400) # energy off for tracking + energy_off = _np.linspace(0, 0.046, 460) # physical limitants + deltas = _np.linspace(0, 0.1, 400) # energy off for tracking - if beam_energy is None: # defining beta factor + if beam_energy is None: # defining beta factor beta = _beam_rigidity(energy=3)[2] self._model_fit = accelerator @@ -38,11 +38,11 @@ def __init__(self, accelerator, self.num_part = 50000 self.energy_dev_min = 1e-4 - self.beta = beta # beta factor + self.beta = beta # beta factor self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') self.ltime = Lifetime(self._model_fit) - self._off_energy = energy_off # (linear model) en_dev to amplitudes + self._off_energy = energy_off # (linear model) en_dev to amplitudes self.nturns = n_turns self._deltas = deltas self.spos = find_spos(self._model_fit, indices='closed') @@ -69,7 +69,8 @@ def nom_model(self): def accep(self): """Defines Touschek energy acceptance""" if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) + self._accep = py_op.calc_touschek_energy_acceptance( + self.accelerator) return self._accep @property @@ -94,12 +95,12 @@ def amp_and_limidx(self): self._model.radiation_on = False self._amps_pos, self._inds_pos = to_fu.calc_amp( - self._model,self.off_energy, self.h_pos, self.h_neg) + self._model, self.off_energy, self.h_pos, self.h_neg) self._amps_neg, self._inds_neg = to_fu.calc_amp( - self._model,-self.off_energy, self.h_pos, self.h_neg) + self._model, -self.off_energy, self.h_pos, self.h_neg) - self._amp_and_limidx = True + self._amp_and_limidx = True return self._amp_and_limidx @@ -114,7 +115,7 @@ def off_energy(self, accep): pass a new energy acceptance tuple of arrays""" accep_pos, accep_neg = accep accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) - steps = int(accep_lim*10000) # choosen to be the number of steps + steps = int(accep_lim*10000) # choosen to be the number of steps self._off_energy = _np.linspace(0, accep_lim, steps) @property @@ -128,7 +129,7 @@ def deltas(self, dev_percent,steps=400): If the user desires to change the sample of energy deviation""" dev_percent /= 100 - self._deltas = _np.linspace(0,dev_percent, steps) + self._deltas = _np.linspace(0, dev_percent, steps) # the four properties defining below are to be static @property @@ -143,15 +144,15 @@ def inds_neg(self): @property def amp_pos(self): - '''.''' + """.""" return self._amps_pos - @property # negative amplitudes from linear model + @property # negative amplitudes from linear model def amp_neg(self): """.""" return self._amps_neg - def get_amps_idxs(self): # Defines various parameters + def get_amps_idxs(self): # Defines various parameters """Defines 3 self params at same time""" return self.amp_and_limidx, self.accep, self.s_calc @@ -168,7 +169,7 @@ def set_vchamber_scraper(self, vchamber): model[iten].vmin = vchamber[2] model[iten].vmax = vchamber[3] - def single_pos_track(self,single_spos, par): + def single_pos_track(self, single_spos, par): """Single position tracking""" self._model.cavity_on = True @@ -178,20 +179,19 @@ def single_pos_track(self,single_spos, par): index = _np.argmin(_np.abs(s-single_spos)) if 'pos' in par: - res = to_fu.track_eletrons(self.deltas,self.nturns,index, + res = to_fu.track_eletrons(self.deltas, self.nturns, index, self._model, pos_x=1e-5, pos_y=3e-6) elif 'neg' in par: - res = to_fu.track_eletrons(-self.deltas,self.nturns,index, + res = to_fu.track_eletrons(-self.deltas, self.nturns, index, self._model, pos_x=1e-5, pos_y=3e-6) return res def get_weighting_tous(self, single_spos, npt=5000): """.""" - - scalc, daccp, daccn = to_fu.get_scaccep( + scalc, daccp, daccn = to_fu.get_scaccep( self.accelerator, self.accep) - bf = self.beta # bf:beta factor + bf = self.beta # bf:beta factor lt = self.ltime b1 = lt.touschek_data['touschek_coeffs']['b1'] b2 = lt.touschek_data['touschek_coeffs']['b2'] @@ -199,8 +199,8 @@ def get_weighting_tous(self, single_spos, npt=5000): taup, taun = (bf* daccp)**2, (bf*daccn)**2 idx = _np.argmin(_np.abs(scalc-single_spos)) taup_0, taun_0 = taup[idx], taun[idx] - kappap_0 = _np.arctan(_np.sqrt(taup_0)) - kappan_0 = _np.arctan(_np.sqrt(taun_0)) + kappap_0 = _np.arctan(_np.sqrt(taup_0)) + kappan_0 = _np.arctan(_np.sqrt(taun_0)) kappa_pos = _np.linspace(kappap_0, _np.pi/2, npt) kappa_neg = _np.linspace(kappan_0, _np.pi/2, npt) @@ -208,21 +208,21 @@ def get_weighting_tous(self, single_spos, npt=5000): deltp = _np.tan(kappa_pos)/bf deltn = _np.tan(kappa_neg)/bf fdensp = to_fu.f_function_arg_mod( - kappa_pos, kappap_0, b1[idx], b2[idx],norm=False) + kappa_pos, kappap_0, b1[idx], b2[idx], norm=False) fdensn = to_fu.f_function_arg_mod( - kappa_neg, kappan_0, b1[idx], b2[idx],norm=False) + kappa_neg, kappan_0, b1[idx], b2[idx], norm=False) # eliminating negative values - indp = _np.where(fdensp<0)[0] - indn = _np.where(fdensn<0)[0] + indp = _np.where(fdensp < 0)[0] + indn = _np.where(fdensn < 0)[0] fdensp[indp] = 0 fdensn[indn] = 0 - ind = _np.intp(_np.where(fdensp>1e-2)[0]) + ind = _np.intp(_np.where(fdensp > 1e-2)[0]) fdensp = fdensp[ind] deltp = deltp[ind] - ind = _np.intp(_np.where(fdensn>1e-2)[0]) + ind = _np.intp(_np.where(fdensn > 1e-2)[0]) fdensn = fdensn[ind] deltn = deltn[ind] @@ -233,8 +233,8 @@ def get_weighting_tous(self, single_spos, npt=5000): def get_trackndens(self, single_spos, par): """get the tracked loss positions, number of turns and the touschek loss density""" - if len(to_fu.t_list(single_spos)) != 1: - raise ValueError('This function suports only one s position') + # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil + # raise ValueError('This function suports only one s position') fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) @@ -259,7 +259,7 @@ def get_trackndens(self, single_spos, par): # this function plot the graphic of tracking and the touschek scattering # distribution for one single position - def plot_track_tousdens(self, single_spos, par, accep,filename): + def plot_track_tousdens(self, single_spos, par, accep): """Plot the graphic of the positions electrons are lost the number of turns electrons realize before the loss, and the touschek loss density.""" @@ -272,9 +272,9 @@ def plot_track_tousdens(self, single_spos, par, accep,filename): inds = _np.intp(self.inds_neg) index = _np.argmin(_np.abs(s-single_spos)) to_fu.plot_track(self.accelerator, res, inds, - self.off_energy, par, index, accep, dp, fp,filename) + self.off_energy, par, index, accep, dp, fp) - def plot_normtousd(self, spos, filename): + def plot_normtousd(self, spos): """User must provide a list of s positions to calculate the loss density for each point""" spos_ring = self.spos @@ -284,21 +284,22 @@ def plot_normtousd(self, spos, filename): fdensp, fdensn = dic['fdensp'], dic['fdensn'] deltasp, deltasn = dic['deltasp'], dic['deltasn'] - fig, ax = _plt.subplots(figsize=(10,5)) - ax.set_title('Probability density analytically calculated', fontsize=20) + _, ax = _plt.subplots(figsize=(10, 5)) + ax.set_title( + 'Probability density analytically calculated', fontsize=20) ax.grid(True, alpha=0.5, ls='--', color='k') ax.xaxis.grid(False) ax.set_xlabel(r'$\delta$ [%]', fontsize=25) ax.set_ylabel('PDF', fontsize=25) ax.tick_params(axis='both', labelsize=28) - for idx, s in enumerate(spos): + for idx, _ in enumerate(spos): array_fdens = fdensp[idx] index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) - # apind.append(index) - # this block selects the best index for plot the density distribution + # this block selects the best index + # for plot the density distribution if not idx: best_index = index else: @@ -328,13 +329,10 @@ def plot_normtousd(self, spos, filename): s_stri = _np.round(spos_ring[mod_ind], 2) stri = f'{fam_name} em {s_stri} m' - ax.plot(deltaspi, fdenspi, label= stri, color=color) - ax.plot(deltasni, fdensni, color=color ) + ax.plot(deltaspi, fdenspi, label=stri, color=color) + ax.plot(deltasni, fdensni, color=color) ax.legend(loc='best', fontsize=20) - fig.savefig(filename, dpi=150) - - # this function plots the histograms returned by the monte carlo simulation def plot_histograms(self, l_spos): """Touschek scattering density from Monte-Carlo simulation; @@ -344,12 +342,12 @@ def plot_histograms(self, l_spos): model = self._model_fit tup = to_fu.histgms(self._model_fit, l_spos, self.num_part, accep, - self.energy_dev_min,cutaccep=False) + self.energy_dev_min, cutaccep=False) hp, hn, idx_model = tup fig, ax = _plt.subplots( - ncols=len(l_spos), nrows=1,figsize=(30,10), sharey=True) + ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True) fig.suptitle( 'Probability density calculated by Monte-Carlo simulation', fontsize=20) @@ -372,7 +370,7 @@ def plot_histograms(self, l_spos): ay.legend() - def get_track(self,l_scattered_pos, scrap, vchamber): + def get_track(self, l_scattered_pos, scrap, vchamber): """Tracking to get the loss profile along the ring. l_scattered_pos: scattered positions, @@ -394,7 +392,8 @@ def get_track(self,l_scattered_pos, scrap, vchamber): index = _np.argmin(_np.abs(scattered_pos-spos)) indices.append(index) - res = to_fu.track_eletrons(self._deltas, self.nturns, index, self._model) + res = to_fu.track_eletrons(self._deltas, self.nturns, + index, self._model) all_track.append(res) hx = self._model_fit[self.scraph_inds[0]].hmax @@ -403,13 +402,13 @@ def get_track(self,l_scattered_pos, scrap, vchamber): vn = self._model_fit[self.scrapv_inds[0]].vmin vchamber = [hx, hn, vx, vn] - self.set_vchamber_scraper(vchamber)# reseting vchamber height and width (nominal) + self.set_vchamber_scraper(vchamber) return all_track, indices def find_data(self, l_scattered_pos, scrap, vchamber): - """obtaining the graphic""" - + # não consegui resolvero erro que o ruff indicou nessa função + """Generating the data for the plot.""" all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) spos = self.spos @@ -421,10 +420,10 @@ def find_data(self, l_scattered_pos, scrap, vchamber): for j, single_track in enumerate(all_track): index = indices[j] - # scattered_pos = l_scattered_pos[j] - lostinds, deltas = _np.zeros(len(iten)), _np.zeros(len(iten)) - for idx,iten in enumerate(single_track): + lostinds = _np.zeros(len(single_track)) + deltas = _np.zeros(len(single_track)) + for idx, iten in enumerate(single_track): _, ellost, delta = iten lostinds[idx] = ellost deltas[idx] = delta @@ -439,27 +438,26 @@ def find_data(self, l_scattered_pos, scrap, vchamber): # dataframe that storages the tracking data lost_pos_column = \ (data.groupby('lost_pos_by_tracking').groups).keys() - data = _pd.DataFrame({'lost_pos_by_tracking':lost_pos_column}) + data = _pd.DataFrame({'lost_pos_by_tracking': lost_pos_column}) # this step agroups the lost_positions itv_delta = [] for current, next_iten in zip(itv_track, itv_track[1:]): stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' - data[stri] = _np.zeros(len(list(lost_pos_column))) # this step - #creates new columns in the dataframe and fill with zeros + data[stri] = _np.zeros(len(list(lost_pos_column))) # this step + # creates new columns in the dataframe and fill with zeros itv_delta.append((current, next_iten)) # Next step must calculate each matrix element from the # dataframe var = list(data.index) - # if var == lost_pos_column: pass else: data = data.set_index('lost_pos_by_tracking') - for idx, lost_pos in enumerate(lost_positions): # essas duas + for idx, lost_pos in enumerate(lost_positions): # essas duas # estruturas de repetição são responsáveis por calcular # o percentual dos eletrons que possuem um determinado desvio # de energia e se perdem em um intervalo de desvio de energia @@ -467,14 +465,14 @@ def find_data(self, l_scattered_pos, scrap, vchamber): delta = deltas[idx] # lps = [] for i, interval in enumerate(itv_delta): - if not i: # subtle difference: <= in first iteraction - if interval[0]<= delta <= interval[1]: + if not i: # subtle difference: <= in first iteraction + if interval[0] <= delta <= interval[1]: stri = \ f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' data.loc[lost_pos, stri] += 1 else: - if interval[0]< delta <= interval[1]: + if interval[0] < delta <= interval[1]: stri = \ f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' data.loc[lost_pos, stri] += 1 @@ -518,13 +516,12 @@ def find_data(self, l_scattered_pos, scrap, vchamber): all_lostp = _np.append(all_lostp, lost_pos_df[ind]) return all_lostp, prob, lostp - # dataframe = _pd.DataFrame(dic_res) - - def get_table(self,l_scattered_pos, scrap, vchamber): - """Generates the heat map of loss positions""" + def get_table(self, l_scattered_pos, scrap, vchamber): + """Generates the heat map of loss positions.""" dic_res = {} - all_lostp, prob, lostp = self.find_data(l_scattered_pos, scrap, vchamber) + all_lostp, prob, lostp = self.find_data(l_scattered_pos, + scrap, vchamber) n_scat = _np.round(l_scattered_pos, 2) for idx, scattered_pos in enumerate(n_scat): @@ -555,8 +552,7 @@ def get_table(self,l_scattered_pos, scrap, vchamber): def get_reordered_dict(self, l_scattered_pos, reording_key, scrap, vchamber): # chatgpt code to reorder the dictionary - """Get the reordered dictionary""" - + """Get the reordered dictionary.""" dic = self.get_table(l_scattered_pos, scrap, vchamber) zip_tuples = zip(*[dic[chave] for chave in dic]) @@ -569,10 +565,9 @@ def get_reordered_dict(self, l_scattered_pos, return new_dict - def get_loss_profile(self, dic, filename): + def get_loss_profile(self, dic): """Integrates the lost positions for all s positions, generating the loss profile along the ring.""" - # dic = self.get_reordered_dict(l_scattered_pos, reording_key) spos = self.spos @@ -583,15 +578,16 @@ def get_loss_profile(self, dic, filename): indices = [] for iten in scat_pos: - ind = _np.argmin(_np.abs(spos-iten)) + ind = _np.argmin(_np.abs(spos-iten)) indices.append(ind) summed = [] - for idx, iten in a.iterrows(): + for idx, _ in a.iterrows(): sum_row = scyint.trapz(a.loc[idx], spos[indices]) summed.append(sum_row) - fig, ax = _plt.subplots(figsize=(13,7),gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) + _, ax = _plt.subplots(figsize=(13, 7), + gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) ax.set_title('loss rate integral along the ring', fontsize=16) ax.set_xlabel('lost position [m]', fontsize=16) @@ -601,7 +597,6 @@ def get_loss_profile(self, dic, filename): ax.plot(list(a.index), summed, color='navy') _pyaccel.graphics.draw_lattice(self._model_fit, offset=-1e-6, height=1e-6, gca=True) - fig.savefig(filename,dpi=150) def get_loss_profilel(self, l_dic): """Comparing distinct loss profiles, could be used to compare with @@ -610,7 +605,7 @@ def get_loss_profilel(self, l_dic): l_dic: list of dictionaries of loss profiles""" # dic = self.get_reordered_dict(l_scattered_pos, reording_key) - l = [] + lista = [] for dic in l_dic: s = self.spos @@ -621,17 +616,17 @@ def get_loss_profilel(self, l_dic): indices = [] for iten in scat_pos: - ind = _np.argmin(_np.abs(s-iten)) + ind = _np.argmin(_np.abs(s-iten)) indices.append(ind) summed = [] - for idx, iten in a.iterrows(): + for idx, _ in a.iterrows(): sum_row = scyint.trapz(a.loc[idx], s[indices]) summed.append(sum_row) - l.append((a.index, summed)) + lista.append((a.index, summed)) - return l + return lista def plot_scat_table(self, new_dic): @@ -646,13 +641,13 @@ def plot_scat_table(self, new_dic): val[idx] = _np.log10(val[idx]) val[~idx] = val[idx].min() - fig, ax = _plt.subplots(figsize=(10,10)) + fig, ax = _plt.subplots(figsize=(10, 10)) - y = _np.linspace(0,s[-1],df.shape[0]+1) - x = _np.linspace(0,s[-1],df.shape[1]+1) - x_mesh,y_mesh = _np.meshgrid(x,y) + y = _np.linspace(0, s[-1], df.shape[0]+1) + x = _np.linspace(0, s[-1], df.shape[1]+1) + x_mesh, y_mesh = _np.meshgrid(x, y) - heatmp = ax.pcolor(x_mesh,y_mesh,val, cmap='jet',shading='flat') + heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap='jet', shading='flat') cbar = _plt.colorbar(heatmp) cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) @@ -664,5 +659,4 @@ def plot_scat_table(self, new_dic): fig.tight_layout() _plt.gca().set_aspect('equal') - # fig.savefig(filename, dpi=300) _plt.show() diff --git a/functions.py b/functions.py index 9d10c6be..fa14cbe7 100644 --- a/functions.py +++ b/functions.py @@ -115,7 +115,7 @@ def el_idx_collector(acc, lname): return all_index def plot_track(acc, lista_resul, lista_idx, - lista_off, param, element_idx, accep, delt, f_dens, filename): + lista_off, param, element_idx, accep, delt, f_dens): """ This function shows the touschek scattering density for s, the number of turns before electron loss and a graphic containing the magnetic lattice with the lost positions @@ -125,9 +125,9 @@ def plot_track(acc, lista_resul, lista_idx, of beta and eta functions""" # ---------------- - cm = 1/2.54 # 'poster' + cm = 1/2.54 # 'poster' - twi0,*_ = _pyaccel.optics.calc_twiss(acc,indices='open') + twi0,*_ = _pyaccel.optics.calc_twiss(acc, indices='open') betax = twi0.betax betax = betax*(1/5) @@ -162,7 +162,7 @@ def plot_track(acc, lista_resul, lista_idx, lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] indx = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', + a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2, 'b.', label=r'accep. limit', alpha=0.25) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') @@ -171,8 +171,8 @@ def plot_track(acc, lista_resul, lista_idx, a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] - indx = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[lista_idx][indx:], -lista_off[indx:]*1e2,'b.', + indx = _np.argmin(_np.abs(lista_off+acp_s)) + a3.plot(spos[lista_idx][:indx], -lista_off[:indx]*1e2, 'b.', label=r'accep. limit', alpha=0.25) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') @@ -185,7 +185,7 @@ def plot_track(acc, lista_resul, lista_idx, a2.set_title(r'$\delta \times$ lost turn', fontsize=20) a2.set_xlabel(r'number of turns', fontsize=25) for iten in lista_resul: - a2.plot(iten[0], iten[2]*1e2, 'k.', label = '') + a2.plot(iten[0], iten[2]*1e2, 'k.') a3.set_title(r'tracking ', fontsize=20) @@ -195,10 +195,10 @@ def plot_track(acc, lista_resul, lista_idx, _plt.hlines(1e2*acp_s, spos[0], spos[-1], color='black', linestyles='dashed', alpha=0.5) - #hlines -> shows accep. limit + # hlines -> shows accep. limit a3.plot(spos, _np.sqrt(betax), - color='orange', label=r'$ \sqrt{\beta_x} $') # beta function + color='orange', label=r'$ \sqrt{\beta_x} $') # beta function _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) stri = f'{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)' @@ -207,17 +207,16 @@ def plot_track(acc, lista_resul, lista_idx, a3.legend(loc='upper right', ncol=1, fontsize=15) # fig.tight_layout() - fig.savefig(filename, dpi=150) fig.show() -def t_list(elmnt): - """.""" - #this condition significates that if the input is only a number, then - #the fucntion transforms it into a list to avoid errors. - if isinstance(elmnt,(float,int)): - return [elmnt] - else: - return list(elmnt) +# def t_list(elmnt): # não sei se isso é útil +# """.""" +# #this condition significates that if the input is only a number, then +# #the fucntion transforms it into a list to avoid errors. +# if isinstance(elmnt,(float,int)): +# return [elmnt] +# else: +# return list(elmnt) def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): From def8c92a29461592c232b939f378210efeb3caf6 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 14 Dec 2023 12:39:56 -0300 Subject: [PATCH 091/108] =?UTF-8?q?adicionando=20mudan=C3=A7as?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 163 +++++++----- tous_analysis.py | 675 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 766 insertions(+), 72 deletions(-) create mode 100644 tous_analysis.py diff --git a/functions.py b/functions.py index fa14cbe7..44da8656 100644 --- a/functions.py +++ b/functions.py @@ -1,3 +1,4 @@ +"""Functions_for_TousAnalysis.""" import pymodels as _pymodels import pyaccel as _pyaccel import matplotlib.pyplot as _plt @@ -6,16 +7,19 @@ import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity -def calc_amp(acc,energy_offsets, hmax, hmin): - - """Calculates the amplitudes and gets the physical - limitants""" +def calc_amp(acc, energy_offsets, hmax, hmin): + """Calculates the amplitudes and gets the physical limitants. + acc = accelerator. + energy_offsets = e_dev for calculate physical limitants. + hmax = horizontal max apperture. + hmin = horizontal min apperture. + """ a_def = _np.zeros(energy_offsets.size) indices = _np.zeros(energy_offsets.size) try: - for idx,delta in enumerate(energy_offsets): - twi,*_ = _pyaccel.optics.calc_twiss( + for idx, delta in enumerate(energy_offsets): + twi, *_ = _pyaccel.optics.calc_twiss( accelerator=acc, energy_offset=delta, indices='closed') if _np.any(_np.isnan(twi[0].betax)): raise _pyaccel.optics.OpticsException('error') @@ -25,17 +29,24 @@ def calc_amp(acc,energy_offsets, hmax, hmin): a_sup = (hmax - rx)**2 /betax a_inf = (hmin - rx)**2 /betax - a_max = _np.minimum(a_sup,a_inf) + a_max = _np.minimum(a_sup, a_inf) idx_min = _np.argmin(a_max) indices[idx] = idx_min a_def[idx] = a_max[idx_min] - except (_pyaccel.optics.OpticsException, _pyaccel.tracking.TrackingException): + except (_pyaccel.optics.OpticsException, + _pyaccel.tracking.TrackingException): pass return _np.sqrt(a_def), indices def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): - """ This function finds the lost electrons by tracking """ - + """Tracking simulation for touschek scattering that ocorred in element_idx. + + model = accelerator. + deltas = e_dev + n_turn = number of turns desired. + pos_x = small shake in x + pos_y = || || || y + """ orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] @@ -56,7 +67,7 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): turnl_element = [] - for i,item in enumerate(turn_lost): + for i, item in enumerate(turn_lost): if item == n_turn and element_lost[i] == element_idx: pass else: @@ -64,29 +75,24 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): return turnl_element -def trackm_elec(acc,deltas, n_turn, lspos): - """Run the tracking simulation for a list of s positions """ - results = [] - spos = _pyaccel.lattice.find_spos(acc, indices='open') - - for _, iten in enumerate(lspos): - - el_idx = _np.argmin(_np.abs(spos-iten)) # initial condition element - turnl = track_eletrons(deltas, n_turn, el_idx, acc) - results.append(turnl) # - - return results def el_idx_collector(acc, lname): - """.""" + """Selects the index of an especific element. + + acc = accelerator. + lname = list of names + """ all_index = [] if 'mia' in lname: - all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) - elif'mib' in lname: - all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) + elif 'mib' in lname: + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) elif 'mip' in lname: - all_index.append(_pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) fam_data = _pymodels.si.get_family_data(acc) @@ -115,25 +121,30 @@ def el_idx_collector(acc, lname): return all_index def plot_track(acc, lista_resul, lista_idx, - lista_off, param, element_idx, accep, delt, f_dens): - """ This function shows the touschek scattering density for s, - the number of turns before electron loss and a graphic - containing the magnetic lattice with the lost positions - of the electrons obtained by tracking simulation, the limit - energy acceptance in a determined point s and the physical - limitants calculated by a linear approach of the dependencies - of beta and eta functions""" + lista_off, par, element_idx, accep, delt, f_dens): + """Plot the tracking results for a given s position. + + acc = accelerator. + lista_resul = list of information provided by tracking. + lista_idx = e_dev for calculating the physical limitants. + lista_off = list of e_dev used in tracking. + par = defines the analysis for positive or negative e_dev. + element_idx = defines initial conditions for tracking. + accep = touschek energy acceptance. + delt = e_dev for calculating the touschek loss rate density. + fdens = touschek loss rate density. + """ # ---------------- cm = 1/2.54 # 'poster' - twi0,*_ = _pyaccel.optics.calc_twiss(acc, indices='open') + twi0, *_ = _pyaccel.optics.calc_twiss(acc, indices='open') betax = twi0.betax betax = betax*(1/5) spos = _pyaccel.lattice.find_spos(acc) - fig = _plt.figure(figsize=(38.5*cm,18*cm)) + fig = _plt.figure(figsize=(38.5*cm, 18*cm)) gs = _plt.GridSpec(1, 3, left=0.1, right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) a1 = fig.add_subplot(gs[0, 0]) @@ -155,7 +166,7 @@ def plot_track(acc, lista_resul, lista_idx, a3.xaxis.grid(False) _plt.subplots_adjust(wspace=0.1) - if 'pos' in param: + if 'pos' in par: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], @@ -166,7 +177,7 @@ def plot_track(acc, lista_resul, lista_idx, label=r'accep. limit', alpha=0.25) for item in lista_resul: a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') - elif 'neg' in param: + elif 'neg' in par: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) a3.plot(spos[int(lista_resul[1][-1])], lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') @@ -221,7 +232,6 @@ def plot_track(acc, lista_resul, lista_idx, def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): """.""" - tau = (_np.tan(kappa)**2)[:, None] taum = _np.tan(kappam)**2 beta = _beam_rigidity(energy=3)[2] @@ -250,7 +260,7 @@ def get_scaccep(acc, accep): spos = _pyaccel.lattice.find_spos(acc, indices='closed') npt = int((spos[-1]-spos[0])/0.1) - scalc = _np.linspace(spos[0],spos[-1], npt) + scalc = _np.linspace(spos[0], spos[-1], npt) daccpp = _np.interp(scalc, spos, accep[1]) daccpn = _np.interp(scalc, spos, accep[0]) @@ -291,9 +301,9 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): deltan = 1/beta * _np.tan(kappan) y_p = f_function_arg_mod(kappa=kappap, - kappam=kappam_p0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + kappam=kappam_p0, b1_=b1[idx], b2_=b2[idx], norm=norm).squeeze() y_n = f_function_arg_mod(kappa=kappan, - kappam=kappam_n0,b1_=b1[idx],b2_=b2[idx], norm=norm).squeeze() + kappam=kappam_n0, b1_=b1[idx], b2_=b2[idx], norm=norm).squeeze() norm_facp = _scyint.trapz(y_p, deltap) norm_facn = _scyint.trapz(y_n, deltan) @@ -301,8 +311,8 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): y_n /= norm_facn # eliminating the negative values from array - indp = _np.where(y_p<0)[0] - indn = _np.where(y_n<0)[0] + indp = _np.where(y_p < 0)[0] + indn = _np.where(y_n < 0)[0] y_p[indp] = 0 y_n[indn] = 0 @@ -324,8 +334,7 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): return dic def create_particles(cov_matrix, num_part): - """ Creates the beam to realize the Monte-Carlo simulation""" - + """Creates the beam to realize the Monte-Carlo simulation.""" # permute indices to change the order of the columns: # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T idcs = [1, 3, 4, 0, 2, 5] @@ -349,7 +358,8 @@ def create_particles(cov_matrix, num_part): new_mean = (sig_xy @ inv_yy) @ vec_a new_cov = sig_xx - sig_xy @ inv_yy @ sig_yx - part2[:3] = _np.random.multivariate_normal(_np.zeros(3), new_cov, num_part).T + part2[:3] = _np.random.multivariate_normal(_np.zeros(3), + new_cov, num_part).T part2[:3] += new_mean part2 = part2[idcs_r, :] @@ -358,7 +368,7 @@ def create_particles(cov_matrix, num_part): return part1, part2 def get_cross_section_distribution(psim, _npts=3000): - """Calculates the Moller's cross section""" + """Calculates the Moller's cross section.""" beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) psi = _np.pi/2 - psi @@ -375,15 +385,21 @@ def get_cross_section_distribution(psim, _npts=3000): def cross_section_draw_samples(psim, num_part): - """Introduces the effect of the moller's cross section - in the M.C. simulation""" + """Interpolates the cross section effect. + + psim = Defines the maximum e_dev that remains the electrons' orbit stable. + num_part = The number of particles to simulate. + """ psi, cross = get_cross_section_distribution(psim) crs = _np.random.rand(num_part) return _np.interp(crs, cross, psi) def scatter_particles(part1, part2, de_min): - """M.C. simulation of a Touschek scattering process""" + """M.C. simulation of the Touschek scattering process. + + docstring. + """ gamma = 3e9 / 0.510e6 beta = _np.sqrt(1 - 1/gamma/gamma) num_part = part1.shape[1] @@ -401,9 +417,9 @@ def scatter_particles(part1, part2, de_min): # new coordinate system p_j = p_1 + p_2 - p_j /= _np.linalg.norm(p_j, axis=0) # sum + p_j /= _np.linalg.norm(p_j, axis=0) # sum p_k = _np.cross(p_1.T, p_2.T).T - p_k /= _np.linalg.norm(p_k, axis=0) # cross product + p_k /= _np.linalg.norm(p_k, axis=0) # cross product p_l = _np.cross(p_j.T, p_k.T).T jkl2xyz = _np.zeros([num_part, 3, 3]) @@ -411,10 +427,8 @@ def scatter_particles(part1, part2, de_min): jkl2xyz[:, :, 1] = p_k.T jkl2xyz[:, :, 2] = p_l.T - # calculating theta and zeta theta = xl1 - xl2 zeta = yl1 - yl2 - # defining the value of the scattering angle chi chi = _np.sqrt(zeta**2 + theta**2)/2 # draw the scattering angles from uniform distribution: @@ -435,7 +449,7 @@ def scatter_particles(part1, part2, de_min): # This method of doing things should be tested and thought about very # carefully, though. psim = _np.arccos(de_min/gamma/(chi.max()*2)) - fact=psim*2/_np.pi + fact = psim*2/_np.pi print(psim*2/_np.pi) psi = cross_section_draw_samples(psim, num_part) @@ -470,15 +484,20 @@ def scatter_particles(part1, part2, de_min): return part1_new, part2_new, fact -def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): - """Calculates the touschek scattering densities for an array - of s positions""" +def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): + """Calculates the touschek scattering densities. + l_spos = list of positions. + num_part = number of particles for M.C. sim. + accep = touschek energy acceptance. + de_min = minimum energy deviation for. + cutaccep = defines the cutoff on the energy acceptance. + """ envelopes = _pyaccel.optics.calc_beamenvelope(acc) - spos=_pyaccel.lattice.find_spos(acc, indices='closed') + spos = _pyaccel.lattice.find_spos(acc, indices='closed') scalc, daccpp, daccpn = get_scaccep(acc, accep) - histsp1, histsp2, indices=[],[],[] + histsp1, histsp2, indices = [], [], [] for iten in l_spos: @@ -486,33 +505,33 @@ def histgms(acc,l_spos,num_part, accep, de_min, cutaccep): idx = _np.argmin(_np.abs(scalc - iten)) indices.append(idx_model) - # this index is necessary to the s position indices from analitically calculated PDF + # this index is necessary to the s position indices + # from analitically calculated PDF # match with monte carlo simulation s position indices env = envelopes[idx_model] - # this two lines of code are the monte-carlo simulation part1, part2 = create_particles(env, num_part) part1_new, part2_new, _ = scatter_particles(part1, part2, de_min) - if cutaccep: # if true the cutoff is the accp at the s + if cutaccep: # if true the cutoff is the accp at the s acpp, acpn = daccpp[idx], daccpn[idx] check1 = acpp - part1_new[4] check2 = -(acpn - part2_new[4]) - ind1 = _np.intp(_np.where(check1<0)[0]) - ind2 = _np.intp(_np.where(check2<0)[0]) + ind1 = _np.intp(_np.where(check1 < 0)[0]) + ind2 = _np.intp(_np.where(check2 < 0)[0]) histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - else: # ximenes cutoff - ind1 = _np.intp(_np.where(part1_new[4]>=0.01)[0]) - ind2 = _np.intp(_np.where(part2_new[4]<=-0.01)[0]) + else: # ximenes cutoff + ind1 = _np.intp(_np.where(part1_new[4] >= 0.01)[0]) + ind2 = _np.intp(_np.where(part2_new[4] <= -0.01)[0]) histsp1.append(part1_new[4][ind1]*1e2) histsp2.append(part2_new[4][ind2]*1e2) - indices=_np.array(indices) + indices = _np.array(indices) return histsp1, histsp2, indices diff --git a/tous_analysis.py b/tous_analysis.py new file mode 100644 index 00000000..c5afb884 --- /dev/null +++ b/tous_analysis.py @@ -0,0 +1,675 @@ +"""tous_analysis.""" +from pyaccel.lifetime import Lifetime +from pyaccel.lattice import get_attribute, find_indices, find_spos +import touschek_pack.functions as to_fu +import pymodels +import pyaccel.optics as py_op +import numpy as _np +import matplotlib.pyplot as _plt +import matplotlib.cm as _cm +from mathphys.beam_optics import beam_rigidity as _beam_rigidity +import pandas as _pd +import scipy.integrate as scyint +import pyaccel as _pyaccel + +class TousAnalysis(): + """Class for the analysis of electron losses along the ring.""" + def __init__(self, accelerator, + energies_off=None, beam_energy=None, n_turns=7): + """Parameters necessary to define the class.""" + if energies_off is None: + energy_off = _np.linspace(0, 0.046, 460) # physical limitants + deltas = _np.linspace(0, 0.1, 400) # energy off for tracking + + if beam_energy is None: # defining beta factor + beta = _beam_rigidity(energy=3)[2] + + self._model_fit = accelerator + self._model = pymodels.si.create_accelerator() + + self._amp_and_limidx = None + self._sc_accps = None + self._accep = None + self._inds_pos = None + self._inds_neg = None + self._amps_pos = None + self._amps_neg = None + self.num_part = 50000 + self.energy_dev_min = 1e-4 + + self.beta = beta # beta factor + self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') + self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') + self.ltime = Lifetime(self._model_fit) + self._off_energy = energy_off # (linear model) en_dev to amplitudes + self.nturns = n_turns + self._deltas = deltas + self.spos = find_spos(self._model_fit, indices='closed') + self.scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') + self.scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') + + @property + def accelerator(self): + """.""" + return self._model_fit + + @accelerator.setter + def accelerator(self, new_model): + """.""" + self._model_fit = new_model + + @property + def nom_model(self): + """Defines nominal model. + + Some calculus involves nominal model without coupling and vertical + dispersion corretion. + """ + return self._model + + @property + def accep(self): + """Defines Touschek energy acceptance.""" + if self._accep is None: + self._accep = py_op.calc_touschek_energy_acceptance( + self.accelerator) + return self._accep + + @property + def s_calc(self): + """Defines property. + + Defines s position and get the energy accpetance both at each 10 + meters. + """ + if self._sc_accps is None: + self._sc_accps = to_fu.get_scaccep(self.accelerator, self.accep) + return self._sc_accps + + @property + def amp_and_limidx(self): + """Defines 4 properties. + + Positive and negative amplitudes. + physical limitants for positive and negative e_dev + """ + if self._amp_and_limidx is None: + self._model.cavity_on = False + self._model.radiation_on = False + + self._amps_pos, self._inds_pos = to_fu.calc_amp( + self._model, self.off_energy, self.h_pos, self.h_neg) + + self._amps_neg, self._inds_neg = to_fu.calc_amp( + self._model, -self.off_energy, self.h_pos, self.h_neg) + + self._amp_and_limidx = True + + return self._amp_and_limidx + + @property + def off_energy(self): + """.""" + return self._off_energy + + @off_energy.setter + def off_energy(self, accep): + """If necessary redefines the e_dev for tracking. + + The property defines the cutoof e_dev with tous_accep + accep = new touschek acceptance. + """ + accep_pos, accep_neg = accep + accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) + steps = int(accep_lim*10000) # choosen to be the number of steps + self._off_energy = _np.linspace(0, accep_lim, steps) + + @property + def deltas(self): + """.""" + return self._deltas + + @deltas.setter + def deltas(self, dev_percent, steps=400): + """Redefines the e_dev for tracking. + + dev_percent = energy deviation in percents [%]. + """ + dev_percent /= 100 + self._deltas = _np.linspace(0, dev_percent, steps) + + # the four properties defining below are to be static + @property + def inds_pos(self): + """.""" + return self._inds_pos + + @property + def inds_neg(self): + """.""" + return self._inds_neg + + @property + def amp_pos(self): + """.""" + return self._amps_pos + + @property # negative amplitudes from linear model + def amp_neg(self): + """.""" + return self._amps_neg + + def get_amps_idxs(self): # Defines various parameters + """Defines 3 self params at same time.""" + return self.amp_and_limidx, self.accep, self.s_calc + + def set_vchamber_scraper(self, vchamber): + """Function for setting the vchamber apperture.""" + model = self._model + scph_inds = self.scraph_inds + scpv_inds = self.scrapv_inds + + for iten in scph_inds: + model[iten].hmin = vchamber[0] + model[iten].hmax = vchamber[1] + for iten in scpv_inds: + model[iten].vmin = vchamber[2] + model[iten].vmax = vchamber[3] + + def single_pos_track(self, single_spos, par): + """Single position tracking.""" + self._model.cavity_on = True + self._model.radiation_on = True + self._model.vchamber_on = True + s = self.spos + + index = _np.argmin(_np.abs(s-single_spos)) + if 'pos' in par: + res = to_fu.track_eletrons(self.deltas, self.nturns, index, + self._model, pos_x=1e-5, pos_y=3e-6) + elif 'neg' in par: + res = to_fu.track_eletrons(-self.deltas, self.nturns, index, + self._model, pos_x=1e-5, pos_y=3e-6) + + return res + + def get_weighting_tous(self, single_spos, npt=5000): + """.""" + scalc, daccp, daccn = to_fu.get_scaccep( + self.accelerator, self.accep) + bf = self.beta # bf:beta factor + lt = self.ltime + b1 = lt.touschek_data['touschek_coeffs']['b1'] + b2 = lt.touschek_data['touschek_coeffs']['b2'] + + taup, taun = (bf* daccp)**2, (bf*daccn)**2 + idx = _np.argmin(_np.abs(scalc-single_spos)) + taup_0, taun_0 = taup[idx], taun[idx] + kappap_0 = _np.arctan(_np.sqrt(taup_0)) + kappan_0 = _np.arctan(_np.sqrt(taun_0)) + + kappa_pos = _np.linspace(kappap_0, _np.pi/2, npt) + kappa_neg = _np.linspace(kappan_0, _np.pi/2, npt) + + deltp = _np.tan(kappa_pos)/bf + deltn = _np.tan(kappa_neg)/bf + fdensp = to_fu.f_function_arg_mod( + kappa_pos, kappap_0, b1[idx], b2[idx], norm=False) + + fdensn = to_fu.f_function_arg_mod( + kappa_neg, kappan_0, b1[idx], b2[idx], norm=False) + + # eliminating negative values + indp = _np.where(fdensp < 0)[0] + indn = _np.where(fdensn < 0)[0] + fdensp[indp] = 0 + fdensn[indn] = 0 + + ind = _np.intp(_np.where(fdensp > 1e-2)[0]) + fdensp = fdensp[ind] + deltp = deltp[ind] + ind = _np.intp(_np.where(fdensn > 1e-2)[0]) + fdensn = fdensn[ind] + deltn = deltn[ind] + + self.deltas = deltp[-1]*1e2 + + return fdensp, fdensn, deltp, deltn + + def get_trackndens(self, single_spos, par): + """Concatenates tracking and touschek loss dens.""" + # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil + # raise ValueError('This function suports only one s position') + + fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) + + fp = fdensp.squeeze() + fn = fdensn.squeeze() + + res = self.single_pos_track(single_spos, par) + delta = _np.zeros(len(res)) + + for index, iten in enumerate(res): + _, _, delt = iten + delta[index] = delt + + delta_ = _np.abs(_np.diff(delta)[0]) + + if 'pos' in par: + return res, fp*delta_, deltp *1e2 + elif 'neg' in par: + return res, fn*delta_, -deltn*1e2 + + # this function plot the graphic of tracking and the touschek scattering + # distribution for one single position + def plot_track_tousdens(self, single_spos, par, accep): + """Plot the results of tracking and the tous. scat. loss density. + + single_spos = single possition. + par = defines the analysis (positive or negative). + accep = touschek scattering acceptance. + """ + res, fp, dp = self.get_trackndens(single_spos, par) + s = self.spos + + if 'pos' in par: + inds = _np.intp(self.inds_pos) + elif 'neg' in par: + inds = _np.intp(self.inds_neg) + index = _np.argmin(_np.abs(s-single_spos)) + to_fu.plot_track(self.accelerator, res, inds, + self.off_energy, par, index, accep, dp, fp) + + def plot_normtousd(self, spos): + """Touschek scattering loss density. + + spos = desired s positions (list or numpy.array) + """ + spos_ring = self.spos + dic = to_fu.norm_cutacp(self._model_fit, + spos, 5000, self._accep, norm=True) + + fdensp, fdensn = dic['fdensp'], dic['fdensn'] + deltasp, deltasn = dic['deltasp'], dic['deltasn'] + + _, ax = _plt.subplots(figsize=(10, 5)) + ax.set_title( + 'Probability density analytically calculated', fontsize=20) + ax.grid(True, alpha=0.5, ls='--', color='k') + ax.xaxis.grid(False) + ax.set_xlabel(r'$\delta$ [%]', fontsize=25) + ax.set_ylabel('PDF', fontsize=25) + ax.tick_params(axis='both', labelsize=28) + + for idx, _ in enumerate(spos): + + array_fdens = fdensp[idx] + index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) + + # this block selects the best index + # for plot the density distribution + if not idx: + best_index = index + else: + if best_index < index: + best_index = index + else: + pass + + for idx, s in enumerate(spos): + + mod_ind = _np.argmin(_np.abs(spos_ring-s)) + + fdenspi = fdensp[idx][:best_index] + fdensni = fdensn[idx][:best_index] + deltaspi = deltasp[idx][:best_index]*1e2 + deltasni = -deltasn[idx][:best_index]*1e2 + + color = _cm.gist_rainbow(idx/len(spos)) + not_desired = ['calc_mom_accep', + 'mia', 'mib', 'mip', + 'mb1', 'mb2', 'mc'] + + while self._model_fit[mod_ind].fam_name in not_desired: + mod_ind += 1 + + fam_name = self._model_fit[mod_ind].fam_name + s_stri = _np.round(spos_ring[mod_ind], 2) + stri = f'{fam_name} em {s_stri} m' + + ax.plot(deltaspi, fdenspi, label=stri, color=color) + ax.plot(deltasni, fdensni, color=color) + + ax.legend(loc='best', fontsize=20) + + def plot_histograms(self, l_spos): + """Touschek scattering density from Monte-Carlo simulation. + + l_spos = desired s positions (list or array). + """ + s = self.spos + accep = self.accep + model = self._model_fit + + tup = to_fu.histgms(self._model_fit, l_spos, self.num_part, accep, + self.energy_dev_min, cutaccep=False) + + hp, hn, idx_model = tup + + fig, ax = _plt.subplots( + ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True) + fig.suptitle( + 'Probability density calculated by Monte-Carlo simulation', + fontsize=20) + + for index, iten in enumerate(idx_model): + color = _cm.jet(index/len(idx_model)) + ay = ax[index] + if not index: + ay.set_ylabel('PDF', fontsize=25) + + ay.grid(True, alpha=0.5, ls='--', color='k') + ay.xaxis.grid(False) + ay.set_xlabel(r'$\delta$ [%]', fontsize=25) + ay.tick_params(axis='both', labelsize=18) + + stri = f'{model[iten].fam_name:s}, {s[iten]:.2f}' + ay.hist(hp[index], density=True, bins=200, color=color, label=stri) + ay.hist(hn[index], density=True, bins=200, color=color) + _plt.tight_layout() + ay.legend() + + + def get_track(self, l_scattered_pos, scrap, vchamber): + """Tracking for getting the loss profile along the ring. + + l_scattered_pos = scattered positions (list or numpy.array). + scrap = if True, the vchamber's height will be changed. + vchmaber = defines the new vchamber's apperture. + """ + all_track = [] + indices = [] + spos = self.spos + + self._model.radiation_on = True + self._model.cavity_on = True + self._model.vchamber_on = True + + if scrap: + self.set_vchamber_scraper(vchamber) + + for _, scattered_pos in enumerate(l_scattered_pos): + + index = _np.argmin(_np.abs(scattered_pos-spos)) + indices.append(index) + res = to_fu.track_eletrons(self._deltas, self.nturns, + index, self._model) + all_track.append(res) + + hx = self._model_fit[self.scraph_inds[0]].hmax + hn = self._model_fit[self.scraph_inds[0]].hmin + vx = self._model_fit[self.scrapv_inds[0]].vmax + vn = self._model_fit[self.scrapv_inds[0]].vmin + vchamber = [hx, hn, vx, vn] + + self.set_vchamber_scraper(vchamber) + + return all_track, indices + + def find_data(self, l_scattered_pos, scrap, vchamber): + # não consegui resolvero erro que o ruff indicou nessa função + """Generating the data for the plot.""" + all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) + spos = self.spos + + fact = 0.03 + # toushcek scattering rate + tous_rate = self.ltime.touschek_data['rate'] + prob, lostp, all_lostp = [], [], [] + + for j, single_track in enumerate(all_track): + + index = indices[j] + + lostinds = _np.zeros(len(single_track)) + deltas = _np.zeros(len(single_track)) + for idx, iten in enumerate(single_track): + _, ellost, delta = iten + lostinds[idx] = ellost + deltas[idx] = delta + + lostinds = _np.intp(lostinds) + lost_positions = _np.round(spos[lostinds], 2) + + step = int((deltas[0]+deltas[-1])/fact) + itv_track = _np.linspace(deltas[0], deltas[-1], step) + + data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) + # dataframe that storages the tracking data + lost_pos_column = \ + (data.groupby('lost_pos_by_tracking').groups).keys() + data = _pd.DataFrame({'lost_pos_by_tracking': lost_pos_column}) + # this step agroups the lost_positions + + itv_delta = [] + for current, next_iten in zip(itv_track, itv_track[1:]): + stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' + data[stri] = _np.zeros(len(list(lost_pos_column))) # this step + # creates new columns in the dataframe and fill with zeros + + itv_delta.append((current, next_iten)) + # Next step must calculate each matrix element from the + # dataframe + + var = list(data.index) + if var == lost_pos_column: + pass + else: + data = data.set_index('lost_pos_by_tracking') + + for idx, lost_pos in enumerate(lost_positions): # essas duas + # estruturas de repetição são responsáveis por calcular + # o percentual dos eletrons que possuem um determinado desvio + # de energia e se perdem em um intervalo de desvio de energia + # específico + delta = deltas[idx] + # lps = [] + for i, interval in enumerate(itv_delta): + if not i: # subtle difference: <= in first iteraction + if interval[0] <= delta <= interval[1]: + stri = \ + f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + data.loc[lost_pos, stri] += 1 + + else: + if interval[0] < delta <= interval[1]: + stri = \ + f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + data.loc[lost_pos, stri] += 1 + + data = data / len(deltas) + + npt = int((spos[-1]-spos[0])/0.1) + + scalc = _np.linspace(spos[0], spos[-1], npt) + rate_nom_lattice = _np.interp(spos, scalc, tous_rate) + + lost_pos_df = [] + part_prob = [] + # Calculates the loss probablity by tracking + for indx, iten in data.iterrows(): + t_prob = 0 + for idx, m in enumerate(iten): + t_prob += m + if idx == iten.count()-1: + # appends the probability after sum + part_prob.append(t_prob) + lost_pos_df.append(indx) + + lost_pos_df = _np.array(lost_pos_df) + part_prob = _np.array(part_prob) + + # Calculates the absolute probability for electron loss + # by touschek scattering rate + prob.append(part_prob * rate_nom_lattice[index]) + lostp.append(lost_pos_df) + + # Aqui eu pego as posições em que os elétrons foram perdidos + # e armazeno todas em uma grande lista sem repetição de qualquer + # posição perdida + if not j: + all_lostp = lost_pos_df + else: + boolean_array = _np.isin(lost_pos_df, all_lostp) + for ind, boolean_indc in enumerate(boolean_array): + if not boolean_indc: + all_lostp = _np.append(all_lostp, lost_pos_df[ind]) + + return all_lostp, prob, lostp + + def get_table(self, l_scattered_pos, scrap, vchamber): + """Generates the heat map of loss positions.""" + dic_res = {} + all_lostp, prob, lostp = self.find_data(l_scattered_pos, + scrap, vchamber) + n_scat = _np.round(l_scattered_pos, 2) + + for idx, scattered_pos in enumerate(n_scat): + + scat_data = [] + bool_array = _np.isin(all_lostp, lostp[idx]) + + for j, boolean in enumerate(bool_array): + if boolean: + index = \ + _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) + scat_data.append(prob[idx][index]) + else: + scat_data.append(0) + + if not idx: + dic_res['lost_positions'] = all_lostp + stri = f'{scattered_pos:s}' + dic_res[stri] = scat_data + else: + stri = f'{scattered_pos}' + dic_res[stri] = scat_data + + # df = _pd.DataFrame(dic_res) + + return dic_res + + def get_reordered_dict(self, l_scattered_pos, + reording_key, scrap, vchamber): + """Get the reordered dictionary.""" + dic = self.get_table(l_scattered_pos, scrap, vchamber) + + zip_tuples = zip(*[dic[chave] for chave in dic]) + new_tuples = sorted(zip_tuples, + key=lambda x: x[list(dic.keys()).index(reording_key)]) + zip_ordered = zip(*new_tuples) + + new_dict = \ + {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} + + return new_dict + + def get_loss_profile(self, dic): + """Integrates the lost positions for all scattering points. + + dic = cointains the lost positions and the scattered points. + """ + # dic = self.get_reordered_dict(l_scattered_pos, reording_key) + spos = self.spos + + df = _pd.DataFrame(dic) + a = df.set_index('lost_positions') + + scat_pos = _np.array(a.columns, dtype=float) + + indices = [] + for iten in scat_pos: + ind = _np.argmin(_np.abs(spos-iten)) + indices.append(ind) + + summed = [] + for idx, _ in a.iterrows(): + sum_row = scyint.trapz(a.loc[idx], spos[indices]) + summed.append(sum_row) + + _, ax = _plt.subplots(figsize=(13, 7), + gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) + ax.set_title('loss rate integral along the ring', fontsize=16) + + ax.set_xlabel('lost position [m]', fontsize=16) + ax.set_ylabel('loss rate [1/s]', fontsize=16) + ax.tick_params(axis='both', labelsize=16) + + ax.plot(list(a.index), summed, color='navy') + _pyaccel.graphics.draw_lattice(self._model_fit, + offset=-1e-6, height=1e-6, gca=True) + + def get_loss_profilel(self, l_dic): + """Comparing distinct loss profiles. + + l_dic = list of dictionaries of loss profiles. + """ + # dic = self.get_reordered_dict(l_scattered_pos, reording_key) + lista = [] + for dic in l_dic: + s = self.spos + + df = _pd.DataFrame(dic) + a = df.set_index('lost_positions') + + scat_pos = _np.array(a.columns, dtype=float) + + indices = [] + for iten in scat_pos: + ind = _np.argmin(_np.abs(s-iten)) + indices.append(ind) + + summed = [] + for idx, _ in a.iterrows(): + sum_row = scyint.trapz(a.loc[idx], s[indices]) + summed.append(sum_row) + + lista.append((a.index, summed)) + + return lista + + def plot_scat_table(self, new_dic): + """Heatmap plot indicating the warm points of loss along the ring. + + new_dic = contains the reordered dict with lost positions and + scattered points. + """ + s = self.spos + + df = _pd.DataFrame(new_dic) + df = df.set_index('lost_positions') + + val = df.values.copy() + idx = val != 0.0 + val[idx] = _np.log10(val[idx]) + val[~idx] = val[idx].min() + + fig, ax = _plt.subplots(figsize=(10, 10)) + + y = _np.linspace(0, s[-1], df.shape[0]+1) + x = _np.linspace(0, s[-1], df.shape[1]+1) + x_mesh, y_mesh = _np.meshgrid(x, y) + + heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap='jet', shading='flat') + + cbar = _plt.colorbar(heatmp) + cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) + + ax.set_title('Loss profile', fontsize=16) + + ax.set_xlabel('scattered positions [m]', fontsize=16) + ax.set_ylabel('lost positions [m]', fontsize=16) + + fig.tight_layout() + _plt.gca().set_aspect('equal') + _plt.show() From b89fe4d86ad6dff18e27798b9f2a1cf6be42c0d1 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 14 Dec 2023 12:48:57 -0300 Subject: [PATCH 092/108] excluindo arquivo Classes.py. Motivo: troca de nome. --- Classes.py | 662 ----------------------------------------------------- 1 file changed, 662 deletions(-) delete mode 100644 Classes.py diff --git a/Classes.py b/Classes.py deleted file mode 100644 index 1470257b..00000000 --- a/Classes.py +++ /dev/null @@ -1,662 +0,0 @@ -"""tous_analysis.""" -from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute, find_indices, find_spos -import touschek_pack.functions as to_fu -import pymodels -import pyaccel.optics as py_op -import numpy as _np -import matplotlib.pyplot as _plt -import matplotlib.cm as _cm -from mathphys.beam_optics import beam_rigidity as _beam_rigidity -import pandas as _pd -import scipy.integrate as scyint -import pyaccel as _pyaccel - -class Tous_analysis(): - """Class for the analysis of electron losses along the ring""" - - def __init__(self, accelerator, - energies_off=None, beam_energy=None, n_turns=7): - """.""" - if energies_off is None: - energy_off = _np.linspace(0, 0.046, 460) # physical limitants - deltas = _np.linspace(0, 0.1, 400) # energy off for tracking - - if beam_energy is None: # defining beta factor - beta = _beam_rigidity(energy=3)[2] - - self._model_fit = accelerator - self._model = pymodels.si.create_accelerator() - - self._amp_and_limidx = None - self._sc_accps = None - self._accep = None - self._inds_pos = None - self._inds_neg = None - self._amps_pos = None - self._amps_neg = None - self.num_part = 50000 - self.energy_dev_min = 1e-4 - - self.beta = beta # beta factor - self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') - self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') - self.ltime = Lifetime(self._model_fit) - self._off_energy = energy_off # (linear model) en_dev to amplitudes - self.nturns = n_turns - self._deltas = deltas - self.spos = find_spos(self._model_fit, indices='closed') - self.scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') - self.scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') - - @property - def accelerator(self): - """Recieves fitted accelerator model""" - return self._model_fit - - @accelerator.setter - def accelerator(self, new_model): - """If requeried to change the accelerator model""" - self._model_fit = new_model - - @property - def nom_model(self): - """Some calculus involves nominal model without coupling - and vertical dispersion corretion""" - return self._model - - @property - def accep(self): - """Defines Touschek energy acceptance""" - if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance( - self.accelerator) - return self._accep - - @property - def s_calc(self): - """Defines s position and get the - energy accpetance both at each 10 - meters""" - if self._sc_accps is None: - self._sc_accps = to_fu.get_scaccep(self.accelerator, self.accep) - return self._sc_accps - - @property - def amp_and_limidx(self): - """Defines 4 properties: - Positive and negative amplitudes - Indices where positive and nega- - tive amp(energy deviation depen- - dence) are minimum - """ - if self._amp_and_limidx is None: - self._model.cavity_on = False - self._model.radiation_on = False - - self._amps_pos, self._inds_pos = to_fu.calc_amp( - self._model, self.off_energy, self.h_pos, self.h_neg) - - self._amps_neg, self._inds_neg = to_fu.calc_amp( - self._model, -self.off_energy, self.h_pos, self.h_neg) - - self._amp_and_limidx = True - - return self._amp_and_limidx - - @property - def off_energy(self): - """.""" - return self._off_energy - - @off_energy.setter - def off_energy(self, accep): - """the cutoff for energy deviation is the energy acceptance limit/ - pass a new energy acceptance tuple of arrays""" - accep_pos, accep_neg = accep - accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) - steps = int(accep_lim*10000) # choosen to be the number of steps - self._off_energy = _np.linspace(0, accep_lim, steps) - - @property - def deltas(self): - """.""" - return self._deltas - - @deltas.setter - def deltas(self, dev_percent,steps=400): - """dev_percent is energy deviation in percents [%] - If the user desires to change the sample of energy - deviation""" - dev_percent /= 100 - self._deltas = _np.linspace(0, dev_percent, steps) - - # the four properties defining below are to be static - @property - def inds_pos(self): - """.""" - return self._inds_pos - - @property - def inds_neg(self): - """.""" - return self._inds_neg - - @property - def amp_pos(self): - """.""" - return self._amps_pos - - @property # negative amplitudes from linear model - def amp_neg(self): - """.""" - return self._amps_neg - - def get_amps_idxs(self): # Defines various parameters - """Defines 3 self params at same time""" - return self.amp_and_limidx, self.accep, self.s_calc - - def set_vchamber_scraper(self, vchamber): - """Function for setting the vchamber apperture""" - model = self._model - scph_inds = self.scraph_inds - scpv_inds = self.scrapv_inds - - for iten in scph_inds: - model[iten].hmin = vchamber[0] - model[iten].hmax = vchamber[1] - for iten in scpv_inds: - model[iten].vmin = vchamber[2] - model[iten].vmax = vchamber[3] - - def single_pos_track(self, single_spos, par): - """Single position tracking""" - - self._model.cavity_on = True - self._model.radiation_on = True - self._model.vchamber_on = True - s = self.spos - - index = _np.argmin(_np.abs(s-single_spos)) - if 'pos' in par: - res = to_fu.track_eletrons(self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) - elif 'neg' in par: - res = to_fu.track_eletrons(-self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) - - return res - - def get_weighting_tous(self, single_spos, npt=5000): - """.""" - scalc, daccp, daccn = to_fu.get_scaccep( - self.accelerator, self.accep) - bf = self.beta # bf:beta factor - lt = self.ltime - b1 = lt.touschek_data['touschek_coeffs']['b1'] - b2 = lt.touschek_data['touschek_coeffs']['b2'] - - taup, taun = (bf* daccp)**2, (bf*daccn)**2 - idx = _np.argmin(_np.abs(scalc-single_spos)) - taup_0, taun_0 = taup[idx], taun[idx] - kappap_0 = _np.arctan(_np.sqrt(taup_0)) - kappan_0 = _np.arctan(_np.sqrt(taun_0)) - - kappa_pos = _np.linspace(kappap_0, _np.pi/2, npt) - kappa_neg = _np.linspace(kappan_0, _np.pi/2, npt) - - deltp = _np.tan(kappa_pos)/bf - deltn = _np.tan(kappa_neg)/bf - fdensp = to_fu.f_function_arg_mod( - kappa_pos, kappap_0, b1[idx], b2[idx], norm=False) - - fdensn = to_fu.f_function_arg_mod( - kappa_neg, kappan_0, b1[idx], b2[idx], norm=False) - - # eliminating negative values - indp = _np.where(fdensp < 0)[0] - indn = _np.where(fdensn < 0)[0] - fdensp[indp] = 0 - fdensn[indn] = 0 - - ind = _np.intp(_np.where(fdensp > 1e-2)[0]) - fdensp = fdensp[ind] - deltp = deltp[ind] - ind = _np.intp(_np.where(fdensn > 1e-2)[0]) - fdensn = fdensn[ind] - deltn = deltn[ind] - - self.deltas = deltp[-1]*1e2 - - return fdensp, fdensn, deltp, deltn - - def get_trackndens(self, single_spos, par): - """get the tracked loss positions, number of turns and - the touschek loss density""" - # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil - # raise ValueError('This function suports only one s position') - - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) - - fp = fdensp.squeeze() - fn = fdensn.squeeze() - - res = self.single_pos_track(single_spos, par) - delta = _np.zeros(len(res)) - - for index, iten in enumerate(res): - _, _, delt = iten - delta[index] = delt - - delta_ = _np.abs(_np.diff(delta)[0]) - - if 'pos' in par: - return res, fp*delta_, deltp *1e2 - elif 'neg' in par: - return res, fn*delta_, -deltn*1e2 - else: - return res, fp*delta_, fn*delta_, deltp*1e2, -deltn*1e2 - - # this function plot the graphic of tracking and the touschek scattering - # distribution for one single position - def plot_track_tousdens(self, single_spos, par, accep): - """Plot the graphic of the positions electrons are lost - the number of turns electrons realize before the loss, - and the touschek loss density.""" - res, fp, dp = self.get_trackndens(single_spos, par) - s = self.spos - - if 'pos' in par: - inds = _np.intp(self.inds_pos) - elif 'neg' in par: - inds = _np.intp(self.inds_neg) - index = _np.argmin(_np.abs(s-single_spos)) - to_fu.plot_track(self.accelerator, res, inds, - self.off_energy, par, index, accep, dp, fp) - - def plot_normtousd(self, spos): - """User must provide a list of s positions to - calculate the loss density for each point""" - spos_ring = self.spos - dic = to_fu.norm_cutacp(self._model_fit, - spos, 5000, self._accep, norm=True) - - fdensp, fdensn = dic['fdensp'], dic['fdensn'] - deltasp, deltasn = dic['deltasp'], dic['deltasn'] - - _, ax = _plt.subplots(figsize=(10, 5)) - ax.set_title( - 'Probability density analytically calculated', fontsize=20) - ax.grid(True, alpha=0.5, ls='--', color='k') - ax.xaxis.grid(False) - ax.set_xlabel(r'$\delta$ [%]', fontsize=25) - ax.set_ylabel('PDF', fontsize=25) - ax.tick_params(axis='both', labelsize=28) - - for idx, _ in enumerate(spos): - - array_fdens = fdensp[idx] - index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) - - # this block selects the best index - # for plot the density distribution - if not idx: - best_index = index - else: - if best_index < index: - best_index = index - else: - pass - - for idx, s in enumerate(spos): - - mod_ind = _np.argmin(_np.abs(spos_ring-s)) - - fdenspi = fdensp[idx][:best_index] - fdensni = fdensn[idx][:best_index] - deltaspi = deltasp[idx][:best_index]*1e2 - deltasni = -deltasn[idx][:best_index]*1e2 - - color = _cm.gist_rainbow(idx/len(spos)) - not_desired = ['calc_mom_accep', - 'mia', 'mib', 'mip', - 'mb1', 'mb2', 'mc'] - - while self._model_fit[mod_ind].fam_name in not_desired: - mod_ind += 1 - - fam_name = self._model_fit[mod_ind].fam_name - s_stri = _np.round(spos_ring[mod_ind], 2) - stri = f'{fam_name} em {s_stri} m' - - ax.plot(deltaspi, fdenspi, label=stri, color=color) - ax.plot(deltasni, fdensni, color=color) - - ax.legend(loc='best', fontsize=20) - - def plot_histograms(self, l_spos): - """Touschek scattering density from Monte-Carlo simulation; - input: list of desired positions""" - s = self.spos - accep = self.accep - model = self._model_fit - - tup = to_fu.histgms(self._model_fit, l_spos, self.num_part, accep, - self.energy_dev_min, cutaccep=False) - - hp, hn, idx_model = tup - - fig, ax = _plt.subplots( - ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True) - fig.suptitle( - 'Probability density calculated by Monte-Carlo simulation', - fontsize=20) - - for index, iten in enumerate(idx_model): - color = _cm.jet(index/len(idx_model)) - ay = ax[index] - if not index: - ay.set_ylabel('PDF', fontsize=25) - - ay.grid(True, alpha=0.5, ls='--', color='k') - ay.xaxis.grid(False) - ay.set_xlabel(r'$\delta$ [%]', fontsize=25) - ay.tick_params(axis='both', labelsize=18) - - stri = f'{model[iten].fam_name:s}, {s[iten]:.2f}' - ay.hist(hp[index], density=True, bins=200, color=color, label=stri) - ay.hist(hn[index], density=True, bins=200, color=color) - _plt.tight_layout() - ay.legend() - - - def get_track(self, l_scattered_pos, scrap, vchamber): - """Tracking to get the loss profile along the ring. - - l_scattered_pos: scattered positions, - scrap: if True, the vchamber's height must be changed, - vchmaber: defines the vchamber's height""" - - all_track = [] - indices = [] - spos = self.spos - - self._model.radiation_on = True - self._model.cavity_on = True - self._model.vchamber_on = True - - if scrap: - self.set_vchamber_scraper(vchamber) - - for _, scattered_pos in enumerate(l_scattered_pos): - - index = _np.argmin(_np.abs(scattered_pos-spos)) - indices.append(index) - res = to_fu.track_eletrons(self._deltas, self.nturns, - index, self._model) - all_track.append(res) - - hx = self._model_fit[self.scraph_inds[0]].hmax - hn = self._model_fit[self.scraph_inds[0]].hmin - vx = self._model_fit[self.scrapv_inds[0]].vmax - vn = self._model_fit[self.scrapv_inds[0]].vmin - vchamber = [hx, hn, vx, vn] - - self.set_vchamber_scraper(vchamber) - - return all_track, indices - - def find_data(self, l_scattered_pos, scrap, vchamber): - # não consegui resolvero erro que o ruff indicou nessa função - """Generating the data for the plot.""" - all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) - spos = self.spos - - fact = 0.03 - # toushcek scattering rate - tous_rate = self.ltime.touschek_data['rate'] - prob, lostp, all_lostp = [], [], [] - - for j, single_track in enumerate(all_track): - - index = indices[j] - - lostinds = _np.zeros(len(single_track)) - deltas = _np.zeros(len(single_track)) - for idx, iten in enumerate(single_track): - _, ellost, delta = iten - lostinds[idx] = ellost - deltas[idx] = delta - - lostinds = _np.intp(lostinds) - lost_positions = _np.round(spos[lostinds], 2) - - step = int((deltas[0]+deltas[-1])/fact) - itv_track = _np.linspace(deltas[0], deltas[-1], step) - - data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) - # dataframe that storages the tracking data - lost_pos_column = \ - (data.groupby('lost_pos_by_tracking').groups).keys() - data = _pd.DataFrame({'lost_pos_by_tracking': lost_pos_column}) - # this step agroups the lost_positions - - itv_delta = [] - for current, next_iten in zip(itv_track, itv_track[1:]): - stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' - data[stri] = _np.zeros(len(list(lost_pos_column))) # this step - # creates new columns in the dataframe and fill with zeros - - itv_delta.append((current, next_iten)) - # Next step must calculate each matrix element from the - # dataframe - - var = list(data.index) - if var == lost_pos_column: - pass - else: - data = data.set_index('lost_pos_by_tracking') - - for idx, lost_pos in enumerate(lost_positions): # essas duas - # estruturas de repetição são responsáveis por calcular - # o percentual dos eletrons que possuem um determinado desvio - # de energia e se perdem em um intervalo de desvio de energia - # específico - delta = deltas[idx] - # lps = [] - for i, interval in enumerate(itv_delta): - if not i: # subtle difference: <= in first iteraction - if interval[0] <= delta <= interval[1]: - stri = \ - f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' - data.loc[lost_pos, stri] += 1 - - else: - if interval[0] < delta <= interval[1]: - stri = \ - f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' - data.loc[lost_pos, stri] += 1 - - data = data / len(deltas) - - npt = int((spos[-1]-spos[0])/0.1) - - scalc = _np.linspace(spos[0], spos[-1], npt) - rate_nom_lattice = _np.interp(spos, scalc, tous_rate) - - lost_pos_df = [] - part_prob = [] - # Calculates the loss probablity by tracking - for indx, iten in data.iterrows(): - t_prob = 0 - for idx, m in enumerate(iten): - t_prob += m - if idx == iten.count()-1: - # appends the probability after sum - part_prob.append(t_prob) - lost_pos_df.append(indx) - - lost_pos_df = _np.array(lost_pos_df) - part_prob = _np.array(part_prob) - - # Calculates the absolute probability for electron loss - # by touschek scattering rate - prob.append(part_prob * rate_nom_lattice[index]) - lostp.append(lost_pos_df) - - # Aqui eu pego as posições em que os elétrons foram perdidos - # e armazeno todas em uma grande lista sem repetição de qualquer - # posição perdida - if not j: - all_lostp = lost_pos_df - else: - boolean_array = _np.isin(lost_pos_df, all_lostp) - for ind, boolean_indc in enumerate(boolean_array): - if not boolean_indc: - all_lostp = _np.append(all_lostp, lost_pos_df[ind]) - - return all_lostp, prob, lostp - - def get_table(self, l_scattered_pos, scrap, vchamber): - """Generates the heat map of loss positions.""" - dic_res = {} - all_lostp, prob, lostp = self.find_data(l_scattered_pos, - scrap, vchamber) - n_scat = _np.round(l_scattered_pos, 2) - - for idx, scattered_pos in enumerate(n_scat): - - scat_data = [] - bool_array = _np.isin(all_lostp, lostp[idx]) - - for j, boolean in enumerate(bool_array): - if boolean: - index = \ - _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) - scat_data.append(prob[idx][index]) - else: - scat_data.append(0) - - if not idx: - dic_res['lost_positions'] = all_lostp - stri = f'{scattered_pos:s}' - dic_res[stri] = scat_data - else: - stri = f'{scattered_pos}' - dic_res[stri] = scat_data - - # df = _pd.DataFrame(dic_res) - - return dic_res - - def get_reordered_dict(self, l_scattered_pos, - reording_key, scrap, vchamber): - # chatgpt code to reorder the dictionary - """Get the reordered dictionary.""" - dic = self.get_table(l_scattered_pos, scrap, vchamber) - - zip_tuples = zip(*[dic[chave] for chave in dic]) - new_tuples = sorted(zip_tuples, - key=lambda x: x[list(dic.keys()).index(reording_key)]) - zip_ordered = zip(*new_tuples) - - new_dict = \ - {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} - - return new_dict - - def get_loss_profile(self, dic): - """Integrates the lost positions for all s positions, - generating the loss profile along the ring.""" - # dic = self.get_reordered_dict(l_scattered_pos, reording_key) - spos = self.spos - - df = _pd.DataFrame(dic) - a = df.set_index('lost_positions') - - scat_pos = _np.array(a.columns, dtype=float) - - indices = [] - for iten in scat_pos: - ind = _np.argmin(_np.abs(spos-iten)) - indices.append(ind) - - summed = [] - for idx, _ in a.iterrows(): - sum_row = scyint.trapz(a.loc[idx], spos[indices]) - summed.append(sum_row) - - _, ax = _plt.subplots(figsize=(13, 7), - gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) - ax.set_title('loss rate integral along the ring', fontsize=16) - - ax.set_xlabel('lost position [m]', fontsize=16) - ax.set_ylabel('loss rate [1/s]', fontsize=16) - ax.tick_params(axis='both', labelsize=16) - - ax.plot(list(a.index), summed, color='navy') - _pyaccel.graphics.draw_lattice(self._model_fit, - offset=-1e-6, height=1e-6, gca=True) - - def get_loss_profilel(self, l_dic): - """Comparing distinct loss profiles, could be used to compare with - the insertion of scrapers or not. - - l_dic: list of dictionaries of loss profiles""" - - # dic = self.get_reordered_dict(l_scattered_pos, reording_key) - lista = [] - for dic in l_dic: - s = self.spos - - df = _pd.DataFrame(dic) - a = df.set_index('lost_positions') - - scat_pos = _np.array(a.columns, dtype=float) - - indices = [] - for iten in scat_pos: - ind = _np.argmin(_np.abs(s-iten)) - indices.append(ind) - - summed = [] - for idx, _ in a.iterrows(): - sum_row = scyint.trapz(a.loc[idx], s[indices]) - summed.append(sum_row) - - lista.append((a.index, summed)) - - return lista - - - def plot_scat_table(self, new_dic): - """ Heatmap plot indicating the warm points of loss along the ring """ - s = self.spos - - df = _pd.DataFrame(new_dic) - df = df.set_index('lost_positions') - - val = df.values.copy() - idx = val != 0.0 - val[idx] = _np.log10(val[idx]) - val[~idx] = val[idx].min() - - fig, ax = _plt.subplots(figsize=(10, 10)) - - y = _np.linspace(0, s[-1], df.shape[0]+1) - x = _np.linspace(0, s[-1], df.shape[1]+1) - x_mesh, y_mesh = _np.meshgrid(x, y) - - heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap='jet', shading='flat') - - cbar = _plt.colorbar(heatmp) - cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) - - ax.set_title('Loss profile', fontsize=16) - - ax.set_xlabel('scattered positions [m]', fontsize=16) - ax.set_ylabel('lost positions [m]', fontsize=16) - - fig.tight_layout() - _plt.gca().set_aspect('equal') - _plt.show() From 6ad0334e635171b434bfe35ef2d1ab1e03870245 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 14 Dec 2023 12:54:12 -0300 Subject: [PATCH 093/108] corrigindo numpy random --- functions.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/functions.py b/functions.py index 44da8656..47cfbe50 100644 --- a/functions.py +++ b/functions.py @@ -349,7 +349,7 @@ def create_particles(cov_matrix, num_part): sig_yy = cov_matrix[3:, 3:] inv_yy = _np.linalg.inv(sig_yy) - part1 = _np.random.multivariate_normal(_np.zeros(6), + part1 = _np.random.Generator.multivariate_normal(_np.zeros(6), cov_matrix, num_part).T part2 = part1.copy() @@ -358,7 +358,7 @@ def create_particles(cov_matrix, num_part): new_mean = (sig_xy @ inv_yy) @ vec_a new_cov = sig_xx - sig_xy @ inv_yy @ sig_yx - part2[:3] = _np.random.multivariate_normal(_np.zeros(3), + part2[:3] = _np.random.Generator.multivariate_normal(_np.zeros(3), new_cov, num_part).T part2[:3] += new_mean @@ -391,7 +391,7 @@ def cross_section_draw_samples(psim, num_part): num_part = The number of particles to simulate. """ psi, cross = get_cross_section_distribution(psim) - crs = _np.random.rand(num_part) + crs = _np.random.Generator.rand(num_part) return _np.interp(crs, cross, psi) @@ -432,8 +432,8 @@ def scatter_particles(part1, part2, de_min): chi = _np.sqrt(zeta**2 + theta**2)/2 # draw the scattering angles from uniform distribution: - phi = _np.random.rand(num_part)* 2*_np.pi - psi = _np.random.rand(num_part)* _np.pi/2 + phi = _np.random.Generator.rand(num_part)* 2*_np.pi + psi = _np.random.Generator.rand(num_part)* _np.pi/2 # draw the psi angle from the cross section probability density: # we need to define a maximum angle to normalize the cross section From ca0458f41911b089f47e68549457bb06d42ca79b Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 15 Dec 2023 13:02:33 -0300 Subject: [PATCH 094/108] =?UTF-8?q?adicionando=20parametro=20para=20n?= =?UTF-8?q?=C3=A3o=20ser=20calculado=20sempre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From dd4b96c2cb3e34f8416719f6deec17701f93656b Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 15 Dec 2023 13:51:59 -0300 Subject: [PATCH 095/108] =?UTF-8?q?adicionando=20os=20limitantes=20f=C3=AD?= =?UTF-8?q?sicos=20por=20desvios=20de=20energia=20negativos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 309ab8f6b64dbff035d91ac1073b7e236fcaa73d Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 15 Dec 2023 15:31:24 -0300 Subject: [PATCH 096/108] =?UTF-8?q?otimizando=20as=20fun=C3=A7=C3=B5es=20d?= =?UTF-8?q?e=20ambos=20os=20arquivos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 197 ++++++++++++++++++++++++++--------------------- tous_analysis.py | 119 +++++++++++++++++++++++----- 2 files changed, 210 insertions(+), 106 deletions(-) diff --git a/functions.py b/functions.py index 47cfbe50..753a3d46 100644 --- a/functions.py +++ b/functions.py @@ -75,59 +75,56 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): return turnl_element +def track_eletrons_d(deltas, n_turn, element_idx, + model, pos_x=1e-5, pos_y=3e-6): + """Tracking simulation for touschek scattering that ocorred in element_idx. -def el_idx_collector(acc, lname): - """Selects the index of an especific element. - - acc = accelerator. - lname = list of names + model = accelerator. + deltas = e_dev + n_turn = number of turns desired. + pos_x = small shake in x + pos_y = || || || y """ - all_index = [] - - if 'mia' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) - elif 'mib' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) - elif 'mip' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) - - fam_data = _pymodels.si.get_family_data(acc) + orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) + orb = orb[:, 1] - for string in list(lname): - element_index = [] - array_idx = _np.array(fam_data[string]['index'], dtype=object) + rin = _np.zeros((6, deltas.size)) + rin += orb[:, None] + rin[0] += pos_x + rin[2] += pos_y + rin[4] += deltas - for _, lista in enumerate(array_idx): - length = len(lista) + track = _pyaccel.tracking.ring_pass( + model, rin, nr_turns=n_turn, turn_by_turn=True, + element_offset=element_idx, parallel=True) - if length % 2 != 0: - ind = int((length-1)/2) - element_index.append(lista[ind]) + _, _, turn_lost, element_lost, _ = track - else: - try: - ind = int(length/2 + 1) - element_index.append(lista[ind]) + dic = {} + t_lost, e_lost, delta = [], [], [] - except IndexError: - ind = int(length/2 - 1) - element_index.append(lista[ind]) + for i, item in enumerate(turn_lost): + if item == n_turn and element_lost[i] == element_idx: + pass + else: + t_lost.append(item) + e_lost.append(element_lost[i]) + delta.append(deltas[i]) - all_index.append(element_index) + dic['turn_lost'] = _np.array(t_lost) + dic['element_lost'] = _np.intp(e_lost) + dic['energy_deviation'] = _np.array(delta) - return all_index + return dic -def plot_track(acc, lista_resul, lista_idx, - lista_off, par, element_idx, accep, delt, f_dens): +def plot_track_d(acc, dic_tracked, index_list, + offs_list, par, element_idx, accep, delt, f_dens): """Plot the tracking results for a given s position. acc = accelerator. - lista_resul = list of information provided by tracking. - lista_idx = e_dev for calculating the physical limitants. - lista_off = list of e_dev used in tracking. + dic_tracked = dictionary of informations provided by tracking. + index_list = e_dev for calculating the physical limitants. + offs_list = list of e_dev used in tracking. par = defines the analysis for positive or negative e_dev. element_idx = defines initial conditions for tracking. accep = touschek energy acceptance. @@ -136,12 +133,14 @@ def plot_track(acc, lista_resul, lista_idx, """ # ---------------- - cm = 1/2.54 # 'poster' + turn_lost = dic_tracked['turn_lost'] + element_lost = dic_tracked['element_lost'] + deltas = dic_tracked['energy_deviation']*1e2 + cm = 1/2.54 # 'poster' twi0, *_ = _pyaccel.optics.calc_twiss(acc, indices='open') betax = twi0.betax betax = betax*(1/5) - spos = _pyaccel.lattice.find_spos(acc) fig = _plt.figure(figsize=(38.5*cm, 18*cm)) @@ -150,75 +149,97 @@ def plot_track(acc, lista_resul, lista_idx, a1 = fig.add_subplot(gs[0, 0]) a2 = fig.add_subplot(gs[0, 1], sharey=a1) a3 = fig.add_subplot(gs[0, 2], sharey=a1) + a1.tick_params(axis='both', labelsize=18) a2.tick_params(axis='y', which='both', - left=False, right=False, labelleft=False) + left=False, right=False, labelleft=False, labelsize=18) a3.tick_params(axis='y', which='both', - left=False, right=False, labelleft=False) - - a1.grid(True, alpha=0.5, ls='--', color='k') - a1.tick_params(axis='both', labelsize=18) - a2.grid(True, alpha=0.5, ls='--', color='k') + left=False, right=False, labelleft=False, labelsize=18) a2.tick_params(axis='both', labelsize=18) - a3.grid(True, alpha=0.5, ls='--', color='k') a3.tick_params(axis='both', labelsize=18) - a1.xaxis.grid(False) - a2.xaxis.grid(False) - a3.xaxis.grid(False) + a1.set_title(r'$\delta \times scat. rate$', fontsize=20) + a2.set_title(r'$\delta \times$ lost turn', fontsize=20) + a3.set_title(r'tracking ', fontsize=20) + + a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) + a2.set_xlabel(r'number of turns', fontsize=25) + a3.set_xlabel(r'$s$ [m]', fontsize=25) + + a1.grid(True, alpha=0.5, ls='--', color='k', axis='y') + a2.grid(True, alpha=0.5, ls='--', color='k', axis='y') + a3.grid(True, alpha=0.5, ls='--', color='k', axis='y') _plt.subplots_adjust(wspace=0.1) if 'pos' in par: a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - - a3.plot(spos[int(lista_resul[1][-1])], - lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[element_lost], deltas, 'r.', label='lost pos. (track)') acp_s = accep[1][element_idx] - indx = _np.argmin(_np.abs(lista_off-acp_s)) - a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2, 'b.', + indx = _np.argmin(_np.abs(offs_list-acp_s)) + a3.plot(spos[index_list][:indx], offs_list[:indx]*1e2, 'b.', label=r'accep. limit', alpha=0.25) - for item in lista_resul: - a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') + elif 'neg' in par: a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[int(lista_resul[1][-1])], - lista_resul[2][-1]*1e2, 'r.', label='lost pos. (track)') + a3.plot(spos[element_lost], deltas, 'r.', label='lost pos. (track)') acp_s = accep[0][element_idx] - indx = _np.argmin(_np.abs(lista_off+acp_s)) - a3.plot(spos[lista_idx][:indx], -lista_off[:indx]*1e2, 'b.', + indx = _np.argmin(_np.abs(offs_list+acp_s)) + a3.plot(spos[index_list][:indx], -offs_list[:indx]*1e2, 'b.', label=r'accep. limit', alpha=0.25) - for item in lista_resul: - a3.plot(spos[int(item[1])], item[2]*1e2, 'r.') - - a1.set_title(r'$\delta \times scat. rate$', fontsize=20) - a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') + a2.plot(turn_lost, deltas, 'k.') + stri = f'{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)' + a3.plot(spos[element_idx], 0, 'ko', label=stri) + a3.plot(spos, _np.sqrt(betax), + color='orange', label=r'$ \sqrt{\beta_x} $') + _plt.hlines(acp_s*1e2, spos[0], + spos[-1], color='black', linestyles='dashed', alpha=0.5) + _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) + a3.legend(loc='upper right', ncol=1, fontsize=15) + fig.show() - a2.set_title(r'$\delta \times$ lost turn', fontsize=20) - a2.set_xlabel(r'number of turns', fontsize=25) - for iten in lista_resul: - a2.plot(iten[0], iten[2]*1e2, 'k.') +def el_idx_collector(acc, lname): + """Selects the index of an especific element. + acc = accelerator. + lname = list of names + """ + all_index = [] - a3.set_title(r'tracking ', fontsize=20) - # plot the physical limitant untill the acceptance limit - # a3.plot(spos[lista_idx][:indx], lista_off[:indx]*1e2,'b.', - # label=r'accep. limit', alpha=0.25) + if 'mia' in lname: + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) + elif 'mib' in lname: + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) + elif 'mip' in lname: + all_index.append( + _pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) - _plt.hlines(1e2*acp_s, spos[0], - spos[-1], color='black', linestyles='dashed', alpha=0.5) - # hlines -> shows accep. limit + fam_data = _pymodels.si.get_family_data(acc) - a3.plot(spos, _np.sqrt(betax), - color='orange', label=r'$ \sqrt{\beta_x} $') # beta function - _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) + for string in list(lname): + element_index = [] + array_idx = _np.array(fam_data[string]['index'], dtype=object) - stri = f'{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)' - a3.plot(spos[element_idx], 0, 'ko', label=stri) - a3.set_xlabel(r'$s$ [m]', fontsize=25) - a3.legend(loc='upper right', ncol=1, fontsize=15) + for _, lista in enumerate(array_idx): + length = len(lista) - # fig.tight_layout() - fig.show() + if length % 2 != 0: + ind = int((length-1)/2) + element_index.append(lista[ind]) + + else: + try: + ind = int(length/2 + 1) + element_index.append(lista[ind]) + + except IndexError: + ind = int(length/2 - 1) + element_index.append(lista[ind]) + + all_index.append(element_index) + + return all_index # def t_list(elmnt): # não sei se isso é útil # """.""" diff --git a/tous_analysis.py b/tous_analysis.py index c5afb884..7e812ffa 100644 --- a/tous_analysis.py +++ b/tous_analysis.py @@ -11,6 +11,7 @@ import pandas as _pd import scipy.integrate as scyint import pyaccel as _pyaccel +from mathphys.functions import load_pickle class TousAnalysis(): """Class for the analysis of electron losses along the ring.""" @@ -30,8 +31,10 @@ def __init__(self, accelerator, self._amp_and_limidx = None self._sc_accps = None self._accep = None - self._inds_pos = None - self._inds_neg = None + self._inds_pos = load_pickle("/".join(__file__.split('/')[:-1]) + + '/ph_lim.pickle') + self._inds_neg = load_pickle("/".join(__file__.split('/')[:-1]) + + '/ph_lim_neg.pickle') self._amps_pos = None self._amps_neg = None self.num_part = 50000 @@ -193,6 +196,23 @@ def single_pos_track(self, single_spos, par): return res + def single_pos_track_d(self, single_spos, par): + """Single position tracking.""" + self._model.cavity_on = True + self._model.radiation_on = True + self._model.vchamber_on = True + s = self.spos + + index = _np.argmin(_np.abs(s-single_spos)) + if 'pos' in par: + res = to_fu.track_eletrons_d(self.deltas, self.nturns, index, + self._model, pos_x=1e-5, pos_y=3e-6) + elif 'neg' in par: + res = to_fu.track_eletrons_d(-self.deltas, self.nturns, index, + self._model, pos_x=1e-5, pos_y=3e-6) + + return res + def get_weighting_tous(self, single_spos, npt=5000): """.""" scalc, daccp, daccn = to_fu.get_scaccep( @@ -260,16 +280,36 @@ def get_trackndens(self, single_spos, par): elif 'neg' in par: return res, fn*delta_, -deltn*1e2 + def get_trackndens_new(self, single_spos, par): + """Concatenates tracking and touschek loss dens.""" + # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil + # raise ValueError('This function suports only one s position') + + fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) + + fp = fdensp.squeeze() + fn = fdensn.squeeze() + + dic = self.single_pos_track_d(single_spos, par) + deltas = dic['energy_deviation'] + delta_ = _np.abs(_np.diff(deltas)[0]) + + if 'pos' in par: + return dic, fp*delta_, deltp *1e2 + elif 'neg' in par: + return dic, fn*delta_, -deltn*1e2 + # this function plot the graphic of tracking and the touschek scattering # distribution for one single position - def plot_track_tousdens(self, single_spos, par, accep): + + def plot_track_tousdens_def(self, single_spos, par, accep): """Plot the results of tracking and the tous. scat. loss density. single_spos = single possition. par = defines the analysis (positive or negative). accep = touschek scattering acceptance. """ - res, fp, dp = self.get_trackndens(single_spos, par) + dic, fp, dp = self.get_trackndens_new(single_spos, par) s = self.spos if 'pos' in par: @@ -277,7 +317,8 @@ def plot_track_tousdens(self, single_spos, par, accep): elif 'neg' in par: inds = _np.intp(self.inds_neg) index = _np.argmin(_np.abs(s-single_spos)) - to_fu.plot_track(self.accelerator, res, inds, + + to_fu.plot_track_d(self.accelerator, dic, inds, self.off_energy, par, index, accep, dp, fp) def plot_normtousd(self, spos): @@ -416,29 +457,71 @@ def get_track(self, l_scattered_pos, scrap, vchamber): return all_track, indices + def get_track_def(self, l_scattered_pos, scrap, vchamber): + """Tracking for getting the loss profile along the ring. + + l_scattered_pos = scattered positions (list or numpy.array). + scrap = if True, the vchamber's height will be changed. + vchmaber = defines the new vchamber's apperture. + """ + all_track = [] + indices = [] + spos = self.spos + + self._model.radiation_on = True + self._model.cavity_on = True + self._model.vchamber_on = True + + if scrap: + self.set_vchamber_scraper(vchamber) + + for _, scattered_pos in enumerate(l_scattered_pos): + + index = _np.argmin(_np.abs(scattered_pos-spos)) + indices.append(index) + dic = to_fu.track_eletrons_d(self._deltas, self.nturns, + index, self._model) + all_track.append(dic) + + hx = self._model_fit[self.scraph_inds[0]].hmax + hn = self._model_fit[self.scraph_inds[0]].hmin + vx = self._model_fit[self.scrapv_inds[0]].vmax + vn = self._model_fit[self.scrapv_inds[0]].vmin + vchamber = [hx, hn, vx, vn] + + self.set_vchamber_scraper(vchamber) + + return all_track, indices + def find_data(self, l_scattered_pos, scrap, vchamber): # não consegui resolvero erro que o ruff indicou nessa função """Generating the data for the plot.""" - all_track, indices = self.get_track(l_scattered_pos, scrap, vchamber) + all_track, indices = self.get_track_def(l_scattered_pos, + scrap, vchamber) spos = self.spos - fact = 0.03 - # toushcek scattering rate - tous_rate = self.ltime.touschek_data['rate'] + + tous_rate = self.ltime.touschek_data['rate'] # scattering rate prob, lostp, all_lostp = [], [], [] - for j, single_track in enumerate(all_track): + # comentar os dois métodos implementados. + # um deles parece ser mais rápido. + # for j, single_track in enumerate(all_track): + for j, dic in enumerate(all_track): index = indices[j] - lostinds = _np.zeros(len(single_track)) - deltas = _np.zeros(len(single_track)) - for idx, iten in enumerate(single_track): - _, ellost, delta = iten - lostinds[idx] = ellost - deltas[idx] = delta + lostinds = dic['element_lost'] + deltas = dic['energy_deviation'] + + # lostinds = _np.zeros(len(single_track)) + # deltas = _np.zeros(len(single_track)) + # for idx, iten in enumerate(single_track): + # _, ellost, delta = iten + # lostinds[idx] = ellost + # deltas[idx] = delta + # lostinds = _np.intp(lostinds) - lostinds = _np.intp(lostinds) lost_positions = _np.round(spos[lostinds], 2) step = int((deltas[0]+deltas[-1])/fact) @@ -549,7 +632,7 @@ def get_table(self, l_scattered_pos, scrap, vchamber): if not idx: dic_res['lost_positions'] = all_lostp - stri = f'{scattered_pos:s}' + stri = f'{scattered_pos}' dic_res[stri] = scat_data else: stri = f'{scattered_pos}' From 88f9b36934c2c61c754f2d5227fc6c5589366aa4 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 20 Dec 2023 14:55:07 -0300 Subject: [PATCH 097/108] =?UTF-8?q?organizando=20conforme=20orienta=C3=A7?= =?UTF-8?q?=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 465 ++++++++++++++++++++++++++--------------------- tous_analysis.py | 441 +++++++++++++++++++++----------------------- 2 files changed, 469 insertions(+), 437 deletions(-) diff --git a/functions.py b/functions.py index 753a3d46..4cf7a839 100644 --- a/functions.py +++ b/functions.py @@ -1,5 +1,4 @@ """Functions_for_TousAnalysis.""" -import pymodels as _pymodels import pyaccel as _pyaccel import matplotlib.pyplot as _plt import numpy as _np @@ -7,45 +6,50 @@ import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity + def calc_amp(acc, energy_offsets, hmax, hmin): """Calculates the amplitudes and gets the physical limitants. - acc = accelerator. - energy_offsets = e_dev for calculate physical limitants. - hmax = horizontal max apperture. - hmin = horizontal min apperture. + acc = accelerator model. + energy_offsets = energy deviation for calculate physical limitants. + hmax = horizontal max apperture. + hmin = horizontal min apperture. """ a_def = _np.zeros(energy_offsets.size) indices = _np.zeros(energy_offsets.size) try: for idx, delta in enumerate(energy_offsets): twi, *_ = _pyaccel.optics.calc_twiss( - accelerator=acc, energy_offset=delta, indices='closed') + accelerator=acc, energy_offset=delta, indices="closed" + ) if _np.any(_np.isnan(twi[0].betax)): - raise _pyaccel.optics.OpticsException('error') + raise _pyaccel.optics.OpticsException("error") rx = twi.rx betax = twi.betax - a_sup = (hmax - rx)**2 /betax - a_inf = (hmin - rx)**2 /betax + a_sup = (hmax - rx) ** 2 / betax + a_inf = (hmin - rx) ** 2 / betax a_max = _np.minimum(a_sup, a_inf) idx_min = _np.argmin(a_max) indices[idx] = idx_min a_def[idx] = a_max[idx_min] - except (_pyaccel.optics.OpticsException, - _pyaccel.tracking.TrackingException): + except ( + _pyaccel.optics.OpticsException, + _pyaccel.tracking.TrackingException, + ): pass return _np.sqrt(a_def), indices + def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): """Tracking simulation for touschek scattering that ocorred in element_idx. - model = accelerator. - deltas = e_dev + model = accelerator model. + deltas = energy deviation. n_turn = number of turns desired. - pos_x = small shake in x - pos_y = || || || y + pos_x = small pertubation in x. + pos_y = small pertubation in y. """ orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] @@ -57,8 +61,13 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): rin[4] += deltas track = _pyaccel.tracking.ring_pass( - model, rin, nr_turns=n_turn, turn_by_turn=True, - element_offset=element_idx, parallel=True) + model, + rin, + nr_turns=n_turn, + turn_by_turn=True, + element_offset=element_idx, + parallel=True, + ) _, _, turn_lost, element_lost, _ = track # oculted variables/ part_out: final coordinates of electrons @@ -75,15 +84,17 @@ def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): return turnl_element -def track_eletrons_d(deltas, n_turn, element_idx, - model, pos_x=1e-5, pos_y=3e-6): + +def track_eletrons_d( + deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6 +): """Tracking simulation for touschek scattering that ocorred in element_idx. - model = accelerator. - deltas = e_dev + model = accelerator model. + deltas = energy deviation. n_turn = number of turns desired. - pos_x = small shake in x - pos_y = || || || y + pos_x = small pertubation in x. + pos_y = small pertubation in y. """ orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) orb = orb[:, 1] @@ -95,8 +106,13 @@ def track_eletrons_d(deltas, n_turn, element_idx, rin[4] += deltas track = _pyaccel.tracking.ring_pass( - model, rin, nr_turns=n_turn, turn_by_turn=True, - element_offset=element_idx, parallel=True) + model, + rin, + nr_turns=n_turn, + turn_by_turn=True, + element_offset=element_idx, + parallel=True, + ) _, _, turn_lost, element_lost, _ = track @@ -111,135 +127,139 @@ def track_eletrons_d(deltas, n_turn, element_idx, e_lost.append(element_lost[i]) delta.append(deltas[i]) - dic['turn_lost'] = _np.array(t_lost) - dic['element_lost'] = _np.intp(e_lost) - dic['energy_deviation'] = _np.array(delta) + dic["turn_lost"] = _np.array(t_lost) + dic["element_lost"] = _np.intp(e_lost) + dic["energy_deviation"] = _np.array(delta) return dic -def plot_track_d(acc, dic_tracked, index_list, - offs_list, par, element_idx, accep, delt, f_dens): + +def plot_track_d( + acc, + dic_tracked, + index_list, + offs_list, + par, + element_idx, + accep, + delt, + f_dens, +): """Plot the tracking results for a given s position. - acc = accelerator. - dic_tracked = dictionary of informations provided by tracking. - index_list = e_dev for calculating the physical limitants. - offs_list = list of e_dev used in tracking. - par = defines the analysis for positive or negative e_dev. - element_idx = defines initial conditions for tracking. - accep = touschek energy acceptance. - delt = e_dev for calculating the touschek loss rate density. - fdens = touschek loss rate density. + acc = accelerator model. + dic_tracked = dictionary of informations provided by tracking. + index_list = defines the physical limitants from linear model. + offs_list = list of e_dev used in tracking. + par = defines the analysis for positive or negative e_dev. + element_idx = defines initial conditions for tracking. + accep = touschek energy acceptance. + delt = energy deviation for the touschek loss rate density. + fdens = touschek loss rate density. """ # ---------------- - turn_lost = dic_tracked['turn_lost'] - element_lost = dic_tracked['element_lost'] - deltas = dic_tracked['energy_deviation']*1e2 + turn_lost = dic_tracked["turn_lost"] + element_lost = dic_tracked["element_lost"] + deltas = dic_tracked["energy_deviation"] * 1e2 - cm = 1/2.54 # 'poster' - twi0, *_ = _pyaccel.optics.calc_twiss(acc, indices='open') + cm = 1 / 2.54 # 'poster' + twi0, *_ = _pyaccel.optics.calc_twiss(acc, indices="open") betax = twi0.betax - betax = betax*(1/5) + betax = betax * (1 / 5) spos = _pyaccel.lattice.find_spos(acc) - fig = _plt.figure(figsize=(38.5*cm, 18*cm)) - gs = _plt.GridSpec(1, 3, left=0.1, - right=0.98, wspace=0.03, top=0.95, bottom=0.1, width_ratios=[2, 3, 8]) + fig = _plt.figure(figsize=(38.5 * cm, 18 * cm)) + gs = _plt.GridSpec( + 1, + 3, + left=0.1, + right=0.98, + wspace=0.03, + top=0.95, + bottom=0.1, + width_ratios=[2, 3, 8], + ) a1 = fig.add_subplot(gs[0, 0]) a2 = fig.add_subplot(gs[0, 1], sharey=a1) a3 = fig.add_subplot(gs[0, 2], sharey=a1) - a1.tick_params(axis='both', labelsize=18) - a2.tick_params(axis='y', which='both', - left=False, right=False, labelleft=False, labelsize=18) - a3.tick_params(axis='y', which='both', - left=False, right=False, labelleft=False, labelsize=18) - a2.tick_params(axis='both', labelsize=18) - a3.tick_params(axis='both', labelsize=18) - a1.set_title(r'$\delta \times scat. rate$', fontsize=20) - a2.set_title(r'$\delta \times$ lost turn', fontsize=20) - a3.set_title(r'tracking ', fontsize=20) - - a1.set_xlabel(r'$\tau _T$ [1/s]', fontsize=25) - a2.set_xlabel(r'number of turns', fontsize=25) - a3.set_xlabel(r'$s$ [m]', fontsize=25) - - a1.grid(True, alpha=0.5, ls='--', color='k', axis='y') - a2.grid(True, alpha=0.5, ls='--', color='k', axis='y') - a3.grid(True, alpha=0.5, ls='--', color='k', axis='y') + a1.tick_params(axis="both", labelsize=18) + a2.tick_params( + axis="y", + which="both", + left=False, + right=False, + labelleft=False, + labelsize=18, + ) + a3.tick_params( + axis="y", + which="both", + left=False, + right=False, + labelleft=False, + labelsize=18, + ) + a2.tick_params(axis="both", labelsize=18) + a3.tick_params(axis="both", labelsize=18) + a1.set_title(r"$\delta \times scat. rate$", fontsize=20) + a2.set_title(r"$\delta \times$ lost turn", fontsize=20) + a3.set_title(r"tracking ", fontsize=20) + + a1.set_xlabel(r"$\tau _T$ [1/s]", fontsize=25) + a2.set_xlabel(r"number of turns", fontsize=25) + a3.set_xlabel(r"$s$ [m]", fontsize=25) + + a1.grid(True, alpha=0.5, ls="--", color="k", axis="y") + a2.grid(True, alpha=0.5, ls="--", color="k", axis="y") + a3.grid(True, alpha=0.5, ls="--", color="k", axis="y") _plt.subplots_adjust(wspace=0.1) - if 'pos' in par: - a1.set_ylabel(r'positive $\delta$ [%]', fontsize=25) - a3.plot(spos[element_lost], deltas, 'r.', label='lost pos. (track)') + if "pos" in par: + a1.set_ylabel(r"positive $\delta$ [%]", fontsize=25) + a3.plot(spos[element_lost], deltas, "r.", label="lost pos. (track)") acp_s = accep[1][element_idx] - indx = _np.argmin(_np.abs(offs_list-acp_s)) - a3.plot(spos[index_list][:indx], offs_list[:indx]*1e2, 'b.', - label=r'accep. limit', alpha=0.25) - - elif 'neg' in par: - a1.set_ylabel(r'negative $\delta$ [%]', fontsize=25) - a3.plot(spos[element_lost], deltas, 'r.', label='lost pos. (track)') + indx = _np.argmin(_np.abs(offs_list - acp_s)) + a3.plot( + spos[index_list][:indx], + offs_list[:indx] * 1e2, + "b.", + label=r"accep. limit", + alpha=0.25, + ) + + elif "neg" in par: + a1.set_ylabel(r"negative $\delta$ [%]", fontsize=25) + a3.plot(spos[element_lost], deltas, "r.", label="lost pos. (track)") acp_s = accep[0][element_idx] - indx = _np.argmin(_np.abs(offs_list+acp_s)) - a3.plot(spos[index_list][:indx], -offs_list[:indx]*1e2, 'b.', - label=r'accep. limit', alpha=0.25) - - a1.plot(f_dens, delt, label='Scattering touschek rate', color='black') - a2.plot(turn_lost, deltas, 'k.') - stri = f'{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)' - a3.plot(spos[element_idx], 0, 'ko', label=stri) - a3.plot(spos, _np.sqrt(betax), - color='orange', label=r'$ \sqrt{\beta_x} $') - _plt.hlines(acp_s*1e2, spos[0], - spos[-1], color='black', linestyles='dashed', alpha=0.5) + indx = _np.argmin(_np.abs(offs_list + acp_s)) + a3.plot( + spos[index_list][:indx], + -offs_list[:indx] * 1e2, + "b.", + label=r"accep. limit", + alpha=0.25, + ) + + a1.plot(f_dens, delt, label="Scattering touschek rate", color="black") + a2.plot(turn_lost, deltas, "k.") + stri = f"{acc[element_idx].fam_name}, ({spos[element_idx]:.2f} m)" + a3.plot(spos[element_idx], 0, "ko", label=stri) + a3.plot( + spos, _np.sqrt(betax), color="orange", label=r"$ \sqrt{\beta_x} $" + ) + _plt.hlines( + acp_s * 1e2, + spos[0], + spos[-1], + color="black", + linestyles="dashed", + alpha=0.5, + ) _pyaccel.graphics.draw_lattice(acc, offset=-0.5, height=0.5, gca=True) - a3.legend(loc='upper right', ncol=1, fontsize=15) + a3.legend(loc="upper right", ncol=1, fontsize=15) fig.show() -def el_idx_collector(acc, lname): - """Selects the index of an especific element. - - acc = accelerator. - lname = list of names - """ - all_index = [] - - if 'mia' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mia')) - elif 'mib' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mib')) - elif 'mip' in lname: - all_index.append( - _pyaccel.lattice.find_indices(acc, 'fam_name', 'mip')) - - fam_data = _pymodels.si.get_family_data(acc) - - for string in list(lname): - element_index = [] - array_idx = _np.array(fam_data[string]['index'], dtype=object) - - for _, lista in enumerate(array_idx): - length = len(lista) - - if length % 2 != 0: - ind = int((length-1)/2) - element_index.append(lista[ind]) - - else: - try: - ind = int(length/2 + 1) - element_index.append(lista[ind]) - - except IndexError: - ind = int(length/2 - 1) - element_index.append(lista[ind]) - - all_index.append(element_index) - - return all_index # def t_list(elmnt): # não sei se isso é útil # """.""" @@ -252,79 +272,100 @@ def el_idx_collector(acc, lname): def f_function_arg_mod(kappa, kappam, b1_, b2_, norm): - """.""" - tau = (_np.tan(kappa)**2)[:, None] - taum = _np.tan(kappam)**2 + """Returns the touschek loss rate density. + + kappa = substitution that turns easier calculations. + kappam = kappa minimum that defines the lower integration limit. + b1_ = optical parameter obtained by accelerator model. + b2_ = optical parameter obtained by accelerator model. + norm = defines if the function will returns density or not. + """ + tau = (_np.tan(kappa) ** 2)[:, None] + taum = _np.tan(kappam) ** 2 beta = _beam_rigidity(energy=3)[2] - ratio = tau/taum/(1+tau) - arg = (2*tau+1)**2 * (ratio - 1)/tau - arg += tau - _np.sqrt(tau*taum*(1+tau)) - arg -= (2+1/(2*tau))*_np.log(ratio) - arg *= _np.sqrt(1+tau) -# arg *= beta* _np.cos(kappa)[:, None]**2 - arg *= 1/(2*_np.sqrt(tau)) * 1/(1+tau) - arg *= 2* beta* _np.sqrt(tau) + ratio = tau / taum / (1 + tau) + arg = (2 * tau + 1) ** 2 * (ratio - 1) / tau + arg += tau - _np.sqrt(tau * taum * (1 + tau)) + arg -= (2 + 1 / (2 * tau)) * _np.log(ratio) + arg *= _np.sqrt(1 + tau) + # arg *= beta* _np.cos(kappa)[:, None]**2 + arg *= 1 / (2 * _np.sqrt(tau)) * 1 / (1 + tau) + arg *= 2 * beta * _np.sqrt(tau) - bessel = _np.exp(-(b1_-b2_)*tau)*_special.i0e(b2_*tau) + bessel = _np.exp(-(b1_ - b2_) * tau) * _special.i0e(b2_ * tau) if norm: pass else: - arg *= 2*_np.sqrt(_np.pi*(b1_**2-b2_**2))*taum + arg *= 2 * _np.sqrt(_np.pi * (b1_**2 - b2_**2)) * taum return arg * bessel def get_scaccep(acc, accep): - """.""" - spos = _pyaccel.lattice.find_spos(acc, indices='closed') + """Returns the s position and the energy acceptance every 10 cm. - npt = int((spos[-1]-spos[0])/0.1) + acc = accelerator model used to acquire the optical parameters. + accep = positive and negative energy acceptance. + """ + spos = _pyaccel.lattice.find_spos(acc, indices="closed") + + npt = int((spos[-1] - spos[0]) / 0.1) scalc = _np.linspace(spos[0], spos[-1], npt) daccpp = _np.interp(scalc, spos, accep[1]) daccpn = _np.interp(scalc, spos, accep[0]) return scalc, daccpp, daccpn + # Como discutido no dia 23.08.2023 corte para a definição da densidade # de espalhamento Touschek ocorre na aceitância de energia para deter # minado ponto. -def norm_cutacp(acc, lsps, _npt, accep, norm=False): - """.""" + +def norm_cutacp(acc, lsps, npt, accep, norm=False): + """Plot loss rate for a list of s positions. + + acc = accelerator model used to acquire the optical parameters. + lsps = list of s positions to calculate loss density. + npt = number of points to a linspace array. + accep = positive and negative energy acceptance. + norm = parameter to define if the function will return density. + """ dic = {} scalc, daccpp, daccpn = get_scaccep(acc, accep) beta = _beam_rigidity(energy=3)[2] - taum_p = (beta*daccpp)**2 - taum_n = (beta*daccpn)**2 + taum_p = (beta * daccpp) ** 2 + taum_n = (beta * daccpn) ** 2 kappam_p = _np.arctan(_np.sqrt(taum_p)) kappam_n = _np.arctan(_np.sqrt(taum_n)) ltime = _pyaccel.lifetime.Lifetime(acc) - b1 = ltime.touschek_data['touschek_coeffs']['b1'] - b2 = ltime.touschek_data['touschek_coeffs']['b2'] + b1 = ltime.touschek_data["touschek_coeffs"]["b1"] + b2 = ltime.touschek_data["touschek_coeffs"]["b2"] fdens_p, fdens_n = [], [] deltasp, deltasn = [], [] for _, s in enumerate(lsps): - idx = _np.argmin(_np.abs(scalc - s)) kappam_p0 = kappam_p[idx] kappam_n0 = kappam_n[idx] - kappap = _np.linspace(kappam_p0, _np.pi/2, _npt) - deltap = 1/beta * _np.tan(kappap) - kappan = _np.linspace(kappam_n0, _np.pi/2, _npt) - deltan = 1/beta * _np.tan(kappan) - - y_p = f_function_arg_mod(kappa=kappap, - kappam=kappam_p0, b1_=b1[idx], b2_=b2[idx], norm=norm).squeeze() - y_n = f_function_arg_mod(kappa=kappan, - kappam=kappam_n0, b1_=b1[idx], b2_=b2[idx], norm=norm).squeeze() + kappap = _np.linspace(kappam_p0, _np.pi / 2, npt) + deltap = 1 / beta * _np.tan(kappap) + kappan = _np.linspace(kappam_n0, _np.pi / 2, npt) + deltan = 1 / beta * _np.tan(kappan) + + y_p = f_function_arg_mod( + kappa=kappap, kappam=kappam_p0, b1_=b1[idx], b2_=b2[idx], norm=norm + ).squeeze() + y_n = f_function_arg_mod( + kappa=kappan, kappam=kappam_n0, b1_=b1[idx], b2_=b2[idx], norm=norm + ).squeeze() norm_facp = _scyint.trapz(y_p, deltap) norm_facn = _scyint.trapz(y_n, deltan) @@ -347,15 +388,20 @@ def norm_cutacp(acc, lsps, _npt, accep, norm=False): deltasp = _np.array(deltasp) deltasn = _np.array(deltasn) - dic['fdensp'] = fdens_p - dic['fdensn'] = fdens_n - dic['deltasp'] = deltasp - dic['deltasn'] = deltasn + dic["fdensp"] = fdens_p + dic["fdensn"] = fdens_n + dic["deltasp"] = deltasp + dic["deltasn"] = deltasn return dic + def create_particles(cov_matrix, num_part): - """Creates the beam to realize the Monte-Carlo simulation.""" + """Creates the beam to realize the Monte-Carlo simulation. + + cov_matrix = covariant matrix to generate beam distribution. + num_part = particles' number for M.C. simulation. + """ # permute indices to change the order of the columns: # [rx, px, ry, py, de, dl]^T -> [px, py, de, rx, ry, dl]^T idcs = [1, 3, 4, 0, 2, 5] @@ -370,8 +416,9 @@ def create_particles(cov_matrix, num_part): sig_yy = cov_matrix[3:, 3:] inv_yy = _np.linalg.inv(sig_yy) - part1 = _np.random.Generator.multivariate_normal(_np.zeros(6), - cov_matrix, num_part).T + part1 = _np.random.Generator.multivariate_normal( + _np.zeros(6), cov_matrix, num_part + ).T part2 = part1.copy() @@ -379,8 +426,9 @@ def create_particles(cov_matrix, num_part): new_mean = (sig_xy @ inv_yy) @ vec_a new_cov = sig_xx - sig_xy @ inv_yy @ sig_yx - part2[:3] = _np.random.Generator.multivariate_normal(_np.zeros(3), - new_cov, num_part).T + part2[:3] = _np.random.Generator.multivariate_normal( + _np.zeros(3), new_cov, num_part + ).T part2[:3] += new_mean part2 = part2[idcs_r, :] @@ -388,17 +436,24 @@ def create_particles(cov_matrix, num_part): return part1, part2 -def get_cross_section_distribution(psim, _npts=3000): - """Calculates the Moller's cross section.""" + +def get_cross_section_distribution(psim, npts=3000): + """Calculates the Moller's cross section. + + psim = minimum scattering angle (lower integration limitant). + npts = number of point for a logspace function. + """ beta_bar = 0 - psi = _np.logspace(_np.log10(_np.pi/2 - psim), 0, _npts) - psi = _np.pi/2 - psi + psi = _np.logspace(_np.log10(_np.pi / 2 - psim), 0, npts) + psi = _np.pi / 2 - psi psi = psi[::-1] cpsi = _np.cos(psi) cross = _np.zeros(cpsi.size) if beta_bar > 1e-19: - cross += (1 + 1/beta_bar**2)**2 * (2*(1 + cpsi**2)/cpsi**3 - 3/cpsi) - cross += 4/cpsi + 1 + cross += (1 + 1 / beta_bar**2) ** 2 * ( + 2 * (1 + cpsi**2) / cpsi**3 - 3 / cpsi + ) + cross += 4 / cpsi + 1 cross *= _np.sin(psi) cross = _scyint.cumtrapz(cross, x=psi, initial=0.0) cross /= cross[-1] @@ -408,8 +463,8 @@ def get_cross_section_distribution(psim, _npts=3000): def cross_section_draw_samples(psim, num_part): """Interpolates the cross section effect. - psim = Defines the maximum e_dev that remains the electrons' orbit stable. - num_part = The number of particles to simulate. + psim = minimum scat. angle that remains the electrons' orbit stable. + num_part = number of particles for simulation. """ psi, cross = get_cross_section_distribution(psim) crs = _np.random.Generator.rand(num_part) @@ -419,18 +474,20 @@ def cross_section_draw_samples(psim, num_part): def scatter_particles(part1, part2, de_min): """M.C. simulation of the Touschek scattering process. - docstring. + part1 = partcile's coordinates. + part2 = partcile's coordinates. + de_min = mimimum energy deviation. """ gamma = 3e9 / 0.510e6 - beta = _np.sqrt(1 - 1/gamma/gamma) + beta = _np.sqrt(1 - 1 / gamma / gamma) num_part = part1.shape[1] xl1, yl1, de1 = part1[1], part1[3], part1[4] xl2, yl2, de2 = part2[1], part2[3], part2[4] # calculating the changing base matrix for every particle - pz1 = _np.sqrt((1+de1)**2 - xl1*xl1 - yl1*yl1) - pz2 = _np.sqrt((1+de2)**2 - xl2*xl2 - yl2*yl2) + pz1 = _np.sqrt((1 + de1) ** 2 - xl1 * xl1 - yl1 * yl1) + pz2 = _np.sqrt((1 + de2) ** 2 - xl2 * xl2 - yl2 * yl2) # desired vectors to construct the transformation matrix p_1 = _np.vstack([xl1, yl1, pz1]) @@ -450,11 +507,11 @@ def scatter_particles(part1, part2, de_min): theta = xl1 - xl2 zeta = yl1 - yl2 - chi = _np.sqrt(zeta**2 + theta**2)/2 + chi = _np.sqrt(zeta**2 + theta**2) / 2 # draw the scattering angles from uniform distribution: - phi = _np.random.Generator.rand(num_part)* 2*_np.pi - psi = _np.random.Generator.rand(num_part)* _np.pi/2 + phi = _np.random.Generator.rand(num_part) * 2 * _np.pi + psi = _np.random.Generator.rand(num_part) * _np.pi / 2 # draw the psi angle from the cross section probability density: # we need to define a maximum angle to normalize the cross section @@ -469,17 +526,20 @@ def scatter_particles(part1, part2, de_min): # the particles distribution. # This method of doing things should be tested and thought about very # carefully, though. - psim = _np.arccos(de_min/gamma/(chi.max()*2)) - fact = psim*2/_np.pi - print(psim*2/_np.pi) + psim = _np.arccos(de_min / gamma / (chi.max() * 2)) + fact = psim * 2 / _np.pi + print(psim * 2 / _np.pi) psi = cross_section_draw_samples(psim, num_part) # new momentum in j,k,l (eq. 16 of Piwinski paper) - gammat = gamma/_np.sqrt(1 + beta*beta*gamma*gamma*chi*chi) - dp_ = _np.sin(chi[None, :]) * _np.vstack([ - gammat*_np.cos(psi), - _np.sin(psi)*_np.cos(phi), - _np.sin(psi)*_np.sin(phi)]) + gammat = gamma / _np.sqrt(1 + beta * beta * gamma * gamma * chi * chi) + dp_ = _np.sin(chi[None, :]) * _np.vstack( + [ + gammat * _np.cos(psi), + _np.sin(psi) * _np.cos(phi), + _np.sin(psi) * _np.sin(phi), + ] + ) p_prime1 = _np.zeros((3, chi.size)) p_prime1[0] = _np.cos(chi) p_prime2 = p_prime1.copy() @@ -505,6 +565,7 @@ def scatter_particles(part1, part2, de_min): return part1_new, part2_new, fact + def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): """Calculates the touschek scattering densities. @@ -515,13 +576,12 @@ def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): cutaccep = defines the cutoff on the energy acceptance. """ envelopes = _pyaccel.optics.calc_beamenvelope(acc) - spos = _pyaccel.lattice.find_spos(acc, indices='closed') + spos = _pyaccel.lattice.find_spos(acc, indices="closed") scalc, daccpp, daccpn = get_scaccep(acc, accep) histsp1, histsp2, indices = [], [], [] for iten in l_spos: - idx_model = _np.argmin(_np.abs(spos - iten)) idx = _np.argmin(_np.abs(scalc - iten)) indices.append(idx_model) @@ -535,7 +595,6 @@ def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): part1_new, part2_new, _ = scatter_particles(part1, part2, de_min) if cutaccep: # if true the cutoff is the accp at the s - acpp, acpn = daccpp[idx], daccpn[idx] check1 = acpp - part1_new[4] check2 = -(acpn - part2_new[4]) @@ -543,15 +602,15 @@ def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): ind1 = _np.intp(_np.where(check1 < 0)[0]) ind2 = _np.intp(_np.where(check2 < 0)[0]) - histsp1.append(part1_new[4][ind1]*1e2) - histsp2.append(part2_new[4][ind2]*1e2) + histsp1.append(part1_new[4][ind1] * 1e2) + histsp2.append(part2_new[4][ind2] * 1e2) else: # ximenes cutoff ind1 = _np.intp(_np.where(part1_new[4] >= 0.01)[0]) ind2 = _np.intp(_np.where(part2_new[4] <= -0.01)[0]) - histsp1.append(part1_new[4][ind1]*1e2) - histsp2.append(part2_new[4][ind2]*1e2) + histsp1.append(part1_new[4][ind1] * 1e2) + histsp2.append(part2_new[4][ind2] * 1e2) indices = _np.array(indices) diff --git a/tous_analysis.py b/tous_analysis.py index 7e812ffa..37057d78 100644 --- a/tous_analysis.py +++ b/tous_analysis.py @@ -13,17 +13,21 @@ import pyaccel as _pyaccel from mathphys.functions import load_pickle -class TousAnalysis(): + +class TousAnalysis: """Class for the analysis of electron losses along the ring.""" - def __init__(self, accelerator, - energies_off=None, beam_energy=None, n_turns=7): + + def __init__( + self, accelerator, energies_off=None, beam_energy=None, n_turns=7 + ): """Parameters necessary to define the class.""" if energies_off is None: energy_off = _np.linspace(0, 0.046, 460) # physical limitants deltas = _np.linspace(0, 0.1, 400) # energy off for tracking if beam_energy is None: # defining beta factor - beta = _beam_rigidity(energy=3)[2] + beam_energy = _beam_rigidity(energy=3)[2] + beta = beam_energy self._model_fit = accelerator self._model = pymodels.si.create_accelerator() @@ -31,25 +35,27 @@ def __init__(self, accelerator, self._amp_and_limidx = None self._sc_accps = None self._accep = None - self._inds_pos = load_pickle("/".join(__file__.split('/')[:-1]) - + '/ph_lim.pickle') - self._inds_neg = load_pickle("/".join(__file__.split('/')[:-1]) - + '/ph_lim_neg.pickle') + self._inds_pos = load_pickle( + "/".join(__file__.split("/")[:-1]) + "/ph_lim.pickle" + ) + self._inds_neg = load_pickle( + "/".join(__file__.split("/")[:-1]) + "/ph_lim_neg.pickle" + ) self._amps_pos = None self._amps_neg = None self.num_part = 50000 self.energy_dev_min = 1e-4 self.beta = beta # beta factor - self.h_pos = get_attribute(self._model_fit, 'hmax', indices='closed') - self.h_neg = get_attribute(self._model_fit, 'hmin', indices='closed') + self.h_pos = get_attribute(self._model_fit, "hmax", indices="closed") + self.h_neg = get_attribute(self._model_fit, "hmin", indices="closed") self.ltime = Lifetime(self._model_fit) self._off_energy = energy_off # (linear model) en_dev to amplitudes self.nturns = n_turns self._deltas = deltas - self.spos = find_spos(self._model_fit, indices='closed') - self.scraph_inds = find_indices(self._model, 'fam_name', 'SHVC') - self.scrapv_inds = find_indices(self._model, 'fam_name', 'SVVC') + self.spos = find_spos(self._model_fit, indices="closed") + self.scraph_inds = find_indices(self._model, "fam_name", "SHVC") + self.scrapv_inds = find_indices(self._model, "fam_name", "SVVC") @property def accelerator(self): @@ -75,7 +81,8 @@ def accep(self): """Defines Touschek energy acceptance.""" if self._accep is None: self._accep = py_op.calc_touschek_energy_acceptance( - self.accelerator) + self.accelerator + ) return self._accep @property @@ -101,10 +108,12 @@ def amp_and_limidx(self): self._model.radiation_on = False self._amps_pos, self._inds_pos = to_fu.calc_amp( - self._model, self.off_energy, self.h_pos, self.h_neg) + self._model, self.off_energy, self.h_pos, self.h_neg + ) self._amps_neg, self._inds_neg = to_fu.calc_amp( - self._model, -self.off_energy, self.h_pos, self.h_neg) + self._model, -self.off_energy, self.h_pos, self.h_neg + ) self._amp_and_limidx = True @@ -124,7 +133,7 @@ def off_energy(self, accep): """ accep_pos, accep_neg = accep accep_lim = _np.max(_np.maximum(accep_pos, _np.abs(accep_neg))) - steps = int(accep_lim*10000) # choosen to be the number of steps + steps = int(accep_lim * 10000) # choosen to be the number of steps self._off_energy = _np.linspace(0, accep_lim, steps) @property @@ -179,65 +188,61 @@ def set_vchamber_scraper(self, vchamber): model[iten].vmin = vchamber[2] model[iten].vmax = vchamber[3] - def single_pos_track(self, single_spos, par): - """Single position tracking.""" - self._model.cavity_on = True - self._model.radiation_on = True - self._model.vchamber_on = True - s = self.spos - - index = _np.argmin(_np.abs(s-single_spos)) - if 'pos' in par: - res = to_fu.track_eletrons(self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) - elif 'neg' in par: - res = to_fu.track_eletrons(-self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) - - return res - - def single_pos_track_d(self, single_spos, par): + def _single_pos_track(self, single_spos, par): """Single position tracking.""" self._model.cavity_on = True self._model.radiation_on = True self._model.vchamber_on = True s = self.spos - index = _np.argmin(_np.abs(s-single_spos)) - if 'pos' in par: - res = to_fu.track_eletrons_d(self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) - elif 'neg' in par: - res = to_fu.track_eletrons_d(-self.deltas, self.nturns, index, - self._model, pos_x=1e-5, pos_y=3e-6) + index = _np.argmin(_np.abs(s - single_spos)) + if "pos" in par: + res = to_fu.track_eletrons_d( + self.deltas, + self.nturns, + index, + self._model, + pos_x=1e-5, + pos_y=3e-6, + ) + elif "neg" in par: + res = to_fu.track_eletrons_d( + -self.deltas, + self.nturns, + index, + self._model, + pos_x=1e-5, + pos_y=3e-6, + ) return res - def get_weighting_tous(self, single_spos, npt=5000): + def _get_weighting_tous(self, single_spos, npt=5000): """.""" - scalc, daccp, daccn = to_fu.get_scaccep( - self.accelerator, self.accep) + scalc, daccp, daccn = to_fu.get_scaccep(self.accelerator, self.accep) bf = self.beta # bf:beta factor lt = self.ltime - b1 = lt.touschek_data['touschek_coeffs']['b1'] - b2 = lt.touschek_data['touschek_coeffs']['b2'] + b1 = lt.touschek_data["touschek_coeffs"]["b1"] + b2 = lt.touschek_data["touschek_coeffs"]["b2"] - taup, taun = (bf* daccp)**2, (bf*daccn)**2 - idx = _np.argmin(_np.abs(scalc-single_spos)) + taup, taun = (bf * daccp) ** 2, (bf * daccn) ** 2 + idx = _np.argmin(_np.abs(scalc - single_spos)) taup_0, taun_0 = taup[idx], taun[idx] kappap_0 = _np.arctan(_np.sqrt(taup_0)) kappan_0 = _np.arctan(_np.sqrt(taun_0)) - kappa_pos = _np.linspace(kappap_0, _np.pi/2, npt) - kappa_neg = _np.linspace(kappan_0, _np.pi/2, npt) + kappa_pos = _np.linspace(kappap_0, _np.pi / 2, npt) + kappa_neg = _np.linspace(kappan_0, _np.pi / 2, npt) - deltp = _np.tan(kappa_pos)/bf - deltn = _np.tan(kappa_neg)/bf + deltp = _np.tan(kappa_pos) / bf + deltn = _np.tan(kappa_neg) / bf fdensp = to_fu.f_function_arg_mod( - kappa_pos, kappap_0, b1[idx], b2[idx], norm=False) + kappa_pos, kappap_0, b1[idx], b2[idx], norm=False + ) fdensn = to_fu.f_function_arg_mod( - kappa_neg, kappan_0, b1[idx], b2[idx], norm=False) + kappa_neg, kappan_0, b1[idx], b2[idx], norm=False + ) # eliminating negative values indp = _np.where(fdensp < 0)[0] @@ -252,74 +257,59 @@ def get_weighting_tous(self, single_spos, npt=5000): fdensn = fdensn[ind] deltn = deltn[ind] - self.deltas = deltp[-1]*1e2 + self.deltas = deltp[-1] * 1e2 return fdensp, fdensn, deltp, deltn - def get_trackndens(self, single_spos, par): + def _get_trackndens(self, single_spos, par): """Concatenates tracking and touschek loss dens.""" # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil # raise ValueError('This function suports only one s position') - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) + fdensp, fdensn, deltp, deltn = self._get_weighting_tous(single_spos) fp = fdensp.squeeze() fn = fdensn.squeeze() - res = self.single_pos_track(single_spos, par) - delta = _np.zeros(len(res)) - - for index, iten in enumerate(res): - _, _, delt = iten - delta[index] = delt - - delta_ = _np.abs(_np.diff(delta)[0]) - - if 'pos' in par: - return res, fp*delta_, deltp *1e2 - elif 'neg' in par: - return res, fn*delta_, -deltn*1e2 - - def get_trackndens_new(self, single_spos, par): - """Concatenates tracking and touschek loss dens.""" - # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil - # raise ValueError('This function suports only one s position') - - fdensp, fdensn, deltp, deltn = self.get_weighting_tous(single_spos) - - fp = fdensp.squeeze() - fn = fdensn.squeeze() - - dic = self.single_pos_track_d(single_spos, par) - deltas = dic['energy_deviation'] + dic = self._single_pos_track(single_spos, par) + deltas = dic["energy_deviation"] delta_ = _np.abs(_np.diff(deltas)[0]) - if 'pos' in par: - return dic, fp*delta_, deltp *1e2 - elif 'neg' in par: - return dic, fn*delta_, -deltn*1e2 + if "pos" in par: + return dic, fp * delta_, deltp * 1e2 + elif "neg" in par: + return dic, fn * delta_, -deltn * 1e2 # this function plot the graphic of tracking and the touschek scattering # distribution for one single position - def plot_track_tousdens_def(self, single_spos, par, accep): + def plot_track_lossdens(self, single_spos, par, accep): """Plot the results of tracking and the tous. scat. loss density. - single_spos = single possition. - par = defines the analysis (positive or negative). - accep = touschek scattering acceptance. + single_spos = single possition. + par = defines the analysis (positive or negative). + accep = touschek scattering acceptance. """ - dic, fp, dp = self.get_trackndens_new(single_spos, par) + dic, fp, dp = self._get_trackndens(single_spos, par) s = self.spos - if 'pos' in par: + if "pos" in par: inds = _np.intp(self.inds_pos) - elif 'neg' in par: + elif "neg" in par: inds = _np.intp(self.inds_neg) - index = _np.argmin(_np.abs(s-single_spos)) - - to_fu.plot_track_d(self.accelerator, dic, inds, - self.off_energy, par, index, accep, dp, fp) + index = _np.argmin(_np.abs(s - single_spos)) + + to_fu.plot_track_d( + self.accelerator, + dic, + inds, + self.off_energy, + par, + index, + accep, + dp, + fp, + ) def plot_normtousd(self, spos): """Touschek scattering loss density. @@ -327,24 +317,27 @@ def plot_normtousd(self, spos): spos = desired s positions (list or numpy.array) """ spos_ring = self.spos - dic = to_fu.norm_cutacp(self._model_fit, - spos, 5000, self._accep, norm=True) + dic = to_fu.norm_cutacp( + self._model_fit, spos, 5000, self._accep, norm=True + ) - fdensp, fdensn = dic['fdensp'], dic['fdensn'] - deltasp, deltasn = dic['deltasp'], dic['deltasn'] + fdensp, fdensn = dic["fdensp"], dic["fdensn"] + deltasp, deltasn = dic["deltasp"], dic["deltasn"] _, ax = _plt.subplots(figsize=(10, 5)) ax.set_title( - 'Probability density analytically calculated', fontsize=20) - ax.grid(True, alpha=0.5, ls='--', color='k') + "Probability density analytically calculated", fontsize=20 + ) + ax.grid(True, alpha=0.5, ls="--", color="k") ax.xaxis.grid(False) - ax.set_xlabel(r'$\delta$ [%]', fontsize=25) - ax.set_ylabel('PDF', fontsize=25) - ax.tick_params(axis='both', labelsize=28) + ax.set_xlabel(r"$\delta$ [%]", fontsize=25) + ax.set_ylabel("PDF", fontsize=25) + ax.tick_params(axis="both", labelsize=28) for idx, _ in enumerate(spos): - array_fdens = fdensp[idx] + # pega o primeiro item onde ocorre a condição passada + # como argumento para a função numpy.where index = _np.intp(_np.where(array_fdens <= 1e-2)[0][1]) # this block selects the best index @@ -352,36 +345,41 @@ def plot_normtousd(self, spos): if not idx: best_index = index else: - if best_index < index: + if best_index < index: # eu não entendi direito porquê disso best_index = index else: pass for idx, s in enumerate(spos): - - mod_ind = _np.argmin(_np.abs(spos_ring-s)) + mod_ind = _np.argmin(_np.abs(spos_ring - s)) fdenspi = fdensp[idx][:best_index] fdensni = fdensn[idx][:best_index] - deltaspi = deltasp[idx][:best_index]*1e2 - deltasni = -deltasn[idx][:best_index]*1e2 - - color = _cm.gist_rainbow(idx/len(spos)) - not_desired = ['calc_mom_accep', - 'mia', 'mib', 'mip', - 'mb1', 'mb2', 'mc'] + deltaspi = deltasp[idx][:best_index] * 1e2 + deltasni = -deltasn[idx][:best_index] * 1e2 + + color = _cm.gist_rainbow(idx / len(spos)) + not_desired = [ + "calc_mom_accep", + "mia", + "mib", + "mip", + "mb1", + "mb2", + "mc", + ] while self._model_fit[mod_ind].fam_name in not_desired: mod_ind += 1 fam_name = self._model_fit[mod_ind].fam_name s_stri = _np.round(spos_ring[mod_ind], 2) - stri = f'{fam_name} em {s_stri} m' + stri = f"{fam_name} em {s_stri} m" ax.plot(deltaspi, fdenspi, label=stri, color=color) ax.plot(deltasni, fdensni, color=color) - ax.legend(loc='best', fontsize=20) + ax.legend(loc="best", fontsize=20) def plot_histograms(self, l_spos): """Touschek scattering density from Monte-Carlo simulation. @@ -392,72 +390,43 @@ def plot_histograms(self, l_spos): accep = self.accep model = self._model_fit - tup = to_fu.histgms(self._model_fit, l_spos, self.num_part, accep, - self.energy_dev_min, cutaccep=False) + tup = to_fu.histgms( + self._model_fit, + l_spos, + self.num_part, + accep, + self.energy_dev_min, + cutaccep=False, + ) hp, hn, idx_model = tup fig, ax = _plt.subplots( - ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True) + ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True + ) fig.suptitle( - 'Probability density calculated by Monte-Carlo simulation', - fontsize=20) + "Probability density calculated by Monte-Carlo simulation", + fontsize=20, + ) for index, iten in enumerate(idx_model): - color = _cm.jet(index/len(idx_model)) + color = _cm.jet(index / len(idx_model)) ay = ax[index] if not index: - ay.set_ylabel('PDF', fontsize=25) + ay.set_ylabel("PDF", fontsize=25) - ay.grid(True, alpha=0.5, ls='--', color='k') + ay.grid(True, alpha=0.5, ls="--", color="k") ay.xaxis.grid(False) - ay.set_xlabel(r'$\delta$ [%]', fontsize=25) - ay.tick_params(axis='both', labelsize=18) + ay.set_xlabel(r"$\delta$ [%]", fontsize=25) + ay.tick_params(axis="both", labelsize=18) - stri = f'{model[iten].fam_name:s}, {s[iten]:.2f}' + stri = f"{model[iten].fam_name:s}, {s[iten]:.2f}" ay.hist(hp[index], density=True, bins=200, color=color, label=stri) ay.hist(hn[index], density=True, bins=200, color=color) _plt.tight_layout() ay.legend() - - def get_track(self, l_scattered_pos, scrap, vchamber): - """Tracking for getting the loss profile along the ring. - - l_scattered_pos = scattered positions (list or numpy.array). - scrap = if True, the vchamber's height will be changed. - vchmaber = defines the new vchamber's apperture. - """ - all_track = [] - indices = [] - spos = self.spos - - self._model.radiation_on = True - self._model.cavity_on = True - self._model.vchamber_on = True - - if scrap: - self.set_vchamber_scraper(vchamber) - - for _, scattered_pos in enumerate(l_scattered_pos): - - index = _np.argmin(_np.abs(scattered_pos-spos)) - indices.append(index) - res = to_fu.track_eletrons(self._deltas, self.nturns, - index, self._model) - all_track.append(res) - - hx = self._model_fit[self.scraph_inds[0]].hmax - hn = self._model_fit[self.scraph_inds[0]].hmin - vx = self._model_fit[self.scrapv_inds[0]].vmax - vn = self._model_fit[self.scrapv_inds[0]].vmin - vchamber = [hx, hn, vx, vn] - - self.set_vchamber_scraper(vchamber) - - return all_track, indices - - def get_track_def(self, l_scattered_pos, scrap, vchamber): + def _get_track_def(self, l_scattered_pos, scrap, vchamber): """Tracking for getting the loss profile along the ring. l_scattered_pos = scattered positions (list or numpy.array). @@ -476,11 +445,11 @@ def get_track_def(self, l_scattered_pos, scrap, vchamber): self.set_vchamber_scraper(vchamber) for _, scattered_pos in enumerate(l_scattered_pos): - - index = _np.argmin(_np.abs(scattered_pos-spos)) + index = _np.argmin(_np.abs(scattered_pos - spos)) indices.append(index) - dic = to_fu.track_eletrons_d(self._deltas, self.nturns, - index, self._model) + dic = to_fu.track_eletrons_d( + self._deltas, self.nturns, index, self._model + ) all_track.append(dic) hx = self._model_fit[self.scraph_inds[0]].hmax @@ -493,26 +462,26 @@ def get_track_def(self, l_scattered_pos, scrap, vchamber): return all_track, indices - def find_data(self, l_scattered_pos, scrap, vchamber): + def _find_data(self, l_scattered_pos, scrap, vchamber): # não consegui resolvero erro que o ruff indicou nessa função """Generating the data for the plot.""" - all_track, indices = self.get_track_def(l_scattered_pos, - scrap, vchamber) + all_track, indices = self._get_track_def( + l_scattered_pos, scrap, vchamber + ) spos = self.spos fact = 0.03 - tous_rate = self.ltime.touschek_data['rate'] # scattering rate + tous_rate = self.ltime.touschek_data["rate"] # scattering rate prob, lostp, all_lostp = [], [], [] # comentar os dois métodos implementados. # um deles parece ser mais rápido. # for j, single_track in enumerate(all_track): for j, dic in enumerate(all_track): - index = indices[j] - lostinds = dic['element_lost'] - deltas = dic['energy_deviation'] + lostinds = dic["element_lost"] + deltas = dic["energy_deviation"] # lostinds = _np.zeros(len(single_track)) # deltas = _np.zeros(len(single_track)) @@ -524,19 +493,20 @@ def find_data(self, l_scattered_pos, scrap, vchamber): lost_positions = _np.round(spos[lostinds], 2) - step = int((deltas[0]+deltas[-1])/fact) + step = int((deltas[0] + deltas[-1]) / fact) itv_track = _np.linspace(deltas[0], deltas[-1], step) - data = _pd.DataFrame({'lost_pos_by_tracking': lost_positions}) + data = _pd.DataFrame({"lost_pos_by_tracking": lost_positions}) # dataframe that storages the tracking data - lost_pos_column = \ - (data.groupby('lost_pos_by_tracking').groups).keys() - data = _pd.DataFrame({'lost_pos_by_tracking': lost_pos_column}) + lost_pos_column = ( + data.groupby("lost_pos_by_tracking").groups + ).keys() + data = _pd.DataFrame({"lost_pos_by_tracking": lost_pos_column}) # this step agroups the lost_positions itv_delta = [] for current, next_iten in zip(itv_track, itv_track[1:]): - stri = f'{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %' + stri = f"{current*1e2:.2f} % < delta < {next_iten*1e2:.2f} %" data[stri] = _np.zeros(len(list(lost_pos_column))) # this step # creates new columns in the dataframe and fill with zeros @@ -548,7 +518,7 @@ def find_data(self, l_scattered_pos, scrap, vchamber): if var == lost_pos_column: pass else: - data = data.set_index('lost_pos_by_tracking') + data = data.set_index("lost_pos_by_tracking") for idx, lost_pos in enumerate(lost_positions): # essas duas # estruturas de repetição são responsáveis por calcular @@ -560,19 +530,17 @@ def find_data(self, l_scattered_pos, scrap, vchamber): for i, interval in enumerate(itv_delta): if not i: # subtle difference: <= in first iteraction if interval[0] <= delta <= interval[1]: - stri = \ - f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + stri = f"{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %" data.loc[lost_pos, stri] += 1 else: if interval[0] < delta <= interval[1]: - stri = \ - f'{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %' + stri = f"{interval[0]*1e2:.2f} % < delta < {interval[1]*1e2:.2f} %" data.loc[lost_pos, stri] += 1 data = data / len(deltas) - npt = int((spos[-1]-spos[0])/0.1) + npt = int((spos[-1] - spos[0]) / 0.1) scalc = _np.linspace(spos[0], spos[-1], npt) rate_nom_lattice = _np.interp(spos, scalc, tous_rate) @@ -584,7 +552,7 @@ def find_data(self, l_scattered_pos, scrap, vchamber): t_prob = 0 for idx, m in enumerate(iten): t_prob += m - if idx == iten.count()-1: + if idx == iten.count() - 1: # appends the probability after sum part_prob.append(t_prob) lost_pos_df.append(indx) @@ -610,50 +578,55 @@ def find_data(self, l_scattered_pos, scrap, vchamber): return all_lostp, prob, lostp - def get_table(self, l_scattered_pos, scrap, vchamber): + def _get_table(self, l_scattered_pos, scrap, vchamber): """Generates the heat map of loss positions.""" dic_res = {} - all_lostp, prob, lostp = self.find_data(l_scattered_pos, - scrap, vchamber) + all_lostp, prob, lostp = self._find_data( + l_scattered_pos, scrap, vchamber + ) n_scat = _np.round(l_scattered_pos, 2) for idx, scattered_pos in enumerate(n_scat): - scat_data = [] bool_array = _np.isin(all_lostp, lostp[idx]) for j, boolean in enumerate(bool_array): if boolean: - index = \ - _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) + index = _np.intp( + _np.where(lostp[idx] == all_lostp[j])[0][0] + ) scat_data.append(prob[idx][index]) else: scat_data.append(0) if not idx: - dic_res['lost_positions'] = all_lostp - stri = f'{scattered_pos}' + dic_res["lost_positions"] = all_lostp + stri = f"{scattered_pos}" dic_res[stri] = scat_data else: - stri = f'{scattered_pos}' + stri = f"{scattered_pos}" dic_res[stri] = scat_data # df = _pd.DataFrame(dic_res) return dic_res - def get_reordered_dict(self, l_scattered_pos, - reording_key, scrap, vchamber): + def get_reordered_dict( + self, l_scattered_pos, reording_key, scrap, vchamber + ): """Get the reordered dictionary.""" - dic = self.get_table(l_scattered_pos, scrap, vchamber) + dic = self._get_table(l_scattered_pos, scrap, vchamber) zip_tuples = zip(*[dic[chave] for chave in dic]) - new_tuples = sorted(zip_tuples, - key=lambda x: x[list(dic.keys()).index(reording_key)]) + new_tuples = sorted( + zip_tuples, key=lambda x: x[list(dic.keys()).index(reording_key)] + ) zip_ordered = zip(*new_tuples) - new_dict = \ - {chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered)} + new_dict = { + chave: list(valores) + for chave, valores in zip(dic.keys(), zip_ordered) + } return new_dict @@ -662,17 +635,16 @@ def get_loss_profile(self, dic): dic = cointains the lost positions and the scattered points. """ - # dic = self.get_reordered_dict(l_scattered_pos, reording_key) spos = self.spos df = _pd.DataFrame(dic) - a = df.set_index('lost_positions') + a = df.set_index("lost_positions") scat_pos = _np.array(a.columns, dtype=float) indices = [] for iten in scat_pos: - ind = _np.argmin(_np.abs(spos-iten)) + ind = _np.argmin(_np.abs(spos - iten)) indices.append(ind) summed = [] @@ -680,36 +652,37 @@ def get_loss_profile(self, dic): sum_row = scyint.trapz(a.loc[idx], spos[indices]) summed.append(sum_row) - _, ax = _plt.subplots(figsize=(13, 7), - gridspec_kw={'hspace': 0.2, 'wspace': 0.2}) - ax.set_title('loss rate integral along the ring', fontsize=16) + _, ax = _plt.subplots( + figsize=(13, 7), gridspec_kw={"hspace": 0.2, "wspace": 0.2} + ) + ax.set_title("loss rate integral along the ring", fontsize=16) - ax.set_xlabel('lost position [m]', fontsize=16) - ax.set_ylabel('loss rate [1/s]', fontsize=16) - ax.tick_params(axis='both', labelsize=16) + ax.set_xlabel("lost position [m]", fontsize=16) + ax.set_ylabel("loss rate [1/s]", fontsize=16) + ax.tick_params(axis="both", labelsize=16) - ax.plot(list(a.index), summed, color='navy') - _pyaccel.graphics.draw_lattice(self._model_fit, - offset=-1e-6, height=1e-6, gca=True) + ax.plot(list(a.index), summed, color="navy") + _pyaccel.graphics.draw_lattice( + self._model_fit, offset=-1e-6, height=1e-6, gca=True + ) def get_loss_profilel(self, l_dic): """Comparing distinct loss profiles. l_dic = list of dictionaries of loss profiles. """ - # dic = self.get_reordered_dict(l_scattered_pos, reording_key) lista = [] for dic in l_dic: s = self.spos df = _pd.DataFrame(dic) - a = df.set_index('lost_positions') + a = df.set_index("lost_positions") scat_pos = _np.array(a.columns, dtype=float) indices = [] for iten in scat_pos: - ind = _np.argmin(_np.abs(s-iten)) + ind = _np.argmin(_np.abs(s - iten)) indices.append(ind) summed = [] @@ -730,7 +703,7 @@ def plot_scat_table(self, new_dic): s = self.spos df = _pd.DataFrame(new_dic) - df = df.set_index('lost_positions') + df = df.set_index("lost_positions") val = df.values.copy() idx = val != 0.0 @@ -739,20 +712,20 @@ def plot_scat_table(self, new_dic): fig, ax = _plt.subplots(figsize=(10, 10)) - y = _np.linspace(0, s[-1], df.shape[0]+1) - x = _np.linspace(0, s[-1], df.shape[1]+1) + y = _np.linspace(0, s[-1], df.shape[0] + 1) + x = _np.linspace(0, s[-1], df.shape[1] + 1) x_mesh, y_mesh = _np.meshgrid(x, y) - heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap='jet', shading='flat') + heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap="jet", shading="flat") cbar = _plt.colorbar(heatmp) - cbar.set_label('Loss rate [1/s] in logarithmic scale', rotation=90) + cbar.set_label("Loss rate [1/s] in logarithmic scale", rotation=90) - ax.set_title('Loss profile', fontsize=16) + ax.set_title("Loss profile", fontsize=16) - ax.set_xlabel('scattered positions [m]', fontsize=16) - ax.set_ylabel('lost positions [m]', fontsize=16) + ax.set_xlabel("scattered positions [m]", fontsize=16) + ax.set_ylabel("lost positions [m]", fontsize=16) fig.tight_layout() - _plt.gca().set_aspect('equal') + _plt.gca().set_aspect("equal") _plt.show() From 297f47e6bf78905fb97b82bed20e8e80dbb77cc1 Mon Sep 17 00:00:00 2001 From: Thales Date: Wed, 20 Dec 2023 14:56:39 -0300 Subject: [PATCH 098/108] =?UTF-8?q?excluindo=20fun=C3=A7=C3=A3o=20duplicad?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 44 -------------------------------------------- 1 file changed, 44 deletions(-) diff --git a/functions.py b/functions.py index 4cf7a839..340ad294 100644 --- a/functions.py +++ b/functions.py @@ -41,50 +41,6 @@ def calc_amp(acc, energy_offsets, hmax, hmin): pass return _np.sqrt(a_def), indices - -def track_eletrons(deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6): - """Tracking simulation for touschek scattering that ocorred in element_idx. - - model = accelerator model. - deltas = energy deviation. - n_turn = number of turns desired. - pos_x = small pertubation in x. - pos_y = small pertubation in y. - """ - orb = _pyaccel.tracking.find_orbit6(model, indices=[0, element_idx]) - orb = orb[:, 1] - - rin = _np.zeros((6, deltas.size)) - rin += orb[:, None] - rin[0] += pos_x - rin[2] += pos_y - rin[4] += deltas - - track = _pyaccel.tracking.ring_pass( - model, - rin, - nr_turns=n_turn, - turn_by_turn=True, - element_offset=element_idx, - parallel=True, - ) - - _, _, turn_lost, element_lost, _ = track - # oculted variables/ part_out: final coordinates of electrons - # flag: indicates if there is any loss - # plane_lost: plane that electron was lost(x or y) - - turnl_element = [] - - for i, item in enumerate(turn_lost): - if item == n_turn and element_lost[i] == element_idx: - pass - else: - turnl_element.append((item, element_lost[i], deltas[i])) - - return turnl_element - - def track_eletrons_d( deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6 ): From 65d4f5ff67bcf9fdbab0115dca14403daf364fa9 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 21 Dec 2023 09:27:46 -0300 Subject: [PATCH 099/108] =?UTF-8?q?alterandoos=20nomes=20de=20algumas=20fu?= =?UTF-8?q?n=C3=A7=C3=B5es,=20adicionando=20docstring=20sobre=20o=20beta?= =?UTF-8?q?=5Fbar=20na=20defini=C3=A7=C3=A3o=20da=20fun=C3=A7=C3=A3o=20par?= =?UTF-8?q?a=20a=20obten=C3=A7=C3=A3o=20da=20distribui=C3=A7=C3=A3o=20da?= =?UTF-8?q?=20se=C3=A7=C3=A3o=20de=20choque=20total?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 8 +++++--- tous_analysis.py | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/functions.py b/functions.py index 340ad294..f282c272 100644 --- a/functions.py +++ b/functions.py @@ -398,6 +398,11 @@ def get_cross_section_distribution(psim, npts=3000): psim = minimum scattering angle (lower integration limitant). npts = number of point for a logspace function. + + beta_bar defined below is the ratio (v/c) and it defines when using the + ultra-relativistic regime equation for the total cross section. + if beta_bar equals zero then is necessary to use the ultra-relativistic + equation for the total crooss section. """ beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi / 2 - psim), 0, npts) @@ -542,9 +547,6 @@ def histgms(acc, l_spos, num_part, accep, de_min, cutaccep): idx = _np.argmin(_np.abs(scalc - iten)) indices.append(idx_model) - # this index is necessary to the s position indices - # from analitically calculated PDF - # match with monte carlo simulation s position indices env = envelopes[idx_model] part1, part2 = create_particles(env, num_part) diff --git a/tous_analysis.py b/tous_analysis.py index 37057d78..b41819f2 100644 --- a/tous_analysis.py +++ b/tous_analysis.py @@ -462,7 +462,7 @@ def _get_track_def(self, l_scattered_pos, scrap, vchamber): return all_track, indices - def _find_data(self, l_scattered_pos, scrap, vchamber): + def _concat_track_lossrate(self, l_scattered_pos, scrap, vchamber): # não consegui resolvero erro que o ruff indicou nessa função """Generating the data for the plot.""" all_track, indices = self._get_track_def( @@ -578,10 +578,10 @@ def _find_data(self, l_scattered_pos, scrap, vchamber): return all_lostp, prob, lostp - def _get_table(self, l_scattered_pos, scrap, vchamber): + def _f_scat_table(self, l_scattered_pos, scrap, vchamber): """Generates the heat map of loss positions.""" dic_res = {} - all_lostp, prob, lostp = self._find_data( + all_lostp, prob, lostp = self._concat_track_lossrate( l_scattered_pos, scrap, vchamber ) n_scat = _np.round(l_scattered_pos, 2) @@ -611,11 +611,11 @@ def _get_table(self, l_scattered_pos, scrap, vchamber): return dic_res - def get_reordered_dict( + def get_scat_dict( self, l_scattered_pos, reording_key, scrap, vchamber ): """Get the reordered dictionary.""" - dic = self._get_table(l_scattered_pos, scrap, vchamber) + dic = self._f_scat_table(l_scattered_pos, scrap, vchamber) zip_tuples = zip(*[dic[chave] for chave in dic]) new_tuples = sorted( @@ -694,7 +694,7 @@ def get_loss_profilel(self, l_dic): return lista - def plot_scat_table(self, new_dic): + def plot_scat_dict(self, new_dic): """Heatmap plot indicating the warm points of loss along the ring. new_dic = contains the reordered dict with lost positions and From e5775ae65860f633e08b8ec75dec1cdc096fff40 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 21 Dec 2023 09:48:29 -0300 Subject: [PATCH 100/108] =?UTF-8?q?corrigindo=20a=20docstring=20da=20fun?= =?UTF-8?q?=C3=A7=C3=A3o=20que=20gera=20a=20distribui=C3=A7=C3=A3o=20da=20?= =?UTF-8?q?se=C3=A7=C3=A3o=20de=20choque=20total?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/functions.py b/functions.py index f282c272..c11f2566 100644 --- a/functions.py +++ b/functions.py @@ -401,8 +401,9 @@ def get_cross_section_distribution(psim, npts=3000): beta_bar defined below is the ratio (v/c) and it defines when using the ultra-relativistic regime equation for the total cross section. - if beta_bar equals zero then is necessary to use the ultra-relativistic - equation for the total crooss section. + if beta_bar equals zero then the total cross section diverges when using + piwinski's relation for the total cross section by the 1/beta_bar + dependence. Therefore, is necessary to neglect this factor contribution. """ beta_bar = 0 psi = _np.logspace(_np.log10(_np.pi / 2 - psim), 0, npts) From a4ea515bba25d9d3b9520dd6b53e1fd467926c89 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 21 Dec 2023 09:49:48 -0300 Subject: [PATCH 101/108] =?UTF-8?q?pequenas=20altera=C3=A7=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/functions.py b/functions.py index c11f2566..52a56f63 100644 --- a/functions.py +++ b/functions.py @@ -436,8 +436,8 @@ def cross_section_draw_samples(psim, num_part): def scatter_particles(part1, part2, de_min): """M.C. simulation of the Touschek scattering process. - part1 = partcile's coordinates. - part2 = partcile's coordinates. + part1 = 1st partcile's coordinates. + part2 = 2nd partcile's coordinates. de_min = mimimum energy deviation. """ gamma = 3e9 / 0.510e6 From 3fb30ee7140af9aa7bb8e013afb050217d1b7d55 Mon Sep 17 00:00:00 2001 From: Thales Date: Thu, 21 Dec 2023 09:51:04 -0300 Subject: [PATCH 102/108] alterando novamente a docstring da cross_section --- functions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/functions.py b/functions.py index 52a56f63..ae1d7791 100644 --- a/functions.py +++ b/functions.py @@ -399,8 +399,6 @@ def get_cross_section_distribution(psim, npts=3000): psim = minimum scattering angle (lower integration limitant). npts = number of point for a logspace function. - beta_bar defined below is the ratio (v/c) and it defines when using the - ultra-relativistic regime equation for the total cross section. if beta_bar equals zero then the total cross section diverges when using piwinski's relation for the total cross section by the 1/beta_bar dependence. Therefore, is necessary to neglect this factor contribution. From a5da097dca6c0bba70bf57f4e36d1193e18a186b Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 22 Dec 2023 08:19:48 -0300 Subject: [PATCH 103/108] Create __init__.py file according to new structure. --- __init__.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 __init__.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 00000000..710a32ef --- /dev/null +++ b/__init__.py @@ -0,0 +1,4 @@ +from . import functions +from . import tous_analysis + +__all__ = ["functions", "tous_analysis"] From 17561b9d391fa77d21d135abfbdcb2d8bb578d84 Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 22 Dec 2023 08:23:36 -0300 Subject: [PATCH 104/108] Move files to right place. --- __init__.py => apsuite/simullib/touschek_loss_spots/__init__.py | 0 functions.py => apsuite/simullib/touschek_loss_spots/functions.py | 0 .../simullib/touschek_loss_spots/tous_analysis.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename __init__.py => apsuite/simullib/touschek_loss_spots/__init__.py (100%) rename functions.py => apsuite/simullib/touschek_loss_spots/functions.py (100%) rename tous_analysis.py => apsuite/simullib/touschek_loss_spots/tous_analysis.py (100%) diff --git a/__init__.py b/apsuite/simullib/touschek_loss_spots/__init__.py similarity index 100% rename from __init__.py rename to apsuite/simullib/touschek_loss_spots/__init__.py diff --git a/functions.py b/apsuite/simullib/touschek_loss_spots/functions.py similarity index 100% rename from functions.py rename to apsuite/simullib/touschek_loss_spots/functions.py diff --git a/tous_analysis.py b/apsuite/simullib/touschek_loss_spots/tous_analysis.py similarity index 100% rename from tous_analysis.py rename to apsuite/simullib/touschek_loss_spots/tous_analysis.py From 6a2a1cb1ad42fc5246f2aa6374727e17ad5591e9 Mon Sep 17 00:00:00 2001 From: Thales Date: Fri, 22 Dec 2023 12:22:24 -0300 Subject: [PATCH 105/108] =?UTF-8?q?adicionando=20mudan=C3=A7as=20sugeridas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apsuite/optimization/__init__.py | 2 +- .../touschek_loss_spots/tous_analysis.py | 70 ++++++++----------- 2 files changed, 29 insertions(+), 43 deletions(-) diff --git a/apsuite/optimization/__init__.py b/apsuite/optimization/__init__.py index 64134ea4..be690d43 100644 --- a/apsuite/optimization/__init__.py +++ b/apsuite/optimization/__init__.py @@ -5,4 +5,4 @@ del genetic_algorithm, pso, scanning, simulated_annealing -__all__ = ('genetic_algorithm', 'pso', 'scanning', 'simulated_annealing') +__all__ = ('genetic_algorithm', 'pso', 'scanning', 'simulated_annealing','simullib') diff --git a/apsuite/simullib/touschek_loss_spots/tous_analysis.py b/apsuite/simullib/touschek_loss_spots/tous_analysis.py index b41819f2..15d46045 100644 --- a/apsuite/simullib/touschek_loss_spots/tous_analysis.py +++ b/apsuite/simullib/touschek_loss_spots/tous_analysis.py @@ -1,4 +1,5 @@ """tous_analysis.""" +import os from pyaccel.lifetime import Lifetime from pyaccel.lattice import get_attribute, find_indices, find_spos import touschek_pack.functions as to_fu @@ -11,15 +12,13 @@ import pandas as _pd import scipy.integrate as scyint import pyaccel as _pyaccel -from mathphys.functions import load_pickle +from mathphys.functions import save_pickle, load_pickle class TousAnalysis: """Class for the analysis of electron losses along the ring.""" - def __init__( - self, accelerator, energies_off=None, beam_energy=None, n_turns=7 - ): + def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): """Parameters necessary to define the class.""" if energies_off is None: energy_off = _np.linspace(0, 0.046, 460) # physical limitants @@ -32,15 +31,10 @@ def __init__( self._model_fit = accelerator self._model = pymodels.si.create_accelerator() - self._amp_and_limidx = None self._sc_accps = None self._accep = None - self._inds_pos = load_pickle( - "/".join(__file__.split("/")[:-1]) + "/ph_lim.pickle" - ) - self._inds_neg = load_pickle( - "/".join(__file__.split("/")[:-1]) + "/ph_lim_neg.pickle" - ) + self._inds_pos = None + self._inds_neg = None self._amps_pos = None self._amps_neg = None self.num_part = 50000 @@ -80,9 +74,7 @@ def nom_model(self): def accep(self): """Defines Touschek energy acceptance.""" if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance( - self.accelerator - ) + self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) return self._accep @property @@ -97,13 +89,19 @@ def s_calc(self): return self._sc_accps @property - def amp_and_limidx(self): + def linear_lim_indices(self): """Defines 4 properties. Positive and negative amplitudes. physical limitants for positive and negative e_dev """ - if self._amp_and_limidx is None: + + try: + self._inds_pos = load_pickle("phy_lim_pos.pickle") + self._inds_neg = load_pickle("phy_lim_neg.pickle") + self._amp_pos = load_pickle("amps_pos.pickle") + self._amp_neg = load_pickle("amps_neg.pickle") + except Exception: self._model.cavity_on = False self._model.radiation_on = False @@ -115,9 +113,12 @@ def amp_and_limidx(self): self._model, -self.off_energy, self.h_pos, self.h_neg ) - self._amp_and_limidx = True + save_pickle(data=self._inds_pos, fname="phy_lim_pos.pickle") + save_pickle(data=self._inds_neg, fname="phy_lim_neg.pickle") + save_pickle(data=self._amps_pos, fname="amps_pos.pickle") + save_pickle(data=self._amps_neg, fname="amps_neg.pickle") - return self._amp_and_limidx + return self._inds_pos, self._inds_neg @property def off_energy(self): @@ -173,7 +174,7 @@ def amp_neg(self): def get_amps_idxs(self): # Defines various parameters """Defines 3 self params at same time.""" - return self.amp_and_limidx, self.accep, self.s_calc + return self.linear_lim_indices, self.accep, self.s_calc def set_vchamber_scraper(self, vchamber): """Function for setting the vchamber apperture.""" @@ -317,17 +318,13 @@ def plot_normtousd(self, spos): spos = desired s positions (list or numpy.array) """ spos_ring = self.spos - dic = to_fu.norm_cutacp( - self._model_fit, spos, 5000, self._accep, norm=True - ) + dic = to_fu.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) fdensp, fdensn = dic["fdensp"], dic["fdensn"] deltasp, deltasn = dic["deltasp"], dic["deltasn"] _, ax = _plt.subplots(figsize=(10, 5)) - ax.set_title( - "Probability density analytically calculated", fontsize=20 - ) + ax.set_title("Probability density analytically calculated", fontsize=20) ax.grid(True, alpha=0.5, ls="--", color="k") ax.xaxis.grid(False) ax.set_xlabel(r"$\delta$ [%]", fontsize=25) @@ -447,9 +444,7 @@ def _get_track_def(self, l_scattered_pos, scrap, vchamber): for _, scattered_pos in enumerate(l_scattered_pos): index = _np.argmin(_np.abs(scattered_pos - spos)) indices.append(index) - dic = to_fu.track_eletrons_d( - self._deltas, self.nturns, index, self._model - ) + dic = to_fu.track_eletrons_d(self._deltas, self.nturns, index, self._model) all_track.append(dic) hx = self._model_fit[self.scraph_inds[0]].hmax @@ -465,9 +460,7 @@ def _get_track_def(self, l_scattered_pos, scrap, vchamber): def _concat_track_lossrate(self, l_scattered_pos, scrap, vchamber): # não consegui resolvero erro que o ruff indicou nessa função """Generating the data for the plot.""" - all_track, indices = self._get_track_def( - l_scattered_pos, scrap, vchamber - ) + all_track, indices = self._get_track_def(l_scattered_pos, scrap, vchamber) spos = self.spos fact = 0.03 @@ -498,9 +491,7 @@ def _concat_track_lossrate(self, l_scattered_pos, scrap, vchamber): data = _pd.DataFrame({"lost_pos_by_tracking": lost_positions}) # dataframe that storages the tracking data - lost_pos_column = ( - data.groupby("lost_pos_by_tracking").groups - ).keys() + lost_pos_column = (data.groupby("lost_pos_by_tracking").groups).keys() data = _pd.DataFrame({"lost_pos_by_tracking": lost_pos_column}) # this step agroups the lost_positions @@ -592,9 +583,7 @@ def _f_scat_table(self, l_scattered_pos, scrap, vchamber): for j, boolean in enumerate(bool_array): if boolean: - index = _np.intp( - _np.where(lostp[idx] == all_lostp[j])[0][0] - ) + index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) scat_data.append(prob[idx][index]) else: scat_data.append(0) @@ -611,9 +600,7 @@ def _f_scat_table(self, l_scattered_pos, scrap, vchamber): return dic_res - def get_scat_dict( - self, l_scattered_pos, reording_key, scrap, vchamber - ): + def get_scat_dict(self, l_scattered_pos, reording_key, scrap, vchamber): """Get the reordered dictionary.""" dic = self._f_scat_table(l_scattered_pos, scrap, vchamber) @@ -624,8 +611,7 @@ def get_scat_dict( zip_ordered = zip(*new_tuples) new_dict = { - chave: list(valores) - for chave, valores in zip(dic.keys(), zip_ordered) + chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered) } return new_dict From 329b271d1198a07efb3310f0d29036db43991d7a Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 11 Apr 2024 09:34:45 -0300 Subject: [PATCH 106/108] OPT.BUG: Fix __init__.py. --- apsuite/optimization/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apsuite/optimization/__init__.py b/apsuite/optimization/__init__.py index be690d43..42d1744c 100644 --- a/apsuite/optimization/__init__.py +++ b/apsuite/optimization/__init__.py @@ -1,3 +1,4 @@ +""".""" from .genetic_algorithm import GA from .pso import PSO from .scanning import SimpleScan @@ -5,4 +6,4 @@ del genetic_algorithm, pso, scanning, simulated_annealing -__all__ = ('genetic_algorithm', 'pso', 'scanning', 'simulated_annealing','simullib') +__all__ = ('genetic_algorithm', 'pso', 'scanning', 'simulated_annealing') From 89f9965023f1a73bb20b4774e0fc9d2eeb2921ce Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 11 Apr 2024 09:35:28 -0300 Subject: [PATCH 107/108] SIMLIB.TOUS.MNT: Fix style of __init__.py file. --- apsuite/simullib/touschek_loss_spots/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apsuite/simullib/touschek_loss_spots/__init__.py b/apsuite/simullib/touschek_loss_spots/__init__.py index 710a32ef..36a5003c 100644 --- a/apsuite/simullib/touschek_loss_spots/__init__.py +++ b/apsuite/simullib/touschek_loss_spots/__init__.py @@ -1,4 +1,4 @@ -from . import functions -from . import tous_analysis +""".""" +from . import functions, tous_analysis __all__ = ["functions", "tous_analysis"] From 290d5399d98949017649cc6c6c414dac3ec7fe5d Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 11 Apr 2024 13:43:50 -0300 Subject: [PATCH 108/108] SIMLIB.TOUS.MNT: Fix style and imports. --- .../simullib/touschek_loss_spots/functions.py | 3 +- .../touschek_loss_spots/tous_analysis.py | 142 ++++++++++-------- 2 files changed, 84 insertions(+), 61 deletions(-) diff --git a/apsuite/simullib/touschek_loss_spots/functions.py b/apsuite/simullib/touschek_loss_spots/functions.py index ae1d7791..3a6fe39d 100644 --- a/apsuite/simullib/touschek_loss_spots/functions.py +++ b/apsuite/simullib/touschek_loss_spots/functions.py @@ -1,7 +1,7 @@ """Functions_for_TousAnalysis.""" -import pyaccel as _pyaccel import matplotlib.pyplot as _plt import numpy as _np +import pyaccel as _pyaccel import scipy.integrate as _scyint import scipy.special as _special from mathphys.beam_optics import beam_rigidity as _beam_rigidity @@ -41,6 +41,7 @@ def calc_amp(acc, energy_offsets, hmax, hmin): pass return _np.sqrt(a_def), indices + def track_eletrons_d( deltas, n_turn, element_idx, model, pos_x=1e-5, pos_y=3e-6 ): diff --git a/apsuite/simullib/touschek_loss_spots/tous_analysis.py b/apsuite/simullib/touschek_loss_spots/tous_analysis.py index 15d46045..efae9fb9 100644 --- a/apsuite/simullib/touschek_loss_spots/tous_analysis.py +++ b/apsuite/simullib/touschek_loss_spots/tous_analysis.py @@ -1,24 +1,23 @@ """tous_analysis.""" -import os -from pyaccel.lifetime import Lifetime -from pyaccel.lattice import get_attribute, find_indices, find_spos -import touschek_pack.functions as to_fu -import pymodels -import pyaccel.optics as py_op + +import matplotlib.pyplot as _mplt import numpy as _np -import matplotlib.pyplot as _plt -import matplotlib.cm as _cm -from mathphys.beam_optics import beam_rigidity as _beam_rigidity import pandas as _pd -import scipy.integrate as scyint -import pyaccel as _pyaccel -from mathphys.functions import save_pickle, load_pickle +import pyaccel as _pa +import scipy.integrate as _sp_int +from mathphys.beam_optics import beam_rigidity as _beam_rigidity +from mathphys.functions import load as _load, save as _save +from pymodels import si as _si + +from . import functions as _to_fu class TousAnalysis: """Class for the analysis of electron losses along the ring.""" - def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): + def __init__( + self, accelerator, energies_off=None, beam_energy=None, n_turns=7 + ): """Parameters necessary to define the class.""" if energies_off is None: energy_off = _np.linspace(0, 0.046, 460) # physical limitants @@ -29,7 +28,7 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): beta = beam_energy self._model_fit = accelerator - self._model = pymodels.si.create_accelerator() + self._model = _si.create_accelerator() self._sc_accps = None self._accep = None @@ -41,15 +40,23 @@ def __init__(self, accelerator, energies_off=None, beam_energy=None, n_turns=7): self.energy_dev_min = 1e-4 self.beta = beta # beta factor - self.h_pos = get_attribute(self._model_fit, "hmax", indices="closed") - self.h_neg = get_attribute(self._model_fit, "hmin", indices="closed") - self.ltime = Lifetime(self._model_fit) + self.h_pos = _pa.lattice.get_attribute( + self._model_fit, "hmax", indices="closed" + ) + self.h_neg = _pa.lattice.get_attribute( + self._model_fit, "hmin", indices="closed" + ) + self.ltime = _pa.lifetime.Lifetime(self._model_fit) self._off_energy = energy_off # (linear model) en_dev to amplitudes self.nturns = n_turns self._deltas = deltas - self.spos = find_spos(self._model_fit, indices="closed") - self.scraph_inds = find_indices(self._model, "fam_name", "SHVC") - self.scrapv_inds = find_indices(self._model, "fam_name", "SVVC") + self.spos = _pa.lattice.find_spos(self._model_fit, indices="closed") + self.scraph_inds = _pa.lattice.find_indices( + self._model, "fam_name", "SHVC" + ) + self.scrapv_inds = _pa.lattice.find_indices( + self._model, "fam_name", "SVVC" + ) @property def accelerator(self): @@ -74,7 +81,9 @@ def nom_model(self): def accep(self): """Defines Touschek energy acceptance.""" if self._accep is None: - self._accep = py_op.calc_touschek_energy_acceptance(self.accelerator) + self._accep = _pa.optics.calc_touschek_energy_acceptance( + self.accelerator + ) return self._accep @property @@ -85,7 +94,7 @@ def s_calc(self): meters. """ if self._sc_accps is None: - self._sc_accps = to_fu.get_scaccep(self.accelerator, self.accep) + self._sc_accps = _to_fu.get_scaccep(self.accelerator, self.accep) return self._sc_accps @property @@ -97,26 +106,26 @@ def linear_lim_indices(self): """ try: - self._inds_pos = load_pickle("phy_lim_pos.pickle") - self._inds_neg = load_pickle("phy_lim_neg.pickle") - self._amp_pos = load_pickle("amps_pos.pickle") - self._amp_neg = load_pickle("amps_neg.pickle") + self._inds_pos = _load("phy_lim_pos.pickle") + self._inds_neg = _load("phy_lim_neg.pickle") + self._amp_pos = _load("amps_pos.pickle") + self._amp_neg = _load("amps_neg.pickle") except Exception: self._model.cavity_on = False self._model.radiation_on = False - self._amps_pos, self._inds_pos = to_fu.calc_amp( + self._amps_pos, self._inds_pos = _to_fu.calc_amp( self._model, self.off_energy, self.h_pos, self.h_neg ) - self._amps_neg, self._inds_neg = to_fu.calc_amp( + self._amps_neg, self._inds_neg = _to_fu.calc_amp( self._model, -self.off_energy, self.h_pos, self.h_neg ) - save_pickle(data=self._inds_pos, fname="phy_lim_pos.pickle") - save_pickle(data=self._inds_neg, fname="phy_lim_neg.pickle") - save_pickle(data=self._amps_pos, fname="amps_pos.pickle") - save_pickle(data=self._amps_neg, fname="amps_neg.pickle") + _save(data=self._inds_pos, fname="phy_lim_pos.pickle") + _save(data=self._inds_neg, fname="phy_lim_neg.pickle") + _save(data=self._amps_pos, fname="amps_pos.pickle") + _save(data=self._amps_neg, fname="amps_neg.pickle") return self._inds_pos, self._inds_neg @@ -198,7 +207,7 @@ def _single_pos_track(self, single_spos, par): index = _np.argmin(_np.abs(s - single_spos)) if "pos" in par: - res = to_fu.track_eletrons_d( + res = _to_fu.track_eletrons_d( self.deltas, self.nturns, index, @@ -207,7 +216,7 @@ def _single_pos_track(self, single_spos, par): pos_y=3e-6, ) elif "neg" in par: - res = to_fu.track_eletrons_d( + res = _to_fu.track_eletrons_d( -self.deltas, self.nturns, index, @@ -220,7 +229,7 @@ def _single_pos_track(self, single_spos, par): def _get_weighting_tous(self, single_spos, npt=5000): """.""" - scalc, daccp, daccn = to_fu.get_scaccep(self.accelerator, self.accep) + scalc, daccp, daccn = _to_fu.get_scaccep(self.accelerator, self.accep) bf = self.beta # bf:beta factor lt = self.ltime b1 = lt.touschek_data["touschek_coeffs"]["b1"] @@ -237,11 +246,11 @@ def _get_weighting_tous(self, single_spos, npt=5000): deltp = _np.tan(kappa_pos) / bf deltn = _np.tan(kappa_neg) / bf - fdensp = to_fu.f_function_arg_mod( + fdensp = _to_fu.f_function_arg_mod( kappa_pos, kappap_0, b1[idx], b2[idx], norm=False ) - fdensn = to_fu.f_function_arg_mod( + fdensn = _to_fu.f_function_arg_mod( kappa_neg, kappan_0, b1[idx], b2[idx], norm=False ) @@ -264,7 +273,7 @@ def _get_weighting_tous(self, single_spos, npt=5000): def _get_trackndens(self, single_spos, par): """Concatenates tracking and touschek loss dens.""" - # if len(to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil + # if len(_to_fu.t_list(single_spos)) != 1: # Não sei se isso é útil # raise ValueError('This function suports only one s position') fdensp, fdensn, deltp, deltn = self._get_weighting_tous(single_spos) @@ -300,7 +309,7 @@ def plot_track_lossdens(self, single_spos, par, accep): inds = _np.intp(self.inds_neg) index = _np.argmin(_np.abs(s - single_spos)) - to_fu.plot_track_d( + _to_fu.plot_track_d( self.accelerator, dic, inds, @@ -318,13 +327,17 @@ def plot_normtousd(self, spos): spos = desired s positions (list or numpy.array) """ spos_ring = self.spos - dic = to_fu.norm_cutacp(self._model_fit, spos, 5000, self._accep, norm=True) + dic = _to_fu.norm_cutacp( + self._model_fit, spos, 5000, self._accep, norm=True + ) fdensp, fdensn = dic["fdensp"], dic["fdensn"] deltasp, deltasn = dic["deltasp"], dic["deltasn"] - _, ax = _plt.subplots(figsize=(10, 5)) - ax.set_title("Probability density analytically calculated", fontsize=20) + _, ax = _mplt.subplots(figsize=(10, 5)) + ax.set_title( + "Probability density analytically calculated", fontsize=20 + ) ax.grid(True, alpha=0.5, ls="--", color="k") ax.xaxis.grid(False) ax.set_xlabel(r"$\delta$ [%]", fontsize=25) @@ -355,7 +368,7 @@ def plot_normtousd(self, spos): deltaspi = deltasp[idx][:best_index] * 1e2 deltasni = -deltasn[idx][:best_index] * 1e2 - color = _cm.gist_rainbow(idx / len(spos)) + color = _mplt.cm.gist_rainbow(idx / len(spos)) not_desired = [ "calc_mom_accep", "mia", @@ -387,7 +400,7 @@ def plot_histograms(self, l_spos): accep = self.accep model = self._model_fit - tup = to_fu.histgms( + tup = _to_fu.histgms( self._model_fit, l_spos, self.num_part, @@ -398,7 +411,7 @@ def plot_histograms(self, l_spos): hp, hn, idx_model = tup - fig, ax = _plt.subplots( + fig, ax = _mplt.subplots( ncols=len(l_spos), nrows=1, figsize=(30, 10), sharey=True ) fig.suptitle( @@ -407,7 +420,7 @@ def plot_histograms(self, l_spos): ) for index, iten in enumerate(idx_model): - color = _cm.jet(index / len(idx_model)) + color = _mplt.cm.jet(index / len(idx_model)) ay = ax[index] if not index: ay.set_ylabel("PDF", fontsize=25) @@ -420,7 +433,7 @@ def plot_histograms(self, l_spos): stri = f"{model[iten].fam_name:s}, {s[iten]:.2f}" ay.hist(hp[index], density=True, bins=200, color=color, label=stri) ay.hist(hn[index], density=True, bins=200, color=color) - _plt.tight_layout() + _mplt.tight_layout() ay.legend() def _get_track_def(self, l_scattered_pos, scrap, vchamber): @@ -444,7 +457,9 @@ def _get_track_def(self, l_scattered_pos, scrap, vchamber): for _, scattered_pos in enumerate(l_scattered_pos): index = _np.argmin(_np.abs(scattered_pos - spos)) indices.append(index) - dic = to_fu.track_eletrons_d(self._deltas, self.nturns, index, self._model) + dic = _to_fu.track_eletrons_d( + self._deltas, self.nturns, index, self._model + ) all_track.append(dic) hx = self._model_fit[self.scraph_inds[0]].hmax @@ -460,7 +475,9 @@ def _get_track_def(self, l_scattered_pos, scrap, vchamber): def _concat_track_lossrate(self, l_scattered_pos, scrap, vchamber): # não consegui resolvero erro que o ruff indicou nessa função """Generating the data for the plot.""" - all_track, indices = self._get_track_def(l_scattered_pos, scrap, vchamber) + all_track, indices = self._get_track_def( + l_scattered_pos, scrap, vchamber + ) spos = self.spos fact = 0.03 @@ -491,7 +508,9 @@ def _concat_track_lossrate(self, l_scattered_pos, scrap, vchamber): data = _pd.DataFrame({"lost_pos_by_tracking": lost_positions}) # dataframe that storages the tracking data - lost_pos_column = (data.groupby("lost_pos_by_tracking").groups).keys() + lost_pos_column = ( + data.groupby("lost_pos_by_tracking").groups + ).keys() data = _pd.DataFrame({"lost_pos_by_tracking": lost_pos_column}) # this step agroups the lost_positions @@ -583,7 +602,9 @@ def _f_scat_table(self, l_scattered_pos, scrap, vchamber): for j, boolean in enumerate(bool_array): if boolean: - index = _np.intp(_np.where(lostp[idx] == all_lostp[j])[0][0]) + index = _np.intp( + _np.where(lostp[idx] == all_lostp[j])[0][0] + ) scat_data.append(prob[idx][index]) else: scat_data.append(0) @@ -611,7 +632,8 @@ def get_scat_dict(self, l_scattered_pos, reording_key, scrap, vchamber): zip_ordered = zip(*new_tuples) new_dict = { - chave: list(valores) for chave, valores in zip(dic.keys(), zip_ordered) + chave: list(valores) + for chave, valores in zip(dic.keys(), zip_ordered) } return new_dict @@ -635,10 +657,10 @@ def get_loss_profile(self, dic): summed = [] for idx, _ in a.iterrows(): - sum_row = scyint.trapz(a.loc[idx], spos[indices]) + sum_row = _sp_int.trapz(a.loc[idx], spos[indices]) summed.append(sum_row) - _, ax = _plt.subplots( + _, ax = _mplt.subplots( figsize=(13, 7), gridspec_kw={"hspace": 0.2, "wspace": 0.2} ) ax.set_title("loss rate integral along the ring", fontsize=16) @@ -648,7 +670,7 @@ def get_loss_profile(self, dic): ax.tick_params(axis="both", labelsize=16) ax.plot(list(a.index), summed, color="navy") - _pyaccel.graphics.draw_lattice( + _pa.graphics.draw_lattice( self._model_fit, offset=-1e-6, height=1e-6, gca=True ) @@ -673,7 +695,7 @@ def get_loss_profilel(self, l_dic): summed = [] for idx, _ in a.iterrows(): - sum_row = scyint.trapz(a.loc[idx], s[indices]) + sum_row = _sp_int.trapz(a.loc[idx], s[indices]) summed.append(sum_row) lista.append((a.index, summed)) @@ -696,7 +718,7 @@ def plot_scat_dict(self, new_dic): val[idx] = _np.log10(val[idx]) val[~idx] = val[idx].min() - fig, ax = _plt.subplots(figsize=(10, 10)) + fig, ax = _mplt.subplots(figsize=(10, 10)) y = _np.linspace(0, s[-1], df.shape[0] + 1) x = _np.linspace(0, s[-1], df.shape[1] + 1) @@ -704,7 +726,7 @@ def plot_scat_dict(self, new_dic): heatmp = ax.pcolor(x_mesh, y_mesh, val, cmap="jet", shading="flat") - cbar = _plt.colorbar(heatmp) + cbar = _mplt.colorbar(heatmp) cbar.set_label("Loss rate [1/s] in logarithmic scale", rotation=90) ax.set_title("Loss profile", fontsize=16) @@ -713,5 +735,5 @@ def plot_scat_dict(self, new_dic): ax.set_ylabel("lost positions [m]", fontsize=16) fig.tight_layout() - _plt.gca().set_aspect("equal") - _plt.show() + _mplt.gca().set_aspect("equal") + _mplt.show()