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 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 __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.")