def _process_frame(self, trj, energy, hbonds, entropy):
        """
        Frame wise calculation of GIST quantities.

        Parameters
        ----------
        trj :
            Molecular dynamic trajectory representing current frame.
        energy :
            If True, solute-water and water-water energies are calculated for each water in each voxel in current
            frame.
        hbonds : bool
            If True, solute-water and water-water hydrogen bonds are calculated for each water in each voxel in current
            frame.
        entropy : bool
            If True, water coordinates and quaternions are stored for each water in each voxel in current frame.
        """

        nbr_cutoff_sq = 3.5 ** 2
        trj.xyz *= 10.0
        coords = trj.xyz
        uc = trj.unitcell_vectors[0]*10.
        waters = []
        calc.assign_voxels(trj.xyz, self.dims, self.gridmax, self.origin, waters, self.wat_oxygen_atom_ids)

        for wat in waters:
            self.voxeldata[wat[0], 4] += 1
            if energy or hbonds:
                e_lj_array, e_elec_array = np.copy(self.acoeff), np.copy(self.chg_product)
                distance_matrix = np.zeros((self.water_sites, self.all_atom_ids.shape[0]))
                calc.get_pairwise_distances(wat, self.all_atom_ids, coords, uc, distance_matrix)
                wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                    (distance_matrix[0, :][self.wat_oxygen_atom_ids] <= nbr_cutoff_sq) & (
                        distance_matrix[0, :][self.wat_oxygen_atom_ids] > 0.0))]
                self.voxeldata[wat[0], 19] += wat_nbrs.shape[0]
                calc.calculate_energy(wat[1], distance_matrix, e_elec_array, e_lj_array, self.bcoeff)

                if self.prot_atom_ids.shape[0] != 0:
                    #self.voxeldata[wat[0], 13] += np.sum(e_lj_array[:, self.prot_atom_ids])
                    #self.voxeldata[wat[0], 13] += np.sum(e_elec_array[:, self.prot_atom_ids])
                    self.voxeldata[wat[0], 13] += np.sum(e_lj_array[:, self.non_water_atom_ids])
                    self.voxeldata[wat[0], 13] += np.sum(e_elec_array[:, self.non_water_atom_ids])

                self.voxeldata[wat[0], 15] += np.sum(
                    e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_lj_array[:, wat[1] + self.water_sites:])
                self.voxeldata[wat[0], 15] += np.sum(
                    e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(
                    e_elec_array[:, wat[1] + self.water_sites:])
                e_nbr_list = [np.sum(e_lj_array[:, wat_nbrs + i] + e_elec_array[:, wat_nbrs + i]) for i in
                              range(self.water_sites)]
                self.voxeldata[wat[0], 17] += np.sum(e_nbr_list)

                # H-bond calculations
                if hbonds:
                    prot_nbrs_all = self.prot_atom_ids[
                        np.where(distance_matrix[0, :][self.prot_atom_ids] <= nbr_cutoff_sq)]
                    prot_nbrs_hb = prot_nbrs_all[np.where(self.prot_hb_types[prot_nbrs_all] != 0)]

                    if wat_nbrs.shape[0] > 0:
                        hb_ww = self.calculate_hydrogen_bonds(trj, wat[1], wat_nbrs)
                        acc_ww = hb_ww[:, 0][np.where(hb_ww[:, 0] == wat[1])].shape[0]
                        don_ww = hb_ww.shape[0] - acc_ww
                        self.voxeldata[wat[0], 25] += hb_ww.shape[0]
                        self.voxeldata[wat[0], 31] += don_ww
                        self.voxeldata[wat[0], 33] += acc_ww
                        if wat_nbrs.shape[0] != 0 and hb_ww.shape[0] != 0:
                            self.voxeldata[wat[0], 21] += wat_nbrs.shape[0] / hb_ww.shape[0]

                    if prot_nbrs_hb.shape[0] > 0:
                        hb_sw = self.calculate_hydrogen_bonds(trj, wat[1], prot_nbrs_hb, water_water=False)
                        acc_sw = hb_sw[:, 0][np.where(hb_sw[:, 0] == wat[1])].shape[0]
                        don_sw = hb_sw.shape[0] - acc_sw
                        self.voxeldata[wat[0], 23] += hb_sw.shape[0]
                        self.voxeldata[wat[0], 27] += don_sw
                        self.voxeldata[wat[0], 29] += acc_sw

            if entropy:
                self.calculate_euler_angles(wat, coords[0, :, :])
    def process_chunk(self, begin_chunk, chunk_size, topology, energy, hbonds,
                      entropy):
        nbr_cutoff_sq = 3.5**2
        with md.open(self.trajectory) as f:
            f.seek(begin_chunk)
            trj = f.read_as_traj(topology, n_frames=chunk_size, stride=1)
            trj.xyz *= 10.0
            pbc = md.utils.in_units_of(trj.unitcell_lengths, "nanometers",
                                       "angstroms")
            frame_data = [[] for i in range(trj.n_frames)]
            calc.assign_voxels(trj.xyz, self.dims, self.gridmax, self.origin,
                               frame_data, self.wat_oxygen_atom_ids)

            for frame in range(trj.n_frames):
                coords = trj.xyz[frame, :, :].reshape(1, trj.xyz.shape[1],
                                                      trj.xyz.shape[2])
                periodic_box = pbc[frame].reshape(1, pbc.shape[1])
                waters = frame_data[frame]
                for wat in waters:
                    self.voxeldata[wat[0], 4] += 1
                    if energy or hbonds:
                        e_lj_array, e_elec_array = np.copy(
                            self.acoeff), np.copy(self.chg_product)
                        distance_matrix = np.zeros(
                            (self.water_sites, self.all_atom_ids.shape[0]))
                        calc.get_pairwise_distances(wat, self.all_atom_ids,
                                                    coords, pbc,
                                                    distance_matrix)
                        wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                            (distance_matrix[0, :][self.wat_oxygen_atom_ids] <=
                             nbr_cutoff_sq) & (distance_matrix[0, :][
                                 self.wat_oxygen_atom_ids] > 0.0))]
                        self.voxeldata[wat[0], 17] += wat_nbrs.shape[0]
                        calc.calculate_energy(wat[1], distance_matrix,
                                              e_elec_array, e_lj_array,
                                              self.bcoeff)
                        self.voxeldata[wat[0], 11] += np.sum(
                            e_lj_array[:, :self.wat_oxygen_atom_ids[0]])
                        self.voxeldata[wat[0], 11] += np.sum(
                            e_elec_array[:, :self.wat_oxygen_atom_ids[0]])
                        self.voxeldata[wat[0], 13] += np.sum(
                            e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]
                        ) + np.sum(e_lj_array[:, wat[1] + self.water_sites:])
                        self.voxeldata[wat[0], 13] += np.sum(
                            e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]
                        ) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                        e_nbr_list = [
                            np.sum(e_lj_array[:, wat_nbrs + i] +
                                   e_elec_array[:, wat_nbrs + i])
                            for i in xrange(self.water_sites)
                        ]
                        self.voxeldata[wat[0], 15] += np.sum(e_nbr_list)
                        """
                        ###DEBUG START###
                        elj_sw = np.sum(e_lj_array[:, :self.wat_oxygen_atom_ids[0]])
                        eelec_sw = np.sum(e_elec_array[:, :self.wat_oxygen_atom_ids[0]])
                        elj_ww = np.sum(e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_lj_array[:, wat[1] + 1:])
                        eelec_ww = np.sum(e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                        e_nbr_list = [np.sum(e_lj_array[:, wat_nbrs + i] + e_elec_array[:, wat_nbrs + i]) for i in xrange(self.water_sites)]
                        enbr = np.sum(e_nbr_list)
                        print "Calc: ", elj_sw, eelec_sw, elj_ww, eelec_ww, enbr
                        distance_matrix = np.sqrt(distance_matrix)
                        energy_lj, energy_elec = self.calculate_energy(distance_matrix)
                        test_1 = np.sum(energy_lj[:self.wat_oxygen_atom_ids[0]:])
                        test_2 = np.sum(energy_elec[:, self.non_water_atom_ids])
                        test_3 = np.nansum(energy_lj[self.wat_oxygen_atom_ids[0]:])
                        test_4 = np.sum(energy_elec[:, self.wat_atom_ids[0]:wat[1]]) + np.sum(energy_elec[:, wat[1] + self.water_sites:])
                        test_5 = 0.0
                        test_5 += np.sum(energy_lj[self.wat_oxygen_atom_ids[0]:][(wat_nbrs - self.wat_oxygen_atom_ids[0]) / self.water_sites])
                        for i in range(self.water_sites):
                            test_5 += np.sum(energy_elec[:, wat_nbrs + i])
                        print "Ref: ", test_1, test_2, test_3, test_4, test_5
                        ###DEBUG END###
                        """
                        # H-bond calculations
                        if hbonds:
                            prot_nbrs_all = self.non_water_atom_ids[np.where(
                                distance_matrix[0, :][
                                    self.non_water_atom_ids] <= nbr_cutoff_sq)]
                            prot_nbrs_hb = prot_nbrs_all[np.where(
                                self.prot_hb_types[prot_nbrs_all] != 0)]
                            if wat_nbrs.shape[0] != 0 and prot_nbrs_hb.shape[
                                    0] != 0:
                                # hb_ww, hb_sw = self.calculate_hydrogen_bonds2(coords, wat[1], wat_nbrs, prot_nbrs_hb)
                                hb_ww, hb_sw = self.calculate_hydrogen_bonds(
                                    trj, wat[1], wat_nbrs, prot_nbrs_hb)
                                acc_ww = hb_ww[:, 0][np.where(
                                    hb_ww[:, 0] == wat[1])].shape[0]
                                don_ww = hb_ww.shape[0] - acc_ww
                                acc_sw = hb_sw[:, 0][np.where(
                                    hb_sw[:, 0] == wat[1])].shape[0]
                                don_sw = hb_sw.shape[0] - acc_sw
                                self.voxeldata[wat[0], 23] += hb_sw.shape[0]
                                self.voxeldata[wat[0], 25] += hb_ww.shape[0]
                                self.voxeldata[wat[0], 27] += don_sw
                                self.voxeldata[wat[0], 29] += acc_sw
                                self.voxeldata[wat[0], 31] += don_ww
                                self.voxeldata[wat[0], 33] += acc_ww
                                if wat_nbrs.shape[0] != 0 and hb_ww.shape[
                                        0] != 0:
                                    self.voxeldata[wat[0],
                                                   19] += wat_nbrs.shape[
                                                       0] / hb_ww.shape[0]
                                    # f_enc =  1.0 - (wat_nbrs.shape[0] / 5.25)
                                    # if f_enc < 0.0:
                                    #    f_enc = 0.0
                                    # self.voxeldata[wat[0], 21] += f_enc
                    if entropy:
                        self.calculate_euler_angles(wat, coords[0, :, :])
Beispiel #3
0
    def _process_frame(self, trj, energy, hbonds, entropy):
        """
        Frame wise calculation of GIST quantities.

        Parameters
        ----------
        trj :
            Molecular dynamic trajectory representing current frame.
        energy :
            If True, solute-water and water-water energies are calculated for each water in each voxel in current
            frame.
        hbonds : bool
            If True, solute-water and water-water hydrogen bonds are calculated for each water in each voxel in current
            frame.
        entropy : bool
            If True, water coordinates and quaternions are stored for each water in each voxel in current frame.
        """

        nbr_cutoff_sq = 3.5**2
        trj.xyz *= 10.0
        coords = trj.xyz
        uc = trj.unitcell_vectors[0] * 10.
        waters = []
        calc.assign_voxels(trj.xyz, self.dims, self.gridmax, self.origin,
                           waters, self.wat_oxygen_atom_ids)

        distance_matrix = np.zeros(
            (self.water_sites, self.all_atom_ids.shape[0]))

        for wat in waters:
            self.voxeldata[wat[0], 4] += 1
            ### wat[0]: Voxel index
            ### wat[1]: water molecule oxygen atom index
            if energy or hbonds:
                e_lj_array, e_elec_array = np.copy(self.acoeff), np.copy(
                    self.chg_product)
                ### Here it is assumed that oxygen atom is always the first atom. Is that always the case?
                ### We should probably check that somewhere during init?
                ###
                ### The self.neighbor_ids array contains atom indices of all atoms that should
                ### be considered as potential neighbors. Valid_neighbors has same shape as
                ### self.neighbor_ids and is False at the position where index wat occures in
                ### self.neighbor_ids, otherwise it is True. neighbor_ids stores the indices of
                ### the actual neighbor candidates that will be commited to get_pairwise_distances
                ### routine and has length of self.neighbor_ids-1. wat_nbrs_shell is of length neighbor_ids
                ### and holds the shell_index of each neighbor candidate atom (0:first shell, 1: beyond first
                ### shell)
                valid_neighbors = np.ones(self.neighbor_ids.shape[0],
                                          dtype=bool)
                valid_neighbors[np.where(self.neighbor_ids == wat)] = False
                neighbor_ids = self.neighbor_ids[valid_neighbors]
                wat_nbrs_shell = self.wat_nbrs_shell[valid_neighbors]
                calc.get_pairwise_distances(wat, self.all_atom_ids,
                                            np.array([nbr_cutoff_sq]),
                                            neighbor_ids, wat_nbrs_shell,
                                            coords, uc, distance_matrix, 0)
                wat_nbrs = self.all_atom_ids[np.where(wat_nbrs_shell == 0)]
                self.voxeldata[wat[0], 19] += wat_nbrs.shape[0]
                calc.calculate_energy(wat[1], distance_matrix, e_elec_array,
                                      e_lj_array, self.bcoeff)

                if self.prot_atom_ids.shape[0] != 0:
                    #self.voxeldata[wat[0], 13] += np.sum(e_lj_array[:, self.prot_atom_ids])
                    #self.voxeldata[wat[0], 13] += np.sum(e_elec_array[:, self.prot_atom_ids])
                    self.voxeldata[wat[0], 13] += np.sum(
                        e_lj_array[:, self.non_water_atom_ids])
                    self.voxeldata[wat[0], 13] += np.sum(
                        e_elec_array[:, self.non_water_atom_ids])

                self.voxeldata[wat[0], 15] += np.sum(
                    e_lj_array[:,
                               self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(
                                   e_lj_array[:, wat[1] + self.water_sites:])
                self.voxeldata[wat[0], 15] += np.sum(
                    e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]
                ) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                e_nbr_list = [
                    np.sum(e_lj_array[:, wat_nbrs + i] +
                           e_elec_array[:, wat_nbrs + i])
                    for i in range(self.water_sites)
                ]
                self.voxeldata[wat[0], 17] += np.sum(e_nbr_list)

                ### Might be usefull for API to have the neighbors and shell
                ### indices available.
                self.wat_nbrs_shell[valid_neighbors] = wat_nbrs_shell
                self.neighbor_ids[valid_neighbors] = neighbor_ids
                """
                ###DEBUG START###
                elj_sw = np.sum(e_lj_array[:, :self.wat_oxygen_atom_ids[0]])
                eelec_sw = np.sum(e_elec_array[:, :self.wat_oxygen_atom_ids[0]])
                elj_ww = np.sum(e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_lj_array[:, wat[1] + 1:])
                eelec_ww = np.sum(e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                e_nbr_list = [np.sum(e_lj_array[:, wat_nbrs + i] + e_elec_array[:, wat_nbrs + i]) for i in xrange(self.water_sites)]
                enbr = np.sum(e_nbr_list)
                print "Calc: ", elj_sw, eelec_sw, elj_ww, eelec_ww, enbr
                distance_matrix = np.sqrt(distance_matrix)
                energy_lj, energy_elec = self.calculate_energy(distance_matrix)
                test_1 = np.sum(energy_lj[:self.wat_oxygen_atom_ids[0]:])
                test_2 = np.sum(energy_elec[:, self.non_water_atom_ids])
                test_3 = np.nansum(energy_lj[self.wat_oxygen_atom_ids[0]:])
                test_4 = np.sum(energy_elec[:, self.wat_atom_ids[0]:wat[1]]) + np.sum(energy_elec[:, wat[1] + self.water_sites:])
                test_5 = 0.0
                test_5 += np.sum(energy_lj[self.wat_oxygen_atom_ids[0]:][(wat_nbrs - self.wat_oxygen_atom_ids[0]) / self.water_sites])
                for i in range(self.water_sites):
                    test_5 += np.sum(energy_elec[:, wat_nbrs + i])
                print "Ref: ", test_1, test_2, test_3, test_4, test_5
                ###DEBUG END###
                """

                # H-bond calculations
                if hbonds:
                    prot_nbrs_all = self.prot_atom_ids[np.where(
                        distance_matrix[0, :][
                            self.prot_atom_ids] <= nbr_cutoff_sq)]
                    prot_nbrs_hb = prot_nbrs_all[np.where(
                        self.prot_hb_types[prot_nbrs_all] != 0)]

                    if wat_nbrs.shape[0] > 0:
                        hb_ww = self.calculate_hydrogen_bonds(
                            trj, wat[1], wat_nbrs)
                        acc_ww = hb_ww[:, 0][np.where(
                            hb_ww[:, 0] == wat[1])].shape[0]
                        don_ww = hb_ww.shape[0] - acc_ww
                        self.voxeldata[wat[0], 25] += hb_ww.shape[0]
                        self.voxeldata[wat[0], 31] += don_ww
                        self.voxeldata[wat[0], 33] += acc_ww
                        if wat_nbrs.shape[0] != 0 and hb_ww.shape[0] != 0:
                            self.voxeldata[
                                wat[0],
                                21] += wat_nbrs.shape[0] / hb_ww.shape[0]

                    if prot_nbrs_hb.shape[0] > 0:
                        hb_sw = self.calculate_hydrogen_bonds(
                            trj, wat[1], prot_nbrs_hb, water_water=False)
                        acc_sw = hb_sw[:, 0][np.where(
                            hb_sw[:, 0] == wat[1])].shape[0]
                        don_sw = hb_sw.shape[0] - acc_sw
                        self.voxeldata[wat[0], 23] += hb_sw.shape[0]
                        self.voxeldata[wat[0], 27] += don_sw
                        self.voxeldata[wat[0], 29] += acc_sw

            if entropy:
                self.calculate_euler_angles(wat, coords[0, :, :])
Beispiel #4
0
    def _process_frame(self, trj, frame_i, energy, hbonds, entropy,
                       energy_lr_breakdown, angular_structure, shell_radii,
                       r_theta_cutoff):
        """Calculates hydration site properties for a given frame.

        Parameters
        ----------
        trj : mdtraj.trajectory
            A trajectory object containing only one frame.
        frame_i : int
            Index of the frame to be processed
        energy : bool
            Flag for energy calculations
        hbonds : bool
            Flag for hydrogen bond calculations
        entropy :bool
            Flag for entropy calculations

        Returns
        -------
        None : NoneType

        """

        site_waters_copy = list(self.site_waters)
        nbr_cutoff_sq = 3.5**2
        # TODO: Use a robust unit conversion approach
        trj.xyz *= 10.0
        coords = trj.xyz
        trj.unitcell_lengths *= 10.0
        uc = trj.unitcell_vectors[0] * 10.

        # Iterate over each site in the current frame if it has a water present
        for site_i in range(self.hsa_data.shape[0]):
            wat_O = None
            if self.is_site_waters_populated:
                if len(site_waters_copy[site_i]) != 0:
                    if site_waters_copy[site_i][0][0] == frame_i:
                        wat_O = site_waters_copy[site_i].pop(0)[1]
                        index = int(self.hsa_data[site_i, 4]) * 3
                        index_pairs = list(
                            zip(list(range(wat_O, wat_O + 3)),
                                list(range(index, index + 3))))
                        for index_pair in index_pairs:
                            self.hsa_dict[site_i][-1][index_pair[1]] += coords[
                                0, index_pair[0], :]
                        self.hsa_data[site_i, 4] += 1

            if wat_O is not None and (energy or hbonds):
                distance_matrix = np.zeros(
                    (self.water_sites, self.all_atom_ids.shape[0]), np.float_)
                calc.get_pairwise_distances(np.asarray([site_i, wat_O]),
                                            self.all_atom_ids, coords, uc,
                                            distance_matrix)
                wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                    (distance_matrix[0, :][self.wat_oxygen_atom_ids] <=
                     nbr_cutoff_sq)
                    & (distance_matrix[0, :][self.wat_oxygen_atom_ids] > 0.0))]
                self.hsa_dict[site_i][17].append(wat_nbrs.shape[0])
                if energy:
                    e_lj_array, e_elec_array = np.copy(self.acoeff), np.copy(
                        self.chg_product)
                    calc.calculate_energy(wat_O, distance_matrix, e_elec_array,
                                          e_lj_array, self.bcoeff)

                    e_lj_sw = np.sum(e_lj_array[:, self.non_water_atom_ids])
                    e_elec_sw = np.sum(e_elec_array[:,
                                                    self.non_water_atom_ids])

                    e_lj_ww_left = e_lj_array[:, self.
                                              wat_oxygen_atom_ids[0]:wat_O]
                    e_lj_ww_right = e_lj_array[:, wat_O + self.water_sites:]
                    e_lj_ww = np.sum(e_lj_ww_left) + np.sum(e_lj_ww_right)
                    e_elec_ww_left = e_elec_array[:, self.
                                                  wat_oxygen_atom_ids[0]:wat_O]
                    e_elec_ww_right = e_elec_array[:,
                                                   wat_O + self.water_sites:]
                    e_elec_ww = np.sum(e_elec_ww_left) + np.sum(
                        e_elec_ww_right)

                    e_nbr_list = [
                        np.sum(e_lj_array[:, nbr:nbr + self.water_sites] +
                               e_elec_array[:, nbr:nbr + self.water_sites])
                        for nbr in wat_nbrs
                    ]

                    e_lj_ww = np.sum(
                        e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat_O]
                    ) + np.sum(e_lj_array[:, wat_O + self.water_sites:])
                    e_elec_ww = np.sum(
                        e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat_O]
                    ) + np.sum(e_elec_array[:, wat_O + self.water_sites:])

                    self.hsa_dict[site_i][7].append(e_lj_sw)
                    self.hsa_dict[site_i][8].append(e_elec_sw)
                    self.hsa_dict[site_i][10].append(e_lj_ww)
                    self.hsa_dict[site_i][11].append(e_elec_ww)
                    self.hsa_dict[site_i][6].append(e_lj_sw + e_elec_sw)
                    self.hsa_dict[site_i][9].append(e_lj_ww + e_elec_ww)
                    self.hsa_dict[site_i][12].append(e_lj_sw + e_elec_sw +
                                                     e_lj_ww + e_elec_ww)
                    self.hsa_dict[site_i][13].extend(
                        e_nbr_list)  # print(e_lj_sw/2.0)

                    if energy_lr_breakdown:
                        for s in range(1, len(shell_radii)):
                            wat_nbrs = self.wat_oxygen_atom_ids[np.where((
                                distance_matrix[0, :][self.wat_oxygen_atom_ids]
                                <= shell_radii[s]) & (distance_matrix[0, :][
                                    self.wat_oxygen_atom_ids] > shell_radii[
                                        s - 1]))]
                            e_nbr_list = [
                                np.sum(e_lj_array[:,
                                                  nbr:nbr + self.water_sites] +
                                       e_elec_array[:, nbr:nbr +
                                                    self.water_sites])
                                for nbr in wat_nbrs
                            ]
                            self.energy_ww_lr_breakdown[site_i][s - 1] += sum(
                                e_nbr_list)

                if hbonds:
                    hbtot = 0
                    prot_nbrs_all = self.prot_atom_ids[np.where(
                        distance_matrix[0, :][
                            self.prot_atom_ids] <= nbr_cutoff_sq)]
                    prot_nbrs_hb = prot_nbrs_all[np.where(
                        self.prot_hb_types[prot_nbrs_all] != 0)]
                    if wat_nbrs.shape[0] > 0:
                        hb_ww = self.calculate_hydrogen_bonds(
                            trj, wat_O, wat_nbrs)
                        acc_ww = hb_ww[:,
                                       0][np.where(hb_ww[:,
                                                         0] == wat_O)].shape[0]
                        don_ww = hb_ww.shape[0] - acc_ww
                        self.hsa_dict[site_i][18].append(hb_ww.shape[0])
                        self.hsa_dict[site_i][23].append(acc_ww)
                        self.hsa_dict[site_i][24].append(don_ww)
                        hbtot += hb_ww.shape[0]
                        if wat_nbrs.shape[0] != 0 and hb_ww.shape[0] != 0:
                            self.hsa_dict[site_i][21].append(hb_ww.shape[0] /
                                                             wat_nbrs.shape[0])
                    if prot_nbrs_hb.shape[0] > 0:
                        hb_sw = self.calculate_hydrogen_bonds(
                            trj, wat_O, prot_nbrs_hb, water_water=False)
                        acc_sw = hb_sw[:,
                                       0][np.where(hb_sw[:,
                                                         0] == wat_O)].shape[0]
                        don_sw = hb_sw.shape[0] - acc_sw
                        don_sw_ids = hb_sw[:, 1][np.where(hb_sw[:,
                                                                0] == wat_O)]
                        acc_sw_ids = hb_sw[:,
                                           0][np.where(hb_sw[:, 0] != wat_O)]
                        self.hsa_dict[site_i][19].append(hb_sw.shape[0])
                        self.hsa_dict[site_i][25].append(acc_sw)
                        self.hsa_dict[site_i][26].append(don_sw)
                        self.hsa_dict[site_i][27].extend(acc_sw_ids)
                        self.hsa_dict[site_i][28].extend(don_sw_ids)
                        hbtot += hb_sw.shape[0]
                    self.hsa_dict[site_i][20].append(hbtot)
                    if angular_structure:
                        wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                            (distance_matrix[0, :][self.wat_oxygen_atom_ids] <=
                             r_theta_cutoff**2) & (distance_matrix[0, :][
                                 self.wat_oxygen_atom_ids] > 0.0))]
                        angles = self.water_nbr_orientations(
                            trj, wat_O, wat_nbrs)
                        dist = np.sqrt(distance_matrix[0, wat_nbrs])
                        self.angular_st_distribution[site_i].extend(
                            zip(dist, angles))

        if entropy:
            # save coordinates of hsa region waters in current frame
            for index, wat_O in enumerate(
                    self.hsa_region_O_ids[frame_i - self.start_frame]):
                flat_id = self.hsa_region_flat_ids[frame_i -
                                                   self.start_frame][index]
                index_pairs = list(
                    zip(list(range(wat_O, wat_O + 3)),
                        list(range(flat_id, flat_id + 3))))
                for index_pair in index_pairs:
                    self.hsa_region_water_coords[index_pair[1], :] += coords[
                        0, index_pair[0], :]
Beispiel #5
0
    def _process_frame(self, trj, frame_i, energy, hbonds, entropy):
        nbr_cutoff_sq = 3.5**2
        trj.xyz *= 10.0
        coords = trj.xyz
        periodic_box = md.utils.in_units_of(trj.unitcell_lengths, "nanometers",
                                            "angstroms")
        waters = []
        calc.assign_voxels(trj.xyz, self.dims, self.gridmax, self.origin,
                           waters, self.wat_oxygen_atom_ids)
        for wat in waters:
            self.voxeldata[wat[0], 4] += 1
            if energy or hbonds:
                e_lj_array, e_elec_array = np.copy(self.acoeff), np.copy(
                    self.chg_product)
                distance_matrix = np.zeros(
                    (self.water_sites, self.all_atom_ids.shape[0]))
                calc.get_pairwise_distances(wat, self.all_atom_ids, coords,
                                            periodic_box, distance_matrix)
                wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                    (distance_matrix[0, :][self.wat_oxygen_atom_ids] <=
                     nbr_cutoff_sq)
                    & (distance_matrix[0, :][self.wat_oxygen_atom_ids] > 0.0))]
                self.voxeldata[wat[0], 19] += wat_nbrs.shape[0]
                calc.calculate_energy(wat[1], distance_matrix, e_elec_array,
                                      e_lj_array, self.bcoeff)

                if self.prot_atom_ids.shape[0] != 0:
                    self.voxeldata[wat[0], 13] += np.sum(
                        e_lj_array[:, self.prot_atom_ids])
                    self.voxeldata[wat[0], 13] += np.sum(
                        e_elec_array[:, self.prot_atom_ids])
                self.voxeldata[wat[0], 15] += np.sum(
                    e_lj_array[:,
                               self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(
                                   e_lj_array[:, wat[1] + self.water_sites:])
                self.voxeldata[wat[0], 15] += np.sum(
                    e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]
                ) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                e_nbr_list = [
                    np.sum(e_lj_array[:, wat_nbrs + i] +
                           e_elec_array[:, wat_nbrs + i])
                    for i in xrange(self.water_sites)
                ]
                self.voxeldata[wat[0], 17] += np.sum(e_nbr_list)
                """
                ###DEBUG START###
                elj_sw = np.sum(e_lj_array[:, :self.wat_oxygen_atom_ids[0]])
                eelec_sw = np.sum(e_elec_array[:, :self.wat_oxygen_atom_ids[0]])
                elj_ww = np.sum(e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_lj_array[:, wat[1] + 1:])
                eelec_ww = np.sum(e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat[1]]) + np.sum(e_elec_array[:, wat[1] + self.water_sites:])
                e_nbr_list = [np.sum(e_lj_array[:, wat_nbrs + i] + e_elec_array[:, wat_nbrs + i]) for i in xrange(self.water_sites)]
                enbr = np.sum(e_nbr_list)
                print "Calc: ", elj_sw, eelec_sw, elj_ww, eelec_ww, enbr
                distance_matrix = np.sqrt(distance_matrix)
                energy_lj, energy_elec = self.calculate_energy(distance_matrix)
                test_1 = np.sum(energy_lj[:self.wat_oxygen_atom_ids[0]:])
                test_2 = np.sum(energy_elec[:, self.non_water_atom_ids])
                test_3 = np.nansum(energy_lj[self.wat_oxygen_atom_ids[0]:])
                test_4 = np.sum(energy_elec[:, self.wat_atom_ids[0]:wat[1]]) + np.sum(energy_elec[:, wat[1] + self.water_sites:])
                test_5 = 0.0
                test_5 += np.sum(energy_lj[self.wat_oxygen_atom_ids[0]:][(wat_nbrs - self.wat_oxygen_atom_ids[0]) / self.water_sites])
                for i in range(self.water_sites):
                    test_5 += np.sum(energy_elec[:, wat_nbrs + i])
                print "Ref: ", test_1, test_2, test_3, test_4, test_5
                ###DEBUG END###
                """
                # H-bond calculations
                if hbonds:
                    prot_nbrs_all = self.non_water_atom_ids[np.where(
                        distance_matrix[0, :][
                            self.non_water_atom_ids] <= nbr_cutoff_sq)]
                    prot_nbrs_hb = prot_nbrs_all[np.where(
                        self.prot_hb_types[prot_nbrs_all] != 0)]

                    if wat_nbrs.shape[0] > 0:
                        hb_ww = self.calculate_hydrogen_bonds(
                            trj, wat[1], wat_nbrs)
                        acc_ww = hb_ww[:, 0][np.where(
                            hb_ww[:, 0] == wat[1])].shape[0]
                        don_ww = hb_ww.shape[0] - acc_ww
                        self.voxeldata[wat[0], 25] += hb_ww.shape[0]
                        self.voxeldata[wat[0], 31] += don_ww
                        self.voxeldata[wat[0], 33] += acc_ww
                        if wat_nbrs.shape[0] != 0 and hb_ww.shape[0] != 0:
                            self.voxeldata[
                                wat[0],
                                21] += wat_nbrs.shape[0] / hb_ww.shape[0]

                    if prot_nbrs_hb.shape[0] > 0:
                        hb_sw = self.calculate_hydrogen_bonds(
                            trj, wat[1], prot_nbrs_hb, water_water=False)
                        acc_sw = hb_sw[:, 0][np.where(
                            hb_sw[:, 0] == wat[1])].shape[0]
                        don_sw = hb_sw.shape[0] - acc_sw
                        self.voxeldata[wat[0], 23] += hb_sw.shape[0]
                        self.voxeldata[wat[0], 27] += don_sw
                        self.voxeldata[wat[0], 29] += acc_sw

            if entropy:
                self.calculate_euler_angles(wat, coords[0, :, :])
Beispiel #6
0
    def calculate_lonranged_ww_energy(self, site_indices=None, shell_radii=[3.5, 5.5, 8.5], start_frame=None,
                                      num_frames=None):
        """Summary
        
        Parameters
        ----------
        site_indices : list, optional
            Description
        shell_radii : list, optional
            Description
        
        Returns
        -------
        TYPE
            Description
            :param start_frame:
            :param num_frames:
        """
        if start_frame is None:
            start_frame = self.start_frame
        if num_frames is None:
            num_frames = self.num_frames

        if site_indices is None:
            site_indices = [int(i) for i in self.hsa_data[:, 0]]
        else:
            for index in site_indices:
                if index > self.hsa_data[:, 0][-1]:
                    sys.exit(
                        "Site %d does not exits, please provide valid site indices." % index)

        n_sites = len(site_indices)
        n_columns = 2 * len(shell_radii)
        shells = [(0.0, shell_radii[0])]
        for i in range(1, len(shell_radii)):
            shells.append((shell_radii[i - 1], shell_radii[i]))
        shells.append((shell_radii[-1], 100.0))
        longranged_data = np.zeros((n_sites, 2 * len(shells)))
        site_waters_copy = list(self.site_waters)

        print_progress_bar(start_frame, start_frame + num_frames)
        for frame_i in range(start_frame, start_frame + num_frames):
            frame = md.load_frame(self.trajectory, frame_i, top=self.topology)
            pos = md.utils.in_units_of(frame.xyz, "nanometers", "angstroms")
            pbc = md.utils.in_units_of(
                frame.unitcell_lengths, "nanometers", "angstroms")
            oxygen_pos = pos[0, self.wat_oxygen_atom_ids, :]
            cluster_search_space = NeighborSearch(oxygen_pos, 1.0)
            water_search_space = NeighborSearch(oxygen_pos, 3.5)
            for site_i in range(len(site_indices)):
                wat_O = None
                if self.is_site_waters_populated:
                    if len(site_waters_copy[site_i]) != 0:
                        if site_waters_copy[site_i][0][0] == frame_i:
                            wat_O = site_waters_copy[site_i].pop(0)[1]
                            self.hsa_data[site_i, 4] += 1
                else:
                    cluster_center_coords = (self.hsa_data[site_i, 1], self.hsa_data[
                        site_i, 2], self.hsa_data[site_i, 3])
                    nbr_indices = cluster_search_space.query_nbrs_single_point(
                        cluster_center_coords)
                    cluster_wat_oxygens = [self.wat_oxygen_atom_ids[
                                               nbr_index] for nbr_index in nbr_indices]
                    if len(cluster_wat_oxygens) != 0:
                        wat_O = cluster_wat_oxygens[0]
                        self.hsa_data[site_i, 4] += 1
                        self.site_waters.append((frame_i, wat_O))

                if wat_O is not None:
                    distance_matrix = np.zeros(
                        (self.water_sites, self.all_atom_ids.shape[0]), np.float_)
                    calc.get_pairwise_distances(np.asarray(
                        [site_i, wat_O]), self.all_atom_ids, pos, pbc, distance_matrix)
                    energy_lj, energy_elec = self.calculate_energy(
                        distance_matrix)
                    for shell_index, shell in enumerate(shells):
                        wat_nbrs = self.wat_oxygen_atom_ids[
                            np.where((distance_matrix[0, :][self.wat_oxygen_atom_ids] <= shell[
                                1]) & (distance_matrix[0, :][self.wat_oxygen_atom_ids] > shell[0]))]
                        longranged_data[site_i, 2 * shell_index] += wat_nbrs.shape[0]
                        for i in range(self.water_sites):
                            longranged_data[
                                site_i, (2 * shell_index) + 1] += np.sum(energy_elec[:, wat_nbrs + i])
            print_progress_bar(frame_i, num_frames)
        # normalize site quantities
        for index, site_i in enumerate(site_indices):
            n_wat = self.hsa_data[site_i, 4]
            if n_wat != 0:
                longranged_data[index, :] /= n_wat * 2.0

        # write data
        with open(self.prefix + "_longrange_Eww_summary.txt", "w") as f:
            header = "index "
            formatted_output = "{0:.0f} "
            for shell_index, shell in enumerate(shells):
                if shell_index + 1 == len(shells):
                    header += "Nnbr_>" + \
                              str(shell_index) + " E_shell_>" + \
                              str(shell_index) + "\n"
                    formatted_output += "{1[%d]:.6f} {1[%d]:.6f}\n" % (
                        2 * shell_index, (2 * shell_index) + 1)
                else:
                    header += "Nnbr_" + \
                              str(shell_index + 1) + " E_shell_" + \
                              str(shell_index + 1) + " "
                    formatted_output += "{1[%d]:.6f} {1[%d]:.6f} " % (
                        2 * shell_index, (2 * shell_index) + 1)
            f.write(header)
            for index, site_i in enumerate(site_indices):
                n_wat = self.hsa_data[site_i, 4]
                site_data_line = formatted_output.format(
                    self.hsa_data[site_i, 0], longranged_data[index, :])
                f.write(site_data_line)
Beispiel #7
0
    def calculate_angular_structure(self, site_indices=None, dist_cutoff=6.0, start_frame=None, num_frames=None):
        '''
        Returns energetic quantities for each hydration site
        
        Parameters
        ----------
        site_indices : list, optional
            Description
        dist_cutoff : float, optional
            Description
            :param start_frame:
            :param num_frames:

        '''
        if start_frame is None:
            start_frame = self.start_frame
        if num_frames is None:
            num_frames = self.num_frames

        if site_indices is None:
            site_indices = [int(i) for i in self.hsa_data[:, 0]]
        else:
            for index in site_indices:
                if index > self.hsa_data[:, 0][-1]:
                    sys.exit(
                        "Site %d does not exits, please provide valid site indices." % index)
        n_sites = len(site_indices)
        r_theta_data = [[] for i in range(n_sites)]
        site_waters_copy = list(self.site_waters)

        print_progress_bar(start_frame, start_frame + num_frames)
        for frame_i in range(start_frame, start_frame + num_frames):
            frame = md.load_frame(self.trajectory, frame_i, top=self.topology)
            pos = md.utils.in_units_of(frame.xyz, "nanometers", "angstroms")
            pbc = md.utils.in_units_of(
                frame.unitcell_lengths, "nanometers", "angstroms")
            oxygen_pos = pos[0, self.wat_oxygen_atom_ids, :]
            cluster_search_space = NeighborSearch(oxygen_pos, 1.0)
            water_search_space = NeighborSearch(oxygen_pos, 3.5)
            for site_i in range(len(site_indices)):
                wat_O = None
                if self.is_site_waters_populated:
                    if len(site_waters_copy[site_i]) != 0:
                        if site_waters_copy[site_i][0][0] == frame_i:
                            wat_O = site_waters_copy[site_i].pop(0)[1]
                            self.hsa_data[site_i, 4] += 1
                else:
                    cluster_center_coords = (self.hsa_data[site_i, 1], self.hsa_data[
                        site_i, 2], self.hsa_data[site_i, 3])
                    nbr_indices = cluster_search_space.query_nbrs_single_point(
                        cluster_center_coords)
                    cluster_wat_oxygens = [self.wat_oxygen_atom_ids[
                                               nbr_index] for nbr_index in nbr_indices]
                    if len(cluster_wat_oxygens) != 0:
                        wat_O = cluster_wat_oxygens[0]
                        self.hsa_data[site_i, 4] += 1
                        self.site_waters.append((frame_i, wat_O))
                        #self.hsa_dict[site_i][-1].append((frame_i, wat_O))

                if wat_O is not None:
                    distance_matrix = np.zeros(
                        (self.water_sites, self.all_atom_ids.shape[0]), np.float_)
                    calc.get_pairwise_distances(np.asarray(
                        [site_i, wat_O]), self.all_atom_ids, pos, pbc, distance_matrix)
                    wat_nbrs = self.wat_oxygen_atom_ids[np.where((distance_matrix[0, :][
                                                                      self.wat_oxygen_atom_ids] <= dist_cutoff) & (
                                                                     distance_matrix[0, :][
                                                                         self.wat_oxygen_atom_ids] > 0.0))]
                    angle_triplets = []
                    for wat_nbr in wat_nbrs:
                        angle_triplets.extend([[wat_O, wat_nbr, wat_nbr + 1], [wat_O, wat_nbr, wat_nbr + 2],
                                               [wat_nbr, wat_O, wat_O + 1], [wat_nbr, wat_O, wat_O + 2]])
                    angle_triplets = np.asarray(angle_triplets)
                    angles = md.utils.in_units_of(md.compute_angles(
                        frame, angle_triplets), "radians", "degrees")
                    for angle_index in range(0, angles.shape[1], 4):
                        hb_angle = np.min(
                            angles[0, angle_index:angle_index + 4])
                        nbr_index = angle_index / 4
                        r_theta_data[site_i].append(
                            (hb_angle, distance_matrix[0, wat_nbrs[nbr_index]]))
            print_progress_bar(frame_i, num_frames)
        directory = self.prefix + "_angular_structure_data"
        if not os.path.exists(directory):
            os.makedirs(directory)
        for index, site_i in enumerate(site_indices):
            with open(directory + "/%03d_r_theta" % site_i, "w") as f:
                for d in r_theta_data[index]:
                    line = "{0[0]:.3f} {0[1]:.3f}\n".format(d)
                    f.write(line)
Beispiel #8
0
    def process_chunk(self, begin_chunk, chunk_size, topology, energy, hbonds, entropy):

        site_waters_copy = list(self.site_waters)
        nbr_cutoff_sq = 3.5 ** 2
        with md.open(self.trajectory) as f:
            f.seek(begin_chunk)
            trj = f.read_as_traj(topology, n_frames=chunk_size, stride=1)
            #md.utils.in_units_of(trj.xyz, "nanometers", "angstroms", inplace=True)
            trj.xyz *= 10.0
            trj.unitcell_lengths *= 10.0
            pbc = trj.unitcell_lengths

            for frame in range(trj.n_frames):
                frame_i = frame + (begin_chunk * chunk_size)
                coords = trj.xyz[frame, :, :].reshape(1, trj.xyz.shape[1], trj.xyz.shape[2])
                oxygen_pos = coords[0, self.wat_oxygen_atom_ids, :]
                for site_i in range(self.hsa_data.shape[0]):
                    wat_O = None
                    if self.is_site_waters_populated:
                        if len(site_waters_copy[site_i]) != 0:
                            if site_waters_copy[site_i][0][0] == frame_i:
                                wat_O = site_waters_copy[site_i].pop(0)[1]
                                index = int(self.hsa_data[site_i, 4]) * 3
                                index_pairs = zip(xrange(wat_O, wat_O + 3), xrange(index, index + 3))
                                for index_pair in index_pairs:
                                    self.hsa_dict[site_i][-1][index_pair[1]] += coords[0, index_pair[0], :]
                                self.hsa_data[site_i, 4] += 1
                    else:
                        cluster_search_space = NeighborSearch(oxygen_pos, 1.0)
                        cluster_center_coords = (self.hsa_data[site_i, 1], self.hsa_data[site_i, 2], self.hsa_data[site_i, 3])
                        nbr_indices = cluster_search_space.query_nbrs_single_point(cluster_center_coords)
                        cluster_wat_oxygens = [self.wat_oxygen_atom_ids[nbr_index] for nbr_index in nbr_indices]
                        if len(cluster_wat_oxygens) != 0:
                            wat_O = cluster_wat_oxygens[0]
                            self.site_waters[site_i].append((frame_i, wat_O))
                            index = int(self.hsa_data[site_i, 4]) * 3
                            index_pairs = zip(xrange(wat_O, wat_O + 3), xrange(index, index + 3))
                            for index_pair in index_pairs:
                                self.hsa_dict[site_i][-1][index_pair[1]] += coords[0, index_pair[0], :]
                            self.hsa_data[site_i, 4] += 1
                    if wat_O is not None and (energy or hbonds):
                        distance_matrix = np.zeros((self.water_sites, self.all_atom_ids.shape[0]), np.float_)
                        calc.get_pairwise_distances(np.asarray([site_i, wat_O]), self.all_atom_ids, coords, pbc, distance_matrix)
                        wat_nbrs = self.wat_oxygen_atom_ids[np.where(
                            (distance_matrix[0, :][self.wat_oxygen_atom_ids] <= nbr_cutoff_sq) & (
                                distance_matrix[0, :][self.wat_oxygen_atom_ids] > 0.0))]
                        self.hsa_dict[site_i][17].append(wat_nbrs.shape[0])
                        if energy:
                            e_lj_array, e_elec_array = np.copy(self.acoeff), np.copy(self.chg_product)
                            calc.calculate_energy(wat_O, distance_matrix, e_elec_array, e_lj_array, self.bcoeff)
                            e_lj_sw = np.sum(e_lj_array[:, :self.wat_oxygen_atom_ids[0]])
                            e_elec_sw = np.sum(e_elec_array[:, :self.wat_oxygen_atom_ids[0]])
                            e_lj_ww = np.sum(
                                e_lj_array[:, self.wat_oxygen_atom_ids[0]:wat_O]) + np.sum(e_lj_array[:, wat_O + self.water_sites:])
                            e_elec_ww = np.sum(
                                e_elec_array[:, self.wat_oxygen_atom_ids[0]:wat_O]) + np.sum(
                                e_elec_array[:, wat_O + self.water_sites:])
                            e_nbr_list = [np.sum(e_lj_array[:, nbr:nbr + self.water_sites] + e_elec_array[:, nbr:nbr + self.water_sites]) for nbr in wat_nbrs]
                            #e_nbr_list = [np.sum(e_lj_array[:, wat_nbrs + i] + e_elec_array[:, wat_nbrs + i]) for i in
                            #              xrange(self.water_sites)]
                            self.hsa_dict[site_i][7].append(e_lj_sw)
                            self.hsa_dict[site_i][8].append(e_elec_sw)
                            self.hsa_dict[site_i][10].append(e_lj_ww)
                            self.hsa_dict[site_i][11].append(e_elec_ww)
                            self.hsa_dict[site_i][6].append(e_lj_sw + e_elec_sw)
                            self.hsa_dict[site_i][9].append(e_lj_ww + e_elec_ww)
                            self.hsa_dict[site_i][12].append(e_lj_sw + e_elec_sw + e_lj_ww + e_elec_ww)
                            self.hsa_dict[site_i][13].extend(e_nbr_list) # print(e_lj_sw/2.0)

                        if hbonds:
                            prot_nbrs_all = self.non_water_atom_ids[
                                np.where(distance_matrix[0, :][self.non_water_atom_ids] <= nbr_cutoff_sq)]
                            prot_nbrs_hb = prot_nbrs_all[np.where(self.prot_hb_types[prot_nbrs_all] != 0)]
                            #print wat_O, wat_nbrs
                            if wat_nbrs.shape[0] + prot_nbrs_hb.shape[0] > 0:
                                hb_ww, hb_sw = self.calculate_hydrogen_bonds(trj, wat_O, wat_nbrs, prot_nbrs_hb)
                                #print wat_nbrs, hb_ww
                                acc_ww = hb_ww[:, 0][np.where(hb_ww[:, 0] == wat_O)].shape[0]
                                don_ww = hb_ww.shape[0] - acc_ww
                                acc_sw = hb_sw[:, 0][np.where(hb_sw[:, 0] == wat_O)].shape[0]
                                don_sw = hb_sw.shape[0] - acc_sw
                                don_sw_ids = hb_sw[:, 1][np.where(hb_sw[:, 0] == wat_O)]
                                acc_sw_ids = hb_sw[:, 0][np.where(hb_sw[:, 0] != wat_O)]
                                self.hsa_dict[site_i][18].append(hb_ww.shape[0])
                                self.hsa_dict[site_i][19].append(hb_sw.shape[0])
                                self.hsa_dict[site_i][20].append(hb_ww.shape[0] + hb_sw.shape[0])
                                self.hsa_dict[site_i][23].append(acc_ww)
                                self.hsa_dict[site_i][24].append(don_ww)
                                self.hsa_dict[site_i][25].append(acc_sw)
                                self.hsa_dict[site_i][26].append(don_sw)
                                self.hsa_dict[site_i][27].extend(acc_sw_ids)
                                self.hsa_dict[site_i][28].extend(don_sw_ids)
                                if wat_nbrs.shape[0] != 0 and hb_ww.shape[0] != 0:
                                    self.hsa_dict[site_i][21].append(
                                        hb_ww.shape[0] / wat_nbrs.shape[0])

                if entropy:
                    # save coordinates of hsa region waters in current frame
                    for index, wat_O in enumerate(self.hsa_region_O_ids[frame_i - self.start_frame]):
                        flat_id = self.hsa_region_flat_ids[frame_i - self.start_frame][index]
                        index_pairs = zip(xrange(wat_O, wat_O + 3), xrange(flat_id, flat_id + 3))
                        for index_pair in index_pairs:
                            self.hsa_region_water_coords[index_pair[1], :] += coords[0, index_pair[0], :]