def toWater(coord, cell): logger = logging.getLogger() dmin = shortest_distance(coord, cell) * 1.4 grid = pl.determine_grid(cell, dmin) pairs = pl.pairs_fine(coord, dmin, cell, grid, distance=False) for vtet, dtet in tetrahedra(pairs, dmin, coord, cell): p = dtet[0] + (dtet[1] + dtet[2] + dtet[3]) / 4 p -= np.floor(p) yield p
def make_lattice_info(oatoms, hatoms, cellmat): logger = getLogger() assert oatoms.shape[0] > 0 assert hatoms is None or oatoms.shape[0] * 2 == hatoms.shape[0] coord = 'relative' density = oatoms.shape[0] / (np.linalg.det(cellmat) * 1e-21) * 18 / 6.022e23 if hatoms is None: return SimpleNamespace(waters=oatoms, coord=coord, density=density, bondlen=0.3, cell=cellmat) rotmat = np.zeros((oatoms.shape[0], 3, 3)) for i in range(oatoms.shape[0]): ro = oatoms[i] rdh0 = rel_wrap(hatoms[i * 2] - ro) rdh1 = rel_wrap(hatoms[i * 2 + 1] - ro) dh0 = np.dot(rdh0, cellmat) dh1 = np.dot(rdh1, cellmat) y = dh0 - dh1 y /= np.linalg.norm(y) z = dh0 + dh1 z /= np.linalg.norm(z) x = np.cross(y, z) rotmat[i] = np.vstack([x, y, z]) # 重心位置を補正。 oatoms[i] += (rdh0 + rdh1) * 1. / 18. grid = pl.determine_grid(cellmat, 0.245) # remove intramolecular OHs # 水素結合は原子の平均位置で定義している。 pairs = [] logger.debug(" Make pair list.") for o, h in pl.pairs_fine_hetero(oatoms, hatoms, 0.245, cellmat, grid, distance=False): if not (h == o * 2 or h == o * 2 + 1): # hとoは別の分子の上にあって近い。 # register a new intermolecular pair pairs.append((h // 2, o)) logger.debug(" # of pairs: {0} {1}".format(len(pairs), oatoms.shape[0])) return SimpleNamespace(waters=oatoms, coord=coord, density=density, pairs=pairs, rotmat=rotmat, cell=cellmat, __doc__=None)
def toWater(coord, cell, tolerance=1.4): """ cell: cell matrix (first row == a) coord: relative coord of the cage position """ logger = logging.getLogger() dmin = shortest_distance(coord, cell) * tolerance grid = pl.determine_grid(cell, dmin) pairs = pl.pairs_fine(coord, dmin, cell, grid, distance=False) for vtet, dtet in tetrahedra(pairs, dmin, coord, cell): p = dtet[0] + (dtet[1] + dtet[2] + dtet[3]) / 4 p -= np.floor(p) yield p
def main(): import sys groname, twiname = sys.argv[1:3] with open(twiname) as twifile: with open(groname) as grofile: while True: if groname[-4:] == ".pdb": gr = pdb.PDB(grofile, "O", "H", resname="WAT") else: # assume it is gromacs gr = gro.Gromacs(grofile, "Ow", "Hw", "Mw") btw = btwc.load_BTWC(twifile) if btw is None or gr is None: break celli = np.linalg.inv(gr.cell) # relative coord rs = np.array([np.dot(x, celli) for x in gr.solutes]) ro = np.array([np.dot(x, celli) for x in gr.waters]) print(len(rs)) print(len(ro)) grid = pl.determine_grid(gr.cell, 0.245) shell1 = np.vstack( pl.pairs_fine_hetero(rs, ro, 0.4, gr.cell, grid, distance=False)) # some solute atoms are isolated from water. shell1s = set(shell1[:, 0]) shell1w = set(shell1[:, 1]) #show all bonds in yaplot s = "" for i in range(-10, 0): s += yap.SetPalette(i + 10 + 3, 255 * (-i) // 10, 0, 0) for i in range(11): s += yap.SetPalette(i + 10 + 3, 0, 0, 255 * i // 10) for b in btw: i, j = b[0] if i in shell1w or j in shell1w: s += yap.Layer(1) else: s += yap.Layer(2) r = abs(b[2]) sine = b[2].imag s += yap.Size(r) s += yap.Color(int(sine * 10) + 10 + 3) s += yap.Circle(b[1]) print(s)
def waters_and_pairs(cell, atomd, sops, rep=(1, 1, 1)): logger = getLogger() oxygens = [] hydrogens = [] for name, pos in fullatoms(atomd, sops): if name[0] in ("O", ): oxygens.append(pos) elif name[0] in "DH": hydrogens.append(pos) assert len(oxygens) * 2 == len(hydrogens) or len( hydrogens) == 0, "{0}:{1}".format(len(oxygens) * 2, len(hydrogens)) cell *= np.array(rep) oo = [[o[0] + x, o[1] + y, o[2] + z] for o in oxygens for x in range(rep[0]) for y in range(rep[1]) for z in range(rep[2])] oxygens = np.array(oo) oxygens /= np.array(rep) if len(hydrogens) == 0: return oxygens, None hh = [[h[0] + x, h[1] + y, h[2] + z] for h in hydrogens for x in range(rep[0]) for y in range(rep[1]) for z in range(rep[2])] hydrogens = np.array(hh) hydrogens /= np.array(rep) oh = defaultdict(list) parent = dict() grid = pl.determine_grid(cell, 0.15) # find covalent OH bonds for i, j in pl.pairs_fine_hetero(oxygens, hydrogens, 0.15, cell, grid, distance=False): oh[i].append(j) parent[j] = i grid = pl.determine_grid(cell, 0.20) pairs = [] # find HBs for i, j in pl.pairs_fine_hetero(oxygens, hydrogens, 0.20, cell, grid, distance=False): if j not in oh[i]: # H is on a different water molecule p = parent[j] pairs.append([p, i]) logger.debug(pairs) waters = [] for i in range(len(oh)): logger.debug((i, oh[i])) j, k = oh[i] dhj = hydrogens[j] - oxygens[i] dhk = hydrogens[k] - oxygens[i] dhj -= np.floor(dhj + 0.5) dhk -= np.floor(dhk + 0.5) com = oxygens[i] + (dhj + dhk) / 18 waters.append(com) return waters, pairs
def __init__( self, lat, argv, density=0, rep=(1, 1, 1), cations=dict(), anions=dict(), spot_guests=dict(), spot_groups=dict(), asis=False, ): self.logger = getLogger() self.rep = rep self.asis = asis self.cations = cations self.anions = anions self.spot_guests = spot_guests self.spot_groups = spot_groups # Show the document of the module try: self.doc = lat.__doc__.splitlines() except BaseException: self.doc = [] self.doc.append("") self.doc.append("Command line: {0}".format(" ".join(argv))) for line in self.doc: self.logger.info(" " + line) # ================================================================ # rotmatrices (analice) # try: self.rotmatrices = lat.rotmat except BaseException: self.logger.info("No rotmatrices in lattice") self.rotmatrices = None # ================================================================ # waters: positions of water molecules # self.waters = put_in_array(lat.waters) self.logger.debug("Waters: {0}".format(len(self.waters))) self.waters = self.waters.reshape((self.waters.size // 3, 3)) # ================================================================ # cell: cell dimension # see parse_cell for syntax. # self.cell = Cell(lat.cell) # ================================================================ # coord: "relative" or "absolute" # Inside genice, molecular positions are always treated as "relative" # if lat.coord == "absolute": self.waters = self.cell.abs2rel(self.waters) self.waters = np.array([w - np.floor(w) for w in self.waters]) # ================================================================ # pairs: specify the pairs of molecules that are connected. # Bond orientation will be shuffled later # unless it is "fixed". # self.pairs = None try: self.pairs = parse_pairs(lat.pairs) except AttributeError: self.logger.info("HB connectivity is not defined.") # ================================================================ # bondlen: specify the bond length threshold. # This is used when "pairs" are not specified. # It is applied to the original positions of molecules (before density setting). # nmol = self.waters.shape[0] # nmol in a unit cell volume = self.cell.volume() # volume of a unit cell in nm**3 self.bondlen = None try: self.bondlen = lat.bondlen self.logger.info("Bond length (specified): {0}".format( self.bondlen)) except AttributeError: self.logger.debug(" Estimating the bond threshold length...") # assume that the particles distribute homogeneously. rc = (volume / nmol)**(1 / 3) * 1.5 grid = pl.determine_grid(self.cell.mat, rc) p = pl.pairs_fine(self.waters, rc, self.cell.mat, grid, distance=False) self.bondlen = 1.1 * shortest_distance( self.waters, self.cell, pairs=p) self.logger.info("Bond length (estim.): {0}".format(self.bondlen)) # Set density mass = 18 # water NB = 6.022e23 density0 = mass * nmol / (NB * volume * 1e-21) if density <= 0: try: self.density = lat.density except AttributeError: self.logger.info( "Density is not specified. Assume the density from lattice." ) dmin = shortest_distance(self.waters, self.cell) self.logger.info( "Closest pair distance: {0} (should be around 0.276 nm)". format(dmin)) self.density = density0 / (0.276 / dmin)**3 # self.density = density0 else: self.density = density self.logger.info("Target Density: {0}".format(self.density)) self.logger.info("Original Density: {0}".format(density0)) # scale the cell according to the (specified) density ratio = (density0 / self.density)**(1.0 / 3.0) self.cell.scale(ratio) if self.bondlen is not None: self.bondlen *= ratio self.logger.info("Bond length (scaled, nm): {0}".format(self.bondlen)) # ================================================================ # double_network: True or False # This is a special option for ices VI and VII that have # interpenetrating double network. # GenIce's fast depolarization algorithm fails in some case. # try: self.double_network = lat.double_network except AttributeError: self.double_network = False # ================================================================ # cages: positions of the centers of cages # In fractional coordinate. # self.cagepos = None self.cagetype = None if "cages" in lat.__dict__: self.cagepos, self.cagetype = parse_cages(lat.cages) self.logger.warn( "Use of 'cages' in a lattice-plugin is deprecated.") elif "cagepos" in lat.__dict__: # pre-parsed data self.cagepos, self.cagetype = np.array(lat.cagepos), lat.cagetype # ================================================================ # fixed: specify the bonds whose directions are fixed. # you can specify them in pairs at a time. # You can also leave it undefined. # self.fixed = [] try: self.fixed = parse_pairs(lat.fixed) self.logger.info("Orientations of some edges are fixed.") except AttributeError: pass if "dopeIonsToUnitCell" in lat.__dict__: self.dopeIonsToUnitCell = lat.dopeIonsToUnitCell else: self.dopeIonsToUnitCell = None self.dopants = set() # if asis, make pairs to be fixed. if self.asis and len(self.fixed) == 0: self.fixed = self.pairs # filled cages self.filled_cages = set() # groups info self.groups = defaultdict(dict) # groups for the semi-guest # experimental; there are many variation of semi-guest inclusion. self.groups_placer = { "Bu-": butyl, "Butyl-": butyl, "Pentyl-": pentyl, "Propyl-": propyl, "2,2-dimethylpropyl-": _2_2_dimethylpropyl, "2,3-dimethylbutyl-": _2_3_dimethylbutyl, "3,3-dimethylbutyl-": _3_3_dimethylbutyl, "3-methylbutyl-": _3_methylbutyl, "Ethyl-": ethyl }
def prepare_random_graph(self, fixed): if self.pairs is None: self.logger.info(" Pairs are not given explicitly.") self.logger.info( " Estimating the bonds according to the pair distances.") self.logger.debug("Bondlen: {0}".format(self.bondlen)) # make bonded pairs according to the pair distance. # make before replicating them. grid = pl.determine_grid(self.cell.mat, self.bondlen) assert np.product( grid ) > 0, "Too thin unit cell. Consider use of --rep option if the cell was made by cif2ice." self.pairs = pl.pairs_fine(self.waters, self.bondlen, self.cell.mat, grid, distance=False) # self.pairs = [v for v in zip(j0,j1)] # Check using a simpler algorithm. # Do not use it for normal debug because it is too slow if False: # self.logger.level <= logging.DEBUG: pairs1 = self.pairs pairs2 = [ v for v in pl.pairs_crude(self.waters, self.bondlen, self.cell.mat, distance=False) ] self.logger.debug("pairs1: {0}".format(len(pairs1))) self.logger.debug("pairs2: {0}".format(len(pairs2))) for pair in pairs1: i, j = pair assert (i, j) in pairs2 or (j, i) in pairs2 for pair in pairs2: i, j = pair assert (i, j) in pairs1 or (j, i) in pairs1 graph = dg.IceGraph() if fixed is not None: for i, j in fixed: graph.add_edge(i, j, fixed=True) # Fixed pairs are default. for pair in self.pairs: i, j = pair if graph.has_edge(i, j) or graph.has_edge(j, i): pass else: if random.randint(0, 1) == 0: graph.add_edge(i, j, fixed=False) else: graph.add_edge(j, i, fixed=False) self.logger.info(" Number of water nodes: {0}".format( graph.number_of_nodes())) return graph
def main(): gro = open(sys.argv[1]) box, atoms = LoadGRO(gro) ratoms = atoms/box cellmat = np.diag(box) page1 = "" page2 = "" page3 = "" page4 = "" page1 += yp.Size(0.05) grid = None while True: line = sys.stdin.readline() #expect *.smatch result of slide-matcher2 if len(line) == 0: break cols = line.split() if len(cols)<7: break # broken line; maybe end of the file. i,j = [int(x) for x in cols[:2]] rad, dx,dy,dz, rmsd = [float(x) for x in cols[2:]] if grid is None: grid = pairlist.determine_grid(cellmat, rad) lastrad = rad p,q,r = pairlist.pairs_fine(ratoms, rad, cellmat, grid, distance=True, raw=True) g = nx.Graph() for k,pq in enumerate(zip(p,q)): p,q = pq g.add_edge(p,q,length=r[k]) else: assert lastrad == rad d = np.array([dx,dy,dz]) if rmsd < 0.09: # 0.09 for hyper ice T # page 1: displacement vectors page1 += yp.Line(atoms[i], atoms[i]+d) page1 += yp.Circle(atoms[j]) # pages 2: displacement vectors (centered) page2 += yp.Size(0.05) page2 += yp.Line(np.zeros(3), d) page2 += yp.Circle(d) page2 += yp.Text(d, "{0} {1}".format(i,j)) # page 3..: matching s = "" s += yp.Size(0.05) s += yp.Layer(1) s += yp.Color(3) for ni in g[i]: s += yp.Circle(atoms[ni]) s += yp.Layer(2) s += yp.Color(4) for nj in g[j]: s += yp.Circle(atoms[nj]-atoms[j]+atoms[i]) page3 += s s = "" s += yp.Size(0.05) s += yp.Layer(1) s += yp.Color(3) for ni in g[i]: s += yp.Circle(atoms[ni]-atoms[i]) s += yp.Layer(2) s += yp.Color(4) for nj in g[j]: s += yp.Circle(atoms[nj]-atoms[j]) page4 += s page4 += yp.NewPage() print(page1) print(page2) print(page3) print(page4)
def hook1(lattice): lattice.logger.info("Hook1: Output sidewalls of water nanotubes in dtc-like ice in yaplot format.") cellmat = lattice.repcell.mat zoom = 100 axes = np.array([(1/8, 1/4), (5/8, 1/4), (3/8, 3/4), (7/8, 3/4)]) # max distance from the axis to the water monolayer maxd = cellmat[0,0] / 4 radius = maxd - 0.276/2 # approx. radius of the water monolayer plusd = maxd + 0.276 # second shell grid = pl.determine_grid(cellmat, 0.3) pairs = [(i,j) for i,j in pl.pairs_fine(lattice.reppositions, 0.3, cellmat, grid, distance=False)] logger.debug(("PAIRS",len(pairs),cellmat,grid)) sx, sy = int(cellmat[2,2]*zoom),int(4*7*radius*zoom) size = (sx//4*4, sy//4*4) image = Image.new("RGB", size, '#fff') draw = ImageDraw.Draw(image, "RGBA") for j, axis in enumerate(axes): dots = dict() dots2 = dict() for i, rpos in enumerate(lattice.reppositions): rd = np.zeros(3) rd[:2] = rpos[:2] - axis rd -= np.floor(rd+0.5) D = rd @ cellmat if D@D < maxd**2: a = atan2(D[1], D[0])+3.5 z = (rpos @ cellmat)[2] c = a*radius dot = np.array([z,c+j*7*radius]) #atom = rpos@cellmat dots[i] = dot elif D@D < plusd**2: a = atan2(D[1], D[0])+3.5 z = (rpos @ cellmat)[2] c = a*radius dot = np.array([z,c+j*7*radius]) #atom = rpos@cellmat dots2[i] = dot alldots = {**dots, **dots2} for p in dots2: r = 0.04 tl = dots2[p] - r br = dots2[p] + r tl *= zoom br *= zoom draw.ellipse([int(x) for x in [tl[0], tl[1], br[0], br[1]]], fill='#f00') for p,q in pairs: if p in alldots and q in alldots and (p in dots2 or q in dots2): pd = alldots[p] * zoom qd = alldots[q] * zoom D = pd-qd if D@D < zoom**2: draw.line([int(x) for x in [pd[0], pd[1], qd[0], qd[1]]], fill='#f00', width=2) for p in dots: r = 0.05 tl = dots[p] - r br = dots[p] + r tl *= zoom br *= zoom draw.ellipse([int(x) for x in [tl[0], tl[1], br[0], br[1]]], fill='#000') for p,q in pairs: if p in dots and q in dots: pd = dots[p] * zoom qd = dots[q] * zoom D = pd-qd if D@D < zoom**2: draw.line([int(x) for x in [pd[0], pd[1], qd[0], qd[1]]], fill='#000', width=3) imgByteArr = io.BytesIO() tn_image = image.resize((image.width//2, image.height//2), Image.LANCZOS) tn_image.save(imgByteArr, format='PNG') imgByteArr = imgByteArr.getvalue() sys.stdout.buffer.write(imgByteArr) lattice.logger.info("Hook1: end.")
def hook7(lattice): global options logger = getLogger() atomtypes = options["atomtypes"] logger.info("Hook7: Output radial distribution functions.") logger.info(" Total number of atoms: {0}".format(len(lattice.atoms))) binw = 0.003 nbin = int(options["range"] / binw) cellmat = lattice.repcell.mat rpos = defaultdict(list) for atom in lattice.atoms: resno, resname, atomname, position, order = atom alias = atomname if len(atomtypes): if atomname in atomtypes: alias = atomtypes[atomname] else: continue rpos[alias].append(lattice.repcell.abs2rel(position)) rdf = [] rdfname = [] volume = np.linalg.det(lattice.repcell.mat) grid = pl.determine_grid(cellmat, binw * nbin) logger.info(" {0}".format(rpos.keys())) for atomname in rpos: ra = rpos[atomname] = np.array(rpos[atomname]) na = ra.shape[0] logger.info(" Pair {0}-{0}".format(atomname)) i, j, delta = pl.pairs_fine(ra, binw * nbin, cellmat, grid, distance=True, raw=True) delta = np.floor(delta / binw) hist = dict(zip(*np.unique(delta, return_counts=True))) rdfname.append((atomname, atomname)) rdf.append(hist2rdf(hist, volume, (na, ), binw, nbin)) for a, b in it.combinations(rpos, 2): ra = rpos[a] rb = rpos[b] na = ra.shape[0] nb = rb.shape[0] logger.info(" Pair {0}-{1}".format(a, b)) i, j, delta = pl.pairs_fine_hetero(ra, rb, binw * nbin, cellmat, grid, distance=True, raw=True) delta = np.floor(delta / binw) hist = dict(zip(*np.unique(delta, return_counts=True))) rdfname.append((a, b)) rdf.append(hist2rdf(hist, volume, (na, nb), binw, nbin)) if options["json"]: D = dict() D["r"] = [i * binw for i in range(1, nbin)] for i, pair in enumerate(rdfname): name = "{0}--{1}".format(*pair) D[name] = [x for x in rdf[i]] print(json.dumps(D, indent=2, sort_keys=True)) else: print("# r/nm ", "\t".join(["{0}-{1}".format(*name) for name in rdfname])) for i in range(1, nbin): values = [i * binw] + [r[i] for r in rdf] print("\t".join(["{0:.3f}".format(v) for v in values])) logger.info("Hook7: end.")
def main(): logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") logger = logging.getLogger() gro = open(sys.argv[1]) unitinfo = open(sys.argv[2]) logger.info("Loading {0}".format(sys.argv[1])) box, atoms = LoadGRO(gro) ratoms = atoms/box cellmat = np.diag(box) celli = np.linalg.inv(cellmat) a,b,c = loadBOX9(unitinfo) unitcell = np.vstack((a,b,c)) # print(unitcell) uniti = np.linalg.inv(unitcell) D = np.linalg.norm((a+b+c)/2)+0.3 # diag of the half cell. grid = pl.determine_grid(cellmat, D) # print(grid) logger.info("Making the neighbor list.") z = pl.pairs_fine(ratoms, D, cellmat, grid, distance=False) g = nx.Graph(list(z)) logger.info("Reading smatch file.") matched = defaultdict(list) while True: line = sys.stdin.readline() #expect *.smatch result of slide-matcher2 if len(line) == 0: break cols = line.split() if len(cols)<7: break # broken line; maybe end of the file. i,j = [int(x) for x in cols[:2]] rad, dx,dy,dz, rmsd = [float(x) for x in cols[2:]] # d = np.array([dx,dy,dz]) # dL = np.linalg.norm(d) if rmsd < 0.085: # 0.08 for T144 # 距離によらず、よく一致したペアのラベルを保存しておく。 matched[i].append(j) matched[j].append(i) # 一番いろんなところと似ていた原子kをさがす。 #上位10個について、それぞれ周辺原子分布を作り、平行移動して重ねる。 # うまくいくかどうかはわからない。 logger.info("Overlaying atomic configurations.") order = sorted(matched, key=lambda x:len(matched[x]), reverse=True) logger.info([len(matched[x]) for x in order[:10]]) gridsize = (32,32,12) sumgrid = None accum = 0 for k in order[:10]: matched[k].append(k) # add itself kL = len(matched[k]) logger.info("Champion: {0} with {1} neighbors.".format(k, kL)) grid = distribute(gridsize, matched[k], ratoms, cellmat, uniti, g) sumgrid = slid_add(sumgrid, grid) accum += kL logger.info("{0} configurations collected.".format(accum)) # ここである程度対称性を整えてから出力するとあとが楽。 print("@GRID") print(*gridsize) for i in range(gridsize[0]): for j in range(gridsize[1]): for k in range(gridsize[2]): print(sumgrid[i,j,k] / accum) logger.info("Done.")