def get_simulated_ensemble(n, **kw): """ Returns: at most n curves (n) using the parameters Args: n: number of curves **kw: for Util.Simulation.hummer_force_extension_curve Returns: n IWT objects """ to_ret = [] for _ in range(n): t, q, z, f, p = Util.Simulation.hummer_force_extension_curve(**kw) velocity = p["velocity"] spring_constant = p['k'] beta = p['beta'] kT = 1 / beta good_idx = np.where((z > 325e-9) & (z < 425e-9)) initial_dict = dict(Time=t[good_idx] - t[good_idx][0], Extension=q[good_idx], Force=f[good_idx], Velocity=velocity, kT=kT, SpringConstant=spring_constant) tmp = InverseWeierstrass.FEC_Pulling_Object(**initial_dict) tmp.SetOffsetAndVelocity(z[good_idx][0], tmp.Velocity) to_ret.append(tmp) return to_ret
def _single_direction_assert(dir_objs, n): """ makes sure that the digitization works well for all of dir_objs """ digitized_ext = [] min_x = min([min(o.Extension) for o in dir_objs]) max_x = max([max(o.Extension) for o in dir_objs]) x_m_abs = [min_x, max_x] for o in dir_objs: _assert_digitization_correct(x_m_abs, n=n, obj=o) bins, digitized_tmp = _get_bins_and_digitized(x_m_abs, o, n=n) digitized_ext.append(digitized_tmp) # # POST: the (single) digitization is OK. # concatenate all the bins digitized_by_bins = [] for i in range(n): these_items = [item for fec in digitized_ext for item in fec[i]] digitized_by_bins.append(these_items) # post: digitzed_by_bins has all of digitized_ext... internal check: digitized_items = sorted( [item for bin_v in digitized_by_bins for item in bin_v]) test_items = sorted( [item for fec in digitized_ext for sublist in fec for item in sublist]) np.testing.assert_allclose(test_items, digitized_items, atol=0) # POST: digitized_items is just a flat list of all the original items, # so that is what the algirthm should give too # check that the ensemble-wide binning is OK. f_ext = lambda obj: obj._GetDigitizedGen(Bins=bins, ToDigitize=obj.Extension) digitized_ext = InverseWeierstrass._digitized_f(dir_objs, f=f_ext) for actual, expected in zip(digitized_ext, digitized_by_bins): np.testing.assert_allclose(actual, expected, atol=0)
def ToIWTObject(o, Offset=0, **kw): """ Returns: o, truend into a IWT object """ obj = InverseWeierstrass.FEC_Pulling_Object( Time=o.Time, Extension=o.Separation, Force=o.Force, SpringConstant=o.SpringConstant, Velocity=o.Velocity, Offset=Offset, **kw) return obj
def _filter_single_landscape(landscape_obj, bins, k=3, ext='const', **kw): """ filters landscape_obj using a smooth splineaccording to bins. If bins goes outside of landscape_obj.q, then the interpolation is constant (preventing wackyness) Args: landscape_obj: Landscape instance bins: where we want to filter along Returns: a filtered version of landscae_obj """ to_ret = copy.deepcopy(landscape_obj) # fit a spline at the given bins x = to_ret.q min_x, max_x = min(x), max(x) # determine where the bins are in the range of the data for this landscape good_idx = np.where((bins >= min_x) & (bins <= max_x)) bins_relevant = bins[good_idx] """ exclude the first and last bins, to make sure the Schoenberg-Whitney condition is met for all interior knots (see: docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.LSQUnivariateSpline """ t = bins_relevant[1:-1] kw = dict(x=x, t=t, ext=ext, k=k, **kw) f_spline = lambda y_tmp: LSQUnivariateSpline(y=y_tmp, **kw) spline_energy = f_spline(to_ret.energy) f_filter = lambda y_tmp_filter: f_spline(y_tmp_filter)(bins) # the new q is just the bins # filter each energy property to_ret.q = bins to_ret.energy = spline_energy(bins) to_ret.A_z = f_filter(to_ret.A_z) to_ret.A_z_dot = f_filter(to_ret.A_z_dot) to_ret.one_minus_A_z_ddot_over_k = \ f_filter(to_ret.one_minus_A_z_ddot_over_k) # dont allow the second derivative to go <= 0... to_ret.one_minus_A_z_ddot_over_k = \ np.maximum(0,to_ret.one_minus_A_z_ddot_over_k) # remove the 'data' property from the spline; otherwise it is too much # to store residual = spline_energy.get_residual() spline_energy.residual = residual spline_energy._data = None to_ret.spline_fit = InverseWeierstrass.SplineInfo(spline=spline_energy) return to_ret
def TestBidirectionalEnsemble(): """ Tests that the DeltaA calculation works well, also that the forward and reverse get the same answer """ n = 200 fwd_objs, rev_objs = HummerData(n=50) delta_A_calc = InverseWeierstrass.NumericallyGetDeltaA(fwd_objs, rev_objs) # the delta_A_calc should make the bennet ratio true. Since we have n_r=n_f, # I ignor that part beta = fwd_objs[0].Beta Wn_fwd = [f.Work[-1] for f in fwd_objs] Wn_rev = [r.Work[-1] for r in rev_objs] boltz_fwd = np.exp([beta * (Wf - delta_A_calc) for Wf in Wn_fwd]) boltz_rev = np.exp([beta * (Wr + delta_A_calc) for Wr in Wn_rev]) lhs = 1 / (n + n * boltz_fwd) rhs = 1 / (n + n * boltz_rev) mean_fwd = np.mean(lhs) mean_rev = np.mean(rhs) diff = abs(mean_fwd - mean_rev) diff_rel = diff / np.mean([mean_fwd, mean_rev]) np.testing.assert_allclose(diff_rel, 0, atol=0.200, rtol=0) # POST: correct DeltaA to within tolerance. # # check that the code works for forward and reverse directions f = InverseWeierstrass.free_energy_inverse_weierstrass landscape_both = f(fwd_objs, rev_objs) landscape_rev = f(refolding=rev_objs) landscape_fwd = f(fwd_objs) # # check that the work definitions are about right, based on equation 7 # of minh and adib, 2008 kT = 4.1e-21 Beta = 1 / kT dA = delta_A_calc # add in delta_A to the reverse; should be ~equal to the forward at that # point total_landscape_mean = \ np.mean([landscape_fwd.G_0,landscape_rev.G_0,landscape_both.G_0],axis=0) max_loss = 0.1 * sum(np.abs(total_landscape_mean)) # make sure they are all close for i, l_tmp in enumerate([landscape_fwd, landscape_rev, landscape_both]): diff = l_tmp.G_0 - total_landscape_mean loss_rel = sum(np.abs(diff)) assert loss_rel < max_loss # make sure the derivatives are OK. XXX why not both? for i, l_tmp in enumerate([landscape_both, landscape_fwd, landscape_rev]): check_derivatives(l_tmp)
def RobTimeSepForceToIWT(o, v, **kw): """ converts a Rob-Walder style pull into a FEC_Pulling_Object Args: o: TimeSepForce object with Robs meta information ZFunc: the z function (schedule) passed along fraction_for_vel : see set_separation_velocity_by_first_frac Returns: properly initialized FEC_Pulling_Object for use in IWT """ # spring constant should be in N/m k = o.K Obj = InverseWeierstrass.FEC_Pulling_Object(Time=o.Time, Extension=o.Separation, Force=o.Force, SpringConstant=k, Velocity=v, Offset=0, **kw) return Obj
def _single_direction_assert(dir_objs,n): """ makes sure that the digitization works well for all of dir_objs """ digitized_ext = [] min_x = min([min(o.Extension) for o in dir_objs]) max_x = max([max(o.Extension) for o in dir_objs]) x_m_abs = [min_x,max_x] for o in dir_objs: _assert_digitization_correct(x_m_abs,n=n,obj=o) bins,digitized_tmp = _get_bins_and_digitized(x_m_abs,o,n=n) digitized_ext.append(digitized_tmp) # # POST: the (single) digitization is OK. # concatenate all the bins digitized_by_bins = [] for i in range(n): these_items = [item for fec in digitized_ext for item in fec[i]] digitized_by_bins.append(these_items) # post: digitzed_by_bins has all of digitized_ext... internal check: digitized_items = sorted([item for bin_v in digitized_by_bins for item in bin_v]) test_items = sorted([item for fec in digitized_ext for sublist in fec for item in sublist]) np.testing.assert_allclose(test_items,digitized_items,atol=0) # POST: digitized_items is just a flat list of all the original items, # so that is what the algirthm should give too # check that the ensemble-wide binning is OK. f_ext = lambda obj: obj._GetDigitizedGen(Bins=bins, ToDigitize=obj.Extension) digitized_ext = InverseWeierstrass._digitized_f(dir_objs, f=f_ext) for actual,expected in zip(digitized_ext,digitized_by_bins): np.testing.assert_allclose(actual,expected,atol=0)
def weighted_histogram(unfolding,refolding=[]): InverseWeierstrass._assert_inputs_valid(unfolding,refolding) # POST: inputs ok pass
def weighted_histogram(unfolding, refolding=[]): InverseWeierstrass._assert_inputs_valid(unfolding, refolding) # POST: inputs ok pass
def _get_landscapes(iwt_obj_subsets,n_bins): for objs in iwt_obj_subsets: yield InverseWeierstrass.free_energy_inverse_weierstrass(objs)