def fluCalFun(flupara, flupara_sys, refpara, qz, sh=0): 'takes in flupara, qz, return fluorescence data.' # unwrap fitting parameters qoff = flupara[0] # q offset, in A^-1 yscale = flupara[1] # y scale, unitless bgcon = flupara[2] # background constant, unitless. R = flupara[3] * 1e10 # surface curvature, in A if R == 0: R = 10000 * 1e10 # radius set to very big when curvature is "zero". conupbk = flupara[4] # background linear is borrowed for upper phase concentration, in M surden = flupara[5] # surface density, in A^-2 conbulk = flupara[6] # bulk concentration, in M # unwrap system parameters k0 = flupara_sys[1][0] mu = flupara_sys[3] bet = flupara_sys[4] del_ = flupara_sys[5] fluelepara = flupara_sys[6] slit = flupara_sys[7] # size of slit1, in A detlen = flupara_sys[8] # detector length, in A mu_top_inc, mu_top_emit, mu_bot_inc, mu_bot_emit = tuple(mu) bet_top_inc, bet_top_emit, bet_bot_inc, bet_bot_emit = tuple(bet) del_top_inc, del_top_emit, del_bot_inc, del_bot_emit = tuple(del_) # calculate reflectivity and footprint span = 75.6 * 1e7 # dimession of the sample call. qz = qz + qoff refModel = ref2min(refpara, None, None, None, fit=False, rrf=False) alpha = qz / k0 / 2 # incident angles fprint = slit / np.sin(alpha) # get the footprints in unit of /AA center = - float(sh) * 1e7 / alpha if fprint[0] >= span: print 'Warning: footprint is %.2e, should not exceed 75.6e7' % fprint[0] # initialize fluorescence data, rows: total, aqueous, organic, interface absorb = lambda x: np.nan_to_num(np.exp(x)) flu = np.zeros((6, len(alpha))) for i, a0 in enumerate(alpha): steps = int(fprint[i] / 0.5e6) # use 0.1 mm as the step size stepsize = fprint[i] / steps # get the position of single ray hitting the surface x0 = np.linspace(center[i] - fprint[i] / 2, center[i] + fprint[i] / 2, steps) surface = np.array([gm.hit_surface([xx, 0], -a0, R, span) for xx in x0]) miss = np.isinf(surface[:, 1]) # number of rays that miss the interface x_s = surface[~miss][:, 0] # x' for rays that hit on the interface z_s = surface[~miss][:, 1] # z' for rays that hit on the interface # sample raised up by sh is equivalent to beam moved toward upstream by sh/a0 # hit_center_ray = gm.hit_surface([center[i], 0], -a0, R, np.inf) # (x,z) and other surface geometry for points where beam hit at the interface. theta = -x_s / R # incline angle a_new = a0 + theta # actual incident angle w.r. to the surface # a1 = a0 + 2 * theta a1 = a0 x_inc = x_s + z_s / a0 # x position where the inc. xray passes z=0 line x_ref = x_s - z_s / a1 # x position where the inc. xray passes z=0 line. mu_eff_inc = mu_top_emit + mu_top_inc / a0 # eff.abs.depth for incident beam in oil phase mu_eff_ref = mu_top_emit - mu_top_inc / a1 # eff.abs.depth for reflected beam in water phase # z coordinate of the intersection of ray with following: z_inc_l = (x_inc + detlen / 2) * a0 # incidence with left det. boundary: x=-l/2 z_inc_r = (x_inc - detlen / 2) * a0 # incidence with right det. boundary: x=l/2 z_ref_l = -(x_ref + detlen / 2) * a1 # reflection with left det. boundary: x=-l/2 z_ref_r = -(x_ref - detlen / 2) * a1 # reflection with right det. boundary: x=l/2 # two regions: [-h/2a0,-l/2] & [-l/2,l/2] x_region = [(x_s <= -detlen / 2), (x_s > -detlen / 2) * (x_s < detlen / 2)] ################### for region x>= l/2 ######################## x0_region1 = x0[surface[:, 0] > detlen / 2] # choose x0 with x'>l/2 upper_bulk1 = absorb(-x0_region1 * mu_top_inc) / mu_eff_inc * \ (absorb((x0_region1 + detlen / 2) * a0 * mu_eff_inc) - absorb((x0_region1 - detlen / 2) * a0 * mu_eff_inc)) # if beam miss the surface entirely, do the following: if len(x_s) == 0: # the entire beam miss the interface, only incidence in upper phase. # sh_offset_factor = absorb(-mu_top_emit * center[i] * a0) sh_offset_factor = 1 usum_inc = sh_offset_factor * stepsize * np.sum(upper_bulk1) flu[2, i] = yscale * usum_inc * N_A * conupbk * fluelepara[0][1] / 1e27 # oil phase incidence only flu[0, i] = flu[2, i] # total intensity only contains oil phase continue else: ref = refModel(2 * k0 * a_new) # calculate the reflectivity at incident angle alpha_prime. effd, trans = frsnllCal(del_top_inc, bet_top_inc, del_bot_inc, bet_bot_inc, mu_bot_emit, k0, a0, a_new) ################### for region -l/2 < x < l/2 ################# lower_bulk2 = x_region[1] * absorb(-x_s * mu_top_inc - z_s / effd) * trans * effd * \ (absorb(z_s / effd) - absorb(z_inc_r / effd)) surface = x_region[1] * trans * absorb(-mu_top_inc * x_s) upper_bulk2_inc = x_region[1] * \ (absorb(-x_inc * mu_top_inc) / mu_eff_inc * ( absorb(z_inc_l * mu_eff_inc) - absorb(z_s * mu_eff_inc))) upper_bulk2_inc[np.isnan(upper_bulk2_inc)] = 0 # if there is nan, set to 0 upper_bulk2_ref = x_region[1] * \ (absorb(-x_ref * mu_top_inc) / mu_eff_ref * ref * ( absorb(z_ref_r * mu_eff_ref) - absorb(z_s * mu_eff_ref))) upper_bulk2_ref[np.isnan(upper_bulk2_ref)] = 0 # if there is nan, set to 0 ###################### for region x<=-l/2 ######################## lower_bulk3 = x_region[0] * absorb(-x_s * mu_top_inc - z_s / effd) * trans * effd * \ (absorb(z_inc_l / effd) - absorb(z_inc_r / effd)) upper_bulk3 = x_region[0] * absorb(-x_ref * mu_top_inc) / mu_eff_ref * ref * \ (absorb(mu_eff_ref * z_ref_r) - absorb(mu_eff_ref * z_ref_l)) # combine the two regions and integrate along x direction by performing np.sum. bsum = stepsize * np.sum(lower_bulk3 + lower_bulk2) ssum = stepsize * np.sum(surface) usum_inc = stepsize * (np.sum(upper_bulk1) + np.sum(upper_bulk2_inc)) usum_ref = stepsize * (np.sum(upper_bulk3) + np.sum(upper_bulk2_ref)) # vectorized integration method is proved to reduce the computation time by a factor of 5 to 10. int_bulk = yscale * bsum * N_A * conbulk * fluelepara[0][1] / 1e27 int_upbk_inc = yscale * usum_inc * N_A * conupbk * fluelepara[0][1] / 1e27 # metal ions in the upper phase. int_upbk_ref = yscale * usum_ref * N_A * conupbk * fluelepara[0][1] / 1e27 # metal ions in the upper phase. int_sur = yscale * ssum * surden int_tot = int_bulk + int_sur + int_upbk_inc + int_upbk_ref + bgcon # total_ref = np.sum(ref>=0.999999)/float(len(ref)) # the ratio of footprint with total reflection total_ref = 1 flu[:, i] = np.array([int_tot, int_bulk, int_upbk_inc, int_upbk_ref, int_sur, total_ref]) return flu
def fluCalFun_core(a0, sh, p): '''takes in flupara_fit, qz, return fluorescence data. Note that 'weights' contains the info of the steps for integration a0: the incident angle of X-ray beam, corrected with Qz_offset, in rad. sh: the sample height shift w.r.t. its norminal position, in A. p['wt']: weights for the beam profile, the length of which is the total amount of steps. p['k0']: wavevector for incident ray Energy, in KeV. p['detR']: detector range, in mm. p['hisc']: scale factor for the top phase, unitless. p['losc']: scale factor for the bottom pahse, unitless. p['bg']: background intensity, unitless. p['k1']: wavevector for emission ray energy, in KeV. p['tC']: ion concentration of the top phase, in M. p['bC']: ion concentration of the bottom phase, in M. p['sC']: ioin surface number density, in A^-2. p['qoff']: q off set for the data p['soff']: sample height offset (effoct of detector offset included) for the measurement p['l2off']: l2 offset for the measurement p['tRho']: electron density of top phase, in A^-3. p['bRho']: electron density of bottom phase, in A^-3. p['itMu']: mu for incident beam in top pahse, in A^-1 p['etMu']: mu for emitted beam in top phass, in A^-1 p['ibMu']: mu for incident beam in bottom pahse, in A^-1 p['ebMu']: mu for emitted beam in bottom phass, in A^-1 p['itBt']: beta for incident beam in top pahse, in A^-1 p['etBt']: beta for emitted beam in top phass, in A^-1 p['ibBt']: beta for incident beam in bottom pahse, in A^-1 p['ebBt']: beta for emitted beam in bottom phass, in A^-1 p['itDt']: delta for incident beam in top pahse, in A^-1 p['etDt']: delta for emitted beam in top phass, in A^-1 p['ibDt']: delta for incident beam in bottom pahse, in cm^-1 p['ebDt']: delta for emitted beam in bottom phass, in cm^-1 p['span']: the length of the sample cell, "the span", in A. p['curv']: the curvature of the interface, in A. p['bmsz']: the size of the beam for footprint calculation, in A. ''' z_depth = -50 # the predifined depth of interfacial ions steps = len(p['wt']) - 1 fprint = p['bmsz'] / np.sin(a0) # foortprint of the beam on the interface. stepsize = fprint / steps center = -sh / a0 # initialize fluorescence data, rows: total, aqueous, organic, interface # get the position of single ray hitting the surface x0 = np.linspace(center - fprint / 2, center + fprint / 2, steps + 1) surface = np.array( [gm.hit_surface([xx, 0], -a0, p['curv'], p['span']) for xx in x0]) hit = np.isfinite(surface[:, 0]) * np.isfinite( surface[:, 1]) # rays that hit the liquid-liquid interface block = np.isfinite(surface[:, 0]) * np.isinf( surface[:, 1]) # rays that are blocked by the tray x_s = surface[:, 0][hit] # x' for rays that hit on the interface z_s = surface[:, 1][hit] # z' for rays that hit on the interface if p['curv'] == 1e14: z_s = np.zeros(x_s.shape) wt_s = p['wt'][hit] # weight for rays that hit on the interface # (x,z) and other surface geometry for points where beam hit at the interface. theta = -x_s / p['curv'] # incident angle a_new = a0 + theta # actual incident angle w.r. to the surface # a1 = a0 + 2 * theta a1 = a0 x_inc = x_s + z_s / a0 # x position where the inc. xray passes z=0 line x_ref = x_s - z_s / a1 # x position where the ref. xray passes z=0 line. mu_eff_inc = p['etMu'] + p[ 'itMu'] / a0 # eff.abs.depth for incident beam in oil phase mu_eff_ref = p['etMu'] - p[ 'itMu'] / a1 # eff.abs.depth for reflected beam in water phase # z coordinate of the intersection of ray with following: z_inc_l = (x_inc + p['detR'] / 2) * a0 # incidence with left det. boundary: x=-l/2 z_inc_r = (x_inc - p['detR'] / 2) * a0 # incidence with right det. boundary: x=l/2 z_ref_l = -(x_ref + p['detR'] / 2) * a1 # reflection with left det. boundary: x=-l/2 z_ref_r = -(x_ref - p['detR'] / 2) * a1 # reflection with right det. boundary: x=l/2 # define the initial intensity to be just background value flu = np.array([p['bg']] * 6) # two regions: region3: [-h/2a0,-l/2] & region 2: [-l/2,l/2] x_region = [(x_s <= -p['detR'] / 2), (x_s > -p['detR'] / 2) * (x_s < p['detR'] / 2)] ################### for redgion 1: region x>= l/2 ######################## # Special treatment for x>L/2 region. # This region only contains incident beam in organic phase if any, i.e. the part of beam before it hits # the interface. So the contribution from this part of the beam is calculated with x0 instead of x_s, # which is much easier. x0_region1 = x0[surface[:, 0] > p['detR'] / 2] # choose x0 with x'>l/2 wt_region1 = p['wt'][surface[:, 0] > p['detR'] / 2] # choose weight with x'>l/2 upper_bulk1 = wt_region1 * \ absorb(-x0_region1 * p['itMu']) / mu_eff_inc * \ (absorb((x0_region1 + p['detR'] / 2) * a0 * mu_eff_inc) - absorb((x0_region1 - p['detR'] / 2) * a0 * mu_eff_inc)) # Equation 5.6 # The following case is that the entire beam misses the interface. In this case only incident beam is # calculated and all the calculation below this segment is skipped. if len( x_s ) == 0: # the entire beam miss the interface, only incidence in upper phase. # sh_offset_factor = absorb(-mu_top_emit * center[i] * a0) usum_inc = stepsize * np.sum(upper_bulk1) flu[3] += p['hisc'] * usum_inc * N_A * p[ 'tC'] / 1e27 # oil phase incidence only + background flu[0] = flu[3] # total intensity only contains oil phase return flu # If the beam hit the interface, reflectivity, transmissivity and the penetration depth is calculated. ref, trans, p_depth = fresnel(a_new, p['k0'], (p['itBt'], p['ibBt']), (p['itDt'], p['ibDt'])) p_depth_eff = 1 / (p['ebMu'] + a_new / a0 / p_depth) ################### for region -l/2 < x < l/2 ################# # original: uniform bulk distribution down to negative infinity. lower_bulk2 = x_region[1] * wt_s * absorb(-x_s * p['itMu'] - z_s / p_depth) * trans * p_depth * \ (absorb(z_s / p_depth_eff) - absorb(z_inc_r / p_depth_eff)) # consider uniform bulk distribution down to 5nm below interface # lower_bulk2 = x_region[1] * wt_s * absorb(-x_s * p['itMu'] - z_s*a1/a0 / p_depth) * trans * p_depth_eff * \ # (absorb(z_s / p_depth_eff) - absorb(z_depth / p_depth_eff)) # consider the interfacial region as z_depth below the interface (z_depth=0 for original model) # interface = x_region[1] * wt_s * trans * absorb(-p['itMu'] * x_s) * absorb(-a1/a0*z_depth/p_depth) interface = x_region[1] * wt_s * trans * absorb(-p['itMu'] * x_s) upper_bulk2_inc = x_region[1] * wt_s * \ (absorb(-x_inc * p['itMu']) / mu_eff_inc * ( absorb(z_inc_l * mu_eff_inc) - absorb(z_s * mu_eff_inc))) upper_bulk2_inc[np.isnan(upper_bulk2_inc)] = 0 # if there is nan, set to 0 upper_bulk2_ref = x_region[1] * wt_s * \ (absorb(-x_ref * p['itMu']) / mu_eff_ref * ref * ( absorb(z_ref_r * mu_eff_ref) - absorb(z_s * mu_eff_ref))) upper_bulk2_ref[np.isnan(upper_bulk2_ref)] = 0 # if there is nan, set to 0 ###################### for region x<=-l/2 ######################## lower_bulk3 = x_region[0] * wt_s * absorb(-x_s * p['itMu'] - z_s / p_depth) * trans * p_depth_eff * \ (absorb(z_inc_l / p_depth_eff) - absorb(z_inc_r / p_depth_eff)) upper_bulk3 = x_region[0] * wt_s * absorb(-x_ref * p['itMu']) / mu_eff_ref * ref * \ (absorb(mu_eff_ref * z_ref_r) - absorb(mu_eff_ref * z_ref_l)) # if there are rays that are blocked by tray, their intensity is still significent if np.sum(block) > 0: edge = None # combine the two regions and integrate along x direction by performing np.sum. bsum = stepsize * np.sum(lower_bulk2 + lower_bulk3) ssum = stepsize * np.sum(interface) usum_inc = stepsize * (np.sum(upper_bulk1) + np.sum(upper_bulk2_inc)) usum_ref = stepsize * (np.sum(upper_bulk3) + np.sum(upper_bulk2_ref)) # vectorized integration method is proved to reduce the computation time by a factor of 5 to 10. int_bulk = p['losc'] * bsum * N_A * p['bC'] / 1e27 int_upbk_inc = p['hisc'] * usum_inc * N_A * p[ 'tC'] / 1e27 # metal ions in the upper phase. int_upbk_ref = p['hisc'] * usum_ref * N_A * p[ 'tC'] / 1e27 # metal ions in the upper phase. int_sur = p['losc'] * ssum * p['sC'] flu += np.array([ int_bulk + int_sur + int_upbk_inc + int_upbk_ref, # 2. total fluorescence + background int_bulk, # 3. lower bulk int_sur, # 4. interface int_upbk_inc + int_upbk_ref, # 5. upper bulk int_upbk_inc, # 6. upper bulk incidence int_upbk_ref ]) # 7. upper bulk reflection return flu
def fluCalFun_core(a0, sh, p): '''takes in flupara_fit, qz, return fluorescence data. Note that 'weights' contains the info of the steps for integration a0: the incident angle of X-ray beam, corrected with Qz_offset, in rad. sh: the sample height shift w.r.s. to its norminal position, in A. p['wt']: weights for the beam profile, the length of which is the total amount of steps. p['k0']: wavevector for incident ray Energy, in KeV. p['detR']: detector range, in mm. p['hisc']: scale factor for the top phase, unitless. p['losc']: scale factor for the bottom pahse, unitless. p['bg']: background intensity, unitless. p['k1']: wavevector for emission ray energy, in KeV. p['tC']: ion concentration of the top phase, in M. p['bC']: ion concentration of the bottom phase, in M. p['sC']: ioin surface number density, in A^-2. p['qoff']: q off set for the data p['doff']: det range offset for the measurement p['l2off']: l2 offset for the measurement p['tRho']: electron density of top phase, in A^-3. p['bRho']: electron density of bottom phase, in A^-3. p['itMu']: mu for incident beam in top pahse, in cm^-1 p['etMu']: mu for emitted beam in top phass, in cm^-1 p['ibMu']: mu for incident beam in bottom pahse, in cm^-1 p['ebMu']: mu for emitted beam in bottom phass, in cm^-1 p['itBt']: beta for incident beam in top pahse, in cm^-1 p['etBt']: beta for emitted beam in top phass, in cm^-1 p['ibBt']: beta for incident beam in bottom pahse, in cm^-1 p['ebBt']: beta for emitted beam in bottom phass, in cm^-1 p['itDt']: delta for incident beam in top pahse, in cm^-1 p['etDt']: delta for emitted beam in top phass, in cm^-1 p['ibDt']: delta for incident beam in bottom pahse, in cm^-1 p['ebDt']: delta for emitted beam in bottom phass, in cm^-1 p['span']: the length of the sample cell, "the span", in A. p['curv']: the curvature of the interface, in A. p['bmsz']: the size of the beam for footprint calculation, in A. ''' steps = len(p['wt']) - 1 fprint = p['bmsz'] / np.sin(a0) # foortprint of the beam on the interface. stepsize = fprint / steps center = -sh / a0 # initialize fluorescence data, rows: total, aqueous, organic, interface absorb = lambda x: np.nan_to_num(np.exp(x)) # get the position of single ray hitting the surface x0 = np.linspace(center - fprint / 2, center + fprint / 2, steps + 1) surface = np.array( [gm.hit_surface([xx, 0], -a0, p['curv'], p['span']) for xx in x0]) miss = np.isinf(surface[:, 1]) # number of rays that miss the interface x_s = surface[:, 0][~miss] # x' for rays that hit on the interface z_s = surface[:, 1][~miss] # z' for rays that hit on the interface wt_s = p['wt'][~miss] # weight for rays that hit on the interface # (x,z) and other surface geometry for points where beam hit at the interface. theta = -x_s / p['curv'] # incline angle a_new = a0 + theta # actual incident angle w.r. to the surface # a1 = a0 + 2 * theta a1 = a0 x_inc = x_s + z_s / a0 # x position where the inc. xray passes z=0 line x_ref = x_s - z_s / a1 # x position where the ref. xray passes z=0 line. mu_eff_inc = p['etMu'] + p[ 'itMu'] / a0 # eff.abs.depth for incident beam in oil phase mu_eff_ref = p['etMu'] - p[ 'itMu'] / a1 # eff.abs.depth for reflected beam in water phase # z coordinate of the intersection of ray with following: z_inc_l = (x_inc + p['detR'] / 2) * a0 # incidence with left det. boundary: x=-l/2 z_inc_r = (x_inc - p['detR'] / 2) * a0 # incidence with right det. boundary: x=l/2 z_ref_l = -(x_ref + p['detR'] / 2) * a1 # reflection with left det. boundary: x=-l/2 z_ref_r = -(x_ref - p['detR'] / 2) * a1 # reflection with right det. boundary: x=l/2 # two regions: [-h/2a0,-l/2] & [-l/2,l/2] x_region = [(x_s <= -p['detR'] / 2), (x_s > -p['detR'] / 2) * (x_s < p['detR'] / 2)] ################### for region x>= l/2 ######################## x0_region1 = x0[surface[:, 0] > p['detR'] / 2] # choose x0 with x'>l/2 wt_region1 = p['wt'][surface[:, 0] > p['detR'] / 2] # choose weight with x'>l/2 upper_bulk1 = wt_region1 * \ absorb(-x0_region1 * p['itMu']) / mu_eff_inc * \ (absorb((x0_region1 + p['detR'] / 2) * a0 * mu_eff_inc) - absorb((x0_region1 - p['detR'] / 2) * a0 * mu_eff_inc)) flu = np.array([0, 0, 0, 0, 0, 0]) # if beam miss the surface entirely, do the following: if len( x_s ) == 0: # the entire beam miss the interface, only incidence in upper phase. # sh_offset_factor = absorb(-mu_top_emit * center[i] * a0) usum_inc = stepsize * np.sum(upper_bulk1) flu[3] = p['hisc'] * usum_inc * N_A * p[ 'tC'] / 1e27 # oil phase incidence only flu[0] = flu[3] # total intensity only contains oil phase else: ref = mfit.refCalFun([], [p['tRho'], p['bRho']], [p['itMu'], p['ibMu']], [3.0], 2 * p['k0'] * a_new) p_depth, trans = penetrate((p['itBt'], p['ibBt']), (p['itDt'], p['ibDt']), a_new, p['k0']) p_depth_eff = 1 / (p['ebMu'] + a_new / a0 / p_depth) ################### for region -l/2 < x < l/2 ################# lower_bulk2 = x_region[1] * wt_s * absorb(-x_s * p['itMu'] - z_s / p_depth) * trans * p_depth * \ (absorb(z_s / p_depth_eff) - absorb(z_inc_r / p_depth_eff)) surface = x_region[1] * wt_s * trans * absorb(-p['itMu'] * x_s) upper_bulk2_inc = x_region[1] * wt_s * \ (absorb(-x_inc * p['itMu']) / mu_eff_inc * ( absorb(z_inc_l * mu_eff_inc) - absorb(z_s * mu_eff_inc))) upper_bulk2_inc[np.isnan( upper_bulk2_inc)] = 0 # if there is nan, set to 0 upper_bulk2_ref = x_region[1] * wt_s * \ (absorb(-x_ref * p['itMu']) / mu_eff_ref * ref * ( absorb(z_ref_r * mu_eff_ref) - absorb(z_s * mu_eff_ref))) upper_bulk2_ref[np.isnan( upper_bulk2_ref)] = 0 # if there is nan, set to 0 ###################### for region x<=-l/2 ######################## lower_bulk3 = x_region[0] * wt_s * absorb(-x_s * p['itMu'] - z_s / p_depth) * trans * p_depth_eff * \ (absorb(z_inc_l / p_depth_eff) - absorb(z_inc_r / p_depth_eff)) upper_bulk3 = x_region[0] * wt_s * absorb(-x_ref * p['itMu']) / mu_eff_ref * ref * \ (absorb(mu_eff_ref * z_ref_r) - absorb(mu_eff_ref * z_ref_l)) # combine the two regions and integrate along x direction by performing np.sum. bsum = stepsize * np.sum(lower_bulk3 + lower_bulk2) ssum = stepsize * np.sum(surface) usum_inc = stepsize * (np.sum(upper_bulk1) + np.sum(upper_bulk2_inc)) usum_ref = stepsize * (np.sum(upper_bulk3) + np.sum(upper_bulk2_ref)) # vectorized integration method is proved to reduce the computation time by a factor of 5 to 10. int_bulk = p['losc'] * bsum * N_A * p['bC'] / 1e27 int_upbk_inc = p['hisc'] * usum_inc * N_A * p[ 'tC'] / 1e27 # metal ions in the upper phase. int_upbk_ref = p['hisc'] * usum_ref * N_A * p[ 'tC'] / 1e27 # metal ions in the upper phase. int_sur = p['losc'] * ssum * p['sC'] flu = np.array([ int_bulk + int_sur + int_upbk_inc + int_upbk_ref + p['bg'], # 2. total fluorescence int_bulk, # 3. lower bulk int_sur, # 4. interface int_upbk_inc + int_upbk_ref, # 5. upper bulk int_upbk_inc, # 6. upper bulk incidence int_upbk_ref ]) # 7. upper bulk reflection return flu