示例#1
0
def merge_virtual_particles(frm):
    """
    Merges the virtual particle species X1,X2 in a base.Container() instance.
    Modifies the base.Container() instance in-place.
    """
    assert isinstance(frm, base.Container)
    # --- sum up the distance histograms
    if frm.contains_key(base.loc_histograms):
        histgrms = frm.get_data(base.loc_histograms)
        for key in list(histgrms.keys()):
            # Use StripVirtualParticles() earlier in the pipeline!
            assert (key not in blacklist)
        elements = util.get_elements(list(histgrms.keys()))
        if ('X1' in elements) and ('X2' in elements):
            all_X1 = []
            all_X2 = []
            for key in list(histgrms.keys()):
                if 'X1' in key:
                    all_X1.append(key)
                elif 'X2' in key:
                    all_X2.append(key)
            all_X1X2 = sorted(set(all_X1 + all_X2))
            for key in all_X1X2:
                key_new = key.replace('X1', 'X').replace('X2', 'X')
                # print "###", key, key_new
                if key_new not in list(histgrms.keys()):
                    histgrms[key_new] = np.zeros_like(histgrms[key])
                histgrms[key_new] += histgrms[key]
                del histgrms[key]
    # --- sum up the particle number arrays
    if frm.contains_key(base.loc_nr_particles):
        partnums = frm.get_data(base.loc_nr_particles)
        elements = util.get_elements(list(partnums.keys()))
        if ('X1' in elements) and ('X2' in elements):
            X1 = partnums['X1']
            X2 = partnums['X2']
            X = X1 + X2
            partnums['X'] = X.copy()
            del X
            del partnums['X1']
            del partnums['X2']
    # --- sum up the length histogram arrays
    if frm.contains_key(base.loc_len_histograms):
        lenhists = frm.get_data(base.loc_len_histograms)
        elements = util.get_elements(list(lenhists.keys()))
        if ('X1' in elements) and ('X2' in elements):
            X1 = lenhists['X1']
            X2 = lenhists['X2']
            X = X1 + X2
            lenhists['X'] = X.copy()
            del X
            del lenhists['X1']
            del lenhists['X2']
 def __next__(self):
     for frm in next(self.src):
         if frm is not None:
             assert isinstance(frm, base.Container)
             histgrms = frm.get_data(base.loc_histograms)
             elements = util.get_elements(list(histgrms.keys()))
             if ('X1' in elements) and ('X2' in elements):
                 for key in blacklist:
                     if key in list(histgrms.keys()):
                         del histgrms[key]
             frm.put_meta(self.get_meta())
             if self.verb:
                 print("StripVirtualParticles.next() :", frm.i)
             yield frm
         else:
             yield None
 def __next__(self):
     for frm in next(self.src):
         if frm is not None:
             assert isinstance(frm, base.Container)
             # ---
             histos = frm.get_data(base.loc_histograms)
             elements = util.get_elements(list(histos.keys()))
             if ('X1' in elements) and ('X2' in elements):
                 selection.merge_virtual_particles(frm)
             # ---
             frm.put_meta(self.get_meta())
             if self.verb:
                 print("MergeVirtualParticles.next() :", frm.i)
             yield frm
         else:
             yield None
示例#4
0
def scaleVirtualHistograms(frm):
    """
    When using the MultiReferenceStructure filter, histograms containing  virtual particles
    have to be properly scaled before averaging. The reason beeing that the volumes of the
    observation volumes vary for each frame. This scaling should also work when using
    a single reference structure, where the volume is constant for each frame.

    To facilitate solvent matching, we properly scale the X,X histograms of the shell
    and save them separately from the original histograms for later use.

    Precondition:
        o Each frames contains a single histogram only (sample=1 in histograms.yaml),
          because the volume varies for each frame.

    Scale factors for the 'gas' and 'lattice' methods are different because
    in the 'lattice' method we evaluate distances between two separate sets
    of particles (called X1 and X2).

    Note that because of the scaling applied here the norms of the cross, core, and
    shell histograms are no longer meaningfull. Only the norm of the full histogram is.
    """

    virtual_param = frm.query_meta('VirtualParticles')
    if (virtual_param is not None):
        method = virtual_param['method']
        xrho = virtual_param['x_density']
    else:
        return frm
    geom = frm.get_geometry()
    meta = frm.query_meta(geom)

    if method == 'gas':
        nrPart = frm.get_data(base.loc_nr_particles)
        nx = nrPart['X'][0]
        # print " nx =", nx
        if meta['shell_width'] > 0:
            shell_Hxx = frm.get_data(base.loc_histograms + "/X.s,X.s")
            frm.put_data(base.loc_shell_Hxx, {'X.s,X.s': shell_Hxx})
            nXs = (frm.get_data(base.loc_nr_particles))['X.s'][0]
            shell_Hxx = frm.get_data(base.loc_shell_Hxx)
            dict_util.scale_values(shell_Hxx, scaleFactorXX(nXs, xrho))

        histgrms = frm.get_data(base.loc_histograms)
        elements = util.get_elements(list(histgrms.keys()))
        # The scaling is the same for core, cross, shell, and full, because
        # full is given by a linear combination of core, cross, and shell.
        # We identify $H_{ix}(r)$ and $H_{xx}(r)$  by counting 'X' in the keys
        # (only works if there is no species a name with multiple 'X').
        for key in frm.get_keys(base.loc_histograms):
            XCounter = key.count('X')
            if XCounter == 1:
                histgrms[key] /= xrho
            elif XCounter == 2:
                # print histgrms[key].sum(), (nx**2-nx)
                histgrms[key] *= scaleFactorXX(nx, xrho)
        frm.put_data(base.loc_histograms, histgrms)
    elif method == 'lattice':
        nrPart = frm.get_data(base.loc_nr_particles)
        nx1 = nrPart['X1'][0] + nrPart['X1.s'][0]
        nx2 = nrPart['X2'][0] + nrPart['X2.s'][0]
        nx = nx1 + nx2

        if meta['shell_width'] > 0:
            shell_Hxx = frm.get_data(base.loc_histograms + "/X1.s,X2.s")
            frm.put_data(base.loc_shell_Hxx, {'X.s,X.s': shell_Hxx})
            nXs1 = nrPart['X1.s'][0]
            nXs2 = nrPart['X2.s'][0]
            shell_Hxx = frm.get_data(base.loc_shell_Hxx)
            # shell_Hxx is normalized in the Solvent filter. A constant scale factor
            # does not have any influence.
            dict_util.scale_values(shell_Hxx,
                                   scaleFactorX1X2(nXs1, nXs2, xrho))

        histgrms = frm.get_data(base.loc_histograms)
        elements = util.get_elements(list(histgrms.keys()))
        for key in frm.get_keys(base.loc_histograms):
            XCounter = key.count('X')
            if XCounter == 1:
                histgrms[key] /= xrho
            elif XCounter == 2:
                histgrms[key] *= scaleFactorX1X2(nx1, nx2, xrho)
        frm.put_data(base.loc_histograms, histgrms)
    return frm
示例#5
0
    def _process_frame(self, frm):
        """Compute the radial distribution function.
        """
        # This implementation follows <legacy/getRDFFromPBC.py> by Juergen Koefinger

        assert (frm.contains_key(base.loc_volumes))
        assert (frm.contains_key(base.loc_nr_particles))
        # obtain array of box volumes from the original trajectory frames
        _volumes = frm.get_data(base.loc_volumes)
        box_volumes = _volumes['box']
        if hasattr(box_volumes, "__len__"):
            n_samples = len(box_volumes)
        else:
            n_samples = 1
        # obtain arrays of the numbers of particles present in the original trajectory frame
        nr_particles = frm.get_data(base.loc_nr_particles)
        for key in nr_particles:
            assert (n_samples == (nr_particles[key]).shape[0])
        histograms = frm.get_data(base.loc_histograms)
        dr = frm.query_meta('histograms/histogram/dr')
        # consistency check if the histogram labels match with the particle numbers
        _species_h = set(util.get_elements(list(histograms.keys())))
        _species_p = set(nr_particles.keys())
        assert (_species_h == _species_p)

        radii = histograms['radii']
        histogram_keys = list(histograms.keys())
        histogram_keys.remove('radii')

        vol = np.sum(box_volumes)
        vol /= n_samples  # QUESTION: 'norm' in the original code, is this just the number of samples?
        vol_inv = np.sum(np.reciprocal(box_volumes))
        vol_inv /= n_samples  # QUESTION: 'norm' in the original code, is this just the number of samples?

        # coefficients repeatedly used by the nested loop below
        coeff = 4.0 * np.pi * dr * vol_inv * np.multiply(radii, radii)

        rdf = {}
        for key in histogram_keys:
            species_1, species_2 = tuple(key.split(','))
            nr_1 = np.sum(nr_particles[species_1]) / float(n_samples)
            nr_2 = np.sum(nr_particles[species_2]) / float(n_samples)
            # the particle number in the box is constant, therefor densities are calculated as
            rho_1 = nr_1 * vol_inv
            rho_2 = nr_2 * vol_inv
            if (nr_1 * nr_2 > 0):
                if (species_1 == species_2):
                    fac = 1.0
                else:
                    fac = 2.0
                histo = np.copy(histograms[key])
                for i in range(len(radii)):
                    histo[i] /= fac * nr_1 * nr_2 * coeff[i]
                # Factor 2 because distances are only counted once in histograms (r_{ij} and r_{ji} are counted as a single distance)
                rdf[key] = 2 * histo
                if (species_1 == species_2):
                    rdf[key][0] = rho_1
            else:
                if self.verb:
                    print(" RDF: skipping " + key)
        rdf['radii'] = radii
        # ---
        if self.verb:
            print(" RDF: average inverse volume =", vol_inv)
            print(" RDF: inverse average volume =", 1. / vol)
            print(" RDF: ratio =", vol_inv * vol)
        # ---
        frm.put_data(base.loc_rdf, rdf)
示例#6
0
    def __next__(self):
        for hs in next(self.src):
            # hs was chosen to mean 'histogram set' ...
            if hs is not None:
                assert isinstance(hs, base.Container)

                # --- obtain information from the pipeline log
                dr = hs.query_meta('histograms/histogram/dr')
                assert (dr is not None)
                # ---
                self.geometry = hs.get_geometry()
                assert (self.geometry is not None)
                geometry_param = hs.query_meta(self.geometry)
                assert (geometry_param is not None)
                if (self.geometry == 'Sphere' or self.geometry == 'Cuboid'
                        or self.geometry == 'Ellipsoid'):
                    V = geometry_param['volume']
                    assert (V is not None)
                    # VAvg is neede below for MultiReference, where V=1 for histograms
                    # but VAvg is used for densities
                    VAvg = V
                else:
                    # --- for non-sphere geometries, we calculate V using x particles below
                    V = None
                # ---
                virtual_param = hs.query_meta('VirtualParticles')
                if (virtual_param is not None):
                    self.x_particle_method = virtual_param['method']
                    xrho = virtual_param['x_density']
                # ---
                rdf_header = list(
                    (hs.get_data(base.loc_solv_match + '/g_scaled')).keys())
                rdf_header.remove('radii')
                rdf_elements = util.get_elements(rdf_header)
                n_solv = len(rdf_elements)
                hs_full = selection.get_full(hs)
                n_part_elements = util.get_elements(
                    list(hs_full.get_data(base.loc_nr_particles).keys()))
                histo_elements = util.get_elements(
                    list(hs_full.get_data(base.loc_histograms).keys()))
                # --- print '###', n_part_elements, histo_elements
                assert (n_part_elements == histo_elements)
                n_prot = len(histo_elements)
                if (self.debug):
                    print(" rdf_header", rdf_header)
                    print(" rdf_elements", rdf_elements)
                    print(" n_solv =", n_solv)
                    print(" n_prot=", n_prot)

                histo = copy.deepcopy(hs_full.get_data(base.loc_histograms))
                nr = len(hs_full.get_data(base.loc_histograms + '/radii'))
                for key in list(histo.keys()):
                    if (key == 'radii'):
                        continue
                    histo[key] *= 2.0

                # --- NOTE : in the following, we're sorting out the virtual particles
                H, Hx = _separate_ghosts_from_histogram(histo)

                # --- consistency checks of the radii
                assert (len(
                    hs.get_data(base.loc_solv_match + '/g_scaled/radii')) >=
                        nr)
                radii_1 = hs.get_data(base.loc_solv_match +
                                      '/g_scaled/radii')[0:nr]
                radii_2 = hs_full.get_data(base.loc_histograms +
                                           '/radii')[0:nr]
                eps = 1.e-9
                assert np.all(np.fabs(radii_1 - radii_2) < eps)
                #
                rdf_expanded = {}
                for key in list(
                    (hs.get_data(base.loc_solv_match + '/g_scaled')).keys()):
                    # Note: g_scaled dictionary includes the radii array
                    rdf_expanded[key] = np.zeros(nr)
                    (rdf_expanded[key])[0:nr] = (
                        hs.get_data(base.loc_solv_match + '/g_scaled/' +
                                    key))[0:nr]
                rdf_org = copy.deepcopy(rdf_expanded)
                # ---
                if (self.debug):
                    hs.put_data(base.loc_delta_h + '/debug/rdf_org', rdf_org)
                rho = hs.get_data(base.loc_solv_match + '/rho')
                # ---
                for key in list(rdf_expanded.keys()):
                    # zero densities as done in the reference code <deltaH.py>
                    if (key == 'radii'):
                        continue
                    (rdf_expanded[key])[0] = 0.0

                if (self.geometry
                        == 'Sphere') and (self.x_particle_method is None):
                    # print "### delta_H :: SPHERE BRANCH ###"
                    R = geometry_param['radius']
                    dHs = copy.deepcopy(H)
                    for key in list(dHs.keys()):
                        if (key == 'radii'):
                            continue
                        (dHs[key])[:] = 0.0
                    dHp = copy.deepcopy(dHs)
                    dH = copy.deepcopy(dHs)
                    # ---
                    assert hs.contains_key(base.loc_len_histograms)
                    # --- construct h matrix
                    x_list = hs.get_data(base.loc_len_histograms + '/radii')
                    r_list = H['radii']
                    # --- implement h using a dictionary
                    h_dict = {}
                    for key in hs.get_keys(base.loc_len_histograms):
                        h_dict[key] = np.zeros(len(r_list))
                    h_dict['radii'][:] = r_list[:]
                    # ---
                    pSphere = np.zeros((r_list.shape[0], 2))
                    pSphere[:, 0] = r_list[:]
                    # ---
                    for j, rv in enumerate(r_list):
                        pSphere[j, 1] = rdf.P(rv, R)
                    if (self.debug):
                        hs.put_data(base.loc_delta_h + '/debug/pSphere',
                                    pSphere)
                    # ---
                    dx = dr  # DANGER! However, these two should be the same anyway!
                    # ---
                    getSr = rdf.SrFast
                    print()
                    for j, rv in enumerate(r_list):
                        if self.verb and (j % 1000 == 0):
                            print(" DeltaH:bin ", j)
                        Sr = getSr(x_list, R, rv)
                        for key in hs.get_keys(base.loc_len_histograms,
                                               skip_keys=['radii']):
                            (h_dict[key])[j] += (
                                hs.get_data(base.loc_len_histograms + '/' +
                                            key)[:] * Sr[:]).sum(axis=0)

                    for key in hs.get_keys(base.loc_len_histograms,
                                           skip_keys=['radii']):
                        h_dict[key] *= 2.0 * dx / V
                        # --- patch rho[] such that it can be used in the block below
                        if key not in rho:
                            rho[key] = 0.0

                    for key in sorted(H.keys()):
                        if (key == 'radii'):
                            continue
                        # --- patch rdf_expanded such that it can be used below
                        if key not in rdf_expanded:
                            rdf_expanded[key] = np.zeros(nr)
                            # ---
                        (el1, el2) = key.split(',')
                        if (el1 == el2):
                            fac = 1.0
                        else:
                            fac = 2.0
                        # ---
                        (dHs[key])[:] = fac * ((rdf_expanded[key])[:] - 2.0) \
                            * rho[el1] * rho[el2] * V * V * pSphere[:, 1] * dr  # Hx[:,ixx]
                        # ---
                        if (fac == 1):
                            (dHp[key])[:] = (H[key])[:] - V * rho[el1] * (
                                h_dict[el1])[:]  # *Hx[:,ix1]
                        else:
                            (dHp[key])[:] = (
                                H[key])[:] - V * (rho[el2] *
                                                  (h_dict[el1])[:] + rho[el1] *
                                                  (h_dict[el2])[:])
                        # ---
                        (dH[key])[:] = (dHp[key])[:] - (dHs[key])[:]
                else:
                    # --- virtual particle method branch
                    # print "delta_h "
                    nx = np.mean(hs_full.get_data(base.loc_nr_particles +
                                                  '/X'),
                                 dtype=np.float64)
                    if not (self.geometry == 'Sphere' or self.geometry
                            == 'Cuboid' or self.geometry == 'Ellipsoid'):
                        V = old_div(nx, xrho)
                    VAvg = V
                    if (self.geometry == 'MultiReferenceStructure'):
                        V = 1.
                        # print " V =", V, "VAvg =", VAvg
                    else:
                        for key in Hx:
                            if key in 'radii':
                                continue
                            pair = key.split(',')
                            assert (len(pair) == 2)
                            if (pair[0] == 'X') and (pair[1] == 'X'):
                                Hx[key] /= (Hx[key]).sum()
                            else:
                                Hx[key] /= nx
                    # ---
                    dHs = copy.deepcopy(H)
                    for key in list(dHs.keys()):
                        if (key == 'radii'):
                            continue
                        (dHs[key])[:] = 0.0
                    dHp = copy.deepcopy(dHs)
                    dH = copy.deepcopy(dHs)
                    # ---
                    for key in sorted(H.keys()):
                        if (key == 'radii'):
                            continue
                        # --- patch rdf_expanded such that it can be used below
                        if key not in rdf_expanded:
                            rdf_expanded[key] = np.zeros(nr)
                        # ---
                        (el1, el2) = key.split(',')
                        # --- patch rho such that it can be used below
                        for el in [el1, el2]:
                            if el not in rho:
                                rho[el] = 0.0
                        # ---
                        if (el1 == el2):
                            fac = 1.0
                        else:
                            fac = 2.0
                        # ---
                        (dHs[key])[:] = fac * ((rdf_expanded[key])[:] - 2.0) \
                            * rho[el1] * rho[el2] * V * V * Hx['X,X']
                        # ---
                        if (fac == 1):
                            (dHp[key])[:] = (
                                H[key])[:] - V * rho[el1] * (Hx[el1 + ',X'])[:]
                        else:
                            (dHp[key])[:] = (H[key])[:] - V * (
                                rho[el2] * (Hx[el1 + ',X'])[:] + rho[el1] *
                                (Hx[el2 + ',X'])[:])
                        # ---
                        (dH[key])[:] = (dHp[key])[:] - (dHs[key])[:]
                # ---
                if (self.debug):
                    hs.put_data(base.loc_delta_h + '/debug/rdf_expanded',
                                rdf_expanded)
                    hs.put_data(base.loc_delta_h + '/debug/dHs', dHs)
                    hs.put_data(base.loc_delta_h + '/debug/dHp', dHp)
                    hs.put_data(base.loc_delta_h + '/debug/dH', dH)
                    hs.put_data(base.loc_delta_h + '/debug/H', H)
                    hs.put_data(base.loc_delta_h + '/debug/rho', rho)
                    hs.put_data(base.loc_delta_h + '/debug/h_dict', h_dict)

                # ---
                hs.put_data(base.loc_intensity + '/dH', dH)

                # --- calculate average particle numbers
                nr_part_avg = {}
                for key in hs_full.get_keys(base.loc_nr_particles):
                    nr_part = hs_full.get_data(base.loc_nr_particles + '/' +
                                               key)
                    nr_part_avg[key] = nr_part.sum(axis=0) / float(
                        nr_part.shape[0])
                # --- calculate difference
                nr_part_diff = {}
                for key in nr_part_avg:
                    if key in rho:
                        nr_part_diff[key] = nr_part_avg[key] - rho[key] * VAvg
                    else:
                        nr_part_diff[key] = nr_part_avg[key]

                hs.put_data(base.loc_intensity + '/dN', nr_part_diff)

                # --- INTENSITY CALCULATION ---

                # --- read atom form factors from file
                ff_dict = ff.readAtomSFParam(self.form_factor_file)

                # --- prepare 2D input array for library routine
                (dH_2d, dH_2d_keys) = _make_2d(dH)
                if (self.debug):
                    hs.put_data(base.loc_delta_h + '/debug/dH_2d', dH_2d)
                # ---
                _pIntInter, dInter = pynt.intensitiesFFFaster(
                    self.nq, self.dq, dH_2d, dH_2d_keys, ff_dict, 1)
                # # --- prepare input
                # nr_part_keys = sorted(nr_part_diff.keys())
                # nr_part_vals = []
                # for key in nr_part_keys:
                #     nr_part_vals.append(nr_part_diff[key])
                # # ---
                # _pIntIntra, dIntra = pynt.intensitiesFFIntraAtom(self.nq, self.dq, \
                #                             nr_part_vals, nr_part_keys, ff_dict)
                # # ---
                # hs.put_data(base.loc_intensity+'/dI_inter', dInter)
                # hs.put_data(base.loc_intensity+'/dI_intra', dIntra)
                dI = dInter.copy()
                # TODO: check, the following line was commented out in <deltaH.py>
                # dI[:,1] += dIntra[:,1]
                hs.put_data(base.loc_intensity + '/dI', dI)

                # --- prepare 2D input array for library routine
                #     (cannot use _make_2d() routine here)
                n_row = len(rdf_org['radii'])
                n_col = len(list(dH.keys()))
                rdf_org_2d = np.zeros((n_row, n_col))
                rdf_org_2d[:, 0] = (rdf_org['radii'])[:]
                rdf_org_2d_keys = sorted(rdf_org.keys())
                rdf_org_2d_keys.remove('radii')
                for key in rdf_org_2d_keys:
                    if key in dH_2d_keys:
                        idx = dH_2d_keys.index(key) + 1
                        rdf_org_2d[:, idx] = (rdf_org[key])[:]
                # ---
                rho_list = []
                rho_keys = sorted(rho.keys())
                for key in ['X', 'X1', 'X2']:
                    if key in rho_keys:
                        rho_keys.remove(key)
                for key in rho_keys:
                    rho_list.append(rho[key])
                # ---
                if (self.debug):
                    hs.put_data(base.loc_delta_h + '/debug/rdf_org_2d',
                                rdf_org_2d)
                # ---
                bulkH = pynt.getBulkIntegrand(rdf_org_2d, rho_list)
                bulkH_keys = dH_2d_keys
                # print "bulkH_keys", bulkH_keys
                _pIntInter, dIntensityInter = pynt.intensitiesFFFaster(
                    self.nq, self.dq, bulkH, bulkH_keys, ff_dict, dr)
                _pIntIntra, dIntensityIntra = pynt.intensitiesFFIntraAtom(
                    self.nq, self.dq, rho_list, rho_keys, ff_dict)
                dIntensity = dIntensityInter.copy()
                dIntensity[:, 1] += dIntensityIntra[:, 1]
                # ---
                hs.put_data(base.loc_intensity + '/I_solv_inter',
                            dIntensityInter)
                hs.put_data(base.loc_intensity + '/I_solv_intra',
                            dIntensityIntra)
                hs.put_data(base.loc_intensity + '/I_solv', dIntensity)

                # TODO: Think about stripping unnecessary information
                # (histograms, length histograms) from hs at this point.

                hs.put_meta(self.get_meta())
                if self.verb:
                    print("DeltaH.next() :", hs.i)
                yield hs
            else:
                yield None