module PLUV import SpecialFunctions: erf ###################################################################################################### ###################################################################################################### ###################################################################################################### ############### POPC/POPG 95/5 mol/mol LUVs ############### ############### Reconstitution buffer: TRIS 20 mM, EDTA 2 mM ############### ############### Buffer used for PLUV exp. in DESY in 2017: ############### ###################################################################################################### ###################################################################################################### ###################################################################################################### const parameter_names = [ :norm, :nv, :rm, :z, :n_tr, :d_tr, :s_tr, :d_chol, :s_chol, :d_pcn, :s_pcn, :d_cg, :s_cg, :a_l, :s_d_c, :s_ch2, :d_ch, :s_ch, :s_ch3, :r_pcn, :r_cg, :r12, :r32, :t, :v_bw, :con ] ############### GLOBAL VARIABLES ############### # POPG molar ratio const CONST_x_PG = 0.05 # ############## POPC and POPG ############### # 1-palmitoyl-2-oleoyl-sn-glycero-3-phosphocholine # 1-palmitoyl-2-oleoyl-sn-glycero-3-phosphoglycerol # number of chain groups const CONST_n_CH = 2 const CONST_n_CH2 = 28 const CONST_n_CH3 = 2 #X-ray scattering length chain groups (nm) const CONST_b_CH = 1.97256E-05 const CONST_b_CH2 = 2.25435E-05 const CONST_b_CH3 = 2.53615E-05 ### POPC # Lipid-head volume const CONST_V_HL_PC = 0.331 # 0.320 # X-ray scattering length of head groups (nm) const CONST_b_PC = 2.73340E-04 const CONST_b_CG = 1.88802E-04 const CONST_b_PCN = 1.97256E-04 const CONST_b_Chol = 7.60844E-05 # Lipid-volume temperature-dependencies a0 + a1*T (nm^3) const CONST_a0_V_POPC = 1.22810311835285 const CONST_a1_V_POPC = 0.000934915795086395 ### POPG # Lipid-head volume const CONST_V_HL_PG = 0.289 # X-ray Scattering length of head groups (nm) const CONST_b_PG = 2.47979E-04 const CONST_b_PG1 = 1.32443E-04 const CONST_b_PG2 = 1.15536E-04 # Lipid-volume temperature-dependencies a0 + a1*T (nm^3) const CONST_a0_V_POPG = 1.17881068602663 const CONST_a1_V_POPG = 0.00108364914520327 ############### Other variables ############### ### Water # V_PW = 24.5e-3 #(nm^3) Perkins 2001 (Hydration shell in proteins) # polynome coefficient for T-dependency of bulk-water-molecule volume (V_HW) # Units in degree Celsius const CONST_p0_VW = 0.0299218 const CONST_p1_VW = -2.25941e-06 const CONST_p2_VW = 2.5675e-07 const CONST_p3_VW = -1.69661e-09 const CONST_p4_VW = 6.52029e-12 # polynome coefficient for T-dependency of bulk-water molar concentration (Cw) #Units in degree Celsius const CONST_p0_Cw = 55.5052 const CONST_p1_Cw = 0.00131894 const CONST_p2_Cw = -0.000334396 const CONST_p3_Cw = 9.10861e-07 const CONST_b_HW = 2.8179E-05 const CONST_d_shl = 0.31 # (nm) Perkins 2001 (Hydration shell in proteins) # Composition of the Reconstitution buffer (M) const CONST_ctris = 0.02 const CONST_cEDTA = 0.002 ### Extra molecules # TRIS buffer const CONST_b_tris = 1.860E-04 const CONST_V_tris = 0.15147 # (nm^3) # EDTA const CONST_b_EDTA = 4.340E-04 const CONST_V_EDTA = 0.56430 # (nm^3) ################################################################################################################## ################################################################################################################## ######################################################### #@njit(parallel=True) function PDF_normal(x, mu, sig) return exp(-(x - mu)^2 / (2 * sig^2)) / (sig * sqrt(2 * pi)) end ######################################################### #@njit(parallel=True) function PDF_lognormal(x, mu_x, sig_x) # https://en.wikipedia.org/wiki/Log-normal_distribution mu = log(mu_x^2 / sqrt(mu_x^2 + sig_x^2)) sig = sqrt(log(1 + sig_x^2 / mu_x^2)) return exp(-(log(x) - mu)^2 / (2 * sig^2)) / (x * sig * sqrt(2 * pi)) end ######################################################### function lipid_volume(T) return (1 - CONST_x_PG) * (CONST_a0_V_POPC + T * CONST_a1_V_POPC) + CONST_x_PG * (CONST_a0_V_POPG + T * CONST_a1_V_POPG) end ######################################################### function water_volume(T) return CONST_p0_VW + CONST_p1_VW * T + CONST_p2_VW * T^2 + CONST_p3_VW * T^3 + CONST_p4_VW * T^4 end ######################################################### #@njit(parallel=True) function FTreal_erf(q, mu, d, sig) """ FTreal_erf(q, mu, d, sig) """ return sin(q * d / 2.0) / (q * d / 2.0) * exp(-(q * sig)^2 / 2.0) * cos(q * mu) end ######################################################### #@njit(parallel=True) function FTreal_gauss(q, mu, sig) """ FTreal_gauss(q, mu, sig) """ return exp(-(q * sig)^2 / 2.0) * cos(q * mu) end ######################################################### function Slab(x, mu, L, sig) return 0.5 * (erf((x - (mu - L / 2.0)) / (sqrt(2) * sig)) - erf((x - (mu + L / 2)) / (sqrt(2) * sig))) end ######################################################### function Gauss(x, V, mu, sig, A_L) return V * PDF_normal(x, mu, sig) / A_L end #################################### j0^2 MOMENTS (SCHULZ PDF) ######################################### #################################### (checked!) ######################################### #@njit(parallel=True) function mu4(q, Z, a) return a^2 * (Z + 2) * (Z + 1) * (1 - (1 + 4 * q^2 * a^2)^(-(Z + 3) / 2.0) * cos((Z + 3) * atan(2 * q * a))) / (2 * q^2) end ################################################################################################################## ################################################################################################################## ################################ SYMMETRIC VESICLE FOR X-RAY SLDs ######################################### ######################################## SDP MODELLING ######################################### #################################### SEPARATED FORM FACTOR ######################################### ################################################################################################################## ################################################################################################################## ######################################################### ######### Symmetric POPC bilayer ######################## ######### liposomes and proteoliposomes ################# ######################################################### ################## function intensity(P::NamedTuple, q) return intensity(Float64[P...], q) end function intensity(P::AbstractArray{Float64}, q) Norm, nv, Rm, Z, n_TR, d_TR, s_TR, d_Chol, s_Chol, d_PCN, s_PCN, d_CG, s_CG, A_L, s_D_C, s_CH2, d_CH, s_CH, s_CH3, r_PCN, r_CG, r12, r32, T, V_BW, Con = P # [Example 1], fixed parameters # Norm 1e5 # Normalization # n_TR 0.0 # Tris fraction # d_TR 1.0 # Tris width (nm) # s_TR 0.29 # Tris position (nm) # d_CH 0.90 # CH position (nm) # s_CH 0.305 # CH width (nm) # r12 0.81 # V_CH/V_CH2 # T 37 # Temperature (°C) # [example 1] fixed Cw = CONST_p0_Cw + CONST_p1_Cw * T + CONST_p2_Cw * T^2 + CONST_p3_Cw * T^3 xtris = CONST_ctris / Cw # mole fraction of free TRIS in bulk xEDTA = CONST_cEDTA / Cw # mole fraction of free EDTA in bulk # Volumes # [example 1] fixed V_L = lipid_volume(T) V_HW = water_volume(T) V_HC = V_L - ((1 - CONST_x_PG) * CONST_V_HL_PC + CONST_x_PG * CONST_V_HL_PG) # Calculation of mean D_C D_C = V_HC / A_L # Quasi-molecular volumes # [example 1] r12 fixed V_CH2 = V_HC / (CONST_n_CH2 + CONST_n_CH * r12 + CONST_n_CH3 * r32) # Volume of CH2 groups V_CH = V_CH2 * r12 # Volume of CH groups V_CH3 = V_CH2 * r32 # Volume of CH3 groups V_CG = CONST_V_HL_PC * r_CG # Volume of CG group V_PCN = CONST_V_HL_PC * r_PCN # Volume of PCN group V_Chol = CONST_V_HL_PC * (1 - r_PCN - r_CG) # Volume of CholCH3 group # CONST CONST_V_PG1 = CONST_V_HL_PG * 0.16 # Kucerka 2012 CONST_V_PG2 = CONST_V_HL_PG * (1 - 0.51 - 0.16) # Kucerka 2012 ############### X-ray scattering lengths (nm) # [example 1] rho_sol fixed rho_sol = (CONST_b_HW + xtris * CONST_b_tris + xEDTA * CONST_b_EDTA) / V_HW drho_Chol = ((1 - CONST_x_PG) * CONST_b_Chol / V_Chol + CONST_x_PG * CONST_b_PG2 / CONST_V_PG2) - rho_sol drho_PCN = ((1 - CONST_x_PG) * CONST_b_PCN / V_PCN + CONST_x_PG * CONST_b_PG1 / CONST_V_PG1) - rho_sol drho_CG = CONST_b_CG / V_CG - rho_sol drho_TR = CONST_b_tris / CONST_V_tris - rho_sol drho_CH = CONST_b_CH / V_CH - rho_sol drho_CH2 = CONST_b_CH2 / V_CH2 - rho_sol drho_CH3 = CONST_b_CH3 / V_CH3 - rho_sol drho_HW = CONST_b_HW / V_BW - rho_sol ############### D_C polydispersity # Number of integration points N = 201 # Parameter dependent integration bounds # HC_min, HC_max = D_C-3*s_D_C, D_C+3*s_D_C # # Hardcoded integration bounds for POPC, fixed T = 37, A_L in [0.598, 0.719] HC_min, HC_max = V_HC / 0.719 - 0.5, V_HC / 0.589 + 0.5 # Minimum and maximum samples (offset by 1/2 of the integration step w.r.t integration bounds for the midpoint rule) integration_step = (HC_max - HC_min) / N HC_first, HC_last = HC_min + 0.5 * integration_step, HC_max - 0.5 * integration_step HC_array = range(HC_first, HC_last, length=N) Normal = PDF_normal.(HC_array, D_C, s_D_C) ############### c-prefactors c_Chol = ((1 - CONST_x_PG) * V_Chol + CONST_x_PG * CONST_V_PG2) / A_L c_PCN = ((1 - CONST_x_PG) * V_PCN + CONST_x_PG * CONST_V_PG1) / A_L c_CG = V_CG / A_L c_TR = CONST_V_tris * n_TR / A_L c_CH = V_CH * CONST_n_CH / V_HC * HC_array c_CH3 = V_CH3 * CONST_n_CH3 / V_HC * HC_array d_comp = d_CG + d_PCN + d_Chol + CONST_d_shl ############### calculating scattering amplitude ----------------------------------------------- Am = zeros(size(q, 1), N) for i in 1:N # Adding hydrocarbon-chain envelope Am[:, i] += 2 * drho_CH2 * HC_array[i] * FTreal_erf.(q, 0, 2 * HC_array[i], s_CH2) # Adding CH and CH3 groups Am[:, i] += 2 * (drho_CH - drho_CH2) * c_CH[i] * FTreal_gauss.(q, d_CH, s_CH) Am[:, i] += 2 * (drho_CH3 - drho_CH2) * c_CH3[i] * FTreal_gauss.(q, 0, s_CH3) # Adding hydration-water envelope Am[:, i] += 4 * drho_HW * d_comp * FTreal_erf.(q, (HC_array[i] + d_comp / 2.0), d_comp, s_CH2) # Adding CG, PCN and CholCH3 groups Am[:, i] += 2 * (drho_TR - drho_HW) * c_TR * FTreal_gauss.(q, (HC_array[i] + d_TR / 2.0), s_TR) Am[:, i] += 2 * (drho_CG - drho_HW) * c_CG * FTreal_gauss.(q, (HC_array[i] + d_CG / 2.0), s_CG) Am[:, i] += 2 * (drho_PCN - drho_HW) * c_PCN * FTreal_gauss.(q, (HC_array[i] + d_CG + d_PCN / 2.0), s_PCN) Am[:, i] += 2 * (drho_Chol - drho_HW) * c_Chol * FTreal_gauss.(q, (HC_array[i] + d_CG + d_PCN + d_Chol / 2.0), s_Chol) ############### Ensemble average # multiply each columns of Am by Normal and sum along the columns, # then multiply by integration step end I = vec(sum(Am .^ 2 .* Normal'; dims=2)) * integration_step alp = Rm / (Z + 1) neg_H20 = negative_water(P) return @. ((Norm * nv * 1e-6) * I * (16 * pi^2 * mu4(q, Z, alp)) + Con * (0.99 * (1.0 / (1 + exp(-8 * (q - 1.0)))) + 0.01), neg_H20) end ################## function negative_water(P::NamedTuple) return negative_water([P...]) end function negative_water(P::AbstractArray{Float64}) _, _, _, _, n_TR, d_TR, s_TR, d_Chol, s_Chol, d_PCN, s_PCN, d_CG, s_CG, A_L, _, s_CH2, _, _, _, r_PCN, r_CG, _, _, T, _, _ = P # Volumes V_L = lipid_volume(T) V_HC = V_L - ((1 - CONST_x_PG) * CONST_V_HL_PC + CONST_x_PG * CONST_V_HL_PG) # Calculation of mean D_C D_C = V_HC / A_L # Quasi-molecular volumes V_CG = CONST_V_HL_PC * r_CG # Volume of CG group V_PCN = CONST_V_HL_PC * r_PCN # Volume of PCN group V_Chol = CONST_V_HL_PC * (1 - r_PCN - r_CG) # Volume of CholCH3 group z_array = range(0.0, 4.0, length=81) CG = Gauss.(z_array, V_CG, D_C + d_CG / 2.0, s_CG, A_L) PCN = Gauss.(z_array, V_PCN, D_C + d_CG + d_PCN / 2.0, s_PCN, A_L) Chol = Gauss.(z_array, V_Chol, D_C + d_CG + d_PCN + d_Chol / 2.0, s_Chol, A_L) TRIS = Gauss.(z_array, n_TR * CONST_V_tris, D_C + d_TR / 2.0, s_TR, A_L) BW = Slab.(z_array, D_C + (d_CG + d_PCN + d_Chol + CONST_d_shl) / 2.0, d_CG + d_PCN + d_Chol + CONST_d_shl, s_CH2) - CG - PCN - Chol - TRIS # return the number of points where BW < -1e-3 return count(<(-1e-3), BW) end function get_free_parameters_idx(metadata::Dict) m = metadata["parameters"] return filter(i -> !m[i]["fixed"], eachindex(m)) end function reduce_to_free_parameters(metadata::Dict, params_init::NamedTuple, lb, ub, q) default_params = Float64[params_init...] free_idx = get_free_parameters_idx(metadata) P_reduced = default_params[free_idx] lb_reduced = lb[free_idx] ub_reduced = ub[free_idx] function reduced(P::AbstractArray{Float64}) P_reduced .= P return intensity(default_params, q) end return reduced, P_reduced, lb_reduced, ub_reduced end function reduce_to_free_parameters(metadata::Dict, params::Vector{Float64}) free_idx = get_free_parameters_idx(metadata) return params[free_idx] end end # module PLUV # vim ts=4,sts=4,sw=4