def hook6(lattice): global nwateratoms lattice.logger.info("Hook6: Output water molecules in Yaplot format.") lattice.logger.info(" Total number of atoms: {0}".format( len(lattice.atoms))) # prepare the reverse dict waters = defaultdict(dict) for atom in lattice.atoms: resno, resname, atomname, position, order = atom if "O" in atomname: waters[order]["O"] = position elif "H" in atomname: if "H0" not in waters[order]: waters[order]["H0"] = position else: waters[order]["H1"] = position s = "" s += yp.Color(3) for order, water in waters.items(): O = water["O"] H0 = water["H0"] H1 = water["H1"] s += yp.Layer(4) s += yp.Color(3) s += yp.Size(0.03) s += yp.Circle(O) s += yp.Line(O, H0) s += yp.Line(O, H1) s += yp.Size(lattice.yaplot_size_H) s += yp.Circle(H0) s += yp.Circle(H1) s += yp.Color(2) s += yp.Layer(1) s += yp.Text(O, "{0}".format(order)) s += yp.Layer(3) s += yp.Color(4) s += yp.ArrowType(1) s += yp.Size(0.03) for i, j in lattice.spacegraph.edges(data=False): if i in waters and j in waters: # edge may connect to the dopant O = waters[j]["O"] H0 = waters[i]["H0"] H1 = waters[i]["H1"] d0 = H0 - O d1 = H1 - O rr0 = np.dot(d0, d0) rr1 = np.dot(d1, d1) if rr0 < rr1 and rr0 < 0.245**2: s += yp.Arrow(H0, O) if rr1 < rr0 and rr1 < 0.245**2: s += yp.Arrow(H1, O) print(s, end="") nwateratoms = len(lattice.atoms) lattice.logger.info("Hook6: end.")
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 hook2(lattice): logger = getLogger() logger.info("Hook2: Show rings in Yaplot format.") # copied from svg_poly graph = nx.Graph(lattice.graph) #undirected cellmat = lattice.repcell.mat s = "" s += yp.Layer(2) s += yp.Color(0) for i, j in graph.edges(): pi, pj = lattice.reppositions[i], lattice.reppositions[j] d = pj - pi d -= np.floor(d + 0.5) s += yp.Line(pi @ cellmat, (pi + d) @ cellmat) for ring in cr.CountRings(graph, pos=lattice.reppositions).rings_iter( lattice.largestring): deltas = np.zeros((len(ring), 3)) d2 = np.zeros(3) for k, i in enumerate(ring): d = lattice.reppositions[i] - lattice.reppositions[ring[0]] d -= np.floor(d + 0.5) deltas[k] = d comofs = np.sum(deltas, axis=0) / len(ring) deltas -= comofs com = lattice.reppositions[ring[0]] + comofs com -= np.floor(com) # rel to abs com = np.dot(com, cellmat) deltas = np.dot(deltas, cellmat) s += face(com, deltas) print(s) logger.info("Hook2: end.")
def face(center, rpos): pos = rpos + center n = rpos.shape[0] s = yp.Color(n) s += yp.Layer(n) s += yp.Polygon(pos) return s
def hook1(lattice): lattice.logger.info("Hook1: Diffraction.") lattice.logger.info(" 3D FFT.") cellmat = lattice.repcell.mat atoms = lattice.reppositions - np.floor(lattice.reppositions) grid = [32, 32, 32] distrib = np.zeros(grid) grid = np.array(grid) iatoms = np.array(np.floor(atoms * grid), dtype=int) for x, y, z in iatoms: distrib[x, y, z] += 1 diffr = np.fft.fftn(distrib, axes=(0, 1, 2)) power = np.real(diffr * np.conj(diffr)) / len(atoms) lattice.logger.info(" Rendering in Yaplot format.") cnt = contour3d.Contour(power, pbc=True, center=True) cnt.double() s = "" for layer, threshold in enumerate(lattice.thresholds): s += yp.Color(layer + 3) s += yp.Layer(layer + 1) nfacet = 0 #for face in cnt.facets(threshold): for face in cnt.contour_flakes(threshold): s += yp.Polygon(face) nfacet += 1 lattice.logger.info( " {0} facets rendered for threshold {1}.".format( nfacet, threshold)) print(s) lattice.logger.info("Hook1: end.")
def hook7(lattice): global nwateratoms lattice.logger.info("Hook7: Output water molecules in Yaplot format.") lattice.logger.info(" Total number of atoms: {0}".format( len(lattice.atoms))) gatoms = lattice.atoms[nwateratoms:] palettes = dict() s = "" s += yp.Layer(4) s += yp.ArrowType(1) H = [] O = "" for atom in gatoms: resno, resname, atomname, position, order = atom if atomname in palettes: pal = palettes[atomname] else: pal = 4 + len(palettes) palettes[atomname] = pal s += yp.Color(pal) s += yp.Size(0.04) s += yp.Circle(position) s = '#' + "\n#".join(lattice.doc) + "\n" + s print(s) lattice.logger.info("Hook7: end.")
def hook1(lattice): lattice.logger.info("Hook1: Draw the cell in Yaplot format.") s = yp.Layer(2) x, y, z = lattice.repcell.mat for p, q, r in ((x, y, z), (y, z, x), (z, x, y)): for a in (np.zeros(3), p, q, p + q): s += yp.Line(a, a + r) print(s, end="") lattice.logger.info("Hook1: end.")
def hook2(lattice): global options logger = getLogger() logger.info("Hook2: Petal statistics.") database = options.database if database is None: logger.info(" Using temporary database. (volatile)") gc = graphstat.GraphStat() elif database[:4] == "http": logger.info(" Using MySQL: {0}".format(database)) gc = graphstat_mysql.GraphStat(database) else: logger.info(" Using local Sqlite3: {0}".format(database)) import os.path create = not os.path.isfile(database) if create: logger.info(" Create new DB.") gc = graphstat_sqlite3.GraphStat(database, create=create) cell = lattice.repcell.mat positions = lattice.reppositions graph = nx.Graph(lattice.graph) #undirected rings, subgraphs, rings_at = prepare(graph, positions) gids = collect(subgraphs, gc) if options.json: # In JSON, a key must be a string. ids = {str(i): gids[i] for i in gids} print(json.dumps(ids, indent=2, sort_keys=True)) elif options.yaplot: # Draw top 10 most popular petal types with Yaplot. count = defaultdict(int) typical = dict() for node in gids: count[gids[node]] += 1 typical[gids[node]] = node top10 = sorted(count, key=lambda gid: -count[gid])[:30] ranks = {gid: i for i, gid in enumerate(top10)} for i, gid in enumerate(ranks): node = typical[gid] logger.info(" Ranking {0}: {2} x {1} (id {3})".format( i, [len(rings[ringid]) for ringid in rings_at[node]], count[gid], gid)) s = "" for node in gids: gid = gids[node] if gid in ranks: rank = ranks[gid] s += yp.Color(rank + 3) s += yp.Layer(rank + 1) for ringid in rings_at[node]: s += draw_ring(rings[ringid], positions, cell=cell, center=positions[node]) print(s) logger.info("Hook2: end.")
def draw_water(water, povray=False): s = "" if povray: s += pov.Sphere(water[0], r="RH", material="MATH") s += pov.Sphere(water[1], r="RH", material="MATH") s += pov.Sphere(water[2], r="RO", material="MATO") s += pov.Cylinder(water[0], water[2], r="ROH", material="MATOH") s += pov.Cylinder(water[1], water[2], r="ROH", material="MATOH") else: s += yp.Layer(1) s += yp.Color(5) s += yp.Size(0.2) s += yp.Circle(water[0]) s += yp.Circle(water[1]) s += yp.Color(4) s += yp.Size(0.4) s += yp.Circle(water[2]) s += yp.Color(2) d0 = water[0] - water[2] L0 = np.linalg.norm(d0) s += yp.Line(water[2] + d0 / L0 * 0.4, water[0] - d0 / L0 * 0.2) d1 = water[1] - water[2] L1 = np.linalg.norm(d1) s += yp.Line(water[2] + d1 / L1 * 0.4, water[1] - d1 / L1 * 0.2) # draw a tetrahedron y = water[1] - water[0] z = (water[1] + water[0]) / 2 - water[2] x = np.cross(y, z) x /= np.linalg.norm(x) y /= np.linalg.norm(y) z /= np.linalg.norm(z) com = (water[1] + water[0] + water[2] * 16) / 18 R = 2.76 / 2 a = y * (2 / 3)**0.5 + z * (1 / 3)**0.5 b = -y * (2 / 3)**0.5 + z * (1 / 3)**0.5 c = x * (2 / 3)**0.5 - z * (1 / 3)**0.5 d = -x * (2 / 3)**0.5 - z * (1 / 3)**0.5 s += yp.Layer(2) for e, f in it.combinations((a, b, c, d), 2): s += yp.Line(com + e * R, com + f * R) return s
def to_yaplot(cellmat, rpos, anions, cations, G, cation="N", anion="F"): """ cellmat: セル行列(後置記法) rpos: 分子のセル内相対位置 anions: アニオン番号 cations: カチオン番号 G: 水素結合ネットワーク """ # 水分子の原子位置 water = tip4picesites() s = "" for mol in G: if mol not in anions and mol not in cations: # genuine water molecule. rO = rpos[mol] H1, H2 = G[mol] rH1 = rpos[H1] - rO rH1 -= np.floor(rH1 + 0.5) rH2 = rpos[H2] - rO rH2 -= np.floor(rH2 + 0.5) # 実座標 (angstrom) pO = rO @ cellmat pH1 = rH1 @ cellmat pH2 = rH2 @ cellmat ey = pH1 - pH2 ez = pH1 + pH2 ex = np.cross(ey, ez) # 分子内座標方向の単位ベクトル ex /= np.linalg.norm(ex) ey /= np.linalg.norm(ey) ez /= np.linalg.norm(ez) # 回転行列 R = np.array([ex, ey, ez]) # 水分子の原子位置 intra = water @ R + pO s += draw_water(intra) s += yp.Layer(3) s += yp.Size(0.5) s += yp.Color(6) for mol in G: if mol in anions: pos = rpos[mol] @ cellmat s += yp.Circle(pos) s += yp.Size(0.3) s += yp.Color(7) for mol in G: if mol in cations: pos = rpos[mol] @ cellmat s += yp.Circle(pos) s += yp.NewPage() return s
def hook2(lattice): global nwateratoms if lattice.yaplot_size_H > 0: return lattice.logger.info( "Hook2: Output CoM of water molecules in Yaplot format.") # prepare the reverse dict waters = defaultdict(dict) pos = lattice.reppositions @ lattice.repcell.mat s = "" for p in pos: s += yp.Layer(4) s += yp.Color(3) s += yp.Size(0.03) s += yp.Circle(p) print(s, end="") lattice.logger.info("Hook2: end.") return True
def draw_cell(voro_cell, box, kind=0): layer = kind + 2 if layer > 30: layer = 30 # draw frame s = yp.Layer(layer) s += yp.Color(0) origin = voro_cell['original'] voro_vertices = voro_cell['vertices'] voro_faces = voro_cell['faces'] g = voro_cell['graph'] for i, j in g.edges(): di = voro_vertices[i] - origin dj = voro_vertices[j] - origin s += yp.Line(origin + di * 0.9, origin + dj * 0.9) # draw faces s += yp.Color(kind + 10) for face in voro_faces: points = [] for point in face['vertices']: d = voro_vertices[point] - origin points.append(d * 0.89 + origin) s += yp.Polygon(points) return s
def main(): basicConfig(level=INFO, format="%(levelname)s %(message)s") logger = getLogger() every = 1 maxval = 1.0 adjdens = False while sys.argv[1][0] == "-": if sys.argv[1] == "-e": sys.argv.pop(1) every = int(sys.argv[2]) sys.argv.pop(1) elif sys.argv[1] == "-v": maxval = float(sys.argv[2]) sys.argv.pop(1) sys.argv.pop(1) elif sys.argv[1] == "-a": adjdens = True sys.argv.pop(1) else: usage() gcell, gatoms = LoadGRO(open(sys.argv[1])) # in AA, in AA ucell, uatoms = LoadGRO(open(sys.argv[2])) # in AA dens0 = gatoms.shape[0] / np.linalg.det(gcell) dens1 = uatoms.shape[0] / np.linalg.det(ucell) ratio = (dens1 / dens0)**(1. / 3.) if adjdens: logger.info(f"Scaling ratio: {ratio}") ucell *= ratio uatoms *= ratio gcelli = np.linalg.inv(gcell) ucelli = np.linalg.inv(ucell) mode = "" if len(sys.argv) > 3: mode = sys.argv[3] s = "" s += yp.Color(2) s += yp.Layer(1) origin = np.zeros(3) s += drawbox(origin, gcell, halfshift=False) #in absolute coord # unitatoms = np.dot(unitatoms, ucell) #s += unitatoms) #s = "" nline = 0 matched = set() palette = dict() while True: line = sys.stdin.readline() if len(line) == 0: break nline += 1 #parse the line cols = line.split() if len(cols) < 13: break # 2018-4-9 New output format of matcher.c msd = float(cols[0]) gcenter = gatoms[int(cols[1])].copy() #atom at the matching center gcenter -= np.floor(gcenter @ gcelli) @ gcell ucenter = int(cols[2]) rotmat = np.array([float(x) for x in cols[3:12]]).reshape((3, 3)) N = int(cols[12]) if len(cols) < 13 + N: break irot = np.linalg.inv(rotmat) members = [int(x) for x in cols[13:N + 13]] #draw matched box # roll the unit cell to center (abs) rel = uatoms - uatoms[ucenter] rel -= np.floor(rel @ ucelli + 0.5) @ ucell # rel to abs Slid = rel # rotate box Rotucell = ucell @ rotmat # Boxslide = -uatoms[ucenter] @ rotmat + gcenter # rotate atoms in the unit cell Slidunit = (Slid @ rotmat) + gcenter #s += yp.Color(3) if mode == "R": color = direction2color(rotmat[0] + rotmat[1] + rotmat[2]) elif mode == "T": color = direction2color(rotmat[2]) else: color = (0, 3, 0) #green if color not in palette: palette[color] = len(palette) + 6 s += yp.SetPalette(palette[color], color[0] * 255 // 3, color[1] * 255 // 3, color[2] * 255 // 3) if msd < maxval: matched |= set(members) if every != 0 and nline % every == 0 and msd < maxval: s += yp.Color(palette[color]) # matched box s += yp.Layer(4) s += drawbox(gcenter, Rotucell, halfshift=True, diag=(mode == "R")) # s += yp.Layer(2) # # unit cell # s += drawbox(Boxslide,Rotucell,halfshift=True) s += yp.Layer(2) #s += drawbox2(Boxslide,Rotucell) s += yp.Layer(5) s += yp.Size(0.3) s += yp.Color(5) s += drawatoms(Slidunit) for i in range(len(Slidunit)): g = gatoms[members[i]] d = Slidunit[i] - gatoms[members[i]] d -= np.floor(d @ gcelli + 0.5) @ gcell s += yp.Line(g, g + d) # 変位ベクトルはどうやってもうまくいかないので、やめる。 s += yp.Size(0.3) s += yp.Color(4) s += yp.Layer(3) s += drawatoms(gatoms, members=matched) print(s) # end of frame
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 hook2(lattice): global options logger = getLogger() logger.info("Hook2: Cages and vitrites") cell = lattice.repcell.mat positions = lattice.reppositions graph = nx.Graph(lattice.graph) #undirected ringsize = options.ring ringlist = [[ int(x) for x in ring ] for ring in cr.CountRings(graph, pos=positions).rings_iter(max(ringsize)) ] ringpos = [centerOfMass(ringnodes, positions) for ringnodes in ringlist] logger.info(" Rings: {0}".format(len(ringlist))) maxcagesize = max(options.sizes) cages = [] for cage in Polyhed(ringlist, maxcagesize): if len(cage) in options.sizes: valid = True for ringid in cage: if len(ringlist[ringid]) not in ringsize: valid = False if valid: cages.append(list(cage)) logger.info(" Cages: {0}".format(len(cages))) cagepos = np.array([centerOfMass(cage, ringpos) for cage in cages]) if options.gromacs: options.rings = ringlist options.cages = cages logger.debug("##2 {0}".format(cages)) logger.info("Hook2: end.") return if options.quad: oncage = defaultdict(list) for cage in cages: nodes = set() for ringid in cage: nodes |= set(ringlist[ringid]) for node in nodes: oncage[node].append(len(cage)) op = dict() for node in oncage: count = [0 for i in range(17)] for v in oncage[node]: count[v] += 1 v = "{0}{1}{2}{3}".format(count[12], count[14], count[15], count[16]) op[node] = v stat = defaultdict(int) for node in sorted(op): v = op[node] stat[v] += 1 if options.json: output = dict() N = positions.shape[0] output["op"] = {str(k): v for k, v in op.items()} output["stat"] = {k: v / N for k, v in stat.items()} print(json.dumps(output, indent=2, sort_keys=True)) else: for node in sorted(op): print(node, op[node]) print("# Statistics") for v in sorted(stat): print("{0} {1} {2}/{3}".format(v, stat[v] / positions.shape[0], stat[v], positions.shape[0])) #ideal = {"CS2": {"2002": 0.7058823529411765, # "3001": 0.23529411764705882, # "4000": 0.058823529411764705}, # "CS1": {"0400": 0.13043478260869565, # "1300": 0.8695652173913043}, #} #for ref in ideal: # dKL = 0 # for v in sorted(stat): # if v in ideal[ref]: # dKL += ideal[ref][v]*(log2(ideal[ref][v]) - log2(stat[v]/positions.shape[0])) # print("{0} dKL={1}".format(ref, dKL)) elif options.json: output = dict() output["rings"] = ringlist output["cages"] = cages output["ringpos"] = [[x, y, z] for x, y, z in ringpos] output["cagepos"] = [[x, y, z] for x, y, z in cagepos] print(json.dumps(output, indent=2, sort_keys=True)) elif options.yaplot: s = "" for c, cage in enumerate(cages): nodes = dict() cagesize = len(cage) for ringid in cage: ns = ringlist[ringid] for node in ns: if node not in nodes: # relative pos of the node nodepos = positions[node] - cagepos[c] nodepos -= np.floor(nodepos + 0.5) # shrink a little nodes[node] = nodepos * 0.9 s += yp.Color(len(ns)) s += yp.Layer(cagesize) polygon = (np.array([nodes[node] for node in ns]) + cagepos[c]) @ cell s += yp.Polygon(polygon) print(s + "\n") elif options.python: import graphstat as gs db = gs.GraphStat() labels = set() g_id2label = dict() print('cages="""') for c, cage in enumerate(cages): g = cage_to_graph(cage, ringlist) cagesize = len(cage) g_id = db.query_id(g) if g_id < 0: g_id = db.register() enum = 0 label = "{0}".format(cagesize, enum) while label in labels: enum += 1 label = "{0}_{1}".format(cagesize, enum) g_id2label[g_id] = label labels.add(label) else: label = g_id2label[g_id] print("{0:10s} {1:.4f} {2:.4f} {3:.4f}".format(label, *cagepos[c])) print('"""') else: # human-friendly redundant format for cageid, cage in enumerate(cages): print("Cage {0}: ({1}, {2}, {3}) {4} hedron".format( cageid, *cagepos[cageid], len(cage))) for ringid in sorted(cage): print(" Ring {0}: ({1}, {2}, {3}) {4} gon".format( ringid, *ringpos[ringid], len(ringlist[ringid]))) print(" Nodes: {0}".format(ringlist[ringid])) logger.info("Hook2: end.") return True # terminate